ReactOS 0.4.16-dev-122-g325d74c
msi.c File Reference
#include <stdio.h>
#include <windows.h>
#include <msi.h>
#include <msiquery.h>
#include <msidefs.h>
#include <sddl.h>
#include <fci.h>
#include <shellapi.h>
#include <objidl.h>
#include "wine/test.h"
#include "utils.h"
Include dependency graph for msi.c:

Go to the source code of this file.

Macros

#define _WIN32_MSI   300
 
#define COBJMACROS
 
#define GUID_SIZE   (39)
 
#define SQUASHED_GUID_SIZE   (33)
 
#define MEDIA_SIZE   0x7FFFFFFF
 
#define FOLDER_THRESHOLD   900000
 
#define HASHSIZE   sizeof(MSIFILEHASHINFO)
 
#define INIT_USERINFO()
 

Functions

static BOOL add_cabinet_storage (LPCSTR db, LPCSTR cabinet)
 
static UINT set_summary_info (MSIHANDLE hdb, LPSTR prodcode)
 
static MSIHANDLE create_package_db (LPSTR prodcode)
 
static void test_usefeature (void)
 
static void test_null (void)
 
static void test_getcomponentpath (void)
 
static void create_test_files (void)
 
static void delete_test_files (void)
 
static void test_MsiGetFileHash (void)
 
static BOOL squash_guid (LPCWSTR in, LPWSTR out)
 
static void create_test_guid (LPSTR prodcode, LPSTR squashed)
 
static charget_user_sid (void)
 
static void test_MsiQueryProductState (void)
 
static void encode_base85_guid (GUID *guid, LPWSTR str)
 
static void compose_base85_guid (LPSTR component, LPSTR comp_base85, LPSTR squashed)
 
static void test_MsiQueryFeatureState (void)
 
static void test_MsiQueryComponentState (void)
 
static void test_MsiGetComponentPath (void)
 
static void test_MsiGetComponentPathEx (void)
 
static void test_MsiProvideComponent (void)
 
static void test_MsiProvideQualifiedComponentEx (void)
 
static void test_MsiGetProductCode (void)
 
static void test_MsiEnumClients (void)
 
static void get_version_info (LPSTR path, LPSTR *vercheck, LPDWORD verchecksz, LPSTR *langcheck, LPDWORD langchecksz)
 
static void test_MsiGetFileVersion (void)
 
static void test_MsiGetProductInfo (void)
 
static void test_MsiGetProductInfoEx (void)
 
static void test_MsiGetUserInfo (void)
 
static void test_MsiOpenProduct (void)
 
static void test_MsiEnumPatchesEx_usermanaged (LPCSTR usersid, LPCSTR expectedsid)
 
static void test_MsiEnumPatchesEx_userunmanaged (LPCSTR usersid, LPCSTR expectedsid)
 
static void test_MsiEnumPatchesEx_machine (void)
 
static void test_MsiEnumPatchesEx (void)
 
static void test_MsiEnumPatches (void)
 
static void test_MsiGetPatchInfoEx (void)
 
static void test_MsiGetPatchInfo (void)
 
static void test_MsiEnumProducts (void)
 
static void test_MsiGetFileSignatureInformation (void)
 
static void test_MsiEnumProductsEx (void)
 
static void test_MsiEnumComponents (void)
 
static void test_MsiEnumComponentsEx (void)
 
static void test_MsiConfigureProductEx (void)
 
static void test_MsiSetFeatureAttributes (void)
 
static void test_MsiGetFeatureInfo (void)
 
static INT CALLBACK handler_a (LPVOID context, UINT type, LPCSTR msg)
 
static INT CALLBACK handler_w (LPVOID context, UINT type, LPCWSTR msg)
 
static INT CALLBACK handler_record (LPVOID context, UINT type, MSIHANDLE record)
 
static void test_MsiSetInternalUI (void)
 
static void test_MsiSetExternalUI (void)
 
static void test_lastusedsource (void)
 
static void test_setpropertyfolder (void)
 
static void test_sourcedir_props (void)
 
static void test_concurrentinstall (void)
 
static void test_command_line_parsing (void)
 
 START_TEST (msi)
 

Variables

static BOOL is_wow64
 
static const char msifile [] = "winetest.msi"
 
static const WCHAR msifileW [] = L"winetest.msi"
 
static const char directory_dat []
 
static const char component_dat []
 
static const char feature_dat []
 
static const char feature_comp_dat []
 
static const char file_dat []
 
static const char install_exec_seq_dat []
 
static const char media_dat []
 
static const char property_dat []
 
static const char ci2_property_dat []
 
static const char mcp_component_dat []
 
static const char mcp_feature_dat []
 
static const char mcp_feature_comp_dat []
 
static const char mcp_file_dat []
 
static const char lus_component_dat []
 
static const char lus_feature_dat []
 
static const char lus_file_dat []
 
static const char lus_feature_comp_dat []
 
static const char lus_install_exec_seq_dat []
 
static const char lus0_media_dat []
 
static const char lus1_media_dat []
 
static const char lus2_media_dat []
 
static const char spf_custom_action_dat []
 
static const char spf_install_exec_seq_dat []
 
static const char spf_install_ui_seq_dat []
 
static const char spf_directory_dat []
 
static const char spf_component_dat []
 
static const char spf2_install_exec_seq_dat []
 
static const char spf2_custom_action_dat []
 
static const char shortcut_dat []
 
static const char sd_file_dat []
 
static const char sd_feature_dat []
 
static const char sd_feature_comp_dat []
 
static const char sd_component_dat []
 
static const char sd_install_ui_seq_dat []
 
static const char sd_install_exec_seq_dat []
 
static const char sd_custom_action_dat []
 
static const char ci_install_exec_seq_dat []
 
static const char ci_custom_action_dat []
 
static const char ci_component_dat []
 
static const char ci2_component_dat []
 
static const char ci2_feature_comp_dat []
 
static const char ci2_file_dat []
 
static const char cl_custom_action_dat []
 
static const char cl_install_exec_seq_dat []
 
static const msi_table tables []
 
static const msi_table mcp_tables []
 
static const msi_table lus0_tables []
 
static const msi_table lus1_tables []
 
static const msi_table lus2_tables []
 
static const msi_table spf_tables []
 
static const msi_table spf2_tables []
 
static const msi_table sd_tables []
 
static const msi_table ci_tables []
 
static const msi_table ci2_tables []
 
static const msi_table cl_tables []
 
struct {
   LPCSTR   data
 
   DWORD   size
 
   MSIFILEHASHINFO   hash
 
hash_data []
 
static const char table_enc85 []
 

Macro Definition Documentation

◆ _WIN32_MSI

#define _WIN32_MSI   300

Definition at line 21 of file msi.c.

◆ COBJMACROS

#define COBJMACROS

Definition at line 22 of file msi.c.

◆ FOLDER_THRESHOLD

#define FOLDER_THRESHOLD   900000

Definition at line 48 of file msi.c.

◆ GUID_SIZE

#define GUID_SIZE   (39)

Definition at line 37 of file msi.c.

◆ HASHSIZE

#define HASHSIZE   sizeof(MSIFILEHASHINFO)

Definition at line 1011 of file msi.c.

◆ INIT_USERINFO

#define INIT_USERINFO ( )
Value:
lstrcpyA(user, "apple"); \
lstrcpyA(org, "orange"); \
lstrcpyA(serial, "banana"); \
usersz = orgsz = serialsz = MAX_PATH;
void user(int argc, const char *argv[])
Definition: cmds.c:1350
#define MAX_PATH
Definition: compat.h:34
uint32_t serial
Definition: fsck.fat.h:29
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
static char org[]
Definition: encode.c:7456

Definition at line 7957 of file msi.c.

◆ MEDIA_SIZE

#define MEDIA_SIZE   0x7FFFFFFF

Definition at line 47 of file msi.c.

◆ SQUASHED_GUID_SIZE

#define SQUASHED_GUID_SIZE   (33)

Definition at line 38 of file msi.c.

Function Documentation

◆ add_cabinet_storage()

static BOOL add_cabinet_storage ( LPCSTR  db,
LPCSTR  cabinet 
)
static

Definition at line 50 of file msi.c.

51{
52 WCHAR dbW[MAX_PATH], cabinetW[MAX_PATH];
53 IStorage *stg;
54 IStream *stm;
55 HRESULT hr;
57
58 MultiByteToWideChar(CP_ACP, 0, db, -1, dbW, MAX_PATH);
60 if (FAILED(hr))
61 return FALSE;
62
63 MultiByteToWideChar(CP_ACP, 0, cabinet, -1, cabinetW, MAX_PATH);
64 hr = IStorage_CreateStream(stg, cabinetW, STGM_WRITE|STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
65 if (FAILED(hr))
66 {
67 IStorage_Release(stg);
68 return FALSE;
69 }
70
73 {
75 char buffer[1024];
76 if (ReadFile(handle, buffer, sizeof(buffer), &count, NULL))
77 IStream_Write(stm, buffer, count, &count);
79 }
80
81 IStream_Release(stm);
82 IStorage_Release(stg);
83
84 return TRUE;
85}
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
#define CP_ACP
Definition: compat.h:109
#define OPEN_EXISTING
Definition: compat.h:775
#define ReadFile(a, b, c, d, e)
Definition: compat.h:742
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define CreateFileW
Definition: compat.h:741
#define MultiByteToWideChar
Definition: compat.h:110
HRESULT WINAPI StgOpenStorage(const OLECHAR *pwcsName, IStorage *pstgPriority, DWORD grfMode, SNB snbExclude, DWORD reserved, IStorage **ppstgOpen)
Definition: storage32.c:8755
unsigned long DWORD
Definition: ntddk_ex.h:95
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint buffer
Definition: glext.h:5915
#define FAILED(hr)
Definition: intsafe.h:51
#define STGM_DIRECT
Definition: objbase.h:914
#define STGM_READWRITE
Definition: objbase.h:919
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_WRITE
Definition: objbase.h:918
HRESULT hr
Definition: shlfolder.c:183
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by test_lastusedsource().

◆ compose_base85_guid()

static void compose_base85_guid ( LPSTR  component,
LPSTR  comp_base85,
LPSTR  squashed 
)
static

Definition at line 1495 of file msi.c.

1496{
1497 WCHAR guidW[MAX_PATH];
1498 WCHAR base85W[MAX_PATH];
1499 WCHAR squashedW[MAX_PATH];
1500 GUID guid;
1501 HRESULT hr;
1502 int size;
1503
1504 hr = CoCreateGuid(&guid);
1505 ok(hr == S_OK, "Expected S_OK, got %#lx\n", hr);
1506
1507 size = StringFromGUID2(&guid, guidW, MAX_PATH);
1508 ok(size == 39, "Expected 39, got %d\n", size);
1509
1510 WideCharToMultiByte(CP_ACP, 0, guidW, size, component, MAX_PATH, NULL, NULL);
1511 encode_base85_guid(&guid, base85W);
1512 WideCharToMultiByte(CP_ACP, 0, base85W, -1, comp_base85, MAX_PATH, NULL, NULL);
1513 squash_guid(guidW, squashedW);
1514 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
1515}
#define ok(value,...)
Definition: atltest.h:57
#define WideCharToMultiByte
Definition: compat.h:111
HRESULT WINAPI CoCreateGuid(GUID *pguid)
Definition: compobj.c:2206
INT WINAPI StringFromGUID2(REFGUID id, LPOLESTR str, INT cmax)
Definition: compobj.c:2434
GLsizeiptr size
Definition: glext.h:5919
#define S_OK
Definition: intsafe.h:52
const GUID * guid
static void encode_base85_guid(GUID *guid, LPWSTR str)
Definition: msi.c:1474
BOOL squash_guid(LPCWSTR in, LPWSTR out)
Definition: registry.c:74

Referenced by test_MsiEnumClients(), test_MsiGetComponentPath(), test_MsiGetComponentPathEx(), test_MsiGetProductCode(), test_MsiProvideQualifiedComponentEx(), test_MsiQueryComponentState(), and test_MsiQueryFeatureState().

◆ create_package_db()

static MSIHANDLE create_package_db ( LPSTR  prodcode)
static

Definition at line 756 of file msi.c.

757{
758 MSIHANDLE hdb = 0;
759 CHAR query[MAX_PATH + 72];
760 UINT res;
761
763
764 /* create an empty database */
766 ok( res == ERROR_SUCCESS , "Failed to create database\n" );
767 if (res != ERROR_SUCCESS)
768 return hdb;
769
770 res = MsiDatabaseCommit(hdb);
771 ok(res == ERROR_SUCCESS, "Failed to commit database\n");
772
773 set_summary_info(hdb, prodcode);
774
775 res = run_query(hdb, 0,
776 "CREATE TABLE `Directory` ( "
777 "`Directory` CHAR(255) NOT NULL, "
778 "`Directory_Parent` CHAR(255), "
779 "`DefaultDir` CHAR(255) NOT NULL "
780 "PRIMARY KEY `Directory`)");
781 ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
782
783 res = run_query(hdb, 0,
784 "CREATE TABLE `Property` ( "
785 "`Property` CHAR(72) NOT NULL, "
786 "`Value` CHAR(255) "
787 "PRIMARY KEY `Property`)");
788 ok(res == ERROR_SUCCESS , "Failed to create directory table\n");
789
790 sprintf(query, "INSERT INTO `Property` "
791 "(`Property`, `Value`) "
792 "VALUES( 'ProductCode', '%s' )", prodcode);
793 res = run_query(hdb, 0, query);
794 ok(res == ERROR_SUCCESS , "Failed\n");
795
796 res = MsiDatabaseCommit(hdb);
797 ok(res == ERROR_SUCCESS, "Failed to commit database\n");
798
799 return hdb;
800}
static int run_query(HKEY root, WCHAR *path, WCHAR *key_name, WCHAR *value_name, BOOL value_empty, BOOL recurse)
Definition: query.c:311
#define ERROR_SUCCESS
Definition: deptool.c:10
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
GLuint res
Definition: glext.h:9613
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const WCHAR msifileW[]
Definition: msi.c:42
static const char msifile[]
Definition: msi.c:41
static UINT set_summary_info(MSIHANDLE hdb, LPSTR prodcode)
Definition: msi.c:712
UINT WINAPI MsiDatabaseCommit(MSIHANDLE hdb)
Definition: msiquery.c:962
#define MSIDBOPEN_CREATE
Definition: msiquery.h:69
unsigned int UINT
Definition: ndis.h:50
unsigned long MSIHANDLE
Definition: winemsi.idl:27
char CHAR
Definition: xmlstorage.h:175

◆ create_test_files()

static void create_test_files ( void  )
static

Definition at line 977 of file msi.c.

978{
979 CreateDirectoryA("msitest", NULL);
980 create_file("msitest\\one.txt", 100);
981 CreateDirectoryA("msitest\\first", NULL);
982 create_file("msitest\\first\\two.txt", 100);
983 CreateDirectoryA("msitest\\second", NULL);
984 create_file("msitest\\second\\three.txt", 100);
985
986 create_file("four.txt", 100);
987 create_file("five.txt", 100);
988 create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
989
990 create_file("msitest\\filename", 100);
991 create_file("msitest\\service.exe", 100);
992
993 DeleteFileA("four.txt");
994 DeleteFileA("five.txt");
995}
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
static void create_cab_file(void)
Definition: files.c:356
#define create_file(name, size)
Definition: asmcache.c:813
#define MEDIA_SIZE
Definition: msi.c:47

Referenced by test_command_line_parsing(), test_MsiProvideComponent(), and test_sourcedir_props().

◆ create_test_guid()

static void create_test_guid ( LPSTR  prodcode,
LPSTR  squashed 
)
static

◆ delete_test_files()

static void delete_test_files ( void  )
static

Definition at line 997 of file msi.c.

998{
999 DeleteFileA("msitest.msi");
1000 DeleteFileA("msitest.cab");
1001 DeleteFileA("msitest\\second\\three.txt");
1002 DeleteFileA("msitest\\first\\two.txt");
1003 DeleteFileA("msitest\\one.txt");
1004 DeleteFileA("msitest\\service.exe");
1005 DeleteFileA("msitest\\filename");
1006 RemoveDirectoryA("msitest\\second");
1007 RemoveDirectoryA("msitest\\first");
1008 RemoveDirectoryA("msitest");
1009}
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714

Referenced by test_command_line_parsing(), test_MsiProvideComponent(), and test_sourcedir_props().

◆ encode_base85_guid()

static void encode_base85_guid ( GUID guid,
LPWSTR  str 
)
static

Definition at line 1474 of file msi.c.

1475{
1476 unsigned int x, *p, i;
1477
1478 p = (unsigned int*) guid;
1479 for( i=0; i<4; i++ )
1480 {
1481 x = p[i];
1482 *str++ = table_enc85[x%85];
1483 x = x/85;
1484 *str++ = table_enc85[x%85];
1485 x = x/85;
1486 *str++ = table_enc85[x%85];
1487 x = x/85;
1488 *str++ = table_enc85[x%85];
1489 x = x/85;
1490 *str++ = table_enc85[x%85];
1491 }
1492 *str = 0;
1493}
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLfloat GLfloat p
Definition: glext.h:8902
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static const char table_enc85[]
Definition: msi.c:1465
const WCHAR * str

Referenced by compose_base85_guid().

◆ get_user_sid()

static char * get_user_sid ( void  )
static

Definition at line 1154 of file msi.c.

1155{
1156 HANDLE token;
1157 DWORD size = 0;
1159 char *usersid = NULL;
1160
1163
1164 user = malloc(size);
1166 ConvertSidToStringSidA(user->User.Sid, &usersid);
1167 free(user);
1168
1170 return usersid;
1171}
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:411
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:294
BOOL WINAPI ConvertSidToStringSidA(PSID Sid, LPSTR *StringSid)
Definition: security.c:3637
#define GetCurrentProcess()
Definition: compat.h:759
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat token
Definition: glfuncs.h:210
#define TOKEN_QUERY
Definition: setypes.h:928
@ TokenUser
Definition: setypes.h:966

Referenced by test_MsiEnumClients(), test_MsiEnumComponents(), test_MsiEnumComponentsEx(), test_MsiEnumPatches(), test_MsiEnumPatchesEx(), test_MsiEnumProducts(), test_MsiEnumProductsEx(), test_MsiGetComponentPath(), test_MsiGetComponentPathEx(), test_MsiGetPatchInfoEx(), test_MsiGetProductCode(), test_MsiGetProductInfoEx(), test_MsiGetUserInfo(), test_MsiOpenProduct(), test_MsiQueryComponentState(), test_MsiQueryFeatureState(), and test_MsiQueryProductState().

◆ get_version_info()

static void get_version_info ( LPSTR  path,
LPSTR vercheck,
LPDWORD  verchecksz,
LPSTR langcheck,
LPDWORD  langchecksz 
)
static

Definition at line 3967 of file msi.c.

3969{
3970 LPSTR version;
3971 VS_FIXEDFILEINFO *ffi;
3973 UINT len;
3974 USHORT *lang;
3975
3976 version = malloc(size);
3978
3979 VerQueryValueA(version, "\\", (LPVOID *)&ffi, &len);
3980 *vercheck = malloc(MAX_PATH);
3981 sprintf(*vercheck, "%d.%d.%d.%d", HIWORD(ffi->dwFileVersionMS),
3983 LOWORD(ffi->dwFileVersionLS));
3984 *verchecksz = lstrlenA(*vercheck);
3985
3986 VerQueryValueA(version, "\\VarFileInfo\\Translation", (void **)&lang, &len);
3987 *langcheck = malloc(MAX_PATH);
3988 sprintf(*langcheck, "%d", *lang);
3989 *langchecksz = lstrlenA(*langcheck);
3990
3991 free(version);
3992}
static const WCHAR version[]
Definition: asmname.c:66
DWORD WINAPI GetFileVersionInfoSizeA(LPCSTR filename, LPDWORD handle)
Definition: version.c:619
BOOL WINAPI VerQueryValueA(LPCVOID pBlock, LPCSTR lpSubBlock, LPVOID *lplpBuffer, PUINT puLen)
Definition: version.c:993
BOOL WINAPI GetFileVersionInfoA(LPCSTR filename, DWORD handle, DWORD datasize, LPVOID data)
Definition: version.c:853
GLenum GLsizei len
Definition: glext.h:6722
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define LOWORD(l)
Definition: pedump.c:82
unsigned short USHORT
Definition: pedump.c:61
DWORD dwFileVersionLS
Definition: compat.h:903
DWORD dwFileVersionMS
Definition: compat.h:902
#define HIWORD(l)
Definition: typedefs.h:247
static const WCHAR lang[]
Definition: wbemdisp.c:287
char * LPSTR
Definition: xmlstorage.h:182

Referenced by test_MsiGetFileVersion().

◆ handler_a()

static INT CALLBACK handler_a ( LPVOID  context,
UINT  type,
LPCSTR  msg 
)
static

Definition at line 12891 of file msi.c.

12892{
12893 return IDOK;
12894}
#define IDOK
Definition: winuser.h:833

Referenced by test_MsiSetExternalUI().

◆ handler_record()

static INT CALLBACK handler_record ( LPVOID  context,
UINT  type,
MSIHANDLE  record 
)
static

Definition at line 12901 of file msi.c.

12902{
12903 return IDOK;
12904}

Referenced by test_MsiSetExternalUI().

◆ handler_w()

static INT CALLBACK handler_w ( LPVOID  context,
UINT  type,
LPCWSTR  msg 
)
static

Definition at line 12896 of file msi.c.

12897{
12898 return IDOK;
12899}

Referenced by test_MsiSetExternalUI().

◆ set_summary_info()

static UINT set_summary_info ( MSIHANDLE  hdb,
LPSTR  prodcode 
)
static

Definition at line 712 of file msi.c.

713{
714 UINT res;
716
717 /* build summary info */
719 ok(res == ERROR_SUCCESS, "Failed to open summaryinfo\n");
720
722 "Installation Database");
723 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
724
726 "Installation Database");
727 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
728
730 "Wine Hackers");
731 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
732
734 ";1033");
735 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
736
738 "{A2078D65-94D6-4205-8DEE-F68D6FD622AA}");
739 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
740
742 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
743
745 ok(res == ERROR_SUCCESS, "Failed to set summary info\n");
746
748 ok(res == ERROR_SUCCESS, "Failed to make summary info persist\n");
749
751 ok(res == ERROR_SUCCESS, "Failed to close suminfo\n");
752
753 return res;
754}
static const CHAR suminfo[]
Definition: db.c:2166
@ VT_LPSTR
Definition: compat.h:2324
@ VT_I4
Definition: compat.h:2298
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, const char *szValue)
Definition: suminfo.c:942
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, const char *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:589
UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE handle)
Definition: suminfo.c:1227
#define PID_REVNUMBER
Definition: suminfo.c:51

Referenced by create_package_db().

◆ squash_guid()

static BOOL squash_guid ( LPCWSTR  in,
LPWSTR  out 
)
static

Definition at line 1100 of file msi.c.

1101{
1102 DWORD i,n=1;
1103 GUID guid;
1104
1105 if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
1106 return FALSE;
1107
1108 for(i=0; i<8; i++)
1109 out[7-i] = in[n++];
1110 n++;
1111 for(i=0; i<4; i++)
1112 out[11-i] = in[n++];
1113 n++;
1114 for(i=0; i<4; i++)
1115 out[15-i] = in[n++];
1116 n++;
1117 for(i=0; i<2; i++)
1118 {
1119 out[17+i*2] = in[n++];
1120 out[16+i*2] = in[n++];
1121 }
1122 n++;
1123 for( ; i<8; i++)
1124 {
1125 out[17+i*2] = in[n++];
1126 out[16+i*2] = in[n++];
1127 }
1128 out[32]=0;
1129 return TRUE;
1130}
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
GLdouble n
Definition: glext.h:7729
GLuint in
Definition: glext.h:9616
static FILE * out
Definition: regtests2xml.c:44

◆ START_TEST()

START_TEST ( msi  )

Definition at line 13426 of file msi.c.

13427{
13428 DWORD len;
13429 char temp_path[MAX_PATH], prev_path[MAX_PATH];
13430
13431#ifdef __REACTOS__
13432 if (!winetest_interactive &&
13433 !strcmp(winetest_platform, "windows"))
13434 {
13435 skip("ROSTESTS-180: Skipping msi_winetest:msi because it hangs on WHS-Testbot. Set winetest_interactive to run it anyway.\n");
13436 return;
13437 }
13438#endif
13439
13441
13443
13444 GetCurrentDirectoryA(MAX_PATH, prev_path);
13447
13450
13451 if(len && (CURR_DIR[len - 1] == '\\'))
13452 CURR_DIR[len - 1] = 0;
13453
13454 ok(get_system_dirs(), "failed to retrieve system dirs\n");
13455
13457 test_null();
13493
13494 SetCurrentDirectoryA(prev_path);
13495}
static char CURR_DIR[MAX_PATH]
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define skip(...)
Definition: atltest.h:64
#define IsWow64Process
Definition: compat.h:760
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
static BOOL is_process_elevated(void)
Definition: dplayx.c:6742
void restart_as_admin_elevated(void)
Definition: action.c:6478
BOOL get_system_dirs(void)
Definition: install.c:2357
static void test_MsiGetComponentPathEx(void)
Definition: msi.c:2938
static void test_MsiGetComponentPath(void)
Definition: msi.c:2391
static void test_MsiGetFileSignatureInformation(void)
Definition: msi.c:12054
static void test_MsiEnumComponents(void)
Definition: msi.c:12268
static void test_MsiGetFeatureInfo(void)
Definition: msi.c:12808
static void test_MsiGetProductInfo(void)
Definition: msi.c:4257
static void test_MsiEnumPatches(void)
Definition: msi.c:10284
static void test_MsiEnumClients(void)
Definition: msi.c:3764
static void test_usefeature(void)
Definition: msi.c:802
static void test_MsiGetPatchInfo(void)
Definition: msi.c:11765
static void test_MsiEnumProductsEx(void)
Definition: msi.c:12097
static void test_MsiSetFeatureAttributes(void)
Definition: msi.c:12726
static void test_MsiQueryFeatureState(void)
Definition: msi.c:1517
static BOOL is_wow64
Definition: msi.c:40
static void test_MsiSetExternalUI(void)
Definition: msi.c:12923
static void test_MsiGetFileVersion(void)
Definition: msi.c:3994
static void test_MsiGetFileHash(void)
Definition: msi.c:1045
static void test_MsiGetUserInfo(void)
Definition: msi.c:7963
static void test_MsiEnumPatchesEx(void)
Definition: msi.c:10098
static void test_MsiOpenProduct(void)
Definition: msi.c:8559
static void test_MsiQueryComponentState(void)
Definition: msi.c:2007
static void test_null(void)
Definition: msi.c:835
static void test_MsiGetProductCode(void)
Definition: msi.c:3485
static void test_MsiProvideComponent(void)
Definition: msi.c:3259
static void test_MsiQueryProductState(void)
Definition: msi.c:1173
static void test_MsiConfigureProductEx(void)
Definition: msi.c:12441
static void test_MsiGetPatchInfoEx(void)
Definition: msi.c:10878
static void test_MsiGetProductInfoEx(void)
Definition: msi.c:5554
static void test_setpropertyfolder(void)
Definition: msi.c:13096
static void test_MsiSetInternalUI(void)
Definition: msi.c:12906
static void test_MsiEnumProducts(void)
Definition: msi.c:11958
static void test_getcomponentpath(void)
Definition: msi.c:940
static void test_command_line_parsing(void)
Definition: msi.c:13266
static void test_MsiEnumComponentsEx(void)
Definition: msi.c:12341
static void test_concurrentinstall(void)
Definition: msi.c:13214
static void test_sourcedir_props(void)
Definition: msi.c:13151
static void test_MsiProvideQualifiedComponentEx(void)
Definition: msi.c:3345
static void test_lastusedsource(void)
Definition: msi.c:12980
char temp_path[MAX_PATH]
Definition: mspatcha.c:123
const char * winetest_platform
int winetest_interactive

◆ test_command_line_parsing()

static void test_command_line_parsing ( void  )
static

Definition at line 13266 of file msi.c.

13267{
13268 UINT r;
13269 const char *cmd;
13270
13271 if (!is_process_elevated())
13272 {
13273 skip("process is limited\n");
13274 return;
13275 }
13276
13279
13281
13282 cmd = " ";
13284 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13285
13286 cmd = "=";
13288 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13289
13290 cmd = "==";
13292 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13293
13294 cmd = "one";
13296 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13297
13298 cmd = "=one";
13300 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13301
13302 cmd = "P=";
13304 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13305
13306 cmd = " P=";
13308 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13309
13310 cmd = "P= ";
13312 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13313
13314 cmd = "P=\"";
13316 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13317
13318 cmd = "P=\"\"";
13320 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13321
13322 cmd = "P=\"\"\"";
13324 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13325
13326 cmd = "P=\"\"\"\"";
13328 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13329
13330 cmd = "P=\" ";
13332 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13333
13334 cmd = "P= \"";
13336 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13337
13338 cmd = "P= \"\" ";
13340 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13341
13342 cmd = "P=\" \"";
13344 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13345
13346 cmd = "P=one";
13348 ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13349
13350 cmd = "P= one";
13352 ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13353
13354 cmd = "P=\"one";
13356 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13357
13358 cmd = "P=one\"";
13360 todo_wine ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13361
13362 cmd = "P=\"one\"";
13364 ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13365
13366 cmd = "P= \"one\" ";
13368 ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13369
13370 cmd = "P=\"one\"\"";
13372 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13373
13374 cmd = "P=\"\"one\"";
13376 ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13377
13378 cmd = "P=\"\"one\"\"";
13380 todo_wine ok(r == ERROR_INVALID_COMMAND_LINE, "Expected ERROR_INVALID_COMMAND_LINE, got %u\n", r);
13381
13382 cmd = "P=\"one two\"";
13384 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13385
13386 cmd = "P=\"\"\"one\"\" two\"";
13388 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13389
13390 cmd = "P=\"\"\"one\"\" two\" Q=three";
13392 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13393
13394 cmd = "P=\"\" Q=\"two\"";
13396 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13397
13398 cmd = "P=\"one\" Q=\"two\"";
13400 ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13401
13402 cmd = "P=\"one=two\"";
13404 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13405
13406 cmd = "Q=\"\" P=\"one\"";
13408 ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
13409
13410 cmd = "P=\"\"\"one\"\"\" Q=\"two\"";
13412 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13413
13414 cmd = "P=\"one \"\"two\"\"\" Q=\"three\"";
13416 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13417
13418 cmd = "P=\"\"\"one\"\" two\" Q=\"three\"";
13420 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13421
13424}
UINT WINAPI MsiInstallProductA(LPCSTR szPackagePath, LPCSTR szCommandLine)
Definition: msi.c:198
INSTALLUILEVEL WINAPI MsiSetInternalUI(INSTALLUILEVEL dwUILevel, HWND *phWnd)
Definition: msi.c:2281
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define todo_wine
Definition: custom.c:89
static void delete_test_files(void)
Definition: msi.c:997
static void create_test_files(void)
Definition: msi.c:977
static const msi_table cl_tables[]
Definition: msi.c:699
#define create_database(name, tables, num_tables)
Definition: utils.h:42
@ INSTALLUILEVEL_NONE
Definition: msi.h:66
Definition: ftp_var.h:139
#define ERROR_INVALID_COMMAND_LINE
Definition: winerror.h:997
#define ERROR_INSTALL_FAILURE
Definition: winerror.h:961

Referenced by START_TEST().

◆ test_concurrentinstall()

static void test_concurrentinstall ( void  )
static

Definition at line 13214 of file msi.c.

13215{
13216 UINT r;
13218
13219 if (!is_process_elevated())
13220 {
13221 skip("process is limited\n");
13222 return;
13223 }
13224
13225 CreateDirectoryA("msitest", NULL);
13226 CreateDirectoryA("msitest\\msitest", NULL);
13227 create_file("msitest\\maximus", 500);
13228 create_file("msitest\\msitest\\augustus", 500);
13229
13231
13233 lstrcatA(path, "\\msitest\\concurrent.msi");
13235
13237
13240 {
13241 skip("Not enough rights to perform tests\n");
13242 goto error;
13243 }
13244 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
13245 ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
13246 ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
13247 ok(delete_pf("msitest", FALSE), "Directory not created\n");
13248
13249 r = MsiConfigureProductA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}", INSTALLLEVEL_DEFAULT,
13251 ok(r == ERROR_SUCCESS, "got %u\n", r);
13252
13253 r = MsiConfigureProductA("{FF4AFE9C-6AC2-44F9-A060-9EA6BD16C75E}", INSTALLLEVEL_DEFAULT,
13255 ok(r == ERROR_SUCCESS, "got %u\n", r);
13256
13257error:
13260 DeleteFileA("msitest\\msitest\\augustus");
13261 DeleteFileA("msitest\\maximus");
13262 RemoveDirectoryA("msitest\\msitest");
13263 RemoveDirectoryA("msitest");
13264}
UINT WINAPI MsiConfigureProductA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState)
Definition: msi.c:946
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
#define error(str)
Definition: mkdosfs.c:1605
BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
Definition: install.c:2433
static const msi_table ci2_tables[]
Definition: msi.c:687
static const msi_table ci_tables[]
Definition: msi.c:674
@ INSTALLSTATE_ABSENT
Definition: msi.h:45
@ INSTALLLEVEL_DEFAULT
Definition: msi.h:87
@ INSTALLUILEVEL_FULL
Definition: msi.h:69
#define ERROR_INSTALL_PACKAGE_REJECTED
Definition: winerror.h:983

Referenced by START_TEST().

◆ test_getcomponentpath()

static void test_getcomponentpath ( void  )
static

Definition at line 940 of file msi.c.

941{
943 char buffer[0x100];
944 DWORD sz;
945
947 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
948
949 r = MsiGetComponentPathA( "bogus", "bogus", NULL, NULL );
950 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
951
952 r = MsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", NULL, NULL );
953 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
954
955 sz = sizeof buffer;
956 buffer[0]=0;
957 r = MsiGetComponentPathA( "bogus", "{00000000-0000-0000-000000000000}", buffer, &sz );
958 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
959
960 r = MsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C998E7}",
961 "{00000000-0000-0000-0000-000000000000}", buffer, &sz );
962 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
963
964 r = MsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
965 "{00000000-0000-0000-0000-00000000}", buffer, &sz );
966 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
967
968 r = MsiGetComponentPathA( "{00000409-78E1-11D2-B60F-006097C998E7}",
969 "{029E403D-A86A-1D11-5B5B0006799C897E}", buffer, &sz );
970 ok( r == INSTALLSTATE_INVALIDARG, "wrong return value\n");
971
972 r = MsiGetComponentPathA( "{00000000-78E1-11D2-B60F-006097C9987e}",
973 "{00000000-A68A-11d1-5B5B-0006799C897E}", buffer, &sz );
974 ok( r == INSTALLSTATE_UNKNOWN, "wrong return value\n");
975}
INSTALLSTATE WINAPI MsiGetComponentPathA(LPCSTR product, LPCSTR comp, LPSTR buf, LPDWORD buflen)
Definition: msi.c:2898
@ INSTALLSTATE_UNKNOWN
Definition: msi.h:42
@ INSTALLSTATE_INVALIDARG
Definition: msi.h:41
int INSTALLSTATE
Definition: winemsi.idl:31

Referenced by START_TEST().

◆ test_lastusedsource()

static void test_lastusedsource ( void  )
static

Definition at line 12980 of file msi.c.

12981{
12982 static const char prodcode[] = "{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}";
12983 char value[MAX_PATH], path[MAX_PATH];
12984 DWORD size;
12985 UINT r;
12986
12987 CreateDirectoryA("msitest", NULL);
12988 create_file("maximus", 500);
12989 create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
12990 DeleteFileA("maximus");
12991
12995
12997
12998 /* no cabinet file */
12999
13000 size = MAX_PATH;
13001 lstrcpyA(value, "aaa");
13004 ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13005 ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13006
13007 r = MsiInstallProductA("msifile0.msi", "PUBLISH_PRODUCT=1");
13009 {
13010 skip("Not enough rights to perform tests\n");
13011 goto error;
13012 }
13013 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13014
13016 lstrcatA(path, "\\");
13017
13018 size = MAX_PATH;
13019 lstrcpyA(value, "aaa");
13022 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13023 ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
13024 ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
13025
13026 r = MsiInstallProductA("msifile0.msi", "REMOVE=ALL FULL=1");
13027 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13028
13029 /* separate cabinet file */
13030
13031 size = MAX_PATH;
13032 lstrcpyA(value, "aaa");
13035 ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13036 ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13037
13038 r = MsiInstallProductA("msifile1.msi", "PUBLISH_PRODUCT=1");
13039 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13040
13042 lstrcatA(path, "\\");
13043
13044 size = MAX_PATH;
13045 lstrcpyA(value, "aaa");
13048 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13049 ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
13050 ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
13051
13052 r = MsiInstallProductA("msifile1.msi", "REMOVE=ALL FULL=1");
13053 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13054
13055 size = MAX_PATH;
13056 lstrcpyA(value, "aaa");
13059 ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13060 ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13061
13062 /* embedded cabinet stream */
13063
13064 add_cabinet_storage("msifile2.msi", "test1.cab");
13065
13066 r = MsiInstallProductA("msifile2.msi", "PUBLISH_PRODUCT=1");
13067 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13068
13069 size = MAX_PATH;
13070 lstrcpyA(value, "aaa");
13073 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13074 ok(!lstrcmpA(value, path), "expected \"%s\", got \"%s\"\n", path, value);
13075 ok(size == lstrlenA(path), "expected %d, got %lu\n", lstrlenA(path), size);
13076
13077 r = MsiInstallProductA("msifile2.msi", "REMOVE=ALL FULL=1");
13078 ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
13079
13080 size = MAX_PATH;
13081 lstrcpyA(value, "aaa");
13084 ok(r == ERROR_UNKNOWN_PRODUCT, "expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
13085 ok(!lstrcmpA(value, "aaa"), "expected \"aaa\", got \"%s\"\n", value);
13086
13087error:
13089 DeleteFileA("msitest\\maximus");
13090 RemoveDirectoryA("msitest");
13091 DeleteFileA("msifile0.msi");
13092 DeleteFileA("msifile1.msi");
13093 DeleteFileA("msifile2.msi");
13094}
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4194
UINT WINAPI MsiSourceListGetInfoA(LPCSTR szProduct, LPCSTR szUserSid, MSIINSTALLCONTEXT dwContext, DWORD dwOptions, LPCSTR szProperty, LPSTR szValue, LPDWORD pcchValue)
Definition: source.c:470
void delete_cab_files(void)
Definition: install.c:3003
static BOOL add_cabinet_storage(LPCSTR db, LPCSTR cabinet)
Definition: msi.c:50
static const msi_table lus0_tables[]
Definition: msi.c:595
static const msi_table lus2_tables[]
Definition: msi.c:619
static const msi_table lus1_tables[]
Definition: msi.c:607
#define INSTALLPROPERTY_LASTUSEDSOURCEA
Definition: msi.h:404
@ MSICODE_PRODUCT
Definition: msi.h:215
@ MSIINSTALLCONTEXT_USERUNMANAGED
Definition: msi.h:199
Definition: pdh_main.c:94
#define ERROR_UNKNOWN_PRODUCT
Definition: winerror.h:963

Referenced by START_TEST().

◆ test_MsiConfigureProductEx()

static void test_MsiConfigureProductEx ( void  )
static

Definition at line 12441 of file msi.c.

12442{
12443 UINT r;
12444 LONG res;
12445 DWORD type, size;
12446 HKEY props, source;
12447 CHAR keypath[MAX_PATH * 2], localpackage[MAX_PATH], packagename[MAX_PATH];
12449
12450 if (!is_process_elevated())
12451 {
12452 skip("process is limited\n");
12453 return;
12454 }
12455
12456 CreateDirectoryA("msitest", NULL);
12457 create_file_data("msitest\\hydrogen", "hydrogen", 500);
12458 create_file_data("msitest\\helium", "helium", 500);
12459 create_file_data("msitest\\lithium", "lithium", 500);
12460
12462
12463 if (is_wow64)
12465
12467
12468 /* NULL szProduct */
12470 INSTALLSTATE_DEFAULT, "PROPVAR=42");
12472 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12473
12474 /* empty szProduct */
12476 INSTALLSTATE_DEFAULT, "PROPVAR=42");
12478 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12479
12480 /* garbage szProduct */
12482 INSTALLSTATE_DEFAULT, "PROPVAR=42");
12484 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12485
12486 /* guid without brackets */
12487 r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
12489 "PROPVAR=42");
12491 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
12492
12493 /* guid with brackets */
12494 r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
12496 "PROPVAR=42");
12498 "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12499
12500 /* same length as guid, but random */
12501 r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
12503 "PROPVAR=42");
12505 "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12506
12507 /* product not installed yet */
12508 r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
12510 "PROPVAR=42");
12512 "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
12513
12514 /* install the product, per-user unmanaged */
12515 r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
12517 {
12518 skip("Not enough rights to perform tests\n");
12519 goto error;
12520 }
12521 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12522 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12523 ok(pf_exists("msitest\\helium"), "File not installed\n");
12524 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12525 ok(pf_exists("msitest"), "File not installed\n");
12526
12527 /* product is installed per-user managed, remove it */
12528 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12530 "PROPVAR=42");
12531 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12532 ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12533 ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12534 ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12535 ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12536
12537 /* product has been removed */
12538 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12540 "PROPVAR=42");
12542 "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12543
12544 /* install the product, machine */
12545 r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12546 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12547 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12548 ok(pf_exists("msitest\\helium"), "File not installed\n");
12549 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12550 ok(pf_exists("msitest"), "File not installed\n");
12551
12552 /* product is installed machine, remove it */
12553 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12555 "PROPVAR=42");
12556 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12557 ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12558 ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12559 ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12560 ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12561
12562 /* product has been removed */
12563 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12565 "PROPVAR=42");
12567 "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
12568
12569 /* install the product, machine */
12570 r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12571 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12572 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12573 ok(pf_exists("msitest\\helium"), "File not installed\n");
12574 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12575 ok(pf_exists("msitest"), "File not installed\n");
12576
12578
12579 /* msifile is removed */
12580 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12582 "PROPVAR=42");
12583 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12584 ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12585 ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12586 ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12587 ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12588
12590
12591 /* install the product, machine */
12592 r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12593 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12594 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12595 ok(pf_exists("msitest\\helium"), "File not installed\n");
12596 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12597 ok(pf_exists("msitest"), "File not installed\n");
12598
12600
12601 lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
12602 lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12603 lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
12604
12606 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12607
12608 type = REG_SZ;
12609 size = MAX_PATH;
12610 res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
12611 (LPBYTE)localpackage, &size);
12612 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12613
12614 res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12615 (const BYTE *)"C:\\idontexist.msi", 18);
12616 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12617
12618 /* LocalPackage is used to find the cached msi package */
12619 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12621 "PROPVAR=42");
12623 "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
12624 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12625 ok(pf_exists("msitest\\helium"), "File not installed\n");
12626 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12627 ok(pf_exists("msitest"), "File not installed\n");
12628
12631
12632 /* LastUsedSource can be used as a last resort */
12633 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12635 "PROPVAR=42");
12636 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12637 ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12638 ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12639 ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12640 ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12641 DeleteFileA( localpackage );
12642
12643 /* install the product, machine */
12644 r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
12645 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
12646 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12647 ok(pf_exists("msitest\\helium"), "File not installed\n");
12648 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12649 ok(pf_exists("msitest"), "File not installed\n");
12650
12651 lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
12652 lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
12653 lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\InstallProperties");
12654
12656 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12657
12658 type = REG_SZ;
12659 size = MAX_PATH;
12660 res = RegQueryValueExA(props, "LocalPackage", NULL, &type,
12661 (LPBYTE)localpackage, &size);
12662 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12663
12664 res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12665 (const BYTE *)"C:\\idontexist.msi", 18);
12666 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12667
12668 lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
12669 lstrcatA(keypath, "83374883CBB1401418CAF2AA7CCEDDDC\\SourceList");
12670
12672 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12673
12674 type = REG_SZ;
12675 size = MAX_PATH;
12676 res = RegQueryValueExA(source, "PackageName", NULL, &type,
12677 (LPBYTE)packagename, &size);
12678 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12679
12680 res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
12681 (const BYTE *)"idontexist.msi", 15);
12682 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12683
12684 /* SourceList is altered */
12685 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12687 "PROPVAR=42");
12689 "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
12690 ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
12691 ok(pf_exists("msitest\\helium"), "File not installed\n");
12692 ok(pf_exists("msitest\\lithium"), "File not installed\n");
12693 ok(pf_exists("msitest"), "File not installed\n");
12694
12695 /* restore PackageName */
12696 res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
12697 (const BYTE *)packagename, lstrlenA(packagename) + 1);
12698 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12699
12700 /* restore LocalPackage */
12701 res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
12702 (const BYTE *)localpackage, lstrlenA(localpackage) + 1);
12703 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
12704
12705 /* finally remove the product */
12706 r = MsiConfigureProductExA("{38847338-1BBC-4104-81AC-2FAAC7ECDDCD}",
12708 "PROPVAR=42");
12709 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
12710 ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
12711 ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
12712 ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
12713 ok(!delete_pf("msitest", FALSE), "Directory not removed\n");
12714
12717
12718error:
12719 DeleteFileA("msitest\\hydrogen");
12720 DeleteFileA("msitest\\helium");
12721 DeleteFileA("msitest\\lithium");
12722 RemoveDirectoryA("msitest");
12724}
#define RegCloseKey(hKey)
Definition: registry.h:49
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3298
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
UINT WINAPI MsiConfigureProductExA(LPCSTR szProduct, int iInstallLevel, INSTALLSTATE eInstallState, LPCSTR szCommandLine)
Definition: msi.c:916
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
#define REG_SZ
Definition: layer.c:22
static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
Definition: asmcache.c:795
static BOOL pf_exists(const char *file)
Definition: custom.c:1414
static const msi_table mcp_tables[]
Definition: msi.c:583
@ INSTALLSTATE_DEFAULT
Definition: msi.h:48
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
long LONG
Definition: pedump.c:60
unsigned char * LPBYTE
Definition: typedefs.h:53
static const WCHAR props[]
Definition: wbemdisp.c:288
#define ERROR_INSTALL_SOURCE_ABSENT
Definition: winerror.h:970
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
unsigned char BYTE
Definition: xxhash.c:193

Referenced by START_TEST().

◆ test_MsiEnumClients()

static void test_MsiEnumClients ( void  )
static

Definition at line 3764 of file msi.c.

3765{
3766 HKEY compkey;
3767 CHAR prodcode[MAX_PATH];
3768 CHAR prod_squashed[MAX_PATH];
3769 CHAR prodcode2[MAX_PATH];
3770 CHAR prod2_squashed[MAX_PATH];
3771 CHAR component[MAX_PATH];
3772 CHAR comp_base85[MAX_PATH];
3773 CHAR comp_squashed[MAX_PATH];
3774 CHAR product[MAX_PATH];
3775 CHAR keypath[MAX_PATH];
3776 LPSTR usersid;
3777 LONG res;
3778 UINT r;
3780
3781 create_test_guid(prodcode, prod_squashed);
3782 create_test_guid(prodcode2, prod2_squashed);
3783 compose_base85_guid(component, comp_base85, comp_squashed);
3784 usersid = get_user_sid();
3785
3786 if (is_wow64)
3788
3789 /* NULL szComponent */
3790 product[0] = '\0';
3791 r = MsiEnumClientsA(NULL, 0, product);
3792 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3793 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3794
3795 /* empty szComponent */
3796 product[0] = '\0';
3797 r = MsiEnumClientsA("", 0, product);
3798 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3799 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3800
3801 /* NULL lpProductBuf */
3802 r = MsiEnumClientsA(component, 0, NULL);
3803 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3804
3805 /* all params correct, component missing */
3806 product[0] = '\0';
3807 r = MsiEnumClientsA(component, 0, product);
3808 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3809 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3810
3811 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3812 lstrcatA(keypath, "Installer\\UserData\\");
3813 lstrcatA(keypath, usersid);
3814 lstrcatA(keypath, "\\Components\\");
3815 lstrcatA(keypath, comp_squashed);
3816
3817 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3818 if (res == ERROR_ACCESS_DENIED)
3819 {
3820 skip("Not enough rights to perform tests\n");
3821 LocalFree(usersid);
3822 return;
3823 }
3824 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3825
3826 /* user unmanaged component key exists */
3827 product[0] = '\0';
3828 r = MsiEnumClientsA(component, 0, product);
3829 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3830 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3831
3832 /* index > 0, no products exist */
3833 product[0] = '\0';
3834 r = MsiEnumClientsA(component, 1, product);
3835 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3836 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3837
3838 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3839 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3840
3841 /* product value exists */
3842 r = MsiEnumClientsA(component, 0, product);
3843 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3844 ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3845
3846 /* try index 0 again */
3847 product[0] = '\0';
3848 r = MsiEnumClientsA(component, 0, product);
3849 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3850 ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3851
3852 /* try index 1, second product value does not exist */
3853 product[0] = '\0';
3854 r = MsiEnumClientsA(component, 1, product);
3855 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3856 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3857
3858 res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3859 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3860
3861 /* try index 1, second product value does exist */
3862 product[0] = '\0';
3863 r = MsiEnumClientsA(component, 1, product);
3864 todo_wine
3865 {
3866 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3867 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3868 }
3869
3870 /* start the enumeration over */
3871 product[0] = '\0';
3872 r = MsiEnumClientsA(component, 0, product);
3873 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3874 ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3875 "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3876
3877 /* correctly query second product */
3878 product[0] = '\0';
3879 r = MsiEnumClientsA(component, 1, product);
3880 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3881 ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3882 "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3883
3884 RegDeleteValueA(compkey, prod_squashed);
3885 RegDeleteValueA(compkey, prod2_squashed);
3886 RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
3887 RegCloseKey(compkey);
3888
3889 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
3890 lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Components\\");
3891 lstrcatA(keypath, comp_squashed);
3892
3893 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &compkey, NULL);
3894 if (res == ERROR_ACCESS_DENIED)
3895 {
3896 skip("Not enough rights to perform tests\n");
3897 LocalFree(usersid);
3898 return;
3899 }
3900 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3901
3902 /* user local component key exists */
3903 product[0] = '\0';
3904 r = MsiEnumClientsA(component, 0, product);
3905 ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3906 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3907
3908 /* index > 0, no products exist */
3909 product[0] = '\0';
3910 r = MsiEnumClientsA(component, 1, product);
3911 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3912 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3913
3914 res = RegSetValueExA(compkey, prod_squashed, 0, REG_SZ, (const BYTE *)"C:\\imapath", 10);
3915 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3916
3917 /* product value exists */
3918 product[0] = '\0';
3919 r = MsiEnumClientsA(component, 0, product);
3920 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3921 ok(!lstrcmpA(product, prodcode), "Expected %s, got %s\n", prodcode, product);
3922
3923 /* try index 0 again */
3924 product[0] = '\0';
3925 r = MsiEnumClientsA(component, 0, product);
3926 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3927
3928 /* try index 1, second product value does not exist */
3929 product[0] = '\0';
3930 r = MsiEnumClientsA(component, 1, product);
3931 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3932 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3933
3934 res = RegSetValueExA(compkey, prod2_squashed, 0, REG_SZ, (const BYTE *)"C:\\another", 10);
3935 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
3936
3937 /* try index 1, second product value does exist */
3938 product[0] = '\0';
3939 r = MsiEnumClientsA(component, 1, product);
3940 todo_wine
3941 {
3942 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
3943 ok(!lstrcmpA(product, ""), "Expected product to be unchanged, got %s\n", product);
3944 }
3945
3946 /* start the enumeration over */
3947 product[0] = '\0';
3948 r = MsiEnumClientsA(component, 0, product);
3949 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3950 ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3951 "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3952
3953 /* correctly query second product */
3954 product[0] = '\0';
3955 r = MsiEnumClientsA(component, 1, product);
3956 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3957 ok(!lstrcmpA(product, prodcode) || !lstrcmpA(product, prodcode2),
3958 "Expected %s or %s, got %s\n", prodcode, prodcode2, product);
3959
3960 RegDeleteValueA(compkey, prod_squashed);
3961 RegDeleteValueA(compkey, prod2_squashed);
3962 RegDeleteKeyExA(compkey, "", access & KEY_WOW64_64KEY, 0);
3963 RegCloseKey(compkey);
3964 LocalFree(usersid);
3965}
LONG WINAPI RegDeleteKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1254
LONG WINAPI RegDeleteValueA(HKEY hKey, LPCSTR lpValueName)
Definition: reg.c:2287
LONG WINAPI RegCreateKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD Reserved, _In_ LPSTR lpClass, _In_ DWORD dwOptions, _In_ REGSAM samDesired, _In_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _Out_ PHKEY phkResult, _Out_ LPDWORD lpdwDisposition)
Definition: reg.c:1034
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define ERROR_ACCESS_DENIED
Definition: compat.h:97
UINT WINAPI MsiEnumClientsA(const char *szComponent, DWORD index, char *szProduct)
Definition: registry.c:1328
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1594
static void compose_base85_guid(LPSTR component, LPSTR comp_base85, LPSTR squashed)
Definition: msi.c:1495
static char * get_user_sid(void)
Definition: msi.c:1154
static void create_test_guid(LPSTR prodcode, LPSTR squashed)
Definition: msi.c:1132
#define ERROR_UNKNOWN_COMPONENT
Definition: winerror.h:965

Referenced by START_TEST().

◆ test_MsiEnumComponents()

static void test_MsiEnumComponents ( void  )
static

Definition at line 12268 of file msi.c.

12269{
12270 UINT r;
12271 BOOL found1, found2;
12272 DWORD index;
12273 char comp1[39], comp2[39], guid[39];
12274 char comp_squashed1[33], comp_squashed2[33];
12275 char keypath1[MAX_PATH], keypath2[MAX_PATH];
12277 char *usersid = get_user_sid();
12278 HKEY key1 = NULL, key2 = NULL;
12279
12280 if (!is_process_elevated())
12281 {
12282 skip("process is limited\n");
12283 return;
12284 }
12285
12286 create_test_guid( comp1, comp_squashed1 );
12287 create_test_guid( comp2, comp_squashed2 );
12288
12290
12291 strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12292 strcat( keypath1, "S-1-5-18\\Components\\" );
12293 strcat( keypath1, comp_squashed1 );
12294
12295 r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12296 if (r == ERROR_ACCESS_DENIED)
12297 {
12298 skip( "insufficient rights\n" );
12299 goto done;
12300 }
12301 ok( r == ERROR_SUCCESS, "got %u\n", r );
12302
12303 strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12304 strcat( keypath2, usersid );
12305 strcat( keypath2, "\\Components\\" );
12306 strcat( keypath2, comp_squashed2 );
12307
12308 r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12309 if (r == ERROR_ACCESS_DENIED)
12310 {
12311 skip( "insufficient rights\n" );
12312 goto done;
12313 }
12314
12315 r = MsiEnumComponentsA( 0, NULL );
12316 ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12317
12318 index = 0;
12319 guid[0] = 0;
12320 found1 = found2 = FALSE;
12321 while (!MsiEnumComponentsA( index, guid ))
12322 {
12323 if (!strcmp( guid, comp1 )) found1 = TRUE;
12324 if (!strcmp( guid, comp2 )) found2 = TRUE;
12325 ok( guid[0], "empty guid\n" );
12326 if (found1 && found2) break;
12327 guid[0] = 0;
12328 index++;
12329 }
12330 ok( found1, "comp1 not found\n" );
12331 ok( found2, "comp2 not found\n" );
12332
12333done:
12334 RegDeleteKeyExA( key1, "", access, 0 );
12335 RegDeleteKeyExA( key2, "", access, 0 );
12336 RegCloseKey( key1 );
12337 RegCloseKey( key2 );
12338 LocalFree( usersid );
12339}
char * strcat(char *DstString, const char *SrcString)
Definition: utclib.c:568
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
#define index(s, c)
Definition: various.h:29
UINT WINAPI MsiEnumComponentsA(DWORD index, char *lpguid)
Definition: registry.c:1099
unsigned int BOOL
Definition: ntddk_ex.h:94
GLuint index
Definition: glext.h:6031
GLuint64EXT GLuint GLuint GLenum GLenum GLuint GLuint GLenum GLuint GLuint key1
Definition: glext.h:10608

Referenced by START_TEST().

◆ test_MsiEnumComponentsEx()

static void test_MsiEnumComponentsEx ( void  )
static

Definition at line 12341 of file msi.c.

12342{
12343 UINT r;
12344 BOOL found1, found2;
12345 DWORD len, index;
12347 char comp1[39], comp2[39], guid[39], sid[128];
12348 char comp_squashed1[33], comp_squashed2[33];
12349 char keypath1[MAX_PATH], keypath2[MAX_PATH];
12350 HKEY key1 = NULL, key2 = NULL;
12352 char *usersid = get_user_sid();
12353
12354 if (!is_process_elevated())
12355 {
12356 skip("process is limited\n");
12357 return;
12358 }
12359
12360 create_test_guid( comp1, comp_squashed1 );
12361 create_test_guid( comp2, comp_squashed2 );
12362
12364
12365 strcpy( keypath1, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12366 strcat( keypath1, "S-1-5-18\\Components\\" );
12367 strcat( keypath1, comp_squashed1 );
12368
12369 r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath1, 0, NULL, 0, access, NULL, &key1, NULL );
12370 if (r == ERROR_ACCESS_DENIED)
12371 {
12372 skip( "insufficient rights\n" );
12373 goto done;
12374 }
12375 ok( r == ERROR_SUCCESS, "got %u\n", r );
12376
12377 strcpy( keypath2, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\" );
12378 strcat( keypath2, usersid );
12379 strcat( keypath2, "\\Components\\" );
12380 strcat( keypath2, comp_squashed2 );
12381
12382 r = RegCreateKeyExA( HKEY_LOCAL_MACHINE, keypath2, 0, NULL, 0, access, NULL, &key2, NULL );
12383 if (r == ERROR_ACCESS_DENIED)
12384 {
12385 skip( "insufficient rights\n" );
12386 goto done;
12387 }
12388 ok( r == ERROR_SUCCESS, "got %u\n", r );
12389 r = RegSetValueExA( key2, comp_squashed2, 0, REG_SZ, (const BYTE *)"c:\\doesnotexist",
12390 sizeof("c:\\doesnotexist"));
12391 ok( r == ERROR_SUCCESS, "got %u\n", r );
12392
12393 index = 0;
12394 guid[0] = 0;
12395 context = 0xdeadbeef;
12396 sid[0] = 0;
12397 len = sizeof(sid);
12398 found1 = found2 = FALSE;
12399 while (!MsiEnumComponentsExA( "S-1-1-0", MSIINSTALLCONTEXT_ALL, index, guid, &context, sid, &len ))
12400 {
12401 if (!strcmp( comp1, guid ))
12402 {
12403 ok( context == MSIINSTALLCONTEXT_MACHINE, "got %u\n", context );
12404 ok( !sid[0], "got \"%s\"\n", sid );
12405 ok( !len, "unexpected length %lu\n", len );
12406 found1 = TRUE;
12407 if (found2) break;
12408 }
12409 if (!strcmp( comp2, guid ))
12410 {
12412 ok( sid[0], "empty sid\n" );
12413 ok( len == strlen(sid), "unexpected length %lu\n", len );
12414 found2 = TRUE;
12415 if (found1) break;
12416 }
12417 index++;
12418 guid[0] = 0;
12419 context = 0xdeadbeef;
12420 sid[0] = 0;
12421 len = sizeof(sid);
12422 }
12423 ok( found1, "comp1 not found\n" );
12424 ok( found2, "comp2 not found\n" );
12425
12426 r = MsiEnumComponentsExA( NULL, 0, 0, NULL, NULL, NULL, NULL );
12427 ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12428
12430 ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r );
12431
12432done:
12433 RegDeleteValueA( key2, comp_squashed2 );
12434 RegDeleteKeyExA( key1, "", access, 0 );
12435 RegDeleteKeyExA( key2, "", access, 0 );
12436 RegCloseKey( key1 );
12437 RegCloseKey( key2 );
12438 LocalFree( usersid );
12439}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
FT_UInt sid
Definition: cffcmap.c:139
UINT WINAPI MsiEnumComponentsExA(const char *user_sid, DWORD ctx, DWORD index, CHAR guid[39], MSIINSTALLCONTEXT *installed_ctx, char *sid, DWORD *sid_len)
Definition: registry.c:1124
enum tagMSIINSTALLCONTEXT MSIINSTALLCONTEXT
@ MSIINSTALLCONTEXT_MACHINE
Definition: msi.h:200
@ MSIINSTALLCONTEXT_ALL
Definition: msi.h:201
Definition: http.c:7252

Referenced by START_TEST().

◆ test_MsiEnumPatches()

static void test_MsiEnumPatches ( void  )
static

Definition at line 10284 of file msi.c.

10285{
10286 CHAR keypath[MAX_PATH], patch[MAX_PATH];
10287 CHAR patchcode[MAX_PATH], patch_squashed[MAX_PATH];
10288 CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10289 CHAR transforms[MAX_PATH];
10290 WCHAR patchW[MAX_PATH], prodcodeW[MAX_PATH], transformsW[MAX_PATH];
10291 HKEY prodkey, patches, udprod;
10292 HKEY userkey, hpatch, udpatch;
10293 DWORD size, data;
10294 LPSTR usersid;
10295 LONG res;
10296 UINT r;
10298
10299 create_test_guid(prodcode, prod_squashed);
10300 create_test_guid(patchcode, patch_squashed);
10301 usersid = get_user_sid();
10302
10303 if (is_wow64)
10305
10306 /* NULL szProduct */
10307 size = MAX_PATH;
10308 lstrcpyA(patch, "apple");
10309 lstrcpyA(transforms, "banana");
10310 r = MsiEnumPatchesA(NULL, 0, patch, transforms, &size);
10312 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10313 ok(!lstrcmpA(patch, "apple"),
10314 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10315 ok(!lstrcmpA(transforms, "banana"),
10316 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10317 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10318
10319 /* empty szProduct */
10320 size = MAX_PATH;
10321 lstrcpyA(patch, "apple");
10322 lstrcpyA(transforms, "banana");
10323 r = MsiEnumPatchesA("", 0, patch, transforms, &size);
10325 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10326 ok(!lstrcmpA(patch, "apple"),
10327 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10328 ok(!lstrcmpA(transforms, "banana"),
10329 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10330 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10331
10332 /* garbage szProduct */
10333 size = MAX_PATH;
10334 lstrcpyA(patch, "apple");
10335 lstrcpyA(transforms, "banana");
10336 r = MsiEnumPatchesA("garbage", 0, patch, transforms, &size);
10338 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10339 ok(!lstrcmpA(patch, "apple"),
10340 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10341 ok(!lstrcmpA(transforms, "banana"),
10342 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10343 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10344
10345 /* guid without brackets */
10346 size = MAX_PATH;
10347 lstrcpyA(patch, "apple");
10348 lstrcpyA(transforms, "banana");
10349 r = MsiEnumPatchesA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", 0, patch,
10350 transforms, &size);
10352 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10353 ok(!lstrcmpA(patch, "apple"),
10354 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10355 ok(!lstrcmpA(transforms, "banana"),
10356 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10357 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10358
10359 /* guid with brackets */
10360 size = MAX_PATH;
10361 lstrcpyA(patch, "apple");
10362 lstrcpyA(transforms, "banana");
10363 r = MsiEnumPatchesA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}", 0, patch,
10364 transforms, &size);
10366 "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10367 ok(!lstrcmpA(patch, "apple"),
10368 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10369 ok(!lstrcmpA(transforms, "banana"),
10370 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10371 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10372
10373 /* same length as guid, but random */
10374 size = MAX_PATH;
10375 lstrcpyA(patch, "apple");
10376 lstrcpyA(transforms, "banana");
10377 r = MsiEnumPatchesA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93", 0, patch,
10378 transforms, &size);
10380 "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10381 ok(!lstrcmpA(patch, "apple"),
10382 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10383 ok(!lstrcmpA(transforms, "banana"),
10384 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10385 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10386
10387 /* MSIINSTALLCONTEXT_USERMANAGED */
10388
10389 size = MAX_PATH;
10390 lstrcpyA(patch, "apple");
10391 lstrcpyA(transforms, "banana");
10392 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10394 "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10395 ok(!lstrcmpA(patch, "apple"),
10396 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10397 ok(!lstrcmpA(transforms, "banana"),
10398 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10399 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10400
10401 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Managed\\");
10402 lstrcatA(keypath, usersid);
10403 lstrcatA(keypath, "\\Installer\\Products\\");
10404 lstrcatA(keypath, prod_squashed);
10405
10406 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10407 if (res == ERROR_ACCESS_DENIED)
10408 {
10409 skip("Not enough rights to perform tests\n");
10410 LocalFree(usersid);
10411 return;
10412 }
10413 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10414
10415 /* managed product key exists */
10416 size = MAX_PATH;
10417 lstrcpyA(patch, "apple");
10418 lstrcpyA(transforms, "banana");
10419 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10420 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10421 ok(!lstrcmpA(patch, "apple"),
10422 "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10423 ok(!lstrcmpA(transforms, "banana"),
10424 "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10425 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10426
10427 res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10428 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10429
10430 /* patches key exists */
10431 size = MAX_PATH;
10432 lstrcpyA(patch, "apple");
10433 lstrcpyA(transforms, "banana");
10434 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10435 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10436 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10437 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10438 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10439
10440 res = RegSetValueExA(patches, "Patches", 0, REG_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 1);
10441 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10442
10443 /* Patches value exists, is not REG_MULTI_SZ */
10444 size = MAX_PATH;
10445 lstrcpyA(patch, "apple");
10446 lstrcpyA(transforms, "banana");
10447 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10448 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10449 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10450 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10451 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10452
10453 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)"a\0b\0c\0\0", 7);
10454 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10455
10456 /* Patches value exists, is not a squashed guid */
10457 size = MAX_PATH;
10458 lstrcpyA(patch, "apple");
10459 lstrcpyA(transforms, "banana");
10460 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10461 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10462 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10463 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10464 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10465
10466 patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10467 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 2);
10468 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10469
10470 /* Patches value exists */
10471 size = MAX_PATH;
10472 lstrcpyA(patch, "apple");
10473 lstrcpyA(transforms, "banana");
10474 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10475 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10476 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10477 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10478 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10479
10480 res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ, (const BYTE *)"whatever", 9);
10481 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10482
10483 /* patch squashed value exists */
10484 size = MAX_PATH;
10485 lstrcpyA(patch, "apple");
10486 lstrcpyA(transforms, "banana");
10487 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10488 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10489 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10490 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10491 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10492
10493 /* lpPatchBuf is NULL */
10494 size = MAX_PATH;
10495 lstrcpyA(transforms, "banana");
10496 r = MsiEnumPatchesA(prodcode, 0, NULL, transforms, &size);
10497 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10498 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10499 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10500
10501 /* lpTransformsBuf is NULL, pcchTransformsBuf is not */
10502 size = MAX_PATH;
10503 lstrcpyA(patch, "apple");
10504 r = MsiEnumPatchesA(prodcode, 0, patch, NULL, &size);
10505 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10506 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10507 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10508
10509 /* pcchTransformsBuf is NULL, lpTransformsBuf is not */
10510 lstrcpyA(patch, "apple");
10511 lstrcpyA(transforms, "banana");
10512 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, NULL);
10513 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10514 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10515 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10516
10517 /* pcchTransformsBuf is too small */
10518 size = 6;
10519 lstrcpyA(patch, "apple");
10520 lstrcpyA(transforms, "banana");
10521 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10522 ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10523 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10524 ok(!lstrcmpA(transforms, "whate"), "Expected \"whate\", got \"%s\"\n", transforms);
10525 ok(size == 8 || size == 16, "Expected 8 or 16, got %lu\n", size);
10526
10527 /* increase the index */
10528 size = MAX_PATH;
10529 lstrcpyA(patch, "apple");
10530 lstrcpyA(transforms, "banana");
10531 r = MsiEnumPatchesA(prodcode, 1, patch, transforms, &size);
10532 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10533 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10534 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10535 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10536
10537 /* increase again */
10538 size = MAX_PATH;
10539 lstrcpyA(patch, "apple");
10540 lstrcpyA(transforms, "banana");
10541 r = MsiEnumPatchesA(prodcode, 2, patch, transforms, &size);
10542 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10543 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10544 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10545 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10546
10547 RegDeleteValueA(patches, "Patches");
10548 RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
10549 RegCloseKey(patches);
10550 RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
10551 RegCloseKey(prodkey);
10552
10553 /* MSIINSTALLCONTEXT_USERUNMANAGED */
10554
10555 size = MAX_PATH;
10556 lstrcpyA(patch, "apple");
10557 lstrcpyA(transforms, "banana");
10558 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10559 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10560 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10561 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10562 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10563
10564 lstrcpyA(keypath, "Software\\Microsoft\\Installer\\Products\\");
10565 lstrcatA(keypath, prod_squashed);
10566
10567 res = RegCreateKeyA(HKEY_CURRENT_USER, keypath, &prodkey);
10568 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10569
10570 /* current user product key exists */
10571 size = MAX_PATH;
10572 lstrcpyA(patch, "apple");
10573 lstrcpyA(transforms, "banana");
10574 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10575 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10576 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10577 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10578 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10579
10580 res = RegCreateKeyA(prodkey, "Patches", &patches);
10581 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10582
10583 /* Patches key exists */
10584 size = MAX_PATH;
10585 lstrcpyA(patch, "apple");
10586 lstrcpyA(transforms, "banana");
10587 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10588 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10589 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10590 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10591 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10592
10593 res = RegSetValueExA(patches, "Patches", 0, REG_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 1);
10594 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10595
10596 /* Patches value exists, is not REG_MULTI_SZ */
10597 size = MAX_PATH;
10598 lstrcpyA(patch, "apple");
10599 lstrcpyA(transforms, "banana");
10600 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10601 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10602 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10603 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10604 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10605
10606 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)"a\0b\0c\0\0", 7);
10607 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10608
10609 /* Patches value exists, is not a squashed guid */
10610 size = MAX_PATH;
10611 lstrcpyA(patch, "apple");
10612 lstrcpyA(transforms, "banana");
10613 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10614 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10615 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10616 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10617 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10618
10619 patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10620 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 2);
10621 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10622
10623 /* Patches value exists */
10624 size = MAX_PATH;
10625 lstrcpyA(patch, "apple");
10626 lstrcpyA(transforms, "banana");
10627 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10628 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10629 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10630 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10631 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10632
10633 res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ, (const BYTE *)"whatever", 9);
10634 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10635
10636 /* patch code value exists */
10637 size = MAX_PATH;
10638 lstrcpyA(patch, "apple");
10639 lstrcpyA(transforms, "banana");
10640 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10641 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10642 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10643 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10644 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10645
10646 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
10647 lstrcatA(keypath, usersid);
10648 lstrcatA(keypath, "\\Patches\\");
10649 lstrcatA(keypath, patch_squashed);
10650
10651 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
10652 if (res == ERROR_ACCESS_DENIED)
10653 {
10654 skip("Not enough rights to perform tests\n");
10655 LocalFree(usersid);
10656 return;
10657 }
10658 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10659
10660 /* userdata patch key exists */
10661 size = MAX_PATH;
10662 lstrcpyA(patch, "apple");
10663 lstrcpyA(transforms, "banana");
10664 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10665 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10666 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10667 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10668 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10669
10670 RegDeleteKeyExA(userkey, "", access & KEY_WOW64_64KEY, 0);
10671 RegCloseKey(userkey);
10672 RegDeleteValueA(patches, patch_squashed);
10673 RegDeleteValueA(patches, "Patches");
10674 RegDeleteKeyA(patches, "");
10675 RegCloseKey(patches);
10676 RegDeleteKeyA(prodkey, "");
10677 RegCloseKey(prodkey);
10678
10679 /* MSIINSTALLCONTEXT_MACHINE */
10680
10681 size = MAX_PATH;
10682 lstrcpyA(patch, "apple");
10683 lstrcpyA(transforms, "banana");
10684 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10685 ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
10686 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10687 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10688 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10689
10690 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
10691 lstrcatA(keypath, prod_squashed);
10692
10693 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
10694 if (res == ERROR_ACCESS_DENIED)
10695 {
10696 skip("Not enough rights to perform tests\n");
10697 LocalFree(usersid);
10698 return;
10699 }
10700 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10701
10702 /* local product key exists */
10703 size = MAX_PATH;
10704 lstrcpyA(patch, "apple");
10705 lstrcpyA(transforms, "banana");
10706 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10707 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10708 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10709 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10710 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10711
10712 res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
10713 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10714
10715 /* Patches key exists */
10716 size = MAX_PATH;
10717 lstrcpyA(patch, "apple");
10718 lstrcpyA(transforms, "banana");
10719 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10720 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10721 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10722 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10723 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10724
10725 res = RegSetValueExA(patches, "Patches", 0, REG_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 1);
10726 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10727
10728 /* Patches value exists, is not REG_MULTI_SZ */
10729 size = MAX_PATH;
10730 lstrcpyA(patch, "apple");
10731 lstrcpyA(transforms, "banana");
10732 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10733 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10734 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10735 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10736 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10737
10738 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)"a\0b\0c\0\0", 7);
10739 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10740
10741 /* Patches value exists, is not a squashed guid */
10742 size = MAX_PATH;
10743 lstrcpyA(patch, "apple");
10744 lstrcpyA(transforms, "banana");
10745 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10746 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
10747 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10748 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10749 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10750
10751 patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
10752 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ, (const BYTE *)patch_squashed, lstrlenA(patch_squashed) + 2);
10753 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10754
10755 /* Patches value exists */
10756 size = MAX_PATH;
10757 lstrcpyA(patch, "apple");
10758 lstrcpyA(transforms, "banana");
10759 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10760 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10761 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10762 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10763 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10764
10765 res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ, (const BYTE *)"whatever", 9);
10766 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10767
10768 /* patch code value exists */
10769 size = MAX_PATH;
10770 lstrcpyA(patch, "apple");
10771 lstrcpyA(transforms, "banana");
10772 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10773 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10774 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10775 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10776 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10777
10778 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
10779 lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
10780 lstrcatA(keypath, prod_squashed);
10781
10782 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
10783 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10784
10785 /* local UserData product key exists */
10786 size = MAX_PATH;
10787 lstrcpyA(patch, "apple");
10788 lstrcpyA(transforms, "banana");
10789 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10790 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10791 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10792 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10793 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10794
10795 res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
10796 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10797
10798 /* local UserData Patches key exists */
10799 size = MAX_PATH;
10800 lstrcpyA(patch, "apple");
10801 lstrcpyA(transforms, "banana");
10802 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10803 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10804 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10805 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10806 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10807
10808 res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
10809 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10810
10811 /* local UserData Product patch key exists */
10812 size = MAX_PATH;
10813 lstrcpyA(patch, "apple");
10814 lstrcpyA(transforms, "banana");
10815 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10816 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10817 ok(!lstrcmpA(patch, "apple"), "Expected lpPatchBuf to be unchanged, got \"%s\"\n", patch);
10818 ok(!lstrcmpA(transforms, "banana"), "Expected lpTransformsBuf to be unchanged, got \"%s\"\n", transforms);
10819 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10820
10822 res = RegSetValueExA(hpatch, "State", 0, REG_DWORD, (const BYTE *)&data, sizeof(DWORD));
10823 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10824
10825 /* State value exists */
10826 size = MAX_PATH;
10827 lstrcpyA(patch, "apple");
10828 lstrcpyA(transforms, "banana");
10829 r = MsiEnumPatchesA(prodcode, 0, patch, transforms, &size);
10830 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10831 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10832 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10833 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10834
10835 /* now duplicate some of the tests for the W version */
10836
10837 /* pcchTransformsBuf is too small */
10838 size = 6;
10839 MultiByteToWideChar( CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH );
10840 MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
10841 MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
10842 r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
10843 ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
10844 WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
10845 WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
10846 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10847 ok(!lstrcmpA(transforms, "whate"), "Expected \"whate\", got \"%s\"\n", transforms);
10848 ok(size == 8, "Expected 8, got %lu\n", size);
10849
10850 /* patch code value exists */
10851 size = MAX_PATH;
10852 MultiByteToWideChar( CP_ACP, 0, "apple", -1, patchW, MAX_PATH );
10853 MultiByteToWideChar( CP_ACP, 0, "banana", -1, transformsW, MAX_PATH );
10854 r = MsiEnumPatchesW(prodcodeW, 0, patchW, transformsW, &size);
10855 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10856 WideCharToMultiByte( CP_ACP, 0, patchW, -1, patch, MAX_PATH, NULL, NULL );
10857 WideCharToMultiByte( CP_ACP, 0, transformsW, -1, transforms, MAX_PATH, NULL, NULL );
10858 ok(!lstrcmpA(patch, patchcode), "Expected \"%s\", got \"%s\"\n", patchcode, patch);
10859 ok(!lstrcmpA(transforms, "whatever"), "Expected \"whatever\", got \"%s\"\n", transforms);
10860 ok(size == 8 || size == MAX_PATH, "Expected 8 or MAX_PATH, got %lu\n", size);
10861
10862 RegDeleteValueA(patches, patch_squashed);
10863 RegDeleteValueA(patches, "Patches");
10864 RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
10865 RegCloseKey(patches);
10866 RegDeleteValueA(hpatch, "State");
10867 RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
10868 RegCloseKey(hpatch);
10869 RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
10870 RegCloseKey(udpatch);
10871 RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
10872 RegCloseKey(udprod);
10873 RegDeleteKeyExA(prodkey, "", access & KEY_WOW64_64KEY, 0);
10874 RegCloseKey(prodkey);
10875 LocalFree(usersid);
10876}
#define ERROR_MORE_DATA
Definition: dderror.h:13
LONG WINAPI RegCreateKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1179
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
UINT WINAPI MsiEnumPatchesW(const WCHAR *szProduct, DWORD iPatchIndex, WCHAR *lpPatchBuf, WCHAR *lpTransformsBuf, DWORD *pcchTransformsBuf)
Definition: registry.c:2054
UINT WINAPI MsiEnumPatchesA(const char *szProduct, DWORD iPatchIndex, char *lpPatchBuf, char *lpTransformsBuf, DWORD *pcchTransformsBuf)
Definition: registry.c:2000
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
@ MSIPATCHSTATE_APPLIED
Definition: msi.h:54
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define REG_DWORD
Definition: sdbapi.c:596
#define ERROR_BAD_CONFIGURATION
Definition: winerror.h:968
#define HKEY_CURRENT_USER
Definition: winreg.h:11

Referenced by START_TEST().

◆ test_MsiEnumPatchesEx()

static void test_MsiEnumPatchesEx ( void  )
static

Definition at line 10098 of file msi.c.

10099{
10100 CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
10101 CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
10102 CHAR patchcode[MAX_PATH];
10104 LPSTR usersid;
10105 DWORD size;
10106 UINT r;
10107
10108 create_test_guid(prodcode, prod_squashed);
10109 usersid = get_user_sid();
10110
10111 /* empty szProductCode */
10112 lstrcpyA(patchcode, "apple");
10113 lstrcpyA(targetprod, "banana");
10114 context = 0xdeadbeef;
10115 lstrcpyA(targetsid, "kiwi");
10116 size = MAX_PATH;
10118 0, patchcode, targetprod, &context, targetsid, &size);
10119 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10120 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10121 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10122 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10123 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10124 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10125
10126 /* garbage szProductCode */
10127 lstrcpyA(patchcode, "apple");
10128 lstrcpyA(targetprod, "banana");
10129 context = 0xdeadbeef;
10130 lstrcpyA(targetsid, "kiwi");
10131 size = MAX_PATH;
10133 0, patchcode, targetprod, &context, targetsid, &size);
10134 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10135 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10136 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10137 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10138 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10139 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10140
10141 /* guid without brackets */
10142 lstrcpyA(patchcode, "apple");
10143 lstrcpyA(targetprod, "banana");
10144 context = 0xdeadbeef;
10145 lstrcpyA(targetsid, "kiwi");
10146 size = MAX_PATH;
10147 r = MsiEnumPatchesExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10148 MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context, targetsid, &size);
10149 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10150 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10151 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10152 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10153 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10154 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10155
10156 /* guid with brackets */
10157 lstrcpyA(patchcode, "apple");
10158 lstrcpyA(targetprod, "banana");
10159 context = 0xdeadbeef;
10160 lstrcpyA(targetsid, "kiwi");
10161 size = MAX_PATH;
10162 r = MsiEnumPatchesExA("{6700E8CF-95AB-4D9C-BC2C-15840DDA7A5D}", usersid, MSIINSTALLCONTEXT_USERUNMANAGED,
10163 MSIPATCHSTATE_ALL, 0, patchcode, targetprod, &context, targetsid, &size);
10164 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10165 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10166 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10167 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10168 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10169 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10170
10171 /* szUserSid is S-1-5-18 */
10172 lstrcpyA(patchcode, "apple");
10173 lstrcpyA(targetprod, "banana");
10174 context = 0xdeadbeef;
10175 lstrcpyA(targetsid, "kiwi");
10176 size = MAX_PATH;
10178 0, patchcode, targetprod, &context, targetsid, &size);
10179 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10180 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10181 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10182 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10183 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10184 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10185
10186 /* dwContext is MSIINSTALLCONTEXT_MACHINE, but szUserSid is non-NULL */
10187 lstrcpyA(patchcode, "apple");
10188 lstrcpyA(targetprod, "banana");
10189 context = 0xdeadbeef;
10190 lstrcpyA(targetsid, "kiwi");
10191 size = MAX_PATH;
10193 0, patchcode, targetprod, &context, targetsid, &size);
10194 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10195 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10196 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10197 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10198 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10199 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10200
10201 /* dwContext is out of bounds */
10202 lstrcpyA(patchcode, "apple");
10203 lstrcpyA(targetprod, "banana");
10204 context = 0xdeadbeef;
10205 lstrcpyA(targetsid, "kiwi");
10206 size = MAX_PATH;
10207 r = MsiEnumPatchesExA(prodcode, usersid, 0, MSIPATCHSTATE_ALL, 0, patchcode, targetprod,
10208 &context, targetsid, &size);
10209 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10210 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10211 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10212 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10213 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10214 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10215
10216 /* dwContext is out of bounds */
10217 lstrcpyA(patchcode, "apple");
10218 lstrcpyA(targetprod, "banana");
10219 context = 0xdeadbeef;
10220 lstrcpyA(targetsid, "kiwi");
10221 size = MAX_PATH;
10222 r = MsiEnumPatchesExA(prodcode, usersid, MSIINSTALLCONTEXT_ALL + 1, MSIPATCHSTATE_ALL, 0, patchcode,
10223 targetprod, &context, targetsid, &size);
10224 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10225 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10226 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10227 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10228 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10229 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10230
10231 /* dwFilter is out of bounds */
10232 lstrcpyA(patchcode, "apple");
10233 lstrcpyA(targetprod, "banana");
10234 context = 0xdeadbeef;
10235 lstrcpyA(targetsid, "kiwi");
10236 size = MAX_PATH;
10238 0, patchcode, targetprod, &context, targetsid, &size);
10239 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10240 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10241 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10242 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10243 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10244 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10245
10246 /* dwFilter is out of bounds */
10247 lstrcpyA(patchcode, "apple");
10248 lstrcpyA(targetprod, "banana");
10249 context = 0xdeadbeef;
10250 lstrcpyA(targetsid, "kiwi");
10251 size = MAX_PATH;
10253 0, patchcode, targetprod, &context, targetsid, &size);
10254 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10255 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10256 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10257 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10258 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10259 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10260
10261 /* pcchTargetUserSid is NULL while szTargetUserSid is non-NULL */
10262 lstrcpyA(patchcode, "apple");
10263 lstrcpyA(targetprod, "banana");
10264 context = 0xdeadbeef;
10265 lstrcpyA(targetsid, "kiwi");
10267 0, patchcode, targetprod, &context, targetsid, NULL);
10268 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
10269 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10270 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10271 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10272 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10273
10274 test_MsiEnumPatchesEx_usermanaged(usersid, usersid);
10276 test_MsiEnumPatchesEx_usermanaged("S-1-2-34", "S-1-2-34");
10277 test_MsiEnumPatchesEx_userunmanaged(usersid, usersid);
10279 /* FIXME: Successfully test userunmanaged with a different user */
10281 LocalFree(usersid);
10282}
UINT WINAPI MsiEnumPatchesExA(const char *szProductCode, const char *szUserSid, DWORD dwContext, DWORD dwFilter, DWORD dwIndex, char *szPatchCode, char *szTargetProductCode, MSIINSTALLCONTEXT *pdwTargetProductContext, char *szTargetUserSid, DWORD *pcchTargetUserSid)
Definition: registry.c:1618
static void test_MsiEnumPatchesEx_usermanaged(LPCSTR usersid, LPCSTR expectedsid)
Definition: msi.c:8886
static void test_MsiEnumPatchesEx_machine(void)
Definition: msi.c:9732
static void test_MsiEnumPatchesEx_userunmanaged(LPCSTR usersid, LPCSTR expectedsid)
Definition: msi.c:9360
@ MSIPATCHSTATE_ALL
Definition: msi.h:58
@ MSIPATCHSTATE_INVALID
Definition: msi.h:53

Referenced by START_TEST().

◆ test_MsiEnumPatchesEx_machine()

static void test_MsiEnumPatchesEx_machine ( void  )
static

Definition at line 9732 of file msi.c.

9733{
9734 CHAR keypath[MAX_PATH], patch[MAX_PATH];
9735 CHAR patch_squashed[MAX_PATH], patchcode[MAX_PATH];
9736 CHAR targetsid[MAX_PATH], targetprod[MAX_PATH];
9737 CHAR prodcode[MAX_PATH], prod_squashed[MAX_PATH];
9738 HKEY prodkey, patches, udprod, udpatch;
9739 HKEY hpatch;
9741 DWORD size, data;
9742 LONG res;
9743 UINT r;
9745
9746 create_test_guid(prodcode, prod_squashed);
9747 create_test_guid(patch, patch_squashed);
9748
9749 if (is_wow64)
9751
9752 /* MSIPATCHSTATE_APPLIED */
9753
9754 lstrcpyA(patchcode, "apple");
9755 lstrcpyA(targetprod, "banana");
9756 context = 0xdeadbeef;
9757 lstrcpyA(targetsid, "kiwi");
9758 size = MAX_PATH;
9760 0, patchcode, targetprod, &context, targetsid, &size);
9761 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9762 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9763 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9764 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9765 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9766 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9767
9768 lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
9769 lstrcatA(keypath, prod_squashed);
9770
9771 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
9772 if (res == ERROR_ACCESS_DENIED)
9773 {
9774 skip("Not enough rights to perform tests\n");
9775 return;
9776 }
9777 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9778
9779 /* local product key exists */
9780 lstrcpyA(patchcode, "apple");
9781 lstrcpyA(targetprod, "banana");
9782 context = 0xdeadbeef;
9783 lstrcpyA(targetsid, "kiwi");
9784 size = MAX_PATH;
9786 0, patchcode, targetprod, &context, targetsid, &size);
9787 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9788 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9789 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9790 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9791 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9792 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9793
9794 res = RegCreateKeyExA(prodkey, "Patches", 0, NULL, 0, access, NULL, &patches, NULL);
9795 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9796
9797 /* Patches key exists */
9798 lstrcpyA(patchcode, "apple");
9799 lstrcpyA(targetprod, "banana");
9800 context = 0xdeadbeef;
9801 lstrcpyA(targetsid, "kiwi");
9802 size = MAX_PATH;
9804 0, patchcode, targetprod, &context, targetsid, &size);
9805 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9806 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9807 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9808 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9809 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9810 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9811
9812 res = RegSetValueExA(patches, "Patches", 0, REG_SZ,
9813 (const BYTE *)patch_squashed,
9814 lstrlenA(patch_squashed) + 1);
9815 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9816
9817 /* Patches value exists, is not REG_MULTI_SZ */
9818 lstrcpyA(patchcode, "apple");
9819 lstrcpyA(targetprod, "banana");
9820 context = 0xdeadbeef;
9821 lstrcpyA(targetsid, "kiwi");
9822 size = MAX_PATH;
9824 0, patchcode, targetprod, &context, targetsid, &size);
9825 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9826 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9827 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9828 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9829 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9830 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9831
9832 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9833 (const BYTE *)"a\0b\0c\0\0", 7);
9834 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9835
9836 /* Patches value exists, is not a squashed guid */
9837 lstrcpyA(patchcode, "apple");
9838 lstrcpyA(targetprod, "banana");
9839 context = 0xdeadbeef;
9840 lstrcpyA(targetsid, "kiwi");
9841 size = MAX_PATH;
9843 0, patchcode, targetprod, &context, targetsid, &size);
9844 ok(r == ERROR_BAD_CONFIGURATION, "Expected ERROR_BAD_CONFIGURATION, got %d\n", r);
9845 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9846 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9847 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9848 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9849 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9850
9851 patch_squashed[lstrlenA(patch_squashed) + 1] = '\0';
9852 res = RegSetValueExA(patches, "Patches", 0, REG_MULTI_SZ,
9853 (const BYTE *)patch_squashed,
9854 lstrlenA(patch_squashed) + 2);
9855 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9856
9857 /* Patches value exists */
9858 lstrcpyA(patchcode, "apple");
9859 lstrcpyA(targetprod, "banana");
9860 context = 0xdeadbeef;
9861 lstrcpyA(targetsid, "kiwi");
9862 size = MAX_PATH;
9864 0, patchcode, targetprod, &context, targetsid, &size);
9865 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9866 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9867 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9868 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9869 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9870 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9871
9872 res = RegSetValueExA(patches, patch_squashed, 0, REG_SZ,
9873 (const BYTE *)"whatever", 9);
9874 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9875
9876 /* patch code value exists */
9877 lstrcpyA(patchcode, "apple");
9878 lstrcpyA(targetprod, "banana");
9879 context = 0xdeadbeef;
9880 lstrcpyA(targetsid, "kiwi");
9881 size = MAX_PATH;
9883 0, patchcode, targetprod, &context, targetsid, &size);
9884 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9885 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9886 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9887 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9888 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9889 ok(size == 0, "Expected 0, got %lu\n", size);
9890
9891 lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
9892 lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
9893 lstrcatA(keypath, prod_squashed);
9894
9895 res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &udprod, NULL);
9896 if (res == ERROR_ACCESS_DENIED)
9897 {
9898 skip("Not enough rights to perform tests\n");
9899 goto done;
9900 }
9901 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9902
9903 /* local UserData product key exists */
9904 lstrcpyA(patchcode, "apple");
9905 lstrcpyA(targetprod, "banana");
9906 context = 0xdeadbeef;
9907 lstrcpyA(targetsid, "kiwi");
9908 size = MAX_PATH;
9910 0, patchcode, targetprod, &context, targetsid, &size);
9911 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9912 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9913 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9914 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9915 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9916 ok(size == 0, "Expected 0, got %lu\n", size);
9917
9918 res = RegCreateKeyExA(udprod, "Patches", 0, NULL, 0, access, NULL, &udpatch, NULL);
9919 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9920
9921 /* local UserData Patches key exists */
9922 lstrcpyA(patchcode, "apple");
9923 lstrcpyA(targetprod, "banana");
9924 context = 0xdeadbeef;
9925 lstrcpyA(targetsid, "kiwi");
9926 size = MAX_PATH;
9928 0, patchcode, targetprod, &context, targetsid, &size);
9929 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9930 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9931 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9932 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9933 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9934 ok(size == 0, "Expected 0, got %lu\n", size);
9935
9936 res = RegCreateKeyExA(udpatch, patch_squashed, 0, NULL, 0, access, NULL, &hpatch, NULL);
9937 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9938
9939 /* local UserData Product patch key exists */
9940 lstrcpyA(patchcode, "apple");
9941 lstrcpyA(targetprod, "banana");
9942 context = 0xdeadbeef;
9943 lstrcpyA(targetsid, "kiwi");
9944 size = MAX_PATH;
9946 0, patchcode, targetprod, &context, targetsid, &size);
9947 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9948 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9949 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9950 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9951 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9952 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9953
9955 res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9956 (const BYTE *)&data, sizeof(DWORD));
9957 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9958
9959 /* State value exists */
9960 lstrcpyA(patchcode, "apple");
9961 lstrcpyA(targetprod, "banana");
9962 context = 0xdeadbeef;
9963 lstrcpyA(targetsid, "kiwi");
9964 size = MAX_PATH;
9966 0, patchcode, targetprod, &context, targetsid, &size);
9967 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9968 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
9969 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
9970 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
9971 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
9972 ok(size == 0, "Expected 0, got %lu\n", size);
9973
9974 /* MSIPATCHSTATE_SUPERSEDED */
9975
9976 lstrcpyA(patchcode, "apple");
9977 lstrcpyA(targetprod, "banana");
9978 context = 0xdeadbeef;
9979 lstrcpyA(targetsid, "kiwi");
9980 size = MAX_PATH;
9982 0, patchcode, targetprod, &context, targetsid, &size);
9983 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
9984 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
9985 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
9986 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
9987 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
9988 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
9989
9991 res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
9992 (const BYTE *)&data, sizeof(DWORD));
9993 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
9994
9995 /* State value is MSIPATCHSTATE_SUPERSEDED */
9996 lstrcpyA(patchcode, "apple");
9997 lstrcpyA(targetprod, "banana");
9998 context = 0xdeadbeef;
9999 lstrcpyA(targetsid, "kiwi");
10000 size = MAX_PATH;
10002 0, patchcode, targetprod, &context, targetsid, &size);
10003 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10004 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10005 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10006 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10007 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10008 ok(size == 0, "Expected 0, got %lu\n", size);
10009
10010 /* MSIPATCHSTATE_OBSOLETED */
10011
10012 lstrcpyA(patchcode, "apple");
10013 lstrcpyA(targetprod, "banana");
10014 context = 0xdeadbeef;
10015 lstrcpyA(targetsid, "kiwi");
10016 size = MAX_PATH;
10018 0, patchcode, targetprod, &context, targetsid, &size);
10019 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10020 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10021 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10022 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10023 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10024 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10025
10027 res = RegSetValueExA(hpatch, "State", 0, REG_DWORD,
10028 (const BYTE *)&data, sizeof(DWORD));
10029 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
10030
10031 /* State value is obsoleted */
10032 lstrcpyA(patchcode, "apple");
10033 lstrcpyA(targetprod, "banana");
10034 context = 0xdeadbeef;
10035 lstrcpyA(targetsid, "kiwi");
10036 size = MAX_PATH;
10038 0, patchcode, targetprod, &context, targetsid, &size);
10039 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10040 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10041 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10042 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10043 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10044 ok(size == 0, "Expected 0, got %lu\n", size);
10045
10046 /* MSIPATCHSTATE_REGISTERED */
10047 /* FIXME */
10048
10049 /* MSIPATCHSTATE_ALL */
10050
10051 /* 1st */
10052 lstrcpyA(patchcode, "apple");
10053 lstrcpyA(targetprod, "banana");
10054 context = 0xdeadbeef;
10055 lstrcpyA(targetsid, "kiwi");
10056 size = MAX_PATH;
10058 0, patchcode, targetprod, &context, targetsid, &size);
10059 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
10060 ok(!lstrcmpA(patchcode, patch), "Expected \"%s\", got \"%s\"\n", patch, patchcode);
10061 ok(!lstrcmpA(targetprod, prodcode), "Expected \"%s\", got \"%s\"\n", prodcode, targetprod);
10062 ok(context == MSIINSTALLCONTEXT_MACHINE, "Expected MSIINSTALLCONTEXT_MACHINE, got %d\n", context);
10063 ok(!lstrcmpA(targetsid, ""), "Expected \"\", got \"%s\"\n", targetsid);
10064 ok(size == 0, "Expected 0, got %lu\n", size);
10065
10066 /* same patch in multiple places, only one is enumerated */
10067 lstrcpyA(patchcode, "apple");
10068 lstrcpyA(targetprod, "banana");
10069 context = 0xdeadbeef;
10070 lstrcpyA(targetsid, "kiwi");
10071 size = MAX_PATH;
10073 1, patchcode, targetprod, &context, targetsid, &size);
10074 ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
10075 ok(!lstrcmpA(patchcode, "apple"), "Expected patchcode to be unchanged, got %s\n", patchcode);
10076 ok(!lstrcmpA(targetprod, "banana"), "Expected targetprod to be unchanged, got %s\n", targetprod);
10077 ok(context == 0xdeadbeef, "Expected context to be unchanged, got %d\n", context);
10078 ok(!lstrcmpA(targetsid, "kiwi"), "Expected targetsid to be unchanged, got %s\n", targetsid);
10079 ok(size == MAX_PATH, "Expected size to be unchanged, got %lu\n", size);
10080
10081 RegDeleteKeyExA(hpatch, "", access & KEY_WOW64_64KEY, 0);
10082 RegDeleteValueA(hpatch, "State");
10083 RegCloseKey(hpatch);
10084 RegDeleteKeyExA(udpatch, "", access & KEY_WOW64_64KEY, 0);
10085 RegCloseKey(udpatch);
10086 RegDeleteKeyExA(udprod, "", access & KEY_WOW64_64KEY, 0);
10087 RegCloseKey(udprod);
10088
10089done:
10090 RegDeleteValueA(patches, patch_squashed);
10091 RegDeleteValueA(patches, "Patches");
10092 RegDeleteKeyExA(patches, "", access & KEY_WOW64_64KEY, 0);
10093 RegCloseKey(patches);
10094 RegDeleteKeyExA(prodkey, "", access &