1c2c66affSColin Finck /*
2c2c66affSColin Finck  * tests for Microsoft Installer functionality
3c2c66affSColin Finck  *
4c2c66affSColin Finck  * Copyright 2005 Mike McCormack for CodeWeavers
5c2c66affSColin Finck  * Copyright 2005 Aric Stewart for CodeWeavers
6c2c66affSColin Finck  *
7c2c66affSColin Finck  * This library is free software; you can redistribute it and/or
8c2c66affSColin Finck  * modify it under the terms of the GNU Lesser General Public
9c2c66affSColin Finck  * License as published by the Free Software Foundation; either
10c2c66affSColin Finck  * version 2.1 of the License, or (at your option) any later version.
11c2c66affSColin Finck  *
12c2c66affSColin Finck  * This library is distributed in the hope that it will be useful,
13c2c66affSColin Finck  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14c2c66affSColin Finck  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15c2c66affSColin Finck  * Lesser General Public License for more details.
16c2c66affSColin Finck  *
17c2c66affSColin Finck  * You should have received a copy of the GNU Lesser General Public
18c2c66affSColin Finck  * License along with this library; if not, write to the Free Software
19c2c66affSColin Finck  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20c2c66affSColin Finck  */
21c2c66affSColin Finck 
2231139640SAmine Khaldi #define COBJMACROS
23c2c66affSColin Finck 
242f8e6f71SAmine Khaldi #include <assert.h>
2531139640SAmine Khaldi #include <stdio.h>
2631139640SAmine Khaldi #include <windows.h>
2731139640SAmine Khaldi #include <msidefs.h>
2831139640SAmine Khaldi #include <msi.h>
2931139640SAmine Khaldi #include <msiquery.h>
3031139640SAmine Khaldi #include <srrestoreptapi.h>
31c2c66affSColin Finck #include <shlobj.h>
32a4930636Swinesync #include <sddl.h>
33c2c66affSColin Finck 
3431139640SAmine Khaldi #include "wine/test.h"
3531139640SAmine Khaldi 
36c2c66affSColin Finck static BOOL is_wow64;
37c2c66affSColin Finck static const char msifile[] = "winetest-package.msi";
38c2c66affSColin Finck static const WCHAR msifileW[] =
39c2c66affSColin Finck     {'w','i','n','e','t','e','s','t','-','p','a','c','k','a','g','e','.','m','s','i',0};
40c2c66affSColin Finck static char CURR_DIR[MAX_PATH];
41c2c66affSColin Finck 
42c2c66affSColin Finck static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
43c2c66affSColin Finck 
44c2c66affSColin Finck static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
45c2c66affSColin Finck static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
46c2c66affSColin Finck static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
47c2c66affSColin Finck static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
48c2c66affSColin Finck static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
49c2c66affSColin Finck 
50c2c66affSColin Finck static void init_functionpointers(void)
51c2c66affSColin Finck {
52c2c66affSColin Finck     HMODULE hmsi = GetModuleHandleA("msi.dll");
53c2c66affSColin Finck     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
54c2c66affSColin Finck     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
55a4930636Swinesync     HMODULE hsrclient = LoadLibraryA("srclient.dll");
56c2c66affSColin Finck 
57c2c66affSColin Finck #define GET_PROC(mod, func) \
58c2c66affSColin Finck     p ## func = (void*)GetProcAddress(mod, #func);
59c2c66affSColin Finck 
60c2c66affSColin Finck     GET_PROC(hmsi, MsiGetComponentPathExA);
61c2c66affSColin Finck 
62c2c66affSColin Finck     GET_PROC(hadvapi32, RegDeleteKeyExA)
63c2c66affSColin Finck     GET_PROC(hadvapi32, RegDeleteKeyExW)
64c2c66affSColin Finck     GET_PROC(hkernel32, IsWow64Process)
65c2c66affSColin Finck 
66c2c66affSColin Finck     GET_PROC(hsrclient, SRRemoveRestorePoint);
67c2c66affSColin Finck     GET_PROC(hsrclient, SRSetRestorePointA);
68a4930636Swinesync 
69c2c66affSColin Finck #undef GET_PROC
70c2c66affSColin Finck }
71c2c66affSColin Finck 
72c2c66affSColin Finck static BOOL is_process_limited(void)
73c2c66affSColin Finck {
74c2c66affSColin Finck     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
75c2c66affSColin Finck     PSID Group = NULL;
76c2c66affSColin Finck     BOOL IsInGroup;
77c2c66affSColin Finck     HANDLE token;
78c2c66affSColin Finck 
79c2c66affSColin Finck     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
80c2c66affSColin Finck                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
81a4930636Swinesync         !CheckTokenMembership(NULL, Group, &IsInGroup))
82c2c66affSColin Finck     {
83c2c66affSColin Finck         trace("Could not check if the current user is an administrator\n");
84c2c66affSColin Finck         FreeSid(Group);
85c2c66affSColin Finck         return FALSE;
86c2c66affSColin Finck     }
87c2c66affSColin Finck     FreeSid(Group);
88c2c66affSColin Finck 
89c2c66affSColin Finck     if (!IsInGroup)
90c2c66affSColin Finck     {
91c2c66affSColin Finck         if (!AllocateAndInitializeSid(&NtAuthority, 2,
92c2c66affSColin Finck                                       SECURITY_BUILTIN_DOMAIN_RID,
93c2c66affSColin Finck                                       DOMAIN_ALIAS_RID_POWER_USERS,
94c2c66affSColin Finck                                       0, 0, 0, 0, 0, 0, &Group) ||
95a4930636Swinesync             !CheckTokenMembership(NULL, Group, &IsInGroup))
96c2c66affSColin Finck         {
97c2c66affSColin Finck             trace("Could not check if the current user is a power user\n");
98c2c66affSColin Finck             return FALSE;
99c2c66affSColin Finck         }
100c2c66affSColin Finck         if (!IsInGroup)
101c2c66affSColin Finck         {
102c2c66affSColin Finck             /* Only administrators and power users can be powerful */
103c2c66affSColin Finck             return TRUE;
104c2c66affSColin Finck         }
105c2c66affSColin Finck     }
106c2c66affSColin Finck 
107a4930636Swinesync     if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
108c2c66affSColin Finck     {
109c2c66affSColin Finck         BOOL ret;
110c2c66affSColin Finck         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
111c2c66affSColin Finck         DWORD size;
112c2c66affSColin Finck 
113c2c66affSColin Finck         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
114c2c66affSColin Finck         CloseHandle(token);
115c2c66affSColin Finck         return (ret && type == TokenElevationTypeLimited);
116c2c66affSColin Finck     }
117c2c66affSColin Finck     return FALSE;
118c2c66affSColin Finck }
119c2c66affSColin Finck 
120c2c66affSColin Finck static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
121c2c66affSColin Finck {
122c2c66affSColin Finck     if (pRegDeleteKeyExA)
123c2c66affSColin Finck         return pRegDeleteKeyExA( key, subkey, access, 0 );
124c2c66affSColin Finck     return RegDeleteKeyA( key, subkey );
125c2c66affSColin Finck }
126c2c66affSColin Finck 
127c2c66affSColin Finck static char *get_user_sid(void)
128c2c66affSColin Finck {
129c2c66affSColin Finck     HANDLE token;
130c2c66affSColin Finck     DWORD size = 0;
131c2c66affSColin Finck     TOKEN_USER *user;
132c2c66affSColin Finck     char *usersid = NULL;
133c2c66affSColin Finck 
134c2c66affSColin Finck     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
135c2c66affSColin Finck     GetTokenInformation(token, TokenUser, NULL, size, &size);
136c2c66affSColin Finck 
137c2c66affSColin Finck     user = HeapAlloc(GetProcessHeap(), 0, size);
138c2c66affSColin Finck     GetTokenInformation(token, TokenUser, user, size, &size);
139a4930636Swinesync     ConvertSidToStringSidA(user->User.Sid, &usersid);
140c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, user);
141c2c66affSColin Finck 
142c2c66affSColin Finck     CloseHandle(token);
143c2c66affSColin Finck     return usersid;
144c2c66affSColin Finck }
145c2c66affSColin Finck 
146c2c66affSColin Finck /* RegDeleteTreeW from dlls/advapi32/registry.c */
147c2c66affSColin Finck static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
148c2c66affSColin Finck {
149c2c66affSColin Finck     LONG ret;
150c2c66affSColin Finck     DWORD dwMaxSubkeyLen, dwMaxValueLen;
151c2c66affSColin Finck     DWORD dwMaxLen, dwSize;
152c2c66affSColin Finck     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
153c2c66affSColin Finck     HKEY hSubKey = hKey;
154c2c66affSColin Finck 
155c2c66affSColin Finck     if(lpszSubKey)
156c2c66affSColin Finck     {
157c2c66affSColin Finck         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
158c2c66affSColin Finck         if (ret) return ret;
159c2c66affSColin Finck     }
160c2c66affSColin Finck 
161c2c66affSColin Finck     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
162c2c66affSColin Finck             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
163c2c66affSColin Finck     if (ret) goto cleanup;
164c2c66affSColin Finck 
165c2c66affSColin Finck     dwMaxSubkeyLen++;
166c2c66affSColin Finck     dwMaxValueLen++;
167c2c66affSColin Finck     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
16886676451Swinesync     if (dwMaxLen > ARRAY_SIZE(szNameBuf))
169c2c66affSColin Finck     {
170c2c66affSColin Finck         /* Name too big: alloc a buffer for it */
171c2c66affSColin Finck         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
172c2c66affSColin Finck         {
173c2c66affSColin Finck             ret = ERROR_NOT_ENOUGH_MEMORY;
174c2c66affSColin Finck             goto cleanup;
175c2c66affSColin Finck         }
176c2c66affSColin Finck     }
177c2c66affSColin Finck 
178c2c66affSColin Finck     /* Recursively delete all the subkeys */
179c2c66affSColin Finck     while (TRUE)
180c2c66affSColin Finck     {
181c2c66affSColin Finck         dwSize = dwMaxLen;
182c2c66affSColin Finck         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
183c2c66affSColin Finck                           NULL, NULL, NULL)) break;
184c2c66affSColin Finck 
185c2c66affSColin Finck         ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
186c2c66affSColin Finck         if (ret) goto cleanup;
187c2c66affSColin Finck     }
188c2c66affSColin Finck 
189c2c66affSColin Finck     if (lpszSubKey)
190c2c66affSColin Finck     {
191c2c66affSColin Finck         if (pRegDeleteKeyExW)
192c2c66affSColin Finck             ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
193c2c66affSColin Finck         else
194c2c66affSColin Finck             ret = RegDeleteKeyW(hKey, lpszSubKey);
195c2c66affSColin Finck     }
196c2c66affSColin Finck     else
197c2c66affSColin Finck         while (TRUE)
198c2c66affSColin Finck         {
199c2c66affSColin Finck             dwSize = dwMaxLen;
200c2c66affSColin Finck             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
201c2c66affSColin Finck                   NULL, NULL, NULL, NULL)) break;
202c2c66affSColin Finck 
203c2c66affSColin Finck             ret = RegDeleteValueW(hKey, lpszName);
204c2c66affSColin Finck             if (ret) goto cleanup;
205c2c66affSColin Finck         }
206c2c66affSColin Finck 
207c2c66affSColin Finck cleanup:
208c2c66affSColin Finck     if (lpszName != szNameBuf)
209c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, lpszName);
210c2c66affSColin Finck     if(lpszSubKey)
211c2c66affSColin Finck         RegCloseKey(hSubKey);
212c2c66affSColin Finck     return ret;
213c2c66affSColin Finck }
214c2c66affSColin Finck 
215c2c66affSColin Finck static BOOL squash_guid(LPCWSTR in, LPWSTR out)
216c2c66affSColin Finck {
217c2c66affSColin Finck     DWORD i,n=1;
218c2c66affSColin Finck     GUID guid;
219c2c66affSColin Finck 
220c2c66affSColin Finck     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
221c2c66affSColin Finck         return FALSE;
222c2c66affSColin Finck 
223c2c66affSColin Finck     for(i=0; i<8; i++)
224c2c66affSColin Finck         out[7-i] = in[n++];
225c2c66affSColin Finck     n++;
226c2c66affSColin Finck     for(i=0; i<4; i++)
227c2c66affSColin Finck         out[11-i] = in[n++];
228c2c66affSColin Finck     n++;
229c2c66affSColin Finck     for(i=0; i<4; i++)
230c2c66affSColin Finck         out[15-i] = in[n++];
231c2c66affSColin Finck     n++;
232c2c66affSColin Finck     for(i=0; i<2; i++)
233c2c66affSColin Finck     {
234c2c66affSColin Finck         out[17+i*2] = in[n++];
235c2c66affSColin Finck         out[16+i*2] = in[n++];
236c2c66affSColin Finck     }
237c2c66affSColin Finck     n++;
238c2c66affSColin Finck     for( ; i<8; i++)
239c2c66affSColin Finck     {
240c2c66affSColin Finck         out[17+i*2] = in[n++];
241c2c66affSColin Finck         out[16+i*2] = in[n++];
242c2c66affSColin Finck     }
243c2c66affSColin Finck     out[32]=0;
244c2c66affSColin Finck     return TRUE;
245c2c66affSColin Finck }
246c2c66affSColin Finck 
247c2c66affSColin Finck static void create_test_guid(LPSTR prodcode, LPSTR squashed)
248c2c66affSColin Finck {
249c2c66affSColin Finck     WCHAR guidW[MAX_PATH];
250c2c66affSColin Finck     WCHAR squashedW[MAX_PATH];
251c2c66affSColin Finck     GUID guid;
252c2c66affSColin Finck     HRESULT hr;
253c2c66affSColin Finck     int size;
254c2c66affSColin Finck 
255c2c66affSColin Finck     hr = CoCreateGuid(&guid);
256c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
257c2c66affSColin Finck 
258c2c66affSColin Finck     size = StringFromGUID2(&guid, guidW, MAX_PATH);
259c2c66affSColin Finck     ok(size == 39, "Expected 39, got %d\n", hr);
260c2c66affSColin Finck 
261c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
262c2c66affSColin Finck     squash_guid(guidW, squashedW);
263c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
264c2c66affSColin Finck }
265c2c66affSColin Finck 
266c2c66affSColin Finck static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
267c2c66affSColin Finck                                LPCSTR guid, LPSTR usersid, BOOL dir)
268c2c66affSColin Finck {
269c2c66affSColin Finck     WCHAR guidW[MAX_PATH];
270c2c66affSColin Finck     WCHAR squashedW[MAX_PATH];
271c2c66affSColin Finck     CHAR squashed[MAX_PATH];
272c2c66affSColin Finck     CHAR comppath[MAX_PATH];
273c2c66affSColin Finck     CHAR prodpath[MAX_PATH];
274c2c66affSColin Finck     CHAR path[MAX_PATH];
275c2c66affSColin Finck     LPCSTR prod = NULL;
276c2c66affSColin Finck     HKEY hkey;
277c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
278c2c66affSColin Finck 
279c2c66affSColin Finck     if (is_wow64)
280c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
281c2c66affSColin Finck 
282c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
283c2c66affSColin Finck     squash_guid(guidW, squashedW);
284c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
285c2c66affSColin Finck 
286c2c66affSColin Finck     if (context == MSIINSTALLCONTEXT_MACHINE)
287c2c66affSColin Finck     {
288c2c66affSColin Finck         prod = "3D0DAE300FACA1300AD792060BCDAA92";
289c2c66affSColin Finck         sprintf(comppath,
290c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
291c2c66affSColin Finck                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
292c2c66affSColin Finck         lstrcpyA(prodpath,
293c2c66affSColin Finck                  "SOFTWARE\\Classes\\Installer\\"
294c2c66affSColin Finck                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
295c2c66affSColin Finck     }
296c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
297c2c66affSColin Finck     {
298c2c66affSColin Finck         prod = "7D2F387510109040002000060BECB6AB";
299c2c66affSColin Finck         sprintf(comppath,
300c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
301c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
302c2c66affSColin Finck         sprintf(prodpath,
303c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
304c2c66affSColin Finck                 "Installer\\%s\\Installer\\Products\\"
305c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
306c2c66affSColin Finck     }
307c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
308c2c66affSColin Finck     {
309c2c66affSColin Finck         prod = "7D2F387510109040002000060BECB6AB";
310c2c66affSColin Finck         sprintf(comppath,
311c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
312c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
313c2c66affSColin Finck         sprintf(prodpath,
314c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
315c2c66affSColin Finck                 "Installer\\Managed\\%s\\Installer\\Products\\"
316c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
317c2c66affSColin Finck     }
318c2c66affSColin Finck 
319c2c66affSColin Finck     RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
320c2c66affSColin Finck 
321c2c66affSColin Finck     lstrcpyA(path, CURR_DIR);
322c2c66affSColin Finck     lstrcatA(path, "\\");
323c2c66affSColin Finck     if (!dir) lstrcatA(path, filename);
324c2c66affSColin Finck 
325c2c66affSColin Finck     RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
326c2c66affSColin Finck     RegCloseKey(hkey);
327c2c66affSColin Finck 
328c2c66affSColin Finck     RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
329c2c66affSColin Finck     RegCloseKey(hkey);
330c2c66affSColin Finck }
331c2c66affSColin Finck 
332c2c66affSColin Finck static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
333c2c66affSColin Finck {
334c2c66affSColin Finck     WCHAR guidW[MAX_PATH];
335c2c66affSColin Finck     WCHAR squashedW[MAX_PATH];
336c2c66affSColin Finck     WCHAR substrW[MAX_PATH];
337c2c66affSColin Finck     CHAR squashed[MAX_PATH];
338c2c66affSColin Finck     CHAR comppath[MAX_PATH];
339c2c66affSColin Finck     CHAR prodpath[MAX_PATH];
340c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
341c2c66affSColin Finck 
342c2c66affSColin Finck     if (is_wow64)
343c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
344c2c66affSColin Finck 
345c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
346c2c66affSColin Finck     squash_guid(guidW, squashedW);
347c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
348c2c66affSColin Finck 
349c2c66affSColin Finck     if (context == MSIINSTALLCONTEXT_MACHINE)
350c2c66affSColin Finck     {
351c2c66affSColin Finck         sprintf(comppath,
352c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
353c2c66affSColin Finck                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
354c2c66affSColin Finck         lstrcpyA(prodpath,
355c2c66affSColin Finck                  "SOFTWARE\\Classes\\Installer\\"
356c2c66affSColin Finck                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
357c2c66affSColin Finck     }
358c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
359c2c66affSColin Finck     {
360c2c66affSColin Finck         sprintf(comppath,
361c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
362c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
363c2c66affSColin Finck         sprintf(prodpath,
364c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
365c2c66affSColin Finck                 "Installer\\%s\\Installer\\Products\\"
366c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
367c2c66affSColin Finck     }
368c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
369c2c66affSColin Finck     {
370c2c66affSColin Finck         sprintf(comppath,
371c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
372c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
373c2c66affSColin Finck         sprintf(prodpath,
374c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
375c2c66affSColin Finck                 "Installer\\Managed\\%s\\Installer\\Products\\"
376c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
377c2c66affSColin Finck     }
378c2c66affSColin Finck 
379c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
380c2c66affSColin Finck     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
381c2c66affSColin Finck 
382c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
383c2c66affSColin Finck     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
384c2c66affSColin Finck }
385c2c66affSColin Finck 
386c2c66affSColin Finck static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
387c2c66affSColin Finck {
388c2c66affSColin Finck     MSIHANDLE hview = 0;
389c2c66affSColin Finck     UINT r, ret;
390c2c66affSColin Finck 
391c2c66affSColin Finck     /* open a select query */
392c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, query, &hview);
393c2c66affSColin Finck     if (r != ERROR_SUCCESS)
394c2c66affSColin Finck         return r;
395c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
396c2c66affSColin Finck     if (r != ERROR_SUCCESS)
397c2c66affSColin Finck         return r;
398c2c66affSColin Finck     ret = MsiViewFetch(hview, phrec);
399c2c66affSColin Finck     r = MsiViewClose(hview);
400c2c66affSColin Finck     if (r != ERROR_SUCCESS)
401c2c66affSColin Finck         return r;
402c2c66affSColin Finck     r = MsiCloseHandle(hview);
403c2c66affSColin Finck     if (r != ERROR_SUCCESS)
404c2c66affSColin Finck         return r;
405c2c66affSColin Finck     return ret;
406c2c66affSColin Finck }
407c2c66affSColin Finck 
408c2c66affSColin Finck static UINT run_query( MSIHANDLE hdb, const char *query )
409c2c66affSColin Finck {
410c2c66affSColin Finck     MSIHANDLE hview = 0;
411c2c66affSColin Finck     UINT r;
412c2c66affSColin Finck 
413c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, query, &hview);
414c2c66affSColin Finck     if( r != ERROR_SUCCESS )
415c2c66affSColin Finck         return r;
416c2c66affSColin Finck 
417c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
418c2c66affSColin Finck     if( r == ERROR_SUCCESS )
419c2c66affSColin Finck         r = MsiViewClose(hview);
420c2c66affSColin Finck     MsiCloseHandle(hview);
421c2c66affSColin Finck     return r;
422c2c66affSColin Finck }
423c2c66affSColin Finck 
424c2c66affSColin Finck static UINT create_component_table( MSIHANDLE hdb )
425c2c66affSColin Finck {
426f860a780SAmine Khaldi     UINT r = run_query( hdb,
427c2c66affSColin Finck             "CREATE TABLE `Component` ( "
428c2c66affSColin Finck             "`Component` CHAR(72) NOT NULL, "
429c2c66affSColin Finck             "`ComponentId` CHAR(38), "
430c2c66affSColin Finck             "`Directory_` CHAR(72) NOT NULL, "
431c2c66affSColin Finck             "`Attributes` SHORT NOT NULL, "
432c2c66affSColin Finck             "`Condition` CHAR(255), "
433c2c66affSColin Finck             "`KeyPath` CHAR(72) "
434c2c66affSColin Finck             "PRIMARY KEY `Component`)" );
435f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
436f860a780SAmine Khaldi     return r;
437c2c66affSColin Finck }
438c2c66affSColin Finck 
439c2c66affSColin Finck static UINT create_feature_table( MSIHANDLE hdb )
440c2c66affSColin Finck {
441f860a780SAmine Khaldi     UINT r = run_query( hdb,
442c2c66affSColin Finck             "CREATE TABLE `Feature` ( "
443c2c66affSColin Finck             "`Feature` CHAR(38) NOT NULL, "
444c2c66affSColin Finck             "`Feature_Parent` CHAR(38), "
445c2c66affSColin Finck             "`Title` CHAR(64), "
446c2c66affSColin Finck             "`Description` CHAR(255), "
447c2c66affSColin Finck             "`Display` SHORT NOT NULL, "
448c2c66affSColin Finck             "`Level` SHORT NOT NULL, "
449c2c66affSColin Finck             "`Directory_` CHAR(72), "
450c2c66affSColin Finck             "`Attributes` SHORT NOT NULL "
451c2c66affSColin Finck             "PRIMARY KEY `Feature`)" );
452f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
453f860a780SAmine Khaldi     return r;
454c2c66affSColin Finck }
455c2c66affSColin Finck 
456c2c66affSColin Finck static UINT create_feature_components_table( MSIHANDLE hdb )
457c2c66affSColin Finck {
458f860a780SAmine Khaldi     UINT r = run_query( hdb,
459c2c66affSColin Finck             "CREATE TABLE `FeatureComponents` ( "
460c2c66affSColin Finck             "`Feature_` CHAR(38) NOT NULL, "
461c2c66affSColin Finck             "`Component_` CHAR(72) NOT NULL "
462c2c66affSColin Finck             "PRIMARY KEY `Feature_`, `Component_` )" );
463f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
464f860a780SAmine Khaldi     return r;
465c2c66affSColin Finck }
466c2c66affSColin Finck 
467c2c66affSColin Finck static UINT create_file_table( MSIHANDLE hdb )
468c2c66affSColin Finck {
469f860a780SAmine Khaldi     UINT r = run_query( hdb,
470c2c66affSColin Finck             "CREATE TABLE `File` ("
471c2c66affSColin Finck             "`File` CHAR(72) NOT NULL, "
472c2c66affSColin Finck             "`Component_` CHAR(72) NOT NULL, "
473c2c66affSColin Finck             "`FileName` CHAR(255) NOT NULL, "
474c2c66affSColin Finck             "`FileSize` LONG NOT NULL, "
475c2c66affSColin Finck             "`Version` CHAR(72), "
476c2c66affSColin Finck             "`Language` CHAR(20), "
477c2c66affSColin Finck             "`Attributes` SHORT, "
478c2c66affSColin Finck             "`Sequence` SHORT NOT NULL "
479c2c66affSColin Finck             "PRIMARY KEY `File`)" );
480f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
481f860a780SAmine Khaldi     return r;
482c2c66affSColin Finck }
483c2c66affSColin Finck 
484c2c66affSColin Finck static UINT create_remove_file_table( MSIHANDLE hdb )
485c2c66affSColin Finck {
486f860a780SAmine Khaldi     UINT r = run_query( hdb,
487c2c66affSColin Finck             "CREATE TABLE `RemoveFile` ("
488c2c66affSColin Finck             "`FileKey` CHAR(72) NOT NULL, "
489c2c66affSColin Finck             "`Component_` CHAR(72) NOT NULL, "
490c2c66affSColin Finck             "`FileName` CHAR(255) LOCALIZABLE, "
491c2c66affSColin Finck             "`DirProperty` CHAR(72) NOT NULL, "
492c2c66affSColin Finck             "`InstallMode` SHORT NOT NULL "
493c2c66affSColin Finck             "PRIMARY KEY `FileKey`)" );
494f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
495f860a780SAmine Khaldi     return r;
496c2c66affSColin Finck }
497c2c66affSColin Finck 
498c2c66affSColin Finck static UINT create_appsearch_table( MSIHANDLE hdb )
499c2c66affSColin Finck {
500f860a780SAmine Khaldi     UINT r = run_query( hdb,
501c2c66affSColin Finck             "CREATE TABLE `AppSearch` ("
502c2c66affSColin Finck             "`Property` CHAR(72) NOT NULL, "
503c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL "
504c2c66affSColin Finck             "PRIMARY KEY `Property`, `Signature_`)" );
505f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
506f860a780SAmine Khaldi     return r;
507c2c66affSColin Finck }
508c2c66affSColin Finck 
509c2c66affSColin Finck static UINT create_reglocator_table( MSIHANDLE hdb )
510c2c66affSColin Finck {
511f860a780SAmine Khaldi     UINT r = run_query( hdb,
512c2c66affSColin Finck             "CREATE TABLE `RegLocator` ("
513c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
514c2c66affSColin Finck             "`Root` SHORT NOT NULL, "
515c2c66affSColin Finck             "`Key` CHAR(255) NOT NULL, "
516c2c66affSColin Finck             "`Name` CHAR(255), "
517c2c66affSColin Finck             "`Type` SHORT "
518c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
519f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
520f860a780SAmine Khaldi     return r;
521c2c66affSColin Finck }
522c2c66affSColin Finck 
523c2c66affSColin Finck static UINT create_signature_table( MSIHANDLE hdb )
524c2c66affSColin Finck {
525f860a780SAmine Khaldi     UINT r = run_query( hdb,
526c2c66affSColin Finck             "CREATE TABLE `Signature` ("
527c2c66affSColin Finck             "`Signature` CHAR(72) NOT NULL, "
528c2c66affSColin Finck             "`FileName` CHAR(255) NOT NULL, "
529c2c66affSColin Finck             "`MinVersion` CHAR(20), "
530c2c66affSColin Finck             "`MaxVersion` CHAR(20), "
531c2c66affSColin Finck             "`MinSize` LONG, "
532c2c66affSColin Finck             "`MaxSize` LONG, "
533c2c66affSColin Finck             "`MinDate` LONG, "
534c2c66affSColin Finck             "`MaxDate` LONG, "
535c2c66affSColin Finck             "`Languages` CHAR(255) "
536c2c66affSColin Finck             "PRIMARY KEY `Signature`)" );
537f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
538f860a780SAmine Khaldi     return r;
539c2c66affSColin Finck }
540c2c66affSColin Finck 
541c2c66affSColin Finck static UINT create_launchcondition_table( MSIHANDLE hdb )
542c2c66affSColin Finck {
543f860a780SAmine Khaldi     UINT r = run_query( hdb,
544c2c66affSColin Finck             "CREATE TABLE `LaunchCondition` ("
545c2c66affSColin Finck             "`Condition` CHAR(255) NOT NULL, "
546c2c66affSColin Finck             "`Description` CHAR(255) NOT NULL "
547c2c66affSColin Finck             "PRIMARY KEY `Condition`)" );
548f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
549f860a780SAmine Khaldi     return r;
550c2c66affSColin Finck }
551c2c66affSColin Finck 
552c2c66affSColin Finck static UINT create_property_table( MSIHANDLE hdb )
553c2c66affSColin Finck {
554f860a780SAmine Khaldi     UINT r = run_query( hdb,
555c2c66affSColin Finck             "CREATE TABLE `Property` ("
556c2c66affSColin Finck             "`Property` CHAR(72) NOT NULL, "
557c2c66affSColin Finck             "`Value` CHAR(0) "
558c2c66affSColin Finck             "PRIMARY KEY `Property`)" );
559f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
560f860a780SAmine Khaldi     return r;
561c2c66affSColin Finck }
562c2c66affSColin Finck 
563c2c66affSColin Finck static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
564c2c66affSColin Finck {
565f860a780SAmine Khaldi     UINT r = run_query( hdb,
566c2c66affSColin Finck             "CREATE TABLE `InstallExecuteSequence` ("
567c2c66affSColin Finck             "`Action` CHAR(72) NOT NULL, "
568c2c66affSColin Finck             "`Condition` CHAR(255), "
569c2c66affSColin Finck             "`Sequence` SHORT "
570c2c66affSColin Finck             "PRIMARY KEY `Action`)" );
571f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
572f860a780SAmine Khaldi     return r;
573f860a780SAmine Khaldi }
574f860a780SAmine Khaldi 
575f860a780SAmine Khaldi static UINT create_install_ui_sequence_table( MSIHANDLE hdb )
576f860a780SAmine Khaldi {
577f860a780SAmine Khaldi     UINT r = run_query( hdb,
578f860a780SAmine Khaldi             "CREATE TABLE `InstallUISequence` ("
579f860a780SAmine Khaldi             "`Action` CHAR(72) NOT NULL, "
580f860a780SAmine Khaldi             "`Condition` CHAR(255), "
581f860a780SAmine Khaldi             "`Sequence` SHORT "
582f860a780SAmine Khaldi             "PRIMARY KEY `Action`)" );
583f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
584f860a780SAmine Khaldi     return r;
585c2c66affSColin Finck }
586c2c66affSColin Finck 
587c2c66affSColin Finck static UINT create_media_table( MSIHANDLE hdb )
588c2c66affSColin Finck {
589f860a780SAmine Khaldi     UINT r = run_query( hdb,
590c2c66affSColin Finck             "CREATE TABLE `Media` ("
591c2c66affSColin Finck             "`DiskId` SHORT NOT NULL, "
592c2c66affSColin Finck             "`LastSequence` SHORT NOT NULL, "
593c2c66affSColin Finck             "`DiskPrompt` CHAR(64), "
594c2c66affSColin Finck             "`Cabinet` CHAR(255), "
595c2c66affSColin Finck             "`VolumeLabel` CHAR(32), "
596c2c66affSColin Finck             "`Source` CHAR(72) "
597c2c66affSColin Finck             "PRIMARY KEY `DiskId`)" );
598f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
599f860a780SAmine Khaldi     return r;
600c2c66affSColin Finck }
601c2c66affSColin Finck 
602c2c66affSColin Finck static UINT create_ccpsearch_table( MSIHANDLE hdb )
603c2c66affSColin Finck {
604f860a780SAmine Khaldi     UINT r = run_query( hdb,
605c2c66affSColin Finck             "CREATE TABLE `CCPSearch` ("
606c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL "
607c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
608f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
609f860a780SAmine Khaldi     return r;
610c2c66affSColin Finck }
611c2c66affSColin Finck 
612c2c66affSColin Finck static UINT create_drlocator_table( MSIHANDLE hdb )
613c2c66affSColin Finck {
614f860a780SAmine Khaldi     UINT r = run_query( hdb,
615c2c66affSColin Finck             "CREATE TABLE `DrLocator` ("
616c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
617c2c66affSColin Finck             "`Parent` CHAR(72), "
618c2c66affSColin Finck             "`Path` CHAR(255), "
619c2c66affSColin Finck             "`Depth` SHORT "
620c2c66affSColin Finck             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
621f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
622f860a780SAmine Khaldi     return r;
623c2c66affSColin Finck }
624c2c66affSColin Finck 
625c2c66affSColin Finck static UINT create_complocator_table( MSIHANDLE hdb )
626c2c66affSColin Finck {
627f860a780SAmine Khaldi     UINT r = run_query( hdb,
628c2c66affSColin Finck             "CREATE TABLE `CompLocator` ("
629c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
630c2c66affSColin Finck             "`ComponentId` CHAR(38) NOT NULL, "
631c2c66affSColin Finck             "`Type` SHORT "
632c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
633f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
634f860a780SAmine Khaldi     return r;
635c2c66affSColin Finck }
636c2c66affSColin Finck 
637c2c66affSColin Finck static UINT create_inilocator_table( MSIHANDLE hdb )
638c2c66affSColin Finck {
639f860a780SAmine Khaldi     UINT r = run_query( hdb,
640c2c66affSColin Finck             "CREATE TABLE `IniLocator` ("
641c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
642c2c66affSColin Finck             "`FileName` CHAR(255) NOT NULL, "
643c2c66affSColin Finck             "`Section` CHAR(96)NOT NULL, "
644c2c66affSColin Finck             "`Key` CHAR(128)NOT NULL, "
645c2c66affSColin Finck             "`Field` SHORT, "
646c2c66affSColin Finck             "`Type` SHORT "
647c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
648f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
649f860a780SAmine Khaldi     return r;
650c2c66affSColin Finck }
651c2c66affSColin Finck 
652c2c66affSColin Finck static UINT create_custom_action_table( MSIHANDLE hdb )
653c2c66affSColin Finck {
654f860a780SAmine Khaldi     UINT r = run_query( hdb,
655c2c66affSColin Finck             "CREATE TABLE `CustomAction` ("
656c2c66affSColin Finck             "`Action` CHAR(72) NOT NULL, "
657c2c66affSColin Finck             "`Type` SHORT NOT NULL, "
658c2c66affSColin Finck             "`Source` CHAR(75), "
659c2c66affSColin Finck             "`Target` CHAR(255) "
660c2c66affSColin Finck             "PRIMARY KEY `Action`)" );
661f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
662f860a780SAmine Khaldi     return r;
663c2c66affSColin Finck }
664c2c66affSColin Finck 
6652f8e6f71SAmine Khaldi static UINT create_dialog_table( MSIHANDLE hdb )
6662f8e6f71SAmine Khaldi {
667f860a780SAmine Khaldi     UINT r = run_query(hdb,
6682f8e6f71SAmine Khaldi             "CREATE TABLE `Dialog` ("
6692f8e6f71SAmine Khaldi             "`Dialog` CHAR(72) NOT NULL, "
6702f8e6f71SAmine Khaldi             "`HCentering` SHORT NOT NULL, "
6712f8e6f71SAmine Khaldi             "`VCentering` SHORT NOT NULL, "
6722f8e6f71SAmine Khaldi             "`Width` SHORT NOT NULL, "
6732f8e6f71SAmine Khaldi             "`Height` SHORT NOT NULL, "
6742f8e6f71SAmine Khaldi             "`Attributes` LONG, "
6752f8e6f71SAmine Khaldi             "`Title` CHAR(128) LOCALIZABLE, "
6762f8e6f71SAmine Khaldi             "`Control_First` CHAR(50) NOT NULL, "
6772f8e6f71SAmine Khaldi             "`Control_Default` CHAR(50), "
6782f8e6f71SAmine Khaldi             "`Control_Cancel` CHAR(50) "
6792f8e6f71SAmine Khaldi             "PRIMARY KEY `Dialog`)");
680f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
681f860a780SAmine Khaldi     return r;
6822f8e6f71SAmine Khaldi }
6832f8e6f71SAmine Khaldi 
6842f8e6f71SAmine Khaldi static UINT create_control_table( MSIHANDLE hdb )
6852f8e6f71SAmine Khaldi {
686f860a780SAmine Khaldi     UINT r = run_query(hdb,
6872f8e6f71SAmine Khaldi             "CREATE TABLE `Control` ("
6882f8e6f71SAmine Khaldi             "`Dialog_` CHAR(72) NOT NULL, "
6892f8e6f71SAmine Khaldi             "`Control` CHAR(50) NOT NULL, "
6902f8e6f71SAmine Khaldi             "`Type` CHAR(20) NOT NULL, "
6912f8e6f71SAmine Khaldi             "`X` SHORT NOT NULL, "
6922f8e6f71SAmine Khaldi             "`Y` SHORT NOT NULL, "
6932f8e6f71SAmine Khaldi             "`Width` SHORT NOT NULL, "
6942f8e6f71SAmine Khaldi             "`Height` SHORT NOT NULL, "
6952f8e6f71SAmine Khaldi             "`Attributes` LONG, "
6962f8e6f71SAmine Khaldi             "`Property` CHAR(50), "
6972f8e6f71SAmine Khaldi             "`Text` CHAR(0) LOCALIZABLE, "
6982f8e6f71SAmine Khaldi             "`Control_Next` CHAR(50), "
6992f8e6f71SAmine Khaldi             "`Help` CHAR(255) LOCALIZABLE "
7002f8e6f71SAmine Khaldi             "PRIMARY KEY `Dialog_`, `Control`)");
701f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
702f860a780SAmine Khaldi     return r;
7032f8e6f71SAmine Khaldi }
7042f8e6f71SAmine Khaldi 
7052f8e6f71SAmine Khaldi static UINT create_controlevent_table( MSIHANDLE hdb )
7062f8e6f71SAmine Khaldi {
707f860a780SAmine Khaldi     UINT r = run_query(hdb,
7082f8e6f71SAmine Khaldi             "CREATE TABLE `ControlEvent` ("
7092f8e6f71SAmine Khaldi             "`Dialog_` CHAR(72) NOT NULL, "
7102f8e6f71SAmine Khaldi             "`Control_` CHAR(50) NOT NULL, "
7112f8e6f71SAmine Khaldi             "`Event` CHAR(50) NOT NULL, "
7122f8e6f71SAmine Khaldi             "`Argument` CHAR(255) NOT NULL, "
7132f8e6f71SAmine Khaldi             "`Condition` CHAR(255), "
7142f8e6f71SAmine Khaldi             "`Ordering` SHORT "
7152f8e6f71SAmine Khaldi             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
716f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
717f860a780SAmine Khaldi     return r;
7182f8e6f71SAmine Khaldi }
7192f8e6f71SAmine Khaldi 
7202f8e6f71SAmine Khaldi static UINT create_actiontext_table( MSIHANDLE hdb )
7212f8e6f71SAmine Khaldi {
722f860a780SAmine Khaldi     UINT r = run_query(hdb,
7232f8e6f71SAmine Khaldi             "CREATE TABLE `ActionText` ("
7242f8e6f71SAmine Khaldi             "`Action` CHAR(72) NOT NULL, "
7252f8e6f71SAmine Khaldi             "`Description` CHAR(64) LOCALIZABLE, "
7262f8e6f71SAmine Khaldi             "`Template` CHAR(128) LOCALIZABLE "
7272f8e6f71SAmine Khaldi             "PRIMARY KEY `Action`)");
728f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
729f860a780SAmine Khaldi     return r;
7302f8e6f71SAmine Khaldi }
7312f8e6f71SAmine Khaldi 
73296486643Swinesync static UINT create_upgrade_table( MSIHANDLE hdb )
73396486643Swinesync {
73496486643Swinesync     UINT r = run_query( hdb,
73596486643Swinesync             "CREATE TABLE `Upgrade` ("
73696486643Swinesync             "`UpgradeCode` CHAR(38) NOT NULL, "
73796486643Swinesync             "`VersionMin` CHAR(20), "
73896486643Swinesync             "`VersionMax` CHAR(20), "
73996486643Swinesync             "`Language` CHAR(255), "
74096486643Swinesync             "`Attributes` SHORT, "
74196486643Swinesync             "`Remove` CHAR(255), "
74296486643Swinesync             "`ActionProperty` CHAR(72) NOT NULL "
74396486643Swinesync             "PRIMARY KEY `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`)" );
74496486643Swinesync     ok(r == ERROR_SUCCESS, "Failed to create Upgrade table: %u\n", r);
74596486643Swinesync     return r;
74696486643Swinesync }
74796486643Swinesync 
748f860a780SAmine Khaldi static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
749f860a780SAmine Khaldi {
750f860a780SAmine Khaldi     char *query;
751f860a780SAmine Khaldi     UINT sz, r;
752f860a780SAmine Khaldi 
753f860a780SAmine Khaldi     sz = strlen(values) + strlen(insert) + 1;
754f860a780SAmine Khaldi     query = HeapAlloc(GetProcessHeap(), 0, sz);
755f860a780SAmine Khaldi     sprintf(query, insert, values);
756f860a780SAmine Khaldi     r = run_query(hdb, query);
757f860a780SAmine Khaldi     HeapFree(GetProcessHeap(), 0, query);
758f860a780SAmine Khaldi     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
759f860a780SAmine Khaldi     return r;
760c2c66affSColin Finck }
761c2c66affSColin Finck 
762f860a780SAmine Khaldi #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
763f860a780SAmine Khaldi                "INSERT INTO `Component`  " \
764f860a780SAmine Khaldi                "(`Component`, `ComponentId`, `Directory_`, " \
765c2c66affSColin Finck                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
766c2c66affSColin Finck 
767f860a780SAmine Khaldi #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
768f860a780SAmine Khaldi                "INSERT INTO `Directory` " \
769c2c66affSColin Finck                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
770c2c66affSColin Finck 
771f860a780SAmine Khaldi #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
772f860a780SAmine Khaldi                "INSERT INTO `Feature` " \
773f860a780SAmine Khaldi                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
774c2c66affSColin Finck                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
775c2c66affSColin Finck 
776f860a780SAmine Khaldi #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
777f860a780SAmine Khaldi                "INSERT INTO `FeatureComponents` " \
778c2c66affSColin Finck                "(`Feature_`, `Component_`) VALUES( %s )")
779c2c66affSColin Finck 
780f860a780SAmine Khaldi #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
781f860a780SAmine Khaldi                "INSERT INTO `File` " \
782f860a780SAmine Khaldi                "(`File`, `Component_`, `FileName`, `FileSize`, " \
783c2c66affSColin Finck                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
784c2c66affSColin Finck 
785f860a780SAmine Khaldi #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
786f860a780SAmine Khaldi                "INSERT INTO `AppSearch` " \
787c2c66affSColin Finck                "(`Property`, `Signature_`) VALUES( %s )")
788c2c66affSColin Finck 
789f860a780SAmine Khaldi #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
790f860a780SAmine Khaldi                "INSERT INTO `Signature` " \
791f860a780SAmine Khaldi                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
792f860a780SAmine Khaldi                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
793c2c66affSColin Finck                "VALUES( %s )")
794c2c66affSColin Finck 
795f860a780SAmine Khaldi #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
796f860a780SAmine Khaldi                "INSERT INTO `LaunchCondition` " \
797c2c66affSColin Finck                "(`Condition`, `Description`) VALUES( %s )")
798c2c66affSColin Finck 
799f860a780SAmine Khaldi #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
800c2c66affSColin Finck                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
801c2c66affSColin Finck 
80296486643Swinesync #define update_ProductVersion_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
80396486643Swinesync                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductVersion'")
80496486643Swinesync 
80596486643Swinesync #define update_ProductCode_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
80696486643Swinesync                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductCode'")
80796486643Swinesync 
808f860a780SAmine Khaldi #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
809f860a780SAmine Khaldi                "INSERT INTO `InstallExecuteSequence` " \
810c2c66affSColin Finck                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
811c2c66affSColin Finck 
812f860a780SAmine Khaldi #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
813f860a780SAmine Khaldi                "INSERT INTO `InstallUISequence` " \
814f860a780SAmine Khaldi                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
815f860a780SAmine Khaldi 
816f860a780SAmine Khaldi #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
817f860a780SAmine Khaldi                "INSERT INTO `Media` " \
818f860a780SAmine Khaldi                "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
819c2c66affSColin Finck                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
820c2c66affSColin Finck 
821f860a780SAmine Khaldi #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
822c2c66affSColin Finck                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
823c2c66affSColin Finck 
824f860a780SAmine Khaldi #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
825f860a780SAmine Khaldi                "INSERT INTO `DrLocator` " \
826c2c66affSColin Finck                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
827c2c66affSColin Finck 
828f860a780SAmine Khaldi #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
829f860a780SAmine Khaldi                "INSERT INTO `CompLocator` " \
830c2c66affSColin Finck                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
831c2c66affSColin Finck 
832f860a780SAmine Khaldi #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
833f860a780SAmine Khaldi                "INSERT INTO `IniLocator` " \
834f860a780SAmine Khaldi                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
835c2c66affSColin Finck                "VALUES( %s )")
836c2c66affSColin Finck 
837f860a780SAmine Khaldi #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
838f860a780SAmine Khaldi                "INSERT INTO `CustomAction`  " \
839c2c66affSColin Finck                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
840c2c66affSColin Finck 
841f860a780SAmine Khaldi #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
842f860a780SAmine Khaldi                "INSERT INTO `Dialog` " \
8432f8e6f71SAmine Khaldi                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
8442f8e6f71SAmine Khaldi 
845f860a780SAmine Khaldi #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
846f860a780SAmine Khaldi                "INSERT INTO `Control` " \
8472f8e6f71SAmine Khaldi                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
8482f8e6f71SAmine Khaldi 
849f860a780SAmine Khaldi #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
850f860a780SAmine Khaldi                "INSERT INTO `ControlEvent` " \
8512f8e6f71SAmine Khaldi                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
8522f8e6f71SAmine Khaldi 
853f860a780SAmine Khaldi #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
854f860a780SAmine Khaldi                "INSERT INTO `ActionText` " \
8552f8e6f71SAmine Khaldi                "(`Action`, `Description`, `Template`) VALUES( %s )");
8562f8e6f71SAmine Khaldi 
85796486643Swinesync #define add_upgrade_entry(hdb, values) add_entry(__FILE__, __LINE__, "Upgrade", hdb, values, \
85896486643Swinesync                "INSERT INTO `Upgrade` " \
85996486643Swinesync                "(`UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes`, `Remove`, `ActionProperty`) VALUES( %s )");
86096486643Swinesync 
861c2c66affSColin Finck static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
862c2c66affSColin Finck                                   const char *name, UINT type )
863c2c66affSColin Finck {
864c2c66affSColin Finck     const char insert[] =
865c2c66affSColin Finck         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
866c2c66affSColin Finck         "VALUES( '%s', %u, '%s', '%s', %u )";
867c2c66affSColin Finck     char *query;
868c2c66affSColin Finck     UINT sz, r;
869c2c66affSColin Finck 
870c2c66affSColin Finck     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
871c2c66affSColin Finck     query = HeapAlloc( GetProcessHeap(), 0, sz );
872c2c66affSColin Finck     sprintf( query, insert, sig, root, path, name, type );
873c2c66affSColin Finck     r = run_query( hdb, query );
874c2c66affSColin Finck     HeapFree( GetProcessHeap(), 0, query );
875f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
876c2c66affSColin Finck     return r;
877c2c66affSColin Finck }
878c2c66affSColin Finck 
879c2c66affSColin Finck static UINT set_summary_info(MSIHANDLE hdb)
880c2c66affSColin Finck {
881c2c66affSColin Finck     UINT res;
882c2c66affSColin Finck     MSIHANDLE suminfo;
883c2c66affSColin Finck 
884c2c66affSColin Finck     /* build summary info */
885c2c66affSColin Finck     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
886c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
887c2c66affSColin Finck 
888c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
889c2c66affSColin Finck                         "Installation Database");
890c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
891c2c66affSColin Finck 
892c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
893c2c66affSColin Finck                         "Installation Database");
894c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
895c2c66affSColin Finck 
896c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
897c2c66affSColin Finck                         "Wine Hackers");
898c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
899c2c66affSColin Finck 
900c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
901c2c66affSColin Finck                     ";1033");
902c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
903c2c66affSColin Finck 
904c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
905c2c66affSColin Finck                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
906c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
907c2c66affSColin Finck 
908c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
909c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
910c2c66affSColin Finck 
911c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
912c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
913c2c66affSColin Finck 
914c2c66affSColin Finck     res = MsiSummaryInfoPersist(suminfo);
915c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
916c2c66affSColin Finck 
917c2c66affSColin Finck     res = MsiCloseHandle( suminfo);
918c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
919c2c66affSColin Finck 
920c2c66affSColin Finck     return res;
921c2c66affSColin Finck }
922c2c66affSColin Finck 
923c2c66affSColin Finck 
924c2c66affSColin Finck static MSIHANDLE create_package_db(void)
925c2c66affSColin Finck {
926c2c66affSColin Finck     MSIHANDLE hdb = 0;
927c2c66affSColin Finck     UINT res;
928c2c66affSColin Finck 
929c2c66affSColin Finck     DeleteFileA(msifile);
930c2c66affSColin Finck 
931c2c66affSColin Finck     /* create an empty database */
932c2c66affSColin Finck     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
933c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
934c2c66affSColin Finck     if( res != ERROR_SUCCESS )
935c2c66affSColin Finck         return hdb;
936c2c66affSColin Finck 
937c2c66affSColin Finck     res = MsiDatabaseCommit( hdb );
938c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
939c2c66affSColin Finck 
940c2c66affSColin Finck     res = set_summary_info(hdb);
941c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
942c2c66affSColin Finck 
943c2c66affSColin Finck     res = run_query( hdb,
944c2c66affSColin Finck             "CREATE TABLE `Directory` ( "
945c2c66affSColin Finck             "`Directory` CHAR(255) NOT NULL, "
946c2c66affSColin Finck             "`Directory_Parent` CHAR(255), "
947c2c66affSColin Finck             "`DefaultDir` CHAR(255) NOT NULL "
948c2c66affSColin Finck             "PRIMARY KEY `Directory`)" );
949c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
950c2c66affSColin Finck 
951c2c66affSColin Finck     return hdb;
952c2c66affSColin Finck }
953c2c66affSColin Finck 
954c2c66affSColin Finck static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
955c2c66affSColin Finck {
956c2c66affSColin Finck     UINT res;
957c2c66affSColin Finck     CHAR szPackage[12];
958c2c66affSColin Finck     MSIHANDLE hPackage;
959c2c66affSColin Finck 
960c2c66affSColin Finck     sprintf(szPackage, "#%u", hdb);
961c2c66affSColin Finck     res = MsiOpenPackageA(szPackage, &hPackage);
962c2c66affSColin Finck     if (res != ERROR_SUCCESS)
963c2c66affSColin Finck     {
964c2c66affSColin Finck         MsiCloseHandle(hdb);
965c2c66affSColin Finck         return res;
966c2c66affSColin Finck     }
967c2c66affSColin Finck 
968c2c66affSColin Finck     res = MsiCloseHandle(hdb);
969c2c66affSColin Finck     if (res != ERROR_SUCCESS)
970c2c66affSColin Finck     {
971c2c66affSColin Finck         MsiCloseHandle(hPackage);
972c2c66affSColin Finck         return res;
973c2c66affSColin Finck     }
974c2c66affSColin Finck 
975c2c66affSColin Finck     *handle = hPackage;
976c2c66affSColin Finck     return ERROR_SUCCESS;
977c2c66affSColin Finck }
978c2c66affSColin Finck 
9792f8e6f71SAmine Khaldi static void create_file_data(LPCSTR name, LPCSTR data)
980c2c66affSColin Finck {
981c2c66affSColin Finck     HANDLE file;
982c2c66affSColin Finck     DWORD written;
983c2c66affSColin Finck 
984c2c66affSColin Finck     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
985c2c66affSColin Finck     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
9862f8e6f71SAmine Khaldi     if (file == INVALID_HANDLE_VALUE)
9872f8e6f71SAmine Khaldi         return;
9882f8e6f71SAmine Khaldi 
9892f8e6f71SAmine Khaldi     WriteFile(file, data, strlen(data), &written, NULL);
990c2c66affSColin Finck     WriteFile(file, "\n", strlen("\n"), &written, NULL);
9912f8e6f71SAmine Khaldi 
992c2c66affSColin Finck     CloseHandle(file);
993c2c66affSColin Finck }
994c2c66affSColin Finck 
9952f8e6f71SAmine Khaldi static void create_test_file(const CHAR *name)
9962f8e6f71SAmine Khaldi {
9972f8e6f71SAmine Khaldi     create_file_data(name, name);
9982f8e6f71SAmine Khaldi }
9992f8e6f71SAmine Khaldi 
1000c2c66affSColin Finck typedef struct _tagVS_VERSIONINFO
1001c2c66affSColin Finck {
1002c2c66affSColin Finck     WORD wLength;
1003c2c66affSColin Finck     WORD wValueLength;
1004c2c66affSColin Finck     WORD wType;
1005c2c66affSColin Finck     WCHAR szKey[1];
1006c2c66affSColin Finck     WORD wPadding1[1];
1007c2c66affSColin Finck     VS_FIXEDFILEINFO Value;
1008c2c66affSColin Finck     WORD wPadding2[1];
1009c2c66affSColin Finck     WORD wChildren[1];
1010c2c66affSColin Finck } VS_VERSIONINFO;
1011c2c66affSColin Finck 
1012c2c66affSColin Finck #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1013c2c66affSColin Finck #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1014c2c66affSColin Finck 
1015c2c66affSColin Finck static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
1016c2c66affSColin Finck {
1017c2c66affSColin Finck     VS_VERSIONINFO *pVerInfo;
1018c2c66affSColin Finck     VS_FIXEDFILEINFO *pFixedInfo;
1019c2c66affSColin Finck     LPBYTE buffer, ofs;
1020c2c66affSColin Finck     CHAR path[MAX_PATH];
1021c2c66affSColin Finck     DWORD handle, size;
1022c2c66affSColin Finck     HANDLE resource;
1023c2c66affSColin Finck     BOOL ret = FALSE;
1024c2c66affSColin Finck 
1025c2c66affSColin Finck     GetSystemDirectoryA(path, MAX_PATH);
1026c2c66affSColin Finck     /* Some dlls can't be updated on Vista/W2K8 */
1027c2c66affSColin Finck     lstrcatA(path, "\\version.dll");
1028c2c66affSColin Finck 
1029c2c66affSColin Finck     CopyFileA(path, name, FALSE);
1030c2c66affSColin Finck 
1031c2c66affSColin Finck     size = GetFileVersionInfoSizeA(path, &handle);
1032c2c66affSColin Finck     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1033c2c66affSColin Finck 
1034c2c66affSColin Finck     GetFileVersionInfoA(path, 0, size, buffer);
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     pVerInfo = (VS_VERSIONINFO *)buffer;
1037c2c66affSColin Finck     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1038c2c66affSColin Finck     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1039c2c66affSColin Finck 
1040c2c66affSColin Finck     pFixedInfo->dwFileVersionMS = ms;
1041c2c66affSColin Finck     pFixedInfo->dwFileVersionLS = ls;
1042c2c66affSColin Finck     pFixedInfo->dwProductVersionMS = ms;
1043c2c66affSColin Finck     pFixedInfo->dwProductVersionLS = ls;
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     resource = BeginUpdateResourceA(name, FALSE);
1046c2c66affSColin Finck     if (!resource)
1047c2c66affSColin Finck         goto done;
1048c2c66affSColin Finck 
1049c2c66affSColin Finck     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
1050c2c66affSColin Finck                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1051c2c66affSColin Finck         goto done;
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     if (!EndUpdateResourceA(resource, FALSE))
1054c2c66affSColin Finck         goto done;
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     ret = TRUE;
1057c2c66affSColin Finck 
1058c2c66affSColin Finck done:
1059c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, buffer);
1060c2c66affSColin Finck     return ret;
1061c2c66affSColin Finck }
1062c2c66affSColin Finck 
1063c2c66affSColin Finck static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1064c2c66affSColin Finck {
1065c2c66affSColin Finck     RESTOREPOINTINFOA spec;
1066c2c66affSColin Finck 
1067c2c66affSColin Finck     spec.dwEventType = event_type;
1068c2c66affSColin Finck     spec.dwRestorePtType = APPLICATION_INSTALL;
1069c2c66affSColin Finck     spec.llSequenceNumber = status->llSequenceNumber;
1070c2c66affSColin Finck     lstrcpyA(spec.szDescription, "msitest restore point");
1071c2c66affSColin Finck 
1072c2c66affSColin Finck     return pSRSetRestorePointA(&spec, status);
1073c2c66affSColin Finck }
1074c2c66affSColin Finck 
1075c2c66affSColin Finck static void remove_restore_point(DWORD seq_number)
1076c2c66affSColin Finck {
1077c2c66affSColin Finck     DWORD res;
1078c2c66affSColin Finck 
1079c2c66affSColin Finck     res = pSRRemoveRestorePoint(seq_number);
1080c2c66affSColin Finck     if (res != ERROR_SUCCESS)
1081c2c66affSColin Finck         trace("Failed to remove the restore point : %08x\n", res);
1082c2c66affSColin Finck }
1083c2c66affSColin Finck 
1084c2c66affSColin Finck static BOOL is_root(const char *path)
1085c2c66affSColin Finck {
1086c2c66affSColin Finck     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1087c2c66affSColin Finck }
1088c2c66affSColin Finck 
1089c2c66affSColin Finck static void test_createpackage(void)
1090c2c66affSColin Finck {
1091c2c66affSColin Finck     MSIHANDLE hPackage = 0;
1092c2c66affSColin Finck     UINT res;
1093c2c66affSColin Finck 
1094c2c66affSColin Finck     res = package_from_db(create_package_db(), &hPackage);
1095c2c66affSColin Finck     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1096c2c66affSColin Finck     {
1097c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1098c2c66affSColin Finck         DeleteFileA(msifile);
1099c2c66affSColin Finck         return;
1100c2c66affSColin Finck     }
1101c2c66affSColin Finck     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1102c2c66affSColin Finck 
1103c2c66affSColin Finck     res = MsiCloseHandle( hPackage);
1104c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1105c2c66affSColin Finck     DeleteFileA(msifile);
1106c2c66affSColin Finck }
1107c2c66affSColin Finck 
1108c2c66affSColin Finck static void test_doaction( void )
1109c2c66affSColin Finck {
1110c2c66affSColin Finck     MSIHANDLE hpkg;
1111c2c66affSColin Finck     UINT r;
1112c2c66affSColin Finck 
1113c2c66affSColin Finck     r = MsiDoActionA( -1, NULL );
1114c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1115c2c66affSColin Finck 
1116c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1117c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1118c2c66affSColin Finck     {
1119c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1120c2c66affSColin Finck         DeleteFileA(msifile);
1121c2c66affSColin Finck         return;
1122c2c66affSColin Finck     }
1123c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1124c2c66affSColin Finck 
1125c2c66affSColin Finck     r = MsiDoActionA(hpkg, NULL);
1126c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1127c2c66affSColin Finck 
1128c2c66affSColin Finck     r = MsiDoActionA(0, "boo");
1129c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1130c2c66affSColin Finck 
1131c2c66affSColin Finck     r = MsiDoActionA(hpkg, "boo");
1132c2c66affSColin Finck     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1133c2c66affSColin Finck 
1134c2c66affSColin Finck     MsiCloseHandle( hpkg );
1135c2c66affSColin Finck     DeleteFileA(msifile);
1136c2c66affSColin Finck }
1137c2c66affSColin Finck 
1138c2c66affSColin Finck static void test_gettargetpath_bad(void)
1139c2c66affSColin Finck {
1140c2c66affSColin Finck     static const WCHAR boo[] = {'b','o','o',0};
1141c2c66affSColin Finck     static const WCHAR empty[] = {0};
1142c2c66affSColin Finck     char buffer[0x80];
1143c2c66affSColin Finck     WCHAR bufferW[0x80];
1144c2c66affSColin Finck     MSIHANDLE hpkg;
1145c2c66affSColin Finck     DWORD sz;
1146c2c66affSColin Finck     UINT r;
1147c2c66affSColin Finck 
1148c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1149c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1150c2c66affSColin Finck     {
1151c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1152c2c66affSColin Finck         DeleteFileA(msifile);
1153c2c66affSColin Finck         return;
1154c2c66affSColin Finck     }
1155c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1156c2c66affSColin Finck 
1157c2c66affSColin Finck     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1158c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1159c2c66affSColin Finck 
1160c2c66affSColin Finck     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1161c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1162c2c66affSColin Finck 
1163c2c66affSColin Finck     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1164c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1165c2c66affSColin Finck 
1166c2c66affSColin Finck     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1167c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1168c2c66affSColin Finck 
1169c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1170c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1171c2c66affSColin Finck 
1172c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1173c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1174c2c66affSColin Finck 
1175c2c66affSColin Finck     sz = 0;
1176c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1177c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1178c2c66affSColin Finck 
1179c2c66affSColin Finck     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1180c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1181c2c66affSColin Finck 
1182c2c66affSColin Finck     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1183c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1186c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1187c2c66affSColin Finck 
1188c2c66affSColin Finck     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1189c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1190c2c66affSColin Finck 
1191c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1192c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1193c2c66affSColin Finck 
1194c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1195c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1196c2c66affSColin Finck 
1197c2c66affSColin Finck     sz = 0;
1198c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1199c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     MsiCloseHandle( hpkg );
1202c2c66affSColin Finck     DeleteFileA(msifile);
1203c2c66affSColin Finck }
1204c2c66affSColin Finck 
1205c2c66affSColin Finck static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1206c2c66affSColin Finck {
1207c2c66affSColin Finck     UINT r;
1208c2c66affSColin Finck     DWORD size;
1209c2c66affSColin Finck     MSIHANDLE rec;
1210c2c66affSColin Finck 
1211c2c66affSColin Finck     rec = MsiCreateRecord( 1 );
1212c2c66affSColin Finck     ok(rec, "MsiCreate record failed\n");
1213c2c66affSColin Finck 
1214c2c66affSColin Finck     r = MsiRecordSetStringA( rec, 0, file );
1215c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1216c2c66affSColin Finck 
1217c2c66affSColin Finck     size = MAX_PATH;
1218c2c66affSColin Finck     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1219c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1220c2c66affSColin Finck 
1221c2c66affSColin Finck     MsiCloseHandle( rec );
1222c2c66affSColin Finck }
1223c2c66affSColin Finck 
1224c2c66affSColin Finck static void test_settargetpath(void)
1225c2c66affSColin Finck {
1226c2c66affSColin Finck     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1227c2c66affSColin Finck     DWORD sz;
1228c2c66affSColin Finck     MSIHANDLE hpkg;
1229c2c66affSColin Finck     UINT r;
1230c2c66affSColin Finck     MSIHANDLE hdb;
1231c2c66affSColin Finck 
1232c2c66affSColin Finck     hdb = create_package_db();
1233c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
1234c2c66affSColin Finck 
1235f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1236c2c66affSColin Finck 
1237f860a780SAmine Khaldi     create_component_table( hdb );
1238f860a780SAmine Khaldi     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1239f860a780SAmine Khaldi     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1240c2c66affSColin Finck 
1241f860a780SAmine Khaldi     create_feature_table( hdb );
1242f860a780SAmine Khaldi     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1243c2c66affSColin Finck 
1244f860a780SAmine Khaldi     create_feature_components_table( hdb );
1245f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1246f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1247c2c66affSColin Finck 
1248c2c66affSColin Finck     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1249c2c66affSColin Finck     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1250c2c66affSColin Finck 
1251f860a780SAmine Khaldi     create_file_table( hdb );
1252f860a780SAmine Khaldi     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1253f860a780SAmine Khaldi     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1254c2c66affSColin Finck 
1255c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
1256c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1257c2c66affSColin Finck     {
1258c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1259c2c66affSColin Finck         DeleteFileA(msifile);
1260c2c66affSColin Finck         return;
1261c2c66affSColin Finck     }
1262c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1263c2c66affSColin Finck 
1264c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1265c2c66affSColin Finck 
1266c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
1267c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
1268c2c66affSColin Finck 
1269c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
1270c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
1271c2c66affSColin Finck 
1272c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
1273c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1274c2c66affSColin Finck 
1275c2c66affSColin Finck     buffer[0] = 0;
1276c2c66affSColin Finck     sz = sizeof(buffer);
1277c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1278c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1279c2c66affSColin Finck     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1280c2c66affSColin Finck 
1281c2c66affSColin Finck     r = MsiSetTargetPathA( 0, NULL, NULL );
1282c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1283c2c66affSColin Finck 
1284c2c66affSColin Finck     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1285c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1286c2c66affSColin Finck 
1287c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1288c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1289c2c66affSColin Finck 
1290c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1291c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1292c2c66affSColin Finck 
1293c2c66affSColin Finck     sz = sizeof tempdir - 1;
1294c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1295c2c66affSColin Finck     sprintf( file, "%srootfile.txt", tempdir );
1296c2c66affSColin Finck     buffer[0] = 0;
1297c2c66affSColin Finck     query_file_path( hpkg, "[#RootFile]", buffer );
1298c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1299c2c66affSColin Finck     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1300c2c66affSColin Finck 
1301c2c66affSColin Finck     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1302c2c66affSColin Finck     sprintf( tempdir, "%s\\subdir", buffer );
1303c2c66affSColin Finck 
1304c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1305c2c66affSColin Finck     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1306c2c66affSColin Finck         "MsiSetTargetPath on file returned %d\n", r );
1307c2c66affSColin Finck 
1308c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1309c2c66affSColin Finck     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1310c2c66affSColin Finck         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1311c2c66affSColin Finck 
1312c2c66affSColin Finck     DeleteFileA( buffer );
1313c2c66affSColin Finck 
1314c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1315c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1316c2c66affSColin Finck 
1317c2c66affSColin Finck     r = GetFileAttributesA( buffer );
1318c2c66affSColin Finck     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1319c2c66affSColin Finck 
1320c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1321c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1322c2c66affSColin Finck 
1323c2c66affSColin Finck     buffer[0] = 0;
1324c2c66affSColin Finck     sz = sizeof buffer - 1;
1325c2c66affSColin Finck     lstrcatA( tempdir, "\\" );
1326c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1327c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1328c2c66affSColin Finck     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     sprintf( file, "%srootfile.txt", tempdir );
1331c2c66affSColin Finck     query_file_path( hpkg, "[#RootFile]", buffer );
1332c2c66affSColin Finck     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1333c2c66affSColin Finck 
1334c2c66affSColin Finck     buffer[0] = 0;
1335c2c66affSColin Finck     sz = sizeof(buffer);
1336c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1337c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1338c2c66affSColin Finck     lstrcatA( tempdir, "TestParent\\" );
1339c2c66affSColin Finck     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1340c2c66affSColin Finck 
1341c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1342c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1343c2c66affSColin Finck 
1344c2c66affSColin Finck     buffer[0] = 0;
1345c2c66affSColin Finck     sz = sizeof(buffer);
1346c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1347c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1348c2c66affSColin Finck     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1349c2c66affSColin Finck         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1350c2c66affSColin Finck 
1351c2c66affSColin Finck     buffer[0] = 0;
1352c2c66affSColin Finck     query_file_path( hpkg, "[#TestFile]", buffer );
1353c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1354c2c66affSColin Finck         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1355c2c66affSColin Finck 
1356c2c66affSColin Finck     buffer[0] = 0;
1357c2c66affSColin Finck     sz = sizeof buffer - 1;
1358c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1359c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1360c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1361c2c66affSColin Finck 
1362c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1363c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1364c2c66affSColin Finck 
1365c2c66affSColin Finck     buffer[0] = 0;
1366c2c66affSColin Finck     sz = sizeof buffer - 1;
1367c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1368c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1369c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1370c2c66affSColin Finck 
1371c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1372c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1373c2c66affSColin Finck 
1374c2c66affSColin Finck     buffer[0] = 0;
1375c2c66affSColin Finck     sz = sizeof buffer - 1;
1376c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1377c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1378c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1379c2c66affSColin Finck 
1380c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1381c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1382c2c66affSColin Finck 
1383c2c66affSColin Finck     buffer[0] = 0;
1384c2c66affSColin Finck     sz = sizeof buffer - 1;
1385c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1386c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1387c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1388c2c66affSColin Finck 
1389c2c66affSColin Finck     MsiCloseHandle( hpkg );
1390c2c66affSColin Finck }
1391c2c66affSColin Finck 
1392c2c66affSColin Finck static void test_condition(void)
1393c2c66affSColin Finck {
1394c2c66affSColin Finck     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1395c2c66affSColin Finck     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1396c2c66affSColin Finck     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1397c2c66affSColin Finck     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1398c2c66affSColin Finck     MSICONDITION r;
1399c2c66affSColin Finck     MSIHANDLE hpkg;
1400c2c66affSColin Finck 
1401c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1402c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1403c2c66affSColin Finck     {
1404c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1405c2c66affSColin Finck         DeleteFileA(msifile);
1406c2c66affSColin Finck         return;
1407c2c66affSColin Finck     }
1408c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1409c2c66affSColin Finck 
1410c2c66affSColin Finck     r = MsiEvaluateConditionA(0, NULL);
1411c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1412c2c66affSColin Finck 
1413c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, NULL);
1414c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1415c2c66affSColin Finck 
1416c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "");
1417c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1418c2c66affSColin Finck 
1419c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1");
1420c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1421c2c66affSColin Finck 
1422c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0");
1423c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1424c2c66affSColin Finck 
1425c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "-1");
1426c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1427c2c66affSColin Finck 
1428c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1429c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1430c2c66affSColin Finck 
1431c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1432c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1433c2c66affSColin Finck 
1434c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1435c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1436c2c66affSColin Finck 
1437c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1438c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1439c2c66affSColin Finck 
1440c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1441c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1442c2c66affSColin Finck 
1443c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1444c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1445c2c66affSColin Finck 
1446c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1447c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1448c2c66affSColin Finck 
1449c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1450c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1451c2c66affSColin Finck 
1452c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1453c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1454c2c66affSColin Finck 
1455c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1456c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1457c2c66affSColin Finck 
1458c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1459c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1460c2c66affSColin Finck 
1461c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1462c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1463c2c66affSColin Finck 
1464c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1465c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1466c2c66affSColin Finck 
1467c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1468c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1469c2c66affSColin Finck 
1470c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1471c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1472c2c66affSColin Finck 
1473c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1474c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1475c2c66affSColin Finck 
1476c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1477c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1478c2c66affSColin Finck 
1479c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1480c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1481c2c66affSColin Finck 
1482c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1483c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1484c2c66affSColin Finck 
1485c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 >=");
1486c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1487c2c66affSColin Finck 
1488c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " ");
1489c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1490c2c66affSColin Finck 
1491c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1492c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1493c2c66affSColin Finck 
1494c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1495c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1496c2c66affSColin Finck 
1497c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1498c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1499c2c66affSColin Finck 
1500c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0");
1501c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1502c2c66affSColin Finck 
1503c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not LicView");
1504c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1505c2c66affSColin Finck 
1506c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1507c2c66affSColin Finck     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1508c2c66affSColin Finck 
1509c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1510c2c66affSColin Finck     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1511c2c66affSColin Finck 
1512c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1513c2c66affSColin Finck     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1514c2c66affSColin Finck 
1515c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1516c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1517c2c66affSColin Finck 
1518c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1519c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1520c2c66affSColin Finck 
1521c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1522c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1523c2c66affSColin Finck 
1524c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1525c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1526c2c66affSColin Finck 
1527c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1528c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1529c2c66affSColin Finck 
1530c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1531c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1532c2c66affSColin Finck 
1533c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1534c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1535c2c66affSColin Finck 
1536c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(0)");
1537c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1538c2c66affSColin Finck 
1539c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1540c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1541c2c66affSColin Finck 
1542c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1543c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1544c2c66affSColin Finck 
1545c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1546c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1547c2c66affSColin Finck 
1548c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1549c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1550c2c66affSColin Finck 
1551c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1552c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1553c2c66affSColin Finck 
1554c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1555c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1556c2c66affSColin Finck 
1557c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1558c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1559c2c66affSColin Finck 
1560c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1561c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1562c2c66affSColin Finck 
1563c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1564c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1565c2c66affSColin Finck 
1566c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1567c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1568c2c66affSColin Finck 
1569c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1570c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1571c2c66affSColin Finck 
1572c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1573c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1574c2c66affSColin Finck 
1575c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1576c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1577c2c66affSColin Finck 
1578c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1579c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1580c2c66affSColin Finck 
1581c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1582c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1583c2c66affSColin Finck 
1584c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1585c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1586c2c66affSColin Finck 
1587c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1588c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1589c2c66affSColin Finck 
1590c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1591c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1592c2c66affSColin Finck 
1593c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1594c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1595c2c66affSColin Finck 
1596c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1597c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1598c2c66affSColin Finck 
1599c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1600c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1601c2c66affSColin Finck 
1602c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1603c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1604c2c66affSColin Finck 
1605c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1606c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1607c2c66affSColin Finck 
1608c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1609c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1610c2c66affSColin Finck 
1611c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1612c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1613c2c66affSColin Finck 
1614c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1615c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1616c2c66affSColin Finck 
1617c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1618c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1619c2c66affSColin Finck 
1620c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1621c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1622c2c66affSColin Finck 
1623c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1624c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1625c2c66affSColin Finck 
1626c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1627c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1628c2c66affSColin Finck 
1629c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1630c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1631c2c66affSColin Finck 
1632c2c66affSColin Finck     MsiSetPropertyA(hpkg, "mm", "5" );
1633c2c66affSColin Finck 
1634c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1635c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1636c2c66affSColin Finck 
1637c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1638c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1639c2c66affSColin Finck 
1640c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1641c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1642c2c66affSColin Finck 
1643c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1644c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1645c2c66affSColin Finck 
1646c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1647c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1648c2c66affSColin Finck 
1649c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1650c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1651c2c66affSColin Finck 
1652c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1653c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1654c2c66affSColin Finck 
1655c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1656c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1657c2c66affSColin Finck 
1658c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1659c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1660c2c66affSColin Finck 
1661c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1662c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1663c2c66affSColin Finck 
1664c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1665c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1666c2c66affSColin Finck 
1667c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1668c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1669c2c66affSColin Finck 
1670c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1671c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1672c2c66affSColin Finck 
1673c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1674c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1675c2c66affSColin Finck 
1676c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1677c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1678c2c66affSColin Finck 
1679c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1680c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1681c2c66affSColin Finck 
1682c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1683c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1684c2c66affSColin Finck 
1685c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1686c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1687c2c66affSColin Finck 
1688c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1689c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1690c2c66affSColin Finck 
1691c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1692c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1693c2c66affSColin Finck 
1694c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1695c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1696c2c66affSColin Finck 
1697c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1698c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1699c2c66affSColin Finck 
1700c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1701c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1702c2c66affSColin Finck 
1703c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1704c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1705c2c66affSColin Finck 
1706c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1707c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1708c2c66affSColin Finck 
1709c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1710c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1711c2c66affSColin Finck 
1712c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1713c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1714c2c66affSColin Finck 
1715c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1716c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1717c2c66affSColin Finck 
1718c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1719c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1720c2c66affSColin Finck 
1721c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1722c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1723c2c66affSColin Finck 
1724c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1725c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1726c2c66affSColin Finck 
1727c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1728c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1730c2c66affSColin Finck 
1731c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "" );
1732c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1733c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1734c2c66affSColin Finck 
1735c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1736c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1737c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1738c2c66affSColin Finck 
1739c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1740c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1741c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1742c2c66affSColin Finck 
1743c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1744c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1745c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1746c2c66affSColin Finck 
1747c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1748c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1749c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1750c2c66affSColin Finck 
1751c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1752c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1753c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1754c2c66affSColin Finck 
1755c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1756c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1757c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1758c2c66affSColin Finck 
1759c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1760c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1761c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1762c2c66affSColin Finck 
1763c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1764c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1765c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1766c2c66affSColin Finck 
1767c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1768c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1769c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1770c2c66affSColin Finck 
1771c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1772c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1773c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1774c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1775c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1776c2c66affSColin Finck 
1777c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1778c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1779c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1780c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1781c2c66affSColin Finck 
1782c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1783c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1784c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1785c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1786c2c66affSColin Finck 
1787c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hello");
1788c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1789c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1790c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1791c2c66affSColin Finck 
1792c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hellohithere");
1793c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1794c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1795c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1796c2c66affSColin Finck 
1797c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1798c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1799c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1800c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1801c2c66affSColin Finck 
1802c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1803c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1804c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1805c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1806c2c66affSColin Finck 
1807c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1808c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1809c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1810c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1811c2c66affSColin Finck 
1812c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1813c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1814c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1815c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1816c2c66affSColin Finck 
1817c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "one 1234");
1818c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1819c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1820c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1821c2c66affSColin Finck 
1822c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1823c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1824c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1825c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1826c2c66affSColin Finck 
1827c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1828c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1829c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1830c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1831c2c66affSColin Finck 
1832c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1833c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1834c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1835c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1836c2c66affSColin Finck 
1837c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1838c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1839c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1840c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1841c2c66affSColin Finck 
1842c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1843c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1844c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1845c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1846c2c66affSColin Finck 
1847c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1848c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1849c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1850c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1851c2c66affSColin Finck 
1852c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1853c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1854c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1855c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1856c2c66affSColin Finck 
1857c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1858c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1859c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1860c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1861c2c66affSColin Finck 
1862c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234 one");
1863c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1864c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1865c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1866c2c66affSColin Finck 
1867c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1868c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1869c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1870c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1871c2c66affSColin Finck 
1872c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1873c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1874c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1875c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1876c2c66affSColin Finck 
1877c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1878c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1879c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1880c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1881c2c66affSColin Finck 
1882c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1883c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1884c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1885c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1886c2c66affSColin Finck 
1887c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1888c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1889c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1890c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1891c2c66affSColin Finck 
1892c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1893c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1894c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1895c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1896c2c66affSColin Finck 
1897c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1898c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1899c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1900c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1901c2c66affSColin Finck 
1902c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1903c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1904c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1905c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1906c2c66affSColin Finck 
1907c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1908c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "4");
1909c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1910c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1911c2c66affSColin Finck 
1912c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "one 1234");
1913c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "4");
1914c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1915c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1916c2c66affSColin Finck 
1917c2c66affSColin Finck     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1918c2c66affSColin Finck 
1919c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1920c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1921c2c66affSColin Finck 
1922c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1923c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1924c2c66affSColin Finck 
1925c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1926c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1927c2c66affSColin Finck 
1928c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1929c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1930c2c66affSColin Finck 
1931c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1932c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1933c2c66affSColin Finck 
1934c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1935c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1936c2c66affSColin Finck 
1937c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1938c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1939c2c66affSColin Finck 
1940c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1941c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1942c2c66affSColin Finck 
1943c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1944c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1945c2c66affSColin Finck 
1946c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1947c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1948c2c66affSColin Finck 
1949c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1950c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1951c2c66affSColin Finck 
1952c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1953c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1954c2c66affSColin Finck 
1955c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1956c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1957c2c66affSColin Finck 
1958c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1959c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1960c2c66affSColin Finck 
1961c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1962c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1963c2c66affSColin Finck 
1964c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1965c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1966c2c66affSColin Finck 
1967c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1968c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1969c2c66affSColin Finck 
1970c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1971c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1972c2c66affSColin Finck 
1973c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1974c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1975c2c66affSColin Finck 
1976c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1977c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1978c2c66affSColin Finck 
1979c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1980c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1981c2c66affSColin Finck 
1982c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1983c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1984c2c66affSColin Finck 
1985c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1986c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1987c2c66affSColin Finck 
1988c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1989c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1990c2c66affSColin Finck 
1991c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1992c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1993c2c66affSColin Finck 
1994c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1995c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1996c2c66affSColin Finck 
1997c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1998c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1999c2c66affSColin Finck 
2000c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
2001c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2002c2c66affSColin Finck 
2003c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
2004c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2005c2c66affSColin Finck 
2006c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
2007c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2008c2c66affSColin Finck 
2009c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
2010c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2011c2c66affSColin Finck 
2012c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
2013c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2014c2c66affSColin Finck 
2015c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
2016c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2017c2c66affSColin Finck 
2018c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
2019c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2020c2c66affSColin Finck 
2021c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
2022c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2023c2c66affSColin Finck 
2024c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
2025c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2026c2c66affSColin Finck 
2027c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
2028c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2029c2c66affSColin Finck 
2030c2c66affSColin Finck     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2031c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2032c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2033c2c66affSColin Finck 
2034c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2035c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2036c2c66affSColin Finck 
2037c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2038c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2039c2c66affSColin Finck 
2040c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2041c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2042c2c66affSColin Finck 
2043c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2044c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2045c2c66affSColin Finck 
2046c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1");
2047c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2048c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2049c2c66affSColin Finck 
2050c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "5.0");
2051c2c66affSColin Finck 
2052c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2053c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2054c2c66affSColin Finck 
2055c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2056c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2057c2c66affSColin Finck 
2058c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2059c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2060c2c66affSColin Finck 
2061c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2062c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2063c2c66affSColin Finck 
2064c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2065c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2066c2c66affSColin Finck 
2067c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2068c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2069c2c66affSColin Finck 
2070c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2071c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2072c2c66affSColin Finck 
2073c2c66affSColin Finck     /* feature doesn't exist */
2074c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2075c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2076f860a780SAmine Khaldi     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2077f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2078331be612Swinesync     r = MsiEvaluateConditionA(hpkg, "&nofeature<>3");
2079331be612Swinesync     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2080331be612Swinesync     r = MsiEvaluateConditionA(hpkg, "\"\"<>3");
2081331be612Swinesync     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2082f860a780SAmine Khaldi     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2083f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2084f51751ddSwinesync     r = MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2085f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2086f51751ddSwinesync     r = MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2087f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2088c2c66affSColin Finck 
2089c2c66affSColin Finck     MsiSetPropertyA(hpkg, "A", "2");
2090c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50");
2091c2c66affSColin Finck 
2092c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2093c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2094c2c66affSColin Finck 
2095c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2096c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2097c2c66affSColin Finck 
2098c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2099c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2100c2c66affSColin Finck 
2101c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50val");
2102c2c66affSColin Finck 
2103c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2104c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2105c2c66affSColin Finck 
2106c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2107c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2108c2c66affSColin Finck 
2109c2c66affSColin Finck     MsiSetPropertyA(hpkg, "A", "7");
2110c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50");
2111c2c66affSColin Finck 
2112c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2113c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2114c2c66affSColin Finck 
2115c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2116c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2117c2c66affSColin Finck 
2118c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2119c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2120c2c66affSColin Finck 
2121c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50val");
2122c2c66affSColin Finck 
2123c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2124c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2125c2c66affSColin Finck 
2126c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2127c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2128c2c66affSColin Finck 
2129c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond1);
2130c2c66affSColin Finck     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2131c2c66affSColin Finck         "wrong return val (%d)\n", r);
2132c2c66affSColin Finck 
2133c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond2);
2134c2c66affSColin Finck     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2135c2c66affSColin Finck         "wrong return val (%d)\n", r);
2136c2c66affSColin Finck 
2137c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond3);
2138c2c66affSColin Finck     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2139c2c66affSColin Finck         "wrong return val (%d)\n", r);
2140c2c66affSColin Finck 
2141c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond4);
2142c2c66affSColin Finck     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2143c2c66affSColin Finck         "wrong return val (%d)\n", r);
2144c2c66affSColin Finck 
2145c2c66affSColin Finck     MsiCloseHandle( hpkg );
2146c2c66affSColin Finck     DeleteFileA(msifile);
2147c2c66affSColin Finck }
2148c2c66affSColin Finck 
2149461c9cb7Swinesync static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect, int match_case)
2150c2c66affSColin Finck {
21513ec0ea99Swinesync     char buffer[MAX_PATH] = "x";
2152c2000429Swinesync     DWORD sz = sizeof(buffer);
2153c2000429Swinesync     UINT r = MsiGetPropertyA(hpkg, prop, buffer, &sz);
2154c2000429Swinesync     ok(!r, "'%s': got %u\n", prop, r);
2155c2000429Swinesync     ok(sz == lstrlenA(buffer), "'%s': expected %u, got %u\n", prop, lstrlenA(buffer), sz);
2156461c9cb7Swinesync     if (match_case)
21573ec0ea99Swinesync         ok(!strcmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2158461c9cb7Swinesync     else
2159461c9cb7Swinesync         ok(!_stricmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2160c2c66affSColin Finck }
2161c2c66affSColin Finck 
2162c2c66affSColin Finck static void test_props(void)
2163c2c66affSColin Finck {
216466669aedSwinesync     static const WCHAR booW[] = {'b','o','o',0};
216566669aedSwinesync     static const WCHAR xyzW[] = {'x','y','z',0};
216666669aedSwinesync     static const WCHAR xyW[] = {'x','y',0};
2167c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
2168c2c66affSColin Finck     UINT r;
2169c2c66affSColin Finck     DWORD sz;
2170c2c66affSColin Finck     char buffer[0x100];
217166669aedSwinesync     WCHAR bufferW[10];
2172c2c66affSColin Finck 
2173c2c66affSColin Finck     hdb = create_package_db();
2174c2c66affSColin Finck 
2175f860a780SAmine Khaldi     create_property_table(hdb);
2176f860a780SAmine Khaldi     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2177c2c66affSColin Finck 
2178c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
2179c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2180c2c66affSColin Finck     {
2181c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2182c2c66affSColin Finck         DeleteFileA(msifile);
2183c2c66affSColin Finck         return;
2184c2c66affSColin Finck     }
2185c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2186c2c66affSColin Finck 
2187c2c66affSColin Finck     /* test invalid values */
2188c2c66affSColin Finck     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2189c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2190c2c66affSColin Finck 
2191c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2192c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2193c2c66affSColin Finck 
2194c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2195c2000429Swinesync     ok(!r, "got %u\n", r);
2196c2c66affSColin Finck 
2197c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2198c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2199c2c66affSColin Finck 
2200c2c66affSColin Finck     /* test retrieving an empty/nonexistent property */
2201c2c66affSColin Finck     sz = sizeof buffer;
2202c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2203c2000429Swinesync     ok(!r, "got %u\n", r);
2204c2000429Swinesync     ok(sz == 0, "got size %d\n", sz);
2205c2c66affSColin Finck 
2206c2c66affSColin Finck     sz = 0;
2207c2c66affSColin Finck     strcpy(buffer,"x");
2208c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2209c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2210c2000429Swinesync     ok(!strcmp(buffer,"x"), "got \"%s\"\n", buffer);
2211c2000429Swinesync     ok(sz == 0, "got size %u\n", sz);
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     sz = 1;
2214c2c66affSColin Finck     strcpy(buffer,"x");
2215c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2216c2000429Swinesync     ok(!r, "got %u\n", r);
2217c2000429Swinesync     ok(!buffer[0], "got \"%s\"\n", buffer);
2218c2000429Swinesync     ok(sz == 0, "got size %u\n", sz);
2219c2c66affSColin Finck 
2220c2c66affSColin Finck     /* set the property to something */
2221c2c66affSColin Finck     r = MsiSetPropertyA( 0, NULL, NULL );
2222c2000429Swinesync     ok(r == ERROR_INVALID_HANDLE, "got %u\n", r);
2223c2c66affSColin Finck 
2224c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, NULL, NULL );
2225c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2226c2c66affSColin Finck 
2227c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "", NULL );
2228c2000429Swinesync     ok(!r, "got %u\n", r);
2229c2c66affSColin Finck 
2230c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "", "asdf" );
2231c2000429Swinesync     ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
2232c2c66affSColin Finck 
2233c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2234c2000429Swinesync     ok(!r, "got %u\n", r);
2235461c9cb7Swinesync     check_prop(hpkg, "=", "asdf", 1);
2236c2c66affSColin Finck 
2237c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2238c2000429Swinesync     ok(!r, "got %u\n", r);
2239461c9cb7Swinesync     check_prop(hpkg, " ", "asdf", 1);
2240c2c66affSColin Finck 
2241c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2242c2000429Swinesync     ok(!r, "got %u\n", r);
2243461c9cb7Swinesync     check_prop(hpkg, "'", "asdf", 1);
2244c2c66affSColin Finck 
2245c2c66affSColin Finck     /* set empty values */
2246c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", NULL );
2247c2000429Swinesync     ok(!r, "got %u\n", r);
2248461c9cb7Swinesync     check_prop(hpkg, "boo", "", 1);
2249c2c66affSColin Finck 
2250c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", "" );
2251c2000429Swinesync     ok(!r, "got %u\n", r);
2252461c9cb7Swinesync     check_prop(hpkg, "boo", "", 1);
2253c2c66affSColin Finck 
2254c2c66affSColin Finck     /* set a non-empty value */
2255c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2256c2000429Swinesync     ok(!r, "got %u\n", r);
2257461c9cb7Swinesync     check_prop(hpkg, "boo", "xyz", 1);
2258c2000429Swinesync 
2259c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", NULL, NULL);
2260c2000429Swinesync     ok(!r, "got %u\n", r);
2261c2000429Swinesync 
2262c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", buffer, NULL);
2263c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2264c2000429Swinesync 
2265c2000429Swinesync     sz = 0;
2266c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", NULL, &sz);
2267c2000429Swinesync     ok(!r, "got %u\n", r);
2268c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2269c2000429Swinesync 
2270c2000429Swinesync     sz = 0;
2271c2000429Swinesync     strcpy(buffer, "q");
2272c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", buffer, &sz);
2273c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2274c2000429Swinesync     ok(!strcmp(buffer, "q"), "got \"%s\"", buffer);
2275c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2276c2c66affSColin Finck 
2277c2c66affSColin Finck     sz = 1;
2278c2c66affSColin Finck     strcpy(buffer,"x");
2279c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2280c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2281c2000429Swinesync     ok(!buffer[0], "got \"%s\"\n", buffer);
2282c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2283c2c66affSColin Finck 
2284c2c66affSColin Finck     sz = 3;
2285c2c66affSColin Finck     strcpy(buffer,"x");
2286c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2287c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2288c2000429Swinesync     ok(!strcmp(buffer,"xy"), "got \"%s\"\n", buffer);
2289c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2290c2c66affSColin Finck 
2291c2c66affSColin Finck     sz = 4;
2292c2000429Swinesync     strcpy(buffer,"x");
2293c2000429Swinesync     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2294c2000429Swinesync     ok(!r, "got %u\n", r);
2295c2000429Swinesync     ok(!strcmp(buffer,"xyz"), "got \"%s\"\n", buffer);
2296c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2297c2c66affSColin Finck 
229866669aedSwinesync     sz = 0;
229966669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, NULL, &sz);
230066669aedSwinesync     ok(!r, "got %u\n", r);
230166669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
230266669aedSwinesync 
230366669aedSwinesync     sz = 0;
230466669aedSwinesync     lstrcpyW(bufferW, booW);
230566669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz);
230666669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
230766669aedSwinesync     ok(!lstrcmpW(bufferW, booW), "got %s\n", wine_dbgstr_w(bufferW));
230866669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
230966669aedSwinesync 
231066669aedSwinesync     sz = 1;
231166669aedSwinesync     lstrcpyW(bufferW, booW);
231266669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
231366669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
231466669aedSwinesync     ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
231566669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
231666669aedSwinesync 
231766669aedSwinesync     sz = 3;
231866669aedSwinesync     lstrcpyW(bufferW, booW);
231966669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
232066669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
232166669aedSwinesync     ok(!lstrcmpW(bufferW, xyW), "got %s\n", wine_dbgstr_w(bufferW));
232266669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
232366669aedSwinesync 
232466669aedSwinesync     sz = 4;
232566669aedSwinesync     lstrcpyW(bufferW, booW);
232666669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
232766669aedSwinesync     ok(!r, "got %u\n", r);
232866669aedSwinesync     ok(!lstrcmpW(bufferW, xyzW), "got %s\n", wine_dbgstr_w(bufferW));
232966669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
233066669aedSwinesync 
2331c2000429Swinesync     /* properties are case-sensitive */
2332461c9cb7Swinesync     check_prop(hpkg, "BOO", "", 1);
2333c2c66affSColin Finck 
2334c2000429Swinesync     /* properties set in Property table should work */
2335461c9cb7Swinesync     check_prop(hpkg, "MetadataCompName", "Photoshop.dll", 1);
2336c2c66affSColin Finck 
2337c2c66affSColin Finck     MsiCloseHandle( hpkg );
2338c2c66affSColin Finck     DeleteFileA(msifile);
2339c2c66affSColin Finck }
2340c2c66affSColin Finck 
2341c2c66affSColin Finck static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2342c2c66affSColin Finck {
2343c2c66affSColin Finck     MSIHANDLE hview, hrec;
2344c2c66affSColin Finck     BOOL found = FALSE;
2345c2c66affSColin Finck     CHAR buffer[MAX_PATH];
2346c2c66affSColin Finck     DWORD sz;
2347c2c66affSColin Finck     UINT r;
2348c2c66affSColin Finck 
2349c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2350c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2351c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
2352c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2353c2c66affSColin Finck 
2354c2c66affSColin Finck     if (len < 0) len = lstrlenA(val);
2355c2c66affSColin Finck 
2356c2c66affSColin Finck     while (r == ERROR_SUCCESS && !found)
2357c2c66affSColin Finck     {
2358c2c66affSColin Finck         r = MsiViewFetch(hview, &hrec);
2359c2c66affSColin Finck         if (r != ERROR_SUCCESS) break;
2360c2c66affSColin Finck 
2361c2c66affSColin Finck         sz = MAX_PATH;
2362c2c66affSColin Finck         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2363c2c66affSColin Finck         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2364c2c66affSColin Finck         {
2365c2c66affSColin Finck             sz = MAX_PATH;
2366c2c66affSColin Finck             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2367c2c66affSColin Finck             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2368c2c66affSColin Finck             {
2369c2c66affSColin Finck                 ok(sz == len, "wrong size %u\n", sz);
2370c2c66affSColin Finck                 found = TRUE;
2371c2c66affSColin Finck             }
2372c2c66affSColin Finck         }
2373c2c66affSColin Finck 
2374c2c66affSColin Finck         MsiCloseHandle(hrec);
2375c2c66affSColin Finck     }
2376c2c66affSColin Finck     MsiViewClose(hview);
2377c2c66affSColin Finck     MsiCloseHandle(hview);
2378c2c66affSColin Finck     return found;
2379c2c66affSColin Finck }
2380c2c66affSColin Finck 
2381c2c66affSColin Finck static void test_property_table(void)
2382c2c66affSColin Finck {
2383c2c66affSColin Finck     const char *query;
2384c2c66affSColin Finck     UINT r;
2385c2c66affSColin Finck     MSIHANDLE hpkg, hdb, hrec;
2386c2c66affSColin Finck     char buffer[MAX_PATH], package[10];
2387c2c66affSColin Finck     DWORD sz;
2388c2c66affSColin Finck     BOOL found;
2389c2c66affSColin Finck 
2390c2c66affSColin Finck     hdb = create_package_db();
2391c2c66affSColin Finck     ok( hdb, "failed to create package\n");
2392c2c66affSColin Finck 
2393c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
2394c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2395c2c66affSColin Finck     {
2396c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2397c2c66affSColin Finck         DeleteFileA(msifile);
2398c2c66affSColin Finck         return;
2399c2c66affSColin Finck     }
2400c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2401c2c66affSColin Finck 
2402c2c66affSColin Finck     MsiCloseHandle(hdb);
2403c2c66affSColin Finck 
2404c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
2405c2c66affSColin Finck 
2406c2c66affSColin Finck     query = "CREATE TABLE `_Property` ( "
2407c2c66affSColin Finck         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2408c2c66affSColin Finck     r = run_query(hdb, query);
2409c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2410c2c66affSColin Finck 
2411c2c66affSColin Finck     MsiCloseHandle(hdb);
2412c2c66affSColin Finck     MsiCloseHandle(hpkg);
2413c2c66affSColin Finck     DeleteFileA(msifile);
2414c2c66affSColin Finck 
2415c2c66affSColin Finck     hdb = create_package_db();
2416c2c66affSColin Finck     ok( hdb, "failed to create package\n");
2417c2c66affSColin Finck 
2418c2c66affSColin Finck     query = "CREATE TABLE `_Property` ( "
2419c2c66affSColin Finck         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2420c2c66affSColin Finck     r = run_query(hdb, query);
2421c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create table\n");
2422c2c66affSColin Finck 
2423c2c66affSColin Finck     query = "ALTER `_Property` ADD `foo` INTEGER";
2424c2c66affSColin Finck     r = run_query(hdb, query);
2425c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2426c2c66affSColin Finck 
2427c2c66affSColin Finck     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2428c2c66affSColin Finck     r = run_query(hdb, query);
2429c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2430c2c66affSColin Finck 
2431c2c66affSColin Finck     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2432c2c66affSColin Finck     r = run_query(hdb, query);
2433c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to add column\n");
2434c2c66affSColin Finck 
2435c2c66affSColin Finck     sprintf(package, "#%i", hdb);
2436c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
2437c2c66affSColin Finck     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2438c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2439c2c66affSColin Finck         MsiCloseHandle(hpkg);
2440c2c66affSColin Finck 
2441c2c66affSColin Finck     r = MsiCloseHandle(hdb);
2442c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2443c2c66affSColin Finck 
2444c2c66affSColin Finck     hdb = create_package_db();
2445c2c66affSColin Finck     ok (hdb, "failed to create package database\n");
2446c2c66affSColin Finck 
2447f860a780SAmine Khaldi     create_property_table(hdb);
2448f860a780SAmine Khaldi     add_property_entry(hdb, "'prop', 'val'");
2449c2c66affSColin Finck 
2450f860a780SAmine Khaldi     create_custom_action_table(hdb);
2451f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2452c2c66affSColin Finck 
2453c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
2454c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2455c2c66affSColin Finck 
2456c2c66affSColin Finck     MsiCloseHandle(hdb);
2457c2c66affSColin Finck 
2458c2c66affSColin Finck     sz = MAX_PATH;
2459c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2460c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2461c2c66affSColin Finck     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2462c2c66affSColin Finck 
2463c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
2464c2c66affSColin Finck 
2465c2c66affSColin Finck     found = find_prop_in_property(hdb, "prop", "val", -1);
2466c2c66affSColin Finck     ok(found, "prop should be in the _Property table\n");
2467c2c66affSColin Finck 
2468f860a780SAmine Khaldi     add_property_entry(hdb, "'dantes', 'mercedes'");
2469c2c66affSColin Finck 
2470c2c66affSColin Finck     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2471c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
2472c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2473c2c66affSColin Finck 
2474c2c66affSColin Finck     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2475c2c66affSColin Finck     ok(found == FALSE, "dantes should not be in the _Property table\n");
2476c2c66affSColin Finck 
2477c2c66affSColin Finck     sz = MAX_PATH;
2478c2c66affSColin Finck     lstrcpyA(buffer, "aaa");
2479c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2480c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2481c2c66affSColin Finck     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2482c2c66affSColin Finck 
2483c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2484c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2485c2c66affSColin Finck 
2486c2c66affSColin Finck     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2487c2c66affSColin Finck     ok(found == TRUE, "dantes should be in the _Property table\n");
2488c2c66affSColin Finck 
2489c2c66affSColin Finck     r = MsiDoActionA( hpkg, "EmbedNull" );
2490c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2491c2c66affSColin Finck 
2492c2c66affSColin Finck     sz = MAX_PATH;
2493c2c66affSColin Finck     memset( buffer, 'a', sizeof(buffer) );
2494c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2495c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2496c2c66affSColin Finck     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2497c2c66affSColin Finck     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2498c2c66affSColin Finck 
2499c2c66affSColin Finck     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2500c2c66affSColin Finck     ok(found == TRUE, "prop2 should be in the _Property table\n");
2501c2c66affSColin Finck 
2502c2c66affSColin Finck     MsiCloseHandle(hdb);
2503c2c66affSColin Finck     MsiCloseHandle(hpkg);
2504c2c66affSColin Finck     DeleteFileA(msifile);
2505c2c66affSColin Finck }
2506c2c66affSColin Finck 
2507c2c66affSColin Finck static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2508c2c66affSColin Finck {
2509c2c66affSColin Finck     MSIHANDLE htab = 0;
2510c2c66affSColin Finck     UINT res;
2511c2c66affSColin Finck 
2512c2c66affSColin Finck     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2513c2c66affSColin Finck     if( res == ERROR_SUCCESS )
2514c2c66affSColin Finck     {
2515c2c66affSColin Finck         UINT r;
2516c2c66affSColin Finck 
2517c2c66affSColin Finck         r = MsiViewExecute( htab, hrec );
2518c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2519c2c66affSColin Finck         {
2520c2c66affSColin Finck             res = r;
2521c2c66affSColin Finck             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2522c2c66affSColin Finck         }
2523c2c66affSColin Finck 
2524c2c66affSColin Finck         r = MsiViewClose( htab );
2525c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2526c2c66affSColin Finck             res = r;
2527c2c66affSColin Finck 
2528c2c66affSColin Finck         r = MsiCloseHandle( htab );
2529c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2530c2c66affSColin Finck             res = r;
2531c2c66affSColin Finck     }
2532c2c66affSColin Finck     return res;
2533c2c66affSColin Finck }
2534c2c66affSColin Finck 
2535c2c66affSColin Finck static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2536c2c66affSColin Finck {
2537c2c66affSColin Finck     return try_query_param( hdb, szQuery, 0 );
2538c2c66affSColin Finck }
2539c2c66affSColin Finck 
2540c2c66affSColin Finck static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2541c2c66affSColin Finck {
2542c2c66affSColin Finck     MSIHANDLE summary;
2543c2c66affSColin Finck     UINT r;
2544c2c66affSColin Finck 
2545c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2546c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2547c2c66affSColin Finck 
2548c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2549c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2550c2c66affSColin Finck 
2551c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
2552c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2553c2c66affSColin Finck 
2554c2c66affSColin Finck     MsiCloseHandle(summary);
2555c2c66affSColin Finck }
2556c2c66affSColin Finck 
2557c2c66affSColin Finck static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2558c2c66affSColin Finck {
2559c2c66affSColin Finck     MSIHANDLE summary;
2560c2c66affSColin Finck     UINT r;
2561c2c66affSColin Finck 
2562c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2563c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2564c2c66affSColin Finck 
2565c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2566c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2567c2c66affSColin Finck 
2568c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
2569c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2570c2c66affSColin Finck 
2571c2c66affSColin Finck     MsiCloseHandle(summary);
2572c2c66affSColin Finck }
2573c2c66affSColin Finck 
2574c2c66affSColin Finck static void test_msipackage(void)
2575c2c66affSColin Finck {
2576c2c66affSColin Finck     MSIHANDLE hdb = 0, hpack = 100;
2577c2c66affSColin Finck     UINT r;
2578c2c66affSColin Finck     const char *query;
2579c2c66affSColin Finck     char name[10];
2580c2c66affSColin Finck 
2581c2c66affSColin Finck     /* NULL szPackagePath */
2582c2c66affSColin Finck     r = MsiOpenPackageA(NULL, &hpack);
2583c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2584c2c66affSColin Finck 
2585c2c66affSColin Finck     /* empty szPackagePath */
2586c2c66affSColin Finck     r = MsiOpenPackageA("", &hpack);
2587c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2588c2c66affSColin Finck     {
2589c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2590c2c66affSColin Finck         return;
2591c2c66affSColin Finck     }
2592c2c66affSColin Finck     todo_wine
2593c2c66affSColin Finck     {
2594c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2595c2c66affSColin Finck     }
2596c2c66affSColin Finck 
2597c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2598c2c66affSColin Finck         MsiCloseHandle(hpack);
2599c2c66affSColin Finck 
2600c2c66affSColin Finck     /* nonexistent szPackagePath */
2601c2c66affSColin Finck     r = MsiOpenPackageA("nonexistent", &hpack);
2602c2c66affSColin Finck     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2603c2c66affSColin Finck 
2604c2c66affSColin Finck     /* NULL hProduct */
2605c2c66affSColin Finck     r = MsiOpenPackageA(msifile, NULL);
2606c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2607c2c66affSColin Finck 
2608c2c66affSColin Finck     name[0]='#';
2609c2c66affSColin Finck     name[1]=0;
2610c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2611c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2612c2c66affSColin Finck 
2613c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2614c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2615c2c66affSColin Finck 
2616c2c66affSColin Finck     /* database exists, but is empty */
2617c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2618c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2619c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2620c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2621c2c66affSColin Finck 
2622c2c66affSColin Finck     query = "CREATE TABLE `Property` ( "
2623c2c66affSColin Finck             "`Property` CHAR(72), `Value` CHAR(0) "
2624c2c66affSColin Finck             "PRIMARY KEY `Property`)";
2625c2c66affSColin Finck     r = try_query(hdb, query);
2626c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2627c2c66affSColin Finck 
2628c2c66affSColin Finck     query = "CREATE TABLE `InstallExecuteSequence` ("
2629c2c66affSColin Finck             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2630c2c66affSColin Finck             "PRIMARY KEY `Action`)";
2631c2c66affSColin Finck     r = try_query(hdb, query);
2632c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2633c2c66affSColin Finck 
2634c2c66affSColin Finck     /* a few key tables exist */
2635c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2636c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2637c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2638c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2639c2c66affSColin Finck 
2640c2c66affSColin Finck     MsiCloseHandle(hdb);
2641c2c66affSColin Finck     DeleteFileA(msifile);
2642c2c66affSColin Finck 
2643c2c66affSColin Finck     /* start with a clean database to show what constitutes a valid package */
2644c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2645c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2646c2c66affSColin Finck 
2647c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2648c2c66affSColin Finck 
2649c2c66affSColin Finck     /* The following summary information props must exist:
2650c2c66affSColin Finck      *  - PID_REVNUMBER
2651c2c66affSColin Finck      *  - PID_PAGECOUNT
2652c2c66affSColin Finck      */
2653c2c66affSColin Finck 
2654c2c66affSColin Finck     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2655c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2656c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2657c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2658c2c66affSColin Finck 
2659c2c66affSColin Finck     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2660c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2661c2c66affSColin Finck     ok(r == ERROR_SUCCESS,
2662c2c66affSColin Finck        "Expected ERROR_SUCCESS, got %d\n", r);
2663c2c66affSColin Finck 
2664c2c66affSColin Finck     MsiCloseHandle(hpack);
2665c2c66affSColin Finck     MsiCloseHandle(hdb);
2666c2c66affSColin Finck     DeleteFileA(msifile);
2667c2c66affSColin Finck }
2668c2c66affSColin Finck 
2669c2c66affSColin Finck static void test_formatrecord2(void)
2670c2c66affSColin Finck {
2671c2c66affSColin Finck     MSIHANDLE hpkg, hrec ;
2672c2c66affSColin Finck     char buffer[0x100];
2673c2c66affSColin Finck     DWORD sz;
2674c2c66affSColin Finck     UINT r;
2675c2c66affSColin Finck 
2676c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
2677c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2678c2c66affSColin Finck     {
2679c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2680c2c66affSColin Finck         DeleteFileA(msifile);
2681c2c66affSColin Finck         return;
2682c2c66affSColin Finck     }
2683c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2684c2c66affSColin Finck 
2685c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2686c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "set property failed\n");
2687c2c66affSColin Finck 
2688c2c66affSColin Finck     hrec = MsiCreateRecord(2);
2689c2c66affSColin Finck     ok(hrec, "create record failed\n");
2690c2c66affSColin Finck 
2691c2c66affSColin Finck     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2692c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format record failed\n");
2693c2c66affSColin Finck 
2694c2c66affSColin Finck     buffer[0] = 0;
2695c2c66affSColin Finck     sz = sizeof buffer;
2696c2c66affSColin Finck     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2697c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2698c2c66affSColin Finck 
2699c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2700c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2701c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "hoo");
2702c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2703c2c66affSColin Finck     sz = sizeof buffer;
2704c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2705c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2706c2c66affSColin Finck     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2707c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2708c2c66affSColin Finck 
2709c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2710c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2711c2c66affSColin Finck     sz = sizeof buffer;
2712c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2713c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2714c2c66affSColin Finck     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2715c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2716c2c66affSColin Finck 
2717c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2718c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2719c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "hoo");
2720c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2721c2c66affSColin Finck     sz = sizeof buffer;
2722c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2723c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2724c2c66affSColin Finck     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2725c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2726c2c66affSColin Finck 
2727c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2728c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2729c2c66affSColin Finck     sz = sizeof buffer;
2730c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2731c2c66affSColin Finck     ok( sz == 1, "size wrong\n");
2732c2c66affSColin Finck     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2733c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2734c2c66affSColin Finck 
2735c2c66affSColin Finck     SetEnvironmentVariableA("FOO", "BAR");
2736c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2737c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2738c2c66affSColin Finck     sz = sizeof buffer;
2739c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2740c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2741c2c66affSColin Finck     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2742c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2743c2c66affSColin Finck 
2744c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2745c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2746c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2747c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2748c2c66affSColin Finck     sz = sizeof buffer;
2749c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2750c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2751c2c66affSColin Finck     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2752c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2753c2c66affSColin Finck 
2754c2c66affSColin Finck     MsiCloseHandle( hrec );
2755c2c66affSColin Finck     MsiCloseHandle( hpkg );
2756c2c66affSColin Finck     DeleteFileA(msifile);
2757c2c66affSColin Finck }
2758c2c66affSColin Finck 
2759f860a780SAmine Khaldi static void test_formatrecord_tables(void)
2760f860a780SAmine Khaldi {
2761f860a780SAmine Khaldi     MSIHANDLE hdb, hrec, hpkg = 0;
2762f860a780SAmine Khaldi     CHAR buf[MAX_PATH];
2763f860a780SAmine Khaldi     CHAR curr_dir[MAX_PATH];
2764f860a780SAmine Khaldi     CHAR expected[MAX_PATH];
2765f860a780SAmine Khaldi     CHAR root[MAX_PATH];
2766f860a780SAmine Khaldi     DWORD size;
2767f860a780SAmine Khaldi     UINT r;
2768f860a780SAmine Khaldi 
2769f860a780SAmine Khaldi     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2770f860a780SAmine Khaldi 
2771f860a780SAmine Khaldi     hdb = create_package_db();
2772f860a780SAmine Khaldi     ok ( hdb, "failed to create package database\n");
2773f860a780SAmine Khaldi 
2774f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2775f860a780SAmine Khaldi     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2776f860a780SAmine Khaldi                              "'I am a really long directory'" );
2777f860a780SAmine Khaldi 
2778f860a780SAmine Khaldi     create_feature_table( hdb );
2779f860a780SAmine Khaldi     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2780f860a780SAmine Khaldi 
2781f860a780SAmine Khaldi     create_component_table( hdb );
2782f860a780SAmine Khaldi     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2783f860a780SAmine Khaldi     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2784f860a780SAmine Khaldi     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2785f860a780SAmine Khaldi 
2786f860a780SAmine Khaldi     create_feature_components_table( hdb );
2787f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2788f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2789f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2790f860a780SAmine Khaldi 
2791f860a780SAmine Khaldi     create_file_table( hdb );
2792f860a780SAmine Khaldi     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2793f860a780SAmine Khaldi     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2794f860a780SAmine Khaldi     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2795f860a780SAmine Khaldi 
2796f860a780SAmine Khaldi     create_custom_action_table( hdb );
2797f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2798f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2799f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2800f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2801f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2802f860a780SAmine Khaldi 
2803f860a780SAmine Khaldi     r = package_from_db( hdb, &hpkg );
2804f860a780SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2805f860a780SAmine Khaldi     {
2806f860a780SAmine Khaldi         skip("Not enough rights to perform tests\n");
2807f860a780SAmine Khaldi         MsiCloseHandle( hdb );
2808f860a780SAmine Khaldi         DeleteFileA( msifile );
2809f860a780SAmine Khaldi         return;
2810f860a780SAmine Khaldi     }
2811f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2812f860a780SAmine Khaldi 
2813f860a780SAmine Khaldi     MsiCloseHandle( hdb );
2814f860a780SAmine Khaldi 
2815f860a780SAmine Khaldi     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2816f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2817f860a780SAmine Khaldi 
2818f860a780SAmine Khaldi     hrec = MsiCreateRecord( 1 );
2819f860a780SAmine Khaldi 
2820f860a780SAmine Khaldi     /* property doesn't exist */
2821f860a780SAmine Khaldi     size = MAX_PATH;
2822f860a780SAmine Khaldi     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2823f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2824f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2825f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2826f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2827f860a780SAmine Khaldi 
2828f860a780SAmine Khaldi     /* property exists */
2829f860a780SAmine Khaldi     size = MAX_PATH;
2830f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2831f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2832f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2833f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2834f860a780SAmine Khaldi 
2835f860a780SAmine Khaldi     size = MAX_PATH;
2836f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2837f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2838f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2839f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2840f860a780SAmine Khaldi 
2841f860a780SAmine Khaldi     /* environment variable doesn't exist */
2842f860a780SAmine Khaldi     size = MAX_PATH;
2843f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2844f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2845f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2846f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2847f860a780SAmine Khaldi 
2848f860a780SAmine Khaldi     /* environment variable exists */
2849f860a780SAmine Khaldi     size = MAX_PATH;
2850f860a780SAmine Khaldi     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2851f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2852f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2853f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2854f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2855f860a780SAmine Khaldi 
2856f860a780SAmine Khaldi     /* file key before CostInitialize */
2857f860a780SAmine Khaldi     size = MAX_PATH;
2858f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2859f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2860f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2861f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2862f860a780SAmine Khaldi 
2863f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2864f860a780SAmine Khaldi 
2865f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "CostInitialize");
2866f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2867f860a780SAmine Khaldi 
2868f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "FileCost");
2869f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2870f860a780SAmine Khaldi 
2871f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "CostFinalize");
2872f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2873f860a780SAmine Khaldi 
2874f860a780SAmine Khaldi     size = MAX_PATH;
2875f860a780SAmine Khaldi     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2876f860a780SAmine Khaldi 
2877f860a780SAmine Khaldi     sprintf( expected, "1: %sfrontal.txt ", root);
2878f860a780SAmine Khaldi 
2879f860a780SAmine Khaldi     /* frontal full file key */
2880f860a780SAmine Khaldi     size = MAX_PATH;
2881f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2882f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2883f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2884f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2885f860a780SAmine Khaldi 
2886f860a780SAmine Khaldi     /* frontal short file key */
2887f860a780SAmine Khaldi     size = MAX_PATH;
2888f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2889f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2890f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2891f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2892f860a780SAmine Khaldi 
2893f860a780SAmine Khaldi     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2894f860a780SAmine Khaldi 
2895f860a780SAmine Khaldi     /* temporal full file key */
2896f860a780SAmine Khaldi     size = MAX_PATH;
2897f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2898f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2899f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2900f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2901f860a780SAmine Khaldi 
2902f860a780SAmine Khaldi     /* temporal short file key */
2903f860a780SAmine Khaldi     size = MAX_PATH;
2904f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2905f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2906f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2907f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2908f860a780SAmine Khaldi 
2909f860a780SAmine Khaldi     /* custom action 51, files don't exist */
2910f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "MyCustom" );
2911f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2912f860a780SAmine Khaldi 
2913f860a780SAmine Khaldi     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2914f860a780SAmine Khaldi 
2915f860a780SAmine Khaldi     size = MAX_PATH;
2916f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2917f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2918f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2919f860a780SAmine Khaldi 
2920f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory", root );
2921f860a780SAmine Khaldi     CreateDirectoryA( buf, NULL );
2922f860a780SAmine Khaldi 
2923f860a780SAmine Khaldi     lstrcatA( buf, "\\temporal.txt" );
2924f860a780SAmine Khaldi     create_test_file( buf );
2925f860a780SAmine Khaldi 
2926f860a780SAmine Khaldi     /* custom action 51, files exist */
2927f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "MyCustom" );
2928f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2929f860a780SAmine Khaldi 
2930f860a780SAmine Khaldi     size = MAX_PATH;
2931f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2932f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2933f860a780SAmine Khaldi     todo_wine
2934f860a780SAmine Khaldi     {
2935f860a780SAmine Khaldi         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2936f860a780SAmine Khaldi     }
2937f860a780SAmine Khaldi 
2938f860a780SAmine Khaldi     /* custom action 51, escaped text 1 */
2939f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt1" );
2940f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2941f860a780SAmine Khaldi 
2942f860a780SAmine Khaldi     size = MAX_PATH;
2943f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2944f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2945f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2946f860a780SAmine Khaldi 
2947f860a780SAmine Khaldi     /* custom action 51, escaped text 2 */
2948f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt2" );
2949f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2950f860a780SAmine Khaldi 
2951f860a780SAmine Khaldi     size = MAX_PATH;
2952f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2953f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2954f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2955f860a780SAmine Khaldi 
2956f860a780SAmine Khaldi     /* custom action 51, escaped text 3 */
2957f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt3" );
2958f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2959f860a780SAmine Khaldi 
2960f860a780SAmine Khaldi     size = MAX_PATH;
2961f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2962f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2963f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2964f860a780SAmine Khaldi 
2965f860a780SAmine Khaldi     /* custom action 51, embedded null */
2966f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EmbedNull" );
2967f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2968f860a780SAmine Khaldi 
2969f860a780SAmine Khaldi     size = MAX_PATH;
2970f860a780SAmine Khaldi     memset( buf, 'a', sizeof(buf) );
2971f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2972f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2973f860a780SAmine Khaldi     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2974f860a780SAmine Khaldi     ok( size == sizeof("\0np") - 1, "got %u\n", size );
2975f860a780SAmine Khaldi 
2976f860a780SAmine Khaldi     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2977f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2978f860a780SAmine Khaldi 
2979f860a780SAmine Khaldi     size = MAX_PATH;
2980f860a780SAmine Khaldi     memset( buf, 'a', sizeof(buf) );
2981f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2982f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2983f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2984f860a780SAmine Khaldi 
2985f860a780SAmine Khaldi     sprintf( expected, "1: %sI am a really long directory\\ ", root);
2986f860a780SAmine Khaldi 
2987f860a780SAmine Khaldi     /* component with INSTALLSTATE_LOCAL */
2988f860a780SAmine Khaldi     size = MAX_PATH;
2989f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2990f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2991f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2992f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2993f860a780SAmine Khaldi 
2994f860a780SAmine Khaldi     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2995f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2996f860a780SAmine Khaldi 
2997f860a780SAmine Khaldi     /* component with INSTALLSTATE_SOURCE */
2998f860a780SAmine Khaldi     lstrcpyA( expected, "1: " );
2999f860a780SAmine Khaldi     lstrcatA( expected, curr_dir );
3000f860a780SAmine Khaldi     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
3001f860a780SAmine Khaldi     lstrcatA( expected, " " );
3002f860a780SAmine Khaldi     size = MAX_PATH;
3003f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
3004f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
3005f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
3006f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
3007f860a780SAmine Khaldi 
3008f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
3009f860a780SAmine Khaldi     DeleteFileA( buf );
3010f860a780SAmine Khaldi 
3011f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory", root );
3012f860a780SAmine Khaldi     RemoveDirectoryA( buf );
3013f860a780SAmine Khaldi 
3014f860a780SAmine Khaldi     MsiCloseHandle( hrec );
3015f860a780SAmine Khaldi     MsiCloseHandle( hpkg );
3016f860a780SAmine Khaldi     DeleteFileA( msifile );
3017f860a780SAmine Khaldi }
3018f860a780SAmine Khaldi 
3019c2c66affSColin Finck static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
3020c2c66affSColin Finck                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3021c2c66affSColin Finck {
3022c2c66affSColin Finck     UINT r;
3023c2c66affSColin Finck     INSTALLSTATE state = 0xdeadbee;
3024c2c66affSColin Finck     INSTALLSTATE action = 0xdeadbee;
3025c2c66affSColin Finck 
3026c2c66affSColin Finck     r = MsiGetFeatureStateA( package, feature, &state, &action );
3027c2c66affSColin Finck     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3028c2c66affSColin Finck     if (r == ERROR_SUCCESS)
3029c2c66affSColin Finck     {
3030c2c66affSColin Finck         ok( state == expected_state, "%u: expected state %d got %d\n",
3031c2c66affSColin Finck             line, expected_state, state );
3032c2c66affSColin Finck         todo_wine_if (todo)
3033c2c66affSColin Finck             ok( action == expected_action, "%u: expected action %d got %d\n",
3034c2c66affSColin Finck                 line, expected_action, action );
3035c2c66affSColin Finck     }
3036c2c66affSColin Finck     else
3037c2c66affSColin Finck     {
3038c2c66affSColin Finck         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3039c2c66affSColin Finck         todo_wine_if (todo)
3040c2c66affSColin Finck             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3041c2c66affSColin Finck 
3042c2c66affSColin Finck     }
3043c2c66affSColin Finck }
3044c2c66affSColin Finck 
3045c2c66affSColin Finck static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3046c2c66affSColin Finck                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3047c2c66affSColin Finck {
3048c2c66affSColin Finck     UINT r;
3049c2c66affSColin Finck     INSTALLSTATE state = 0xdeadbee;
3050c2c66affSColin Finck     INSTALLSTATE action = 0xdeadbee;
3051c2c66affSColin Finck 
3052c2c66affSColin Finck     r = MsiGetComponentStateA( package, component, &state, &action );
3053c2c66affSColin Finck     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3054c2c66affSColin Finck     if (r == ERROR_SUCCESS)
3055c2c66affSColin Finck     {
3056c2c66affSColin Finck         ok( state == expected_state, "%u: expected state %d got %d\n",
3057c2c66affSColin Finck             line, expected_state, state );
3058c2c66affSColin Finck         todo_wine_if (todo)
3059c2c66affSColin Finck             ok( action == expected_action, "%u: expected action %d got %d\n",
3060c2c66affSColin Finck                 line, expected_action, action );
3061c2c66affSColin Finck     }
3062c2c66affSColin Finck     else
3063c2c66affSColin Finck     {
3064c2c66affSColin Finck         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3065c2c66affSColin Finck             line, state );
3066c2c66affSColin Finck         todo_wine_if (todo)
3067c2c66affSColin Finck             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3068c2c66affSColin Finck                 line, action );
3069c2c66affSColin Finck     }
3070c2c66affSColin Finck }
3071c2c66affSColin Finck 
3072c2c66affSColin Finck static void test_states(void)
3073c2c66affSColin Finck {
3074c2c66affSColin Finck     static const char msifile2[] = "winetest2-package.msi";
3075c2c66affSColin Finck     static const char msifile3[] = "winetest3-package.msi";
3076c2c66affSColin Finck     static const char msifile4[] = "winetest4-package.msi";
3077c2c66affSColin Finck     static const WCHAR msifile2W[] =
3078c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
3079c2c66affSColin Finck     static const WCHAR msifile3W[] =
3080c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
3081c2c66affSColin Finck     static const WCHAR msifile4W[] =
3082c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
3083f860a780SAmine Khaldi     char msi_cache_file[MAX_PATH];
3084f860a780SAmine Khaldi     DWORD cache_file_name_len;
3085c2c66affSColin Finck     INSTALLSTATE state;
308696486643Swinesync     MSIHANDLE hpkg, hprod;
3087c2c66affSColin Finck     UINT r;
3088c2c66affSColin Finck     MSIHANDLE hdb;
3089f860a780SAmine Khaldi     BOOL is_broken;
309096486643Swinesync     char value[MAX_PATH];
309196486643Swinesync     DWORD size;
3092c2c66affSColin Finck 
3093c2c66affSColin Finck     if (is_process_limited())
3094c2c66affSColin Finck     {
3095c2c66affSColin Finck         skip("process is limited\n");
3096c2c66affSColin Finck         return;
3097c2c66affSColin Finck     }
3098c2c66affSColin Finck 
3099c2c66affSColin Finck     hdb = create_package_db();
3100c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3101c2c66affSColin Finck 
3102f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3103c2c66affSColin Finck 
3104f860a780SAmine Khaldi     create_property_table( hdb );
3105f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3106f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductLanguage', '1033'" );
3107f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3108f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3109f860a780SAmine Khaldi     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
311096486643Swinesync     add_property_entry( hdb, "'UpgradeCode', '{3494EEEA-4221-4A66-802E-DED8916BC5C5}'" );
3111c2c66affSColin Finck 
3112f860a780SAmine Khaldi     create_install_execute_sequence_table( hdb );
3113f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3114f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3115f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3116f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3117f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3118f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3119f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3120f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3121f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3122f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3123f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3124c2c66affSColin Finck 
3125f860a780SAmine Khaldi     create_media_table( hdb );
3126f860a780SAmine Khaldi     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3127c2c66affSColin Finck 
3128f860a780SAmine Khaldi     create_feature_table( hdb );
3129c2c66affSColin Finck 
3130f860a780SAmine Khaldi     create_component_table( hdb );
3131c2c66affSColin Finck 
3132c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3133f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3134c2c66affSColin Finck 
3135c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3136f860a780SAmine Khaldi     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3137c2c66affSColin Finck 
3138c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3139f860a780SAmine Khaldi     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3140c2c66affSColin Finck 
3141c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3142f860a780SAmine Khaldi     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3143c2c66affSColin Finck 
3144c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3145f860a780SAmine Khaldi     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3146c2c66affSColin Finck 
3147c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3148f860a780SAmine Khaldi     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3149c2c66affSColin Finck 
3150c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3151f860a780SAmine Khaldi     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3152c2c66affSColin Finck 
3153c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3154f860a780SAmine Khaldi     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3155c2c66affSColin Finck 
3156c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3157f860a780SAmine Khaldi     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3158c2c66affSColin Finck 
3159c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3160f860a780SAmine Khaldi     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3161c2c66affSColin Finck 
3162c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3163f860a780SAmine Khaldi     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3164c2c66affSColin Finck 
3165c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3166f860a780SAmine Khaldi     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3167c2c66affSColin Finck 
3168c2c66affSColin Finck     /* disabled */
3169f860a780SAmine Khaldi     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3170c2c66affSColin Finck 
3171c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3172f860a780SAmine Khaldi     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3173c2c66affSColin Finck 
3174c2c66affSColin Finck     /* no feature parent:msidbComponentAttributesLocalOnly */
3175f860a780SAmine Khaldi     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3176c2c66affSColin Finck 
3177c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed */
3178f860a780SAmine Khaldi     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3179c2c66affSColin Finck 
3180c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3181f860a780SAmine Khaldi     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3182c2c66affSColin Finck 
3183c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3184f860a780SAmine Khaldi     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3185c2c66affSColin Finck 
3186c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3187f860a780SAmine Khaldi     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3188c2c66affSColin Finck 
3189c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3190f860a780SAmine Khaldi     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3191c2c66affSColin Finck 
3192c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed */
3193f860a780SAmine Khaldi     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3194c2c66affSColin Finck 
3195c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3196f860a780SAmine Khaldi     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3197c2c66affSColin Finck 
3198c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3199f860a780SAmine Khaldi     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3200c2c66affSColin Finck 
3201c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3202f860a780SAmine Khaldi     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3203c2c66affSColin Finck 
3204c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3205f860a780SAmine Khaldi     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3206c2c66affSColin Finck 
3207c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3208f860a780SAmine Khaldi     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3209c2c66affSColin Finck 
3210f860a780SAmine Khaldi     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3211c2c66affSColin Finck 
3212c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3213f860a780SAmine Khaldi     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3214c2c66affSColin Finck 
3215f860a780SAmine Khaldi     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3216c2c66affSColin Finck 
3217c2c66affSColin Finck     /* msidbFeatureAttributesFavorAdvertise */
3218f860a780SAmine Khaldi     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3219c2c66affSColin Finck 
3220f860a780SAmine Khaldi     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3221c2c66affSColin Finck 
3222c2c66affSColin Finck     /* msidbFeatureAttributesUIDisallowAbsent */
3223f860a780SAmine Khaldi     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3224c2c66affSColin Finck 
3225f860a780SAmine Khaldi     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3226c2c66affSColin Finck 
3227c2c66affSColin Finck     /* high install level */
3228f860a780SAmine Khaldi     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3229c2c66affSColin Finck 
3230f860a780SAmine Khaldi     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3231c2c66affSColin Finck 
3232c2c66affSColin Finck     /* msidbFeatureAttributesFollowParent */
3233f860a780SAmine Khaldi     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3234c2c66affSColin Finck 
3235f860a780SAmine Khaldi     create_feature_components_table( hdb );
3236f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'alpha'" );
3237f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'beta'" );
3238f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'gamma'" );
3239f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'theta'" );
3240f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'delta'" );
3241f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3242f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'zeta'" );
3243f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'iota'" );
3244f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'three', 'eta'" );
3245f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'four', 'eta'" );
3246f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'five', 'eta'" );
3247f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'lambda'" );
3248f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'mu'" );
3249f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'nu'" );
3250f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'xi'" );
3251f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3252f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'pi'" );
3253f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'rho'" );
3254f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3255f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'eight', 'tau'" );
3256f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'nine', 'phi'" );
3257f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'ten', 'chi'" );
3258f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3259f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3260f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3261c2c66affSColin Finck 
3262f860a780SAmine Khaldi     create_file_table( hdb );
3263f860a780SAmine Khaldi     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3264f860a780SAmine Khaldi     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3265f860a780SAmine Khaldi     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3266f860a780SAmine Khaldi     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3267f860a780SAmine Khaldi     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3268f860a780SAmine Khaldi     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3269f860a780SAmine Khaldi     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3270f860a780SAmine Khaldi     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3271c2c66affSColin Finck 
3272c2c66affSColin Finck     /* compressed file */
3273f860a780SAmine Khaldi     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3274c2c66affSColin Finck 
3275f860a780SAmine Khaldi     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3276f860a780SAmine Khaldi     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3277f860a780SAmine Khaldi     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3278f860a780SAmine Khaldi     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3279f860a780SAmine Khaldi     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3280f860a780SAmine Khaldi     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3281f860a780SAmine Khaldi     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3282f860a780SAmine Khaldi     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3283f860a780SAmine Khaldi     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3284f860a780SAmine Khaldi     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3285f860a780SAmine Khaldi     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3286f860a780SAmine Khaldi     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3287f860a780SAmine Khaldi     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3288f860a780SAmine Khaldi     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3289c2c66affSColin Finck 
3290f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
3291f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3292c2c66affSColin Finck 
3293c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3294f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3295f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3296f860a780SAmine Khaldi     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3297f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3298f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3299c2c66affSColin Finck 
3300c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3301c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3302c2c66affSColin Finck     {
3303c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3304c2c66affSColin Finck         DeleteFileA(msifile);
3305c2c66affSColin Finck         return;
3306c2c66affSColin Finck     }
3307c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3308c2c66affSColin Finck 
3309c2c66affSColin Finck     MsiCloseHandle(hdb);
3310c2c66affSColin Finck 
3311c2c66affSColin Finck     CopyFileA(msifile, msifile2, FALSE);
3312c2c66affSColin Finck     CopyFileA(msifile, msifile3, FALSE);
3313c2c66affSColin Finck     CopyFileA(msifile, msifile4, FALSE);
3314c2c66affSColin Finck 
3315fbdb719bSwinesync     size = sizeof(value);
3316fbdb719bSwinesync     memset(value, 0, sizeof(value));
3317fbdb719bSwinesync     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3318fbdb719bSwinesync     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3319fbdb719bSwinesync     ok(!value[0], "ProductToBeRegistered = %s\n", value);
3320fbdb719bSwinesync 
3321c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3322c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3323c2c66affSColin Finck 
3324c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3325c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3326c2c66affSColin Finck 
3327c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3328c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3329c2c66affSColin Finck 
3330c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3331c2c66affSColin Finck 
3332c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3333c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3334c2c66affSColin Finck 
3335c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3336c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3337c2c66affSColin Finck 
3338c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3339c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3340c2c66affSColin Finck 
3341c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3342c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3343c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3344c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3345c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3346c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3347c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3348c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3349c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3350c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3351c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3352c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3353c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3354c2c66affSColin Finck 
3355c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3356c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3357c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3358c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3359c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3360c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3361c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3362c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3363c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3364c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3365c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3366c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3367c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3368c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3369c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3370c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3371c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3372c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3373c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3374c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3375c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3376c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3377c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3378c2c66affSColin Finck 
3379c2c66affSColin Finck     MsiCloseHandle( hpkg );
3380c2c66affSColin Finck 
3381c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3382c2c66affSColin Finck 
3383c2c66affSColin Finck     /* publish the features and components */
3384c2c66affSColin Finck     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3385c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3386c2c66affSColin Finck 
3387c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3388c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3389c2c66affSColin Finck 
3390c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3391f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3392f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3393f860a780SAmine Khaldi     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3394f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3395c2c66affSColin Finck 
3396c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3397c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3398c2c66affSColin Finck 
3399c2c66affSColin Finck     MsiCloseHandle(hdb);
3400c2c66affSColin Finck 
3401fbdb719bSwinesync     size = sizeof(value);
3402fbdb719bSwinesync     memset(value, 0, sizeof(value));
3403fbdb719bSwinesync     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3404fbdb719bSwinesync     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3405fbdb719bSwinesync     ok(value[0]=='1' && !value[1], "ProductToBeRegistered = %s\n", value);
3406fbdb719bSwinesync 
3407c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3408c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3409c2c66affSColin Finck 
3410c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3411c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3412c2c66affSColin Finck 
3413c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3414c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3415c2c66affSColin Finck 
3416c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3417c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3418c2c66affSColin Finck 
3419c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3420c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3421c2c66affSColin Finck 
3422c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3423c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3424c2c66affSColin Finck 
3425c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3426c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3427c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3428c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3429c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3430c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3431c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3432c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3433c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3434c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3435c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3436c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3437c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3438c2c66affSColin Finck 
3439c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3440c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3441c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3442c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3443c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3444c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3445c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3446c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3447c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3448c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3449c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3450c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3451c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3452c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3453c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3454c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3455c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3456c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3457c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3458c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3459c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3460c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3461c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3462c2c66affSColin Finck 
3463c2c66affSColin Finck     MsiCloseHandle(hpkg);
3464c2c66affSColin Finck 
3465c2c66affSColin Finck     /* uninstall the product */
3466c2c66affSColin Finck     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3467c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3468c2c66affSColin Finck 
3469c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3470c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3471c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3472c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3473c2c66affSColin Finck 
3474c2c66affSColin Finck     /* all features installed locally */
3475c2c66affSColin Finck     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3476c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3477c2c66affSColin Finck 
3478c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3479c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3480c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3481c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3482c2c66affSColin Finck 
3483c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3484c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3485c2c66affSColin Finck 
3486c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3487f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3488c2c66affSColin Finck 
3489c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3490c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3491c2c66affSColin Finck 
3492c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3493c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3494c2c66affSColin Finck 
3495c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3496c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3497c2c66affSColin Finck 
3498c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3499c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3500c2c66affSColin Finck 
3501c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3502c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3503c2c66affSColin Finck 
3504c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3505c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3506c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3507c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3508c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3509c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3510c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3511c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3512c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3513c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3514c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3515c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3516c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3517c2c66affSColin Finck 
3518c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3519c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3520c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3521c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3522c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3523c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3524c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3525c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3526c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3527c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3528c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3529c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3530c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3531c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3532c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3533c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3534c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3535c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3536c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3537c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3538c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3539c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3540c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3541c2c66affSColin Finck 
3542c2c66affSColin Finck     MsiCloseHandle(hpkg);
3543c2c66affSColin Finck 
3544c2c66affSColin Finck     /* uninstall the product */
3545c2c66affSColin Finck     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3546c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3547c2c66affSColin Finck 
3548c2c66affSColin Finck     /* all features installed from source */
3549c2c66affSColin Finck     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3550c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3551c2c66affSColin Finck 
3552c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3553c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3554c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3555c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3556c2c66affSColin Finck 
3557c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3558c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3559c2c66affSColin Finck 
3560c2c66affSColin Finck     /* this property must not be in the saved msi file */
3561f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3562c2c66affSColin Finck 
3563c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3564c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3565c2c66affSColin Finck 
3566c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3567c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3568c2c66affSColin Finck 
3569c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3570c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3571c2c66affSColin Finck 
3572c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3573c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3574c2c66affSColin Finck 
3575c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3576c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3577c2c66affSColin Finck 
3578c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3579c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3580c2c66affSColin Finck 
3581c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3582c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3583c2c66affSColin Finck 
3584c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3585c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3586c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3587c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3588c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3589c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3590c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3591c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3592c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3593c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3594c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3595c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3596c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3597c2c66affSColin Finck 
3598c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3599c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3600c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3601c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3602c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3603c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3604c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3605c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3606c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3607c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3608c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3609c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3610c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3611c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3612c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3613c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3614c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3615c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3616c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3617c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3618c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3619c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3620f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3621c2c66affSColin Finck 
3622c2c66affSColin Finck     MsiCloseHandle(hpkg);
3623c2c66affSColin Finck 
3624c2c66affSColin Finck     /* reinstall the product */
3625c2c66affSColin Finck     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3626f860a780SAmine Khaldi     is_broken = (r == ERROR_INSTALL_FAILURE);
3627f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3628c2c66affSColin Finck 
3629c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3630c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3631c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3632c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3633c2c66affSColin Finck 
3634c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3635c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3636c2c66affSColin Finck 
3637c2c66affSColin Finck     /* this property must not be in the saved msi file */
3638f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3639c2c66affSColin Finck 
3640c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3641c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3642c2c66affSColin Finck 
3643c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3644c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3645c2c66affSColin Finck 
3646c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3647c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3648c2c66affSColin Finck 
3649c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3650c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3651c2c66affSColin Finck 
3652c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3653c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3654c2c66affSColin Finck 
3655c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3656c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3657c2c66affSColin Finck 
3658c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3659c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3660c2c66affSColin Finck 
3661c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3662c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3663c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3664c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3665c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3666c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3667c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3668c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3669c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3670c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3671c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3672c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3673c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3674c2c66affSColin Finck 
3675c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3676c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3677c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3678c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3679c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3680c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3681c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3682c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3683c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3684c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3685c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3686c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3687c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3688c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3689c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3690c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3691c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3692c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3693c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3694c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3695c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3696c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3697f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3698c2c66affSColin Finck 
3699c2c66affSColin Finck     MsiCloseHandle(hpkg);
3700c2c66affSColin Finck 
3701f860a780SAmine Khaldi     /* test source only install */
3702f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3703f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3704f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3705f860a780SAmine Khaldi     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3706f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3707f860a780SAmine Khaldi     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3708f860a780SAmine Khaldi 
3709f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3710f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3711f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3712f860a780SAmine Khaldi     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3713f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3714f860a780SAmine Khaldi     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3715f860a780SAmine Khaldi 
3716f860a780SAmine Khaldi     /* no arguments test */
3717f860a780SAmine Khaldi     cache_file_name_len = sizeof(msi_cache_file);
3718f860a780SAmine Khaldi     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3719f860a780SAmine Khaldi             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3720f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3721f860a780SAmine Khaldi     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3722f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3723f860a780SAmine Khaldi 
3724f860a780SAmine Khaldi     create_custom_action_table( hdb );
3725f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3726f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3727f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3728f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3729f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3730f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3731f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3732f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
37332dce4ee7Swinesync     add_custom_action_entry( hdb,
373418123440Swinesync             "'VBFeatureRequest', 38, NULL, 'Session.FeatureRequestState(\"three\") = 3'" );
3735f860a780SAmine Khaldi 
3736f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3737f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
37382dce4ee7Swinesync     add_install_execute_sequence_entry( hdb, "'VBFeatureRequest', 'NOT REMOVE', '1001'" );
3739f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3740f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3741f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3742f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3743f860a780SAmine Khaldi     /* Add "one" feature action tests */
3744f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3745f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3746f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
3747f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3748f860a780SAmine Khaldi     r = package_from_db( hdb, &hpkg );
3749f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3750f860a780SAmine Khaldi     MsiCloseHandle(hdb);
3751f860a780SAmine Khaldi 
3752f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3753f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3754f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "CostInitialize");
3755f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3756f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3757f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3758f860a780SAmine Khaldi 
3759f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "FileCost");
3760f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3761f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3762f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3763f860a780SAmine Khaldi 
3764f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "CostFinalize");
3765f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3766f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3767f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3768f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3769f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3770f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3771f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3772f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3773f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3774f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3775f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3776f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3777f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3778f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3779f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3780f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3781f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3782f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3783f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3784f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3785f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3786f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3787f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3788f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3789f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3790f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3791f860a780SAmine Khaldi 
3792f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "InstallValidate");
3793f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3794f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3795f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3796f860a780SAmine Khaldi     MsiCloseHandle( hpkg );
3797f860a780SAmine Khaldi 
3798f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "");
3799f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS || (is_broken && r == ERROR_INSTALL_FAILURE) /* win2k3 */,
3800f860a780SAmine Khaldi             "Expected ERROR_SUCCESS, got %d\n", r);
3801f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3802f860a780SAmine Khaldi     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3803f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3804f860a780SAmine Khaldi     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
38052dce4ee7Swinesync     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "three");
38062dce4ee7Swinesync     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3807f860a780SAmine Khaldi 
380896486643Swinesync     /* minor upgrade test with no REINSTALL argument */
380996486643Swinesync     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
381096486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
381196486643Swinesync     size = MAX_PATH;
381296486643Swinesync     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
381396486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
381496486643Swinesync     ok(!strcmp(value, "1.1.1"), "ProductVersion = %s\n", value);
381596486643Swinesync     MsiCloseHandle(hprod);
381696486643Swinesync 
381796486643Swinesync     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
381896486643Swinesync     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
381996486643Swinesync     update_ProductVersion_property( hdb, "1.1.2" );
382096486643Swinesync     set_summary_str(hdb, PID_REVNUMBER, "{A219A62A-D931-4F1B-89DB-FF1C300A8D43}");
382196486643Swinesync     r = MsiDatabaseCommit(hdb);
382296486643Swinesync     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
382396486643Swinesync     MsiCloseHandle(hdb);
382496486643Swinesync 
382596486643Swinesync     r = MsiInstallProductA(msifile2, "");
3826b7b9c0c4Swinesync     ok(r == ERROR_PRODUCT_VERSION, "Expected ERROR_PRODUCT_VERSION, got %d\n", r);
382796486643Swinesync 
3828a2371385Swinesync     r = MsiInstallProductA(msifile2, "REINSTALLMODe=V");
3829a2371385Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3830366dd26eSwinesync 
3831366dd26eSwinesync     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3832366dd26eSwinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3833366dd26eSwinesync     size = MAX_PATH;
3834366dd26eSwinesync     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3835366dd26eSwinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3836a2371385Swinesync     ok(!strcmp(value, "1.1.2"), "ProductVersion = %s\n", value);
3837366dd26eSwinesync     MsiCloseHandle(hprod);
3838366dd26eSwinesync 
383996486643Swinesync     /* major upgrade test */
384096486643Swinesync     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
384196486643Swinesync     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3842366dd26eSwinesync     add_install_execute_sequence_entry( hdb, "'FindRelatedProducts', '', '100'" );
3843366dd26eSwinesync     add_install_execute_sequence_entry( hdb, "'RemoveExistingProducts', '', '1401'" );
3844366dd26eSwinesync     create_upgrade_table( hdb );
3845366dd26eSwinesync     add_upgrade_entry( hdb, "'{3494EEEA-4221-4A66-802E-DED8916BC5C5}', NULL, '1.1.3', NULL, 0, NULL, 'OLDERVERSIONBEINGUPGRADED'");
384696486643Swinesync     update_ProductCode_property( hdb, "{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}" );
3847366dd26eSwinesync     update_ProductVersion_property( hdb, "1.1.3" );
3848366dd26eSwinesync     set_summary_str(hdb, PID_REVNUMBER, "{5F99011C-02E6-48BD-8B8D-DE7CFABC7A09}");
384996486643Swinesync     r = MsiDatabaseCommit(hdb);
385096486643Swinesync     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
385196486643Swinesync     MsiCloseHandle(hdb);
385296486643Swinesync 
385396486643Swinesync     r = MsiInstallProductA(msifile2, "");
3854366dd26eSwinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
385596486643Swinesync 
385696486643Swinesync     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
385796486643Swinesync     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
385896486643Swinesync     r = MsiOpenProductA("{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}", &hprod);
385996486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
386096486643Swinesync     size = MAX_PATH;
386196486643Swinesync     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
386296486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3863366dd26eSwinesync     ok(!strcmp(value, "1.1.3"), "ProductVersion = %s\n", value);
386496486643Swinesync     MsiCloseHandle(hprod);
386596486643Swinesync 
3866c2c66affSColin Finck     /* uninstall the product */
386796486643Swinesync     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3868c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3869c2c66affSColin Finck 
3870c2c66affSColin Finck     DeleteFileA(msifile);
3871c2c66affSColin Finck     DeleteFileA(msifile2);
3872c2c66affSColin Finck     DeleteFileA(msifile3);
3873c2c66affSColin Finck     DeleteFileA(msifile4);
3874c2c66affSColin Finck }
3875c2c66affSColin Finck 
3876c2c66affSColin Finck static void test_removefiles(void)
3877c2c66affSColin Finck {
3878c2c66affSColin Finck     MSIHANDLE hpkg;
3879c2c66affSColin Finck     UINT r;
3880c2c66affSColin Finck     MSIHANDLE hdb;
3881c2c66affSColin Finck     INSTALLSTATE installed, action;
3882c2c66affSColin Finck 
3883c2c66affSColin Finck     hdb = create_package_db();
3884c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3885c2c66affSColin Finck 
3886f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3887c2c66affSColin Finck 
3888f860a780SAmine Khaldi     create_feature_table( hdb );
3889f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3890c2c66affSColin Finck 
3891f860a780SAmine Khaldi     create_component_table( hdb );
3892f860a780SAmine Khaldi     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3893f860a780SAmine Khaldi     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3894f860a780SAmine Khaldi     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3895f860a780SAmine Khaldi     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3896f860a780SAmine Khaldi     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3897f860a780SAmine Khaldi     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3898f860a780SAmine Khaldi     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3899c2c66affSColin Finck 
3900f860a780SAmine Khaldi     create_feature_components_table( hdb );
3901f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3902f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'helium'" );
3903f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'lithium'" );
3904f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3905f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'boron'" );
3906f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'carbon'" );
3907f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3908c2c66affSColin Finck 
3909f860a780SAmine Khaldi     create_file_table( hdb );
3910f860a780SAmine Khaldi     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3911f860a780SAmine Khaldi     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3912f860a780SAmine Khaldi     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3913f860a780SAmine Khaldi     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3914f860a780SAmine Khaldi     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3915f860a780SAmine Khaldi     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3916f860a780SAmine Khaldi     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3917c2c66affSColin Finck 
3918f860a780SAmine Khaldi     create_remove_file_table( hdb );
3919c2c66affSColin Finck 
3920c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3921c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3922c2c66affSColin Finck     {
3923c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3924c2c66affSColin Finck         DeleteFileA(msifile);
3925c2c66affSColin Finck         return;
3926c2c66affSColin Finck     }
3927c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3928c2c66affSColin Finck 
3929c2c66affSColin Finck     MsiCloseHandle( hdb );
3930c2c66affSColin Finck 
3931c2c66affSColin Finck     create_test_file( "hydrogen.txt" );
3932c2c66affSColin Finck     create_test_file( "helium.txt" );
3933c2c66affSColin Finck     create_test_file( "lithium.txt" );
3934c2c66affSColin Finck     create_test_file( "beryllium.txt" );
3935c2c66affSColin Finck     create_test_file( "boron.txt" );
3936c2c66affSColin Finck     create_test_file( "carbon.txt" );
3937c2c66affSColin Finck     create_test_file( "oxygen.txt" );
3938c2c66affSColin Finck 
3939c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3940c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "set property failed\n");
3941c2c66affSColin Finck 
3942c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3943c2c66affSColin Finck 
3944c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3945c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3946c2c66affSColin Finck 
3947c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3948c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3949c2c66affSColin Finck 
3950c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3951c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3952c2c66affSColin Finck 
3953c2c66affSColin Finck     installed = action = 0xdeadbeef;
3954c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3955c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3956c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3957c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3958c2c66affSColin Finck 
3959c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3960c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3961c2c66affSColin Finck 
3962c2c66affSColin Finck     r = MsiDoActionA( hpkg, "InstallValidate");
3963c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "install validate failed\n");
3964c2c66affSColin Finck 
3965c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3966c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3967c2c66affSColin Finck 
3968c2c66affSColin Finck     installed = action = 0xdeadbeef;
3969c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3970c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3971c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3972c2c66affSColin Finck     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3973c2c66affSColin Finck 
3974c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3975c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3976c2c66affSColin Finck 
3977c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3978c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3979c2c66affSColin Finck 
3980c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3981c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3982c2c66affSColin Finck 
3983c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3984c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3985c2c66affSColin Finck 
3986c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3987c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3988c2c66affSColin Finck 
3989c2c66affSColin Finck     installed = action = 0xdeadbeef;
3990c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3991c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3992c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3993c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3994c2c66affSColin Finck 
3995c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3996c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3997c2c66affSColin Finck 
3998c2c66affSColin Finck     installed = action = 0xdeadbeef;
3999c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
4000c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
4001c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
4002c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
4003c2c66affSColin Finck 
4004c2c66affSColin Finck     r = MsiDoActionA( hpkg, "RemoveFiles");
4005c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "remove files failed\n");
4006c2c66affSColin Finck 
4007c2c66affSColin Finck     installed = action = 0xdeadbeef;
4008c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
4009c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
4010c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
4011c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
4012c2c66affSColin Finck 
4013c2c66affSColin Finck     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
4014c2c66affSColin Finck     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
4015c2c66affSColin Finck     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
4016c2c66affSColin Finck     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
4017c2c66affSColin Finck     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
4018c2c66affSColin Finck     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
4019c2c66affSColin Finck     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
4020c2c66affSColin Finck 
4021c2c66affSColin Finck     MsiCloseHandle( hpkg );
4022c2c66affSColin Finck     DeleteFileA(msifile);
4023c2c66affSColin Finck }
4024c2c66affSColin Finck 
4025c2c66affSColin Finck static void test_appsearch(void)
4026c2c66affSColin Finck {
4027c2c66affSColin Finck     MSIHANDLE hpkg;
4028c2c66affSColin Finck     UINT r;
4029c2c66affSColin Finck     MSIHANDLE hdb;
4030c2c66affSColin Finck     CHAR prop[MAX_PATH];
4031c2c66affSColin Finck     DWORD size;
4032c2c66affSColin Finck     HKEY hkey;
4033c2c66affSColin Finck     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
4034c2c66affSColin Finck 
4035c2c66affSColin Finck     hdb = create_package_db();
4036c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
4037c2c66affSColin Finck 
4038f860a780SAmine Khaldi     create_appsearch_table( hdb );
4039f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
4040f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
4041f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
4042435274d1Swinesync     add_appsearch_entry( hdb, "'32KEYVAL', 'NewSignature4'" );
4043435274d1Swinesync     add_appsearch_entry( hdb, "'64KEYVAL', 'NewSignature5'" );
4044c2c66affSColin Finck 
4045f860a780SAmine Khaldi     create_reglocator_table( hdb );
4046f860a780SAmine Khaldi     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
4047c2c66affSColin Finck 
4048c2c66affSColin Finck     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
4049c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4050c2c66affSColin Finck     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
4051c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4052c2c66affSColin Finck     RegCloseKey(hkey);
4053435274d1Swinesync     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", msidbLocatorTypeFileName );
4054435274d1Swinesync 
4055435274d1Swinesync     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_32KEY,
4056435274d1Swinesync                         NULL, &hkey, NULL);
4057435274d1Swinesync     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4058d7c30ed1Swinesync     if (r == ERROR_ACCESS_DENIED)
4059d7c30ed1Swinesync     {
4060d7c30ed1Swinesync         skip("insufficient rights\n");
4061d7c30ed1Swinesync         RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4062d7c30ed1Swinesync         MsiCloseHandle(hdb);
4063d7c30ed1Swinesync         DeleteFileA(msifile);
4064d7c30ed1Swinesync         return;
4065d7c30ed1Swinesync     }
4066d7c30ed1Swinesync 
4067435274d1Swinesync     r = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE *)"c:\\windows\\system32\\notepad.exe",
4068435274d1Swinesync                        sizeof("c:\\windows\\system32\\notepad.exe"));
4069435274d1Swinesync     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4070435274d1Swinesync     RegCloseKey(hkey);
4071435274d1Swinesync     add_reglocator_entry( hdb, "NewSignature4", 2, "Software\\Winetest_msi", "", msidbLocatorTypeFileName );
4072435274d1Swinesync 
4073435274d1Swinesync     r = RegCreateKeyExA(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS|KEY_WOW64_64KEY,
4074435274d1Swinesync                         NULL, &hkey, NULL);
4075435274d1Swinesync     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4076435274d1Swinesync     r = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const BYTE *)"c:\\windows\\system32\\notepad.exe",
4077435274d1Swinesync                        sizeof("c:\\windows\\system32\\notepad.exe"));
4078435274d1Swinesync     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4079435274d1Swinesync     RegCloseKey(hkey);
4080435274d1Swinesync     add_reglocator_entry( hdb, "NewSignature5", 2, "Software\\Winetest_msi", "",
4081435274d1Swinesync                           msidbLocatorTypeFileName|msidbLocatorType64bit );
4082c2c66affSColin Finck 
4083f860a780SAmine Khaldi     create_drlocator_table( hdb );
4084f860a780SAmine Khaldi     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
4085c2c66affSColin Finck 
4086f860a780SAmine Khaldi     create_signature_table( hdb );
4087f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
4088f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4089f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4090435274d1Swinesync     add_signature_entry( hdb, "'NewSignature4', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4091435274d1Swinesync     add_signature_entry( hdb, "'NewSignature5', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4092c2c66affSColin Finck 
4093c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
4094c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4095c2c66affSColin Finck     {
4096c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4097c2c66affSColin Finck         DeleteFileA(msifile);
4098c2c66affSColin Finck         return;
4099c2c66affSColin Finck     }
4100c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
4101c2c66affSColin Finck     MsiCloseHandle( hdb );
4102c2c66affSColin Finck     if (r != ERROR_SUCCESS)
4103c2c66affSColin Finck         goto done;
4104c2c66affSColin Finck 
4105c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4106c2c66affSColin Finck 
4107c2c66affSColin Finck     r = MsiDoActionA( hpkg, "AppSearch" );
4108c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
4109c2c66affSColin Finck 
4110c2c66affSColin Finck     size = sizeof(prop);
4111c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
4112c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4113c2c66affSColin Finck     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4114c2c66affSColin Finck 
4115c2c66affSColin Finck     size = sizeof(prop);
4116c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
4117c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4118c2c66affSColin Finck 
4119c2c66affSColin Finck     size = sizeof(prop);
4120c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
4121c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4122c2c66affSColin Finck     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4123c2c66affSColin Finck 
4124435274d1Swinesync     size = sizeof(prop);
4125435274d1Swinesync     r = MsiGetPropertyA( hpkg, "32KEYVAL", prop, &size );
4126435274d1Swinesync     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4127435274d1Swinesync     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4128435274d1Swinesync 
4129435274d1Swinesync     size = sizeof(prop);
4130435274d1Swinesync     r = MsiGetPropertyA( hpkg, "64KEYVAL", prop, &size );
4131435274d1Swinesync     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4132435274d1Swinesync     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4133435274d1Swinesync 
4134c2c66affSColin Finck done:
4135c2c66affSColin Finck     MsiCloseHandle( hpkg );
4136c2c66affSColin Finck     DeleteFileA(msifile);
4137c2c66affSColin Finck     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4138435274d1Swinesync     delete_key(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", KEY_WOW64_32KEY);
4139435274d1Swinesync     delete_key(HKEY_LOCAL_MACHINE, "Software\\Winetest_msi", KEY_WOW64_64KEY);
4140c2c66affSColin Finck }
4141c2c66affSColin Finck 
4142c2c66affSColin Finck static void test_appsearch_complocator(void)
4143c2c66affSColin Finck {
4144c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4145c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4146c2c66affSColin Finck     LPSTR usersid;
4147c2c66affSColin Finck     DWORD size;
4148c2c66affSColin Finck     UINT r;
4149c2c66affSColin Finck 
4150c2c66affSColin Finck     if (!(usersid = get_user_sid()))
4151c2c66affSColin Finck         return;
4152c2c66affSColin Finck 
4153c2c66affSColin Finck     if (is_process_limited())
4154c2c66affSColin Finck     {
4155c2c66affSColin Finck         skip("process is limited\n");
4156c2c66affSColin Finck         return;
4157c2c66affSColin Finck     }
4158c2c66affSColin Finck 
4159c2c66affSColin Finck     create_test_file("FileName1");
4160c2c66affSColin Finck     create_test_file("FileName4");
4161c2c66affSColin Finck     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
4162c2c66affSColin Finck                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
4163c2c66affSColin Finck 
4164c2c66affSColin Finck     create_test_file("FileName2");
4165c2c66affSColin Finck     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4166c2c66affSColin Finck                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4167c2c66affSColin Finck 
4168c2c66affSColin Finck     create_test_file("FileName3");
4169c2c66affSColin Finck     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4170c2c66affSColin Finck                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4171c2c66affSColin Finck 
4172c2c66affSColin Finck     create_test_file("FileName5");
4173c2c66affSColin Finck     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4174c2c66affSColin Finck                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4175c2c66affSColin Finck 
4176c2c66affSColin Finck     create_test_file("FileName6");
4177c2c66affSColin Finck     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4178c2c66affSColin Finck                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4179c2c66affSColin Finck 
4180c2c66affSColin Finck     create_test_file("FileName7");
4181c2c66affSColin Finck     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4182c2c66affSColin Finck                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4183c2c66affSColin Finck 
4184c2c66affSColin Finck     /* dir is FALSE, but we're pretending it's a directory */
4185c2c66affSColin Finck     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4186c2c66affSColin Finck                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4187c2c66affSColin Finck 
4188c2c66affSColin Finck     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4189c2c66affSColin Finck     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4190c2c66affSColin Finck                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4191c2c66affSColin Finck 
4192c2c66affSColin Finck     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4193c2c66affSColin Finck     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4194c2c66affSColin Finck                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4195c2c66affSColin Finck 
4196c2c66affSColin Finck     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4197c2c66affSColin Finck     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4198c2c66affSColin Finck                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4199c2c66affSColin Finck 
4200c2c66affSColin Finck     hdb = create_package_db();
4201c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4202c2c66affSColin Finck 
4203f860a780SAmine Khaldi     create_appsearch_table(hdb);
4204f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4205f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4206f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4207f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4208f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4209f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4210f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4211f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4212f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4213f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4214f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4215f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4216c2c66affSColin Finck 
4217f860a780SAmine Khaldi     create_complocator_table(hdb);
4218c2c66affSColin Finck 
4219c2c66affSColin Finck     /* published component, machine, file, signature, misdbLocatorTypeFile */
4220f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4221c2c66affSColin Finck 
4222c2c66affSColin Finck     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4223f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4224c2c66affSColin Finck 
4225c2c66affSColin Finck     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4226f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4227c2c66affSColin Finck 
4228c2c66affSColin Finck     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4229f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4230c2c66affSColin Finck 
4231c2c66affSColin Finck     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4232f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4233c2c66affSColin Finck 
4234c2c66affSColin Finck     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4235f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4236c2c66affSColin Finck 
4237c2c66affSColin Finck     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4238f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4239c2c66affSColin Finck 
4240c2c66affSColin Finck     /* unpublished component, no signature, misdbLocatorTypeDir */
4241f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4242c2c66affSColin Finck 
4243c2c66affSColin Finck     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4244f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4245c2c66affSColin Finck 
4246c2c66affSColin Finck     /* published component, signature w/ ver, misdbLocatorTypeFile */
4247f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4248c2c66affSColin Finck 
4249c2c66affSColin Finck     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4250f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4251c2c66affSColin Finck 
4252c2c66affSColin Finck     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4253f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4254c2c66affSColin Finck 
4255f860a780SAmine Khaldi     create_signature_table(hdb);
4256f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4257f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4258f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4259f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4260f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4261f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4262f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4263f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4264c2c66affSColin Finck 
4265c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4266c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4267c2c66affSColin Finck     {
4268c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4269c2c66affSColin Finck         goto error;
4270c2c66affSColin Finck     }
4271c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4272c2c66affSColin Finck 
4273c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4274c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4275c2c66affSColin Finck 
4276c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4277c2c66affSColin Finck 
4278c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4279c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4280c2c66affSColin Finck 
4281c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4282c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4283c2c66affSColin Finck 
4284c2c66affSColin Finck     size = MAX_PATH;
4285c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4286c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4287c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4288c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4289c2c66affSColin Finck 
4290c2c66affSColin Finck     size = MAX_PATH;
4291c2c66affSColin Finck     sprintf(path, "%s\\FileName2", expected);
4292c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4293c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4294c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4295c2c66affSColin Finck 
4296c2c66affSColin Finck     size = MAX_PATH;
4297c2c66affSColin Finck     sprintf(path, "%s\\FileName3", expected);
4298c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4299c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4300c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4301c2c66affSColin Finck 
4302c2c66affSColin Finck     size = MAX_PATH;
4303c2c66affSColin Finck     sprintf(path, "%s\\FileName4", expected);
4304c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4305c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4306c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4307c2c66affSColin Finck 
4308c2c66affSColin Finck     size = MAX_PATH;
4309c2c66affSColin Finck     sprintf(path, "%s\\FileName5", expected);
4310c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4311c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4312c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4313c2c66affSColin Finck 
4314c2c66affSColin Finck     size = MAX_PATH;
4315c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4316c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4317c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4318c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4319c2c66affSColin Finck 
4320c2c66affSColin Finck     size = MAX_PATH;
4321c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4322c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4323c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4324c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4325c2c66affSColin Finck 
4326c2c66affSColin Finck     size = MAX_PATH;
4327c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4328c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4329c2c66affSColin Finck     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4330c2c66affSColin Finck 
4331c2c66affSColin Finck     size = MAX_PATH;
4332c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4333c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4334c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4335c2c66affSColin Finck 
4336c2c66affSColin Finck     size = MAX_PATH;
4337c2c66affSColin Finck     sprintf(path, "%s\\FileName8.dll", expected);
4338c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4339c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4340c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4341c2c66affSColin Finck 
4342c2c66affSColin Finck     size = MAX_PATH;
4343c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4344c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4345c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4346c2c66affSColin Finck 
4347c2c66affSColin Finck     size = MAX_PATH;
4348c2c66affSColin Finck     sprintf(path, "%s\\FileName10.dll", expected);
4349c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4350c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4351c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4352c2c66affSColin Finck 
4353c2c66affSColin Finck     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4354c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4355c2c66affSColin Finck     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4356c2c66affSColin Finck                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4357c2c66affSColin Finck     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4358c2c66affSColin Finck                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4359c2c66affSColin Finck     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4360c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4361c2c66affSColin Finck     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4362c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4363c2c66affSColin Finck     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4364c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4365c2c66affSColin Finck     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4366c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4367c2c66affSColin Finck     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4368c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4369c2c66affSColin Finck     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4370c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4371c2c66affSColin Finck     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4372c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4373c2c66affSColin Finck 
4374c2c66affSColin Finck     MsiCloseHandle(hpkg);
4375c2c66affSColin Finck 
4376c2c66affSColin Finck error:
4377c2c66affSColin Finck     DeleteFileA("FileName1");
4378c2c66affSColin Finck     DeleteFileA("FileName2");
4379c2c66affSColin Finck     DeleteFileA("FileName3");
4380c2c66affSColin Finck     DeleteFileA("FileName4");
4381c2c66affSColin Finck     DeleteFileA("FileName5");
4382c2c66affSColin Finck     DeleteFileA("FileName6");
4383c2c66affSColin Finck     DeleteFileA("FileName7");
4384c2c66affSColin Finck     DeleteFileA("FileName8.dll");
4385c2c66affSColin Finck     DeleteFileA("FileName9.dll");
4386c2c66affSColin Finck     DeleteFileA("FileName10.dll");
4387c2c66affSColin Finck     DeleteFileA(msifile);
4388c2c66affSColin Finck     LocalFree(usersid);
4389c2c66affSColin Finck }
4390c2c66affSColin Finck 
4391c2c66affSColin Finck static void test_appsearch_reglocator(void)
4392c2c66affSColin Finck {
4393c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4394c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4395c2c66affSColin Finck     DWORD binary[2], size, val;
4396c2c66affSColin Finck     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4397c2c66affSColin Finck     HKEY hklm, classes, hkcu, users;
4398c2c66affSColin Finck     LPSTR pathdata, pathvar, ptr;
4399c2c66affSColin Finck     LONG res;
4400c2c66affSColin Finck     UINT r, type = 0;
4401c2c66affSColin Finck     SYSTEM_INFO si;
4402c2c66affSColin Finck 
4403c2c66affSColin Finck     version = TRUE;
4404c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4405c2c66affSColin Finck         version = FALSE;
4406c2c66affSColin Finck 
4407c2c66affSColin Finck     DeleteFileA("test.dll");
4408c2c66affSColin Finck 
4409c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4410c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
4411c2c66affSColin Finck     {
4412c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4413c2c66affSColin Finck         return;
4414c2c66affSColin Finck     }
4415c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4416c2c66affSColin Finck 
4417c2c66affSColin Finck     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4418c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4419c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4420c2c66affSColin Finck 
4421c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4422c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4423c2c66affSColin Finck 
4424c2c66affSColin Finck     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4425c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4426c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4427c2c66affSColin Finck 
4428c2c66affSColin Finck     users = 0;
4429c2c66affSColin Finck     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4430c2c66affSColin Finck     ok(res == ERROR_SUCCESS ||
4431c2c66affSColin Finck        broken(res == ERROR_INVALID_PARAMETER),
4432c2c66affSColin Finck        "Expected ERROR_SUCCESS, got %d\n", res);
4433c2c66affSColin Finck 
4434c2c66affSColin Finck     if (res == ERROR_SUCCESS)
4435c2c66affSColin Finck     {
4436c2c66affSColin Finck         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4437c2c66affSColin Finck                              (const BYTE *)"regszdata", 10);
4438c2c66affSColin Finck         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4439c2c66affSColin Finck     }
4440c2c66affSColin Finck 
4441c2c66affSColin Finck     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4442c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4443c2c66affSColin Finck 
4444c2c66affSColin Finck     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4445c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4446c2c66affSColin Finck 
4447c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4448c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4449c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4450c2c66affSColin Finck 
4451c2c66affSColin Finck     val = 42;
4452c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4453c2c66affSColin Finck                          (const BYTE *)&val, sizeof(DWORD));
4454c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4455c2c66affSColin Finck 
4456c2c66affSColin Finck     val = -42;
4457c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4458c2c66affSColin Finck                          (const BYTE *)&val, sizeof(DWORD));
4459c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4460c2c66affSColin Finck 
4461c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4462c2c66affSColin Finck                          (const BYTE *)"%PATH%", 7);
4463c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4464c2c66affSColin Finck 
4465c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4466c2c66affSColin Finck                          (const BYTE *)"my%NOVAR%", 10);
4467c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4468c2c66affSColin Finck 
4469c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4470c2c66affSColin Finck                          (const BYTE *)"one\0two\0", 9);
4471c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4472c2c66affSColin Finck 
4473c2c66affSColin Finck     binary[0] = 0x1234abcd;
4474c2c66affSColin Finck     binary[1] = 0x567890ef;
4475c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4476c2c66affSColin Finck                          (const BYTE *)binary, sizeof(binary));
4477c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4478c2c66affSColin Finck 
4479c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4480c2c66affSColin Finck                          (const BYTE *)"#regszdata", 11);
4481c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4482c2c66affSColin Finck 
4483c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4484c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4485c2c66affSColin Finck 
4486c2c66affSColin Finck     create_test_file("FileName1");
4487c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4488c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4489c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4490c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4491c2c66affSColin Finck 
4492c2c66affSColin Finck     sprintf(path, "%s\\FileName2", expected);
4493c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4494c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4495c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4496c2c66affSColin Finck 
4497c2c66affSColin Finck     lstrcpyA(path, expected);
4498c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4499c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4500c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4501c2c66affSColin Finck 
4502c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4503c2c66affSColin Finck                          (const BYTE *)"", 1);
4504c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4505c2c66affSColin Finck 
4506c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4507c2c66affSColin Finck     sprintf(path, "%s\\FileName3.dll", expected);
4508c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4509c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4510c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4511c2c66affSColin Finck 
4512c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4513c2c66affSColin Finck     sprintf(path, "%s\\FileName4.dll", expected);
4514c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4515c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4516c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4517c2c66affSColin Finck 
4518c2c66affSColin Finck     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4519c2c66affSColin Finck     sprintf(path, "%s\\FileName5.dll", expected);
4520c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4521c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4522c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4523c2c66affSColin Finck 
4524c2c66affSColin Finck     sprintf(path, "\"%s\\FileName1\" -option", expected);
4525c2c66affSColin Finck     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4526c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4527c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4528c2c66affSColin Finck 
4529c2c66affSColin Finck     space = strchr(expected, ' ') != NULL;
4530c2c66affSColin Finck     sprintf(path, "%s\\FileName1 -option", expected);
4531c2c66affSColin Finck     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4532c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4533c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4534c2c66affSColin Finck 
4535c2c66affSColin Finck     hdb = create_package_db();
4536c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4537c2c66affSColin Finck 
4538f860a780SAmine Khaldi     create_appsearch_table(hdb);
4539f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4540f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4541f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4542f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4543f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4544f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4545f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4546f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4547f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4548f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4549f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4550f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4551f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4552f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4553f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4554f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4555f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4556f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4557f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4558f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4559f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4560f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4561f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4562f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4563f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4564f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4565f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4566f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4567f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4568f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4569c2c66affSColin Finck 
4570f860a780SAmine Khaldi     create_reglocator_table(hdb);
4571c2c66affSColin Finck 
4572c2c66affSColin Finck     type = msidbLocatorTypeRawValue;
4573c2c66affSColin Finck     if (is_64bit)
4574c2c66affSColin Finck         type |= msidbLocatorType64bit;
4575c2c66affSColin Finck 
4576c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4577f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4578c2c66affSColin Finck 
4579c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4580f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4581c2c66affSColin Finck 
4582c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4583f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4584c2c66affSColin Finck 
4585c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4586f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4587c2c66affSColin Finck 
4588c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4589f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4590c2c66affSColin Finck 
4591c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4592f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4593c2c66affSColin Finck 
4594c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4595f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4596c2c66affSColin Finck 
4597c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4598f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4599c2c66affSColin Finck 
4600c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4601c2c66affSColin Finck     if (is_64bit)
4602c2c66affSColin Finck         type |= msidbLocatorType64bit;
4603c2c66affSColin Finck 
4604c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4605f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4606c2c66affSColin Finck 
4607c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4608f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4609c2c66affSColin Finck 
4610c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature */
4611f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4612c2c66affSColin Finck 
4613c2c66affSColin Finck     type = msidbLocatorTypeDirectory;
4614c2c66affSColin Finck     if (is_64bit)
4615c2c66affSColin Finck         type |= msidbLocatorType64bit;
4616c2c66affSColin Finck 
4617c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4618f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4619c2c66affSColin Finck 
4620c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4621f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4622c2c66affSColin Finck 
4623c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4624f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4625c2c66affSColin Finck 
4626c2c66affSColin Finck     type = msidbLocatorTypeRawValue;
4627c2c66affSColin Finck     if (is_64bit)
4628c2c66affSColin Finck         type |= msidbLocatorType64bit;
4629c2c66affSColin Finck 
4630c2c66affSColin Finck     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4631f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4632c2c66affSColin Finck 
4633c2c66affSColin Finck     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4634f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4635c2c66affSColin Finck 
4636c2c66affSColin Finck     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4637f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4638c2c66affSColin Finck 
4639c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4640f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4641c2c66affSColin Finck 
4642c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4643f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4644c2c66affSColin Finck 
4645c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4646f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4647c2c66affSColin Finck 
4648c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4649c2c66affSColin Finck     if (is_64bit)
4650c2c66affSColin Finck         type |= msidbLocatorType64bit;
4651c2c66affSColin Finck 
4652c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4653f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4654c2c66affSColin Finck 
4655c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4656f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4657c2c66affSColin Finck 
4658c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4659f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4660c2c66affSColin Finck 
4661c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4662f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4663c2c66affSColin Finck 
4664c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4665f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4666c2c66affSColin Finck 
4667c2c66affSColin Finck     type = msidbLocatorTypeDirectory;
4668c2c66affSColin Finck     if (is_64bit)
4669c2c66affSColin Finck         type |= msidbLocatorType64bit;
4670c2c66affSColin Finck 
4671c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4672f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4673c2c66affSColin Finck 
4674c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4675f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4676c2c66affSColin Finck 
4677c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4678f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4679c2c66affSColin Finck 
4680c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4681c2c66affSColin Finck     if (is_64bit)
4682c2c66affSColin Finck         type |= msidbLocatorType64bit;
4683c2c66affSColin Finck 
4684c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4685f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4686c2c66affSColin Finck 
4687c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4688f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4689c2c66affSColin Finck 
4690f860a780SAmine Khaldi     create_signature_table(hdb);
4691f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4692f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4693f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4694f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4695f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4696f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4697c2c66affSColin Finck 
4698c2c66affSColin Finck     if (!is_root(CURR_DIR))
4699c2c66affSColin Finck     {
4700c2c66affSColin Finck         ptr = strrchr(expected, '\\') + 1;
4701c2c66affSColin Finck         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4702f860a780SAmine Khaldi         add_signature_entry(hdb, path);
4703c2c66affSColin Finck     }
4704f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4705f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4706f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4707c2c66affSColin Finck 
4708c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4709c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4710c2c66affSColin Finck 
4711c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4712c2c66affSColin Finck 
4713c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4714c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4715c2c66affSColin Finck 
4716c2c66affSColin Finck     size = MAX_PATH;
4717c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4718c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4719c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4720c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4721c2c66affSColin Finck 
4722c2c66affSColin Finck     size = MAX_PATH;
4723c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4724c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4725c2c66affSColin Finck     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4726c2c66affSColin Finck 
4727c2c66affSColin Finck     size = MAX_PATH;
4728c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4729c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4730c2c66affSColin Finck     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4731c2c66affSColin Finck 
4732c2c66affSColin Finck     memset(&si, 0, sizeof(si));
4733a4930636Swinesync     GetNativeSystemInfo(&si);
4734c2c66affSColin Finck 
4735c2c66affSColin Finck     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4736c2c66affSColin Finck     {
4737c2c66affSColin Finck         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4738c2c66affSColin Finck         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4739c2c66affSColin Finck         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4740c2c66affSColin Finck 
4741c2c66affSColin Finck         size = 0;
4742c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4743c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4744c2c66affSColin Finck 
4745c2c66affSColin Finck         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4746c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4747c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4748c2c66affSColin Finck         ok(!lstrcmpA(pathdata, pathvar),
4749c2c66affSColin Finck             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4750c2c66affSColin Finck 
4751c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pathvar);
4752c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pathdata);
4753c2c66affSColin Finck     }
4754c2c66affSColin Finck 
4755c2c66affSColin Finck     size = MAX_PATH;
4756c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4757c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4758c2c66affSColin Finck     ok(!lstrcmpA(prop,
4759c2c66affSColin Finck        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4760c2c66affSColin Finck 
4761c2c66affSColin Finck     size = MAX_PATH;
4762c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4763c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4764c2c66affSColin Finck     todo_wine
4765c2c66affSColin Finck     {
4766c2c66affSColin Finck         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4767c2c66affSColin Finck            "Expected \"\\0one\\0two\\0\\0\"\n");
4768c2c66affSColin Finck     }
4769c2c66affSColin Finck 
4770c2c66affSColin Finck     size = MAX_PATH;
4771c2c66affSColin Finck     lstrcpyA(path, "#xCDAB3412EF907856");
4772c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4773c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4774c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4775c2c66affSColin Finck 
4776c2c66affSColin Finck     size = MAX_PATH;
4777c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4778c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4779c2c66affSColin Finck     ok(!lstrcmpA(prop, "##regszdata"),
4780c2c66affSColin Finck        "Expected \"##regszdata\", got \"%s\"\n", prop);
4781c2c66affSColin Finck 
4782c2c66affSColin Finck     size = MAX_PATH;
4783c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4784c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4785c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4786c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4787c2c66affSColin Finck 
4788c2c66affSColin Finck     size = MAX_PATH;
4789c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4790c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4791c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4792c2c66affSColin Finck 
4793c2c66affSColin Finck     size = MAX_PATH;
4794c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4795c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4796c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4797c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4798c2c66affSColin Finck 
4799c2c66affSColin Finck     size = MAX_PATH;
4800c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4801c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4802c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4803c2c66affSColin Finck 
4804c2c66affSColin Finck     size = MAX_PATH;
4805c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4806c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4807c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4808c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4809c2c66affSColin Finck 
4810c2c66affSColin Finck     size = MAX_PATH;
4811c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4812c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4813c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4814c2c66affSColin Finck 
4815c2c66affSColin Finck     size = MAX_PATH;
4816c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4817c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4818c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4819c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4820c2c66affSColin Finck 
4821c2c66affSColin Finck     size = MAX_PATH;
4822c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4823c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4824c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4825c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4826c2c66affSColin Finck 
4827c2c66affSColin Finck     if (users)
4828c2c66affSColin Finck     {
4829c2c66affSColin Finck         size = MAX_PATH;
4830c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4831c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4832c2c66affSColin Finck         ok(!lstrcmpA(prop, "regszdata"),
4833c2c66affSColin Finck            "Expected \"regszdata\", got \"%s\"\n", prop);
4834c2c66affSColin Finck     }
4835c2c66affSColin Finck 
4836c2c66affSColin Finck     size = MAX_PATH;
4837c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4838c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4839c2c66affSColin Finck     ok(!lstrcmpA(prop, "defvalue"),
4840c2c66affSColin Finck        "Expected \"defvalue\", got \"%s\"\n", prop);
4841c2c66affSColin Finck 
4842c2c66affSColin Finck     size = MAX_PATH;
4843c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4844c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4845c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4846c2c66affSColin Finck 
4847c2c66affSColin Finck     size = MAX_PATH;
4848c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4849c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4850c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4851c2c66affSColin Finck 
4852c2c66affSColin Finck     if (version)
4853c2c66affSColin Finck     {
4854c2c66affSColin Finck         size = MAX_PATH;
4855c2c66affSColin Finck         sprintf(path, "%s\\FileName3.dll", expected);
4856c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4857c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4858c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4859c2c66affSColin Finck 
4860c2c66affSColin Finck         size = MAX_PATH;
4861c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4862c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4863c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4864c2c66affSColin Finck 
4865c2c66affSColin Finck         size = MAX_PATH;
4866c2c66affSColin Finck         sprintf(path, "%s\\FileName5.dll", expected);
4867c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4868c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4869c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4870c2c66affSColin Finck     }
4871c2c66affSColin Finck 
4872c2c66affSColin Finck     if (!is_root(CURR_DIR))
4873c2c66affSColin Finck     {
4874c2c66affSColin Finck         size = MAX_PATH;
4875c2c66affSColin Finck         lstrcpyA(path, expected);
4876c2c66affSColin Finck         ptr = strrchr(path, '\\') + 1;
4877c2c66affSColin Finck         *ptr = '\0';
4878c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4879c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4880c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4881c2c66affSColin Finck     }
4882c2c66affSColin Finck     size = MAX_PATH;
4883c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4884c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4885c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4886c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4887c2c66affSColin Finck 
4888c2c66affSColin Finck     size = MAX_PATH;
4889c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4890c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4891c2c66affSColin Finck     if (is_root(CURR_DIR))
4892c2c66affSColin Finck         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4893c2c66affSColin Finck     else
4894c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4895c2c66affSColin Finck 
4896c2c66affSColin Finck     size = MAX_PATH;
4897c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4898c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4899c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4900c2c66affSColin Finck 
4901c2c66affSColin Finck     size = MAX_PATH;
4902c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4903c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4904c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4905c2c66affSColin Finck 
4906c2c66affSColin Finck     size = MAX_PATH;
4907c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4908c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4909c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4910c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4911c2c66affSColin Finck 
4912c2c66affSColin Finck     size = MAX_PATH;
4913c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4914c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4915c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4916c2c66affSColin Finck     if (space)
4917c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4918c2c66affSColin Finck     else
4919c2c66affSColin Finck         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4920c2c66affSColin Finck 
4921c2c66affSColin Finck     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4922c2c66affSColin Finck     RegDeleteValueA(hklm, "Value1");
4923c2c66affSColin Finck     RegDeleteValueA(hklm, "Value2");
4924c2c66affSColin Finck     RegDeleteValueA(hklm, "Value3");
4925c2c66affSColin Finck     RegDeleteValueA(hklm, "Value4");
4926c2c66affSColin Finck     RegDeleteValueA(hklm, "Value5");
4927c2c66affSColin Finck     RegDeleteValueA(hklm, "Value6");
4928c2c66affSColin Finck     RegDeleteValueA(hklm, "Value7");
4929c2c66affSColin Finck     RegDeleteValueA(hklm, "Value8");
4930c2c66affSColin Finck     RegDeleteValueA(hklm, "Value9");
4931c2c66affSColin Finck     RegDeleteValueA(hklm, "Value10");
4932c2c66affSColin Finck     RegDeleteValueA(hklm, "Value11");
4933c2c66affSColin Finck     RegDeleteValueA(hklm, "Value12");
4934c2c66affSColin Finck     RegDeleteValueA(hklm, "Value13");
4935c2c66affSColin Finck     RegDeleteValueA(hklm, "Value14");
4936c2c66affSColin Finck     RegDeleteValueA(hklm, "Value15");
4937c2c66affSColin Finck     RegDeleteValueA(hklm, "Value16");
4938c2c66affSColin Finck     RegDeleteValueA(hklm, "Value17");
4939c2c66affSColin Finck     RegDeleteKeyA(hklm, "");
4940c2c66affSColin Finck     RegCloseKey(hklm);
4941c2c66affSColin Finck 
4942c2c66affSColin Finck     RegDeleteValueA(classes, "Value1");
4943c2c66affSColin Finck     RegDeleteKeyA(classes, "");
4944c2c66affSColin Finck     RegCloseKey(classes);
4945c2c66affSColin Finck 
4946c2c66affSColin Finck     RegDeleteValueA(hkcu, "Value1");
4947c2c66affSColin Finck     RegDeleteKeyA(hkcu, "");
4948c2c66affSColin Finck     RegCloseKey(hkcu);
4949c2c66affSColin Finck 
4950c2c66affSColin Finck     RegDeleteValueA(users, "Value1");
4951c2c66affSColin Finck     RegDeleteKeyA(users, "");
4952c2c66affSColin Finck     RegCloseKey(users);
4953c2c66affSColin Finck 
4954c2c66affSColin Finck     DeleteFileA("FileName1");
4955c2c66affSColin Finck     DeleteFileA("FileName3.dll");
4956c2c66affSColin Finck     DeleteFileA("FileName4.dll");
4957c2c66affSColin Finck     DeleteFileA("FileName5.dll");
4958c2c66affSColin Finck     MsiCloseHandle(hpkg);
4959c2c66affSColin Finck     DeleteFileA(msifile);
4960c2c66affSColin Finck }
4961c2c66affSColin Finck 
4962c2c66affSColin Finck static void delete_win_ini(LPCSTR file)
4963c2c66affSColin Finck {
4964c2c66affSColin Finck     CHAR path[MAX_PATH];
4965c2c66affSColin Finck 
4966c2c66affSColin Finck     GetWindowsDirectoryA(path, MAX_PATH);
4967c2c66affSColin Finck     lstrcatA(path, "\\");
4968c2c66affSColin Finck     lstrcatA(path, file);
4969c2c66affSColin Finck 
4970c2c66affSColin Finck     DeleteFileA(path);
4971c2c66affSColin Finck }
4972c2c66affSColin Finck 
4973c2c66affSColin Finck static void test_appsearch_inilocator(void)
4974c2c66affSColin Finck {
4975c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4976c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4977c2c66affSColin Finck     BOOL version;
4978c2c66affSColin Finck     LPSTR ptr;
4979c2c66affSColin Finck     DWORD size;
4980c2c66affSColin Finck     UINT r;
4981c2c66affSColin Finck 
4982c2c66affSColin Finck     version = TRUE;
4983c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4984c2c66affSColin Finck         version = FALSE;
4985c2c66affSColin Finck 
4986c2c66affSColin Finck     DeleteFileA("test.dll");
4987c2c66affSColin Finck 
4988c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4989c2c66affSColin Finck 
4990c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4991c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4992c2c66affSColin Finck 
4993c2c66affSColin Finck     create_test_file("FileName1");
4994c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4995c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4996c2c66affSColin Finck 
4997c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4998c2c66affSColin Finck 
4999c2c66affSColin Finck     sprintf(path, "%s\\IDontExist", expected);
5000c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
5001c2c66affSColin Finck 
5002c2c66affSColin Finck     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5003c2c66affSColin Finck     sprintf(path, "%s\\FileName2.dll", expected);
5004c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
5005c2c66affSColin Finck 
5006c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5007c2c66affSColin Finck     sprintf(path, "%s\\FileName3.dll", expected);
5008c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
5009c2c66affSColin Finck 
5010c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5011c2c66affSColin Finck     sprintf(path, "%s\\FileName4.dll", expected);
5012c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
5013c2c66affSColin Finck 
5014c2c66affSColin Finck     hdb = create_package_db();
5015c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
5016c2c66affSColin Finck 
5017f860a780SAmine Khaldi     create_appsearch_table(hdb);
5018f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5019f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5020f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5021f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5022f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5023f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5024f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5025f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5026f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5027f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5028f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5029f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
5030c2c66affSColin Finck 
5031f860a780SAmine Khaldi     create_inilocator_table(hdb);
5032c2c66affSColin Finck 
5033c2c66affSColin Finck     /* msidbLocatorTypeRawValue, field 1 */
5034f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
5035c2c66affSColin Finck 
5036c2c66affSColin Finck     /* msidbLocatorTypeRawValue, field 2 */
5037f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
5038c2c66affSColin Finck 
5039c2c66affSColin Finck     /* msidbLocatorTypeRawValue, entire field */
5040f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
5041c2c66affSColin Finck 
5042c2c66affSColin Finck     /* msidbLocatorTypeFile */
5043f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
5044c2c66affSColin Finck 
5045c2c66affSColin Finck     /* msidbLocatorTypeDirectory, file */
5046f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
5047c2c66affSColin Finck 
5048c2c66affSColin Finck     /* msidbLocatorTypeDirectory, directory */
5049f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
5050c2c66affSColin Finck 
5051c2c66affSColin Finck     /* msidbLocatorTypeFile, file, no signature */
5052f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
5053c2c66affSColin Finck 
5054c2c66affSColin Finck     /* msidbLocatorTypeFile, dir, no signature */
5055f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
5056c2c66affSColin Finck 
5057c2c66affSColin Finck     /* msidbLocatorTypeFile, file does not exist */
5058f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
5059c2c66affSColin Finck 
5060c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version */
5061f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
5062c2c66affSColin Finck 
5063c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version, ver > max */
5064f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
5065c2c66affSColin Finck 
5066c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
5067f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
5068c2c66affSColin Finck 
5069f860a780SAmine Khaldi     create_signature_table(hdb);
5070f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
5071f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
5072f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5073f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5074f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5075c2c66affSColin Finck 
5076c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5077c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5078c2c66affSColin Finck     {
5079c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5080c2c66affSColin Finck         goto error;
5081c2c66affSColin Finck     }
5082c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5083c2c66affSColin Finck 
5084c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5085c2c66affSColin Finck 
5086c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
5087c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5088c2c66affSColin Finck 
5089c2c66affSColin Finck     size = MAX_PATH;
5090c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5091c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5092c2c66affSColin Finck     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
5093c2c66affSColin Finck 
5094c2c66affSColin Finck     size = MAX_PATH;
5095c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5096c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5097c2c66affSColin Finck     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5098c2c66affSColin Finck 
5099c2c66affSColin Finck     size = MAX_PATH;
5100c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5101c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5102c2c66affSColin Finck     ok(!lstrcmpA(prop, "keydata,field2"),
5103c2c66affSColin Finck        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5104c2c66affSColin Finck 
5105c2c66affSColin Finck     size = MAX_PATH;
5106c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
5107c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5108c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5109c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5110c2c66affSColin Finck 
5111c2c66affSColin Finck     size = MAX_PATH;
5112c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5113c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5114c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5115c2c66affSColin Finck 
5116c2c66affSColin Finck     size = MAX_PATH;
5117c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5118c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5119c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5120c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5121c2c66affSColin Finck 
5122c2c66affSColin Finck     size = MAX_PATH;
5123c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5124c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5125c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5126c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5127c2c66affSColin Finck 
5128c2c66affSColin Finck     if (!is_root(CURR_DIR))
5129c2c66affSColin Finck     {
5130c2c66affSColin Finck         size = MAX_PATH;
5131c2c66affSColin Finck         lstrcpyA(path, expected);
5132c2c66affSColin Finck         ptr = strrchr(path, '\\');
5133c2c66affSColin Finck         *(ptr + 1) = 0;
5134c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5135c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5136c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5137c2c66affSColin Finck     }
5138c2c66affSColin Finck     size = MAX_PATH;
5139c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5140c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5141c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5142c2c66affSColin Finck 
5143c2c66affSColin Finck     if (version)
5144c2c66affSColin Finck     {
5145c2c66affSColin Finck         size = MAX_PATH;
5146c2c66affSColin Finck         sprintf(path, "%s\\FileName2.dll", expected);
5147c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5148c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5149c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5150c2c66affSColin Finck 
5151c2c66affSColin Finck         size = MAX_PATH;
5152c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5153c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5154c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5155c2c66affSColin Finck 
5156c2c66affSColin Finck         size = MAX_PATH;
5157c2c66affSColin Finck         sprintf(path, "%s\\FileName4.dll", expected);
5158c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5159c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5160c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5161c2c66affSColin Finck     }
5162c2c66affSColin Finck 
5163c2c66affSColin Finck     MsiCloseHandle(hpkg);
5164c2c66affSColin Finck 
5165c2c66affSColin Finck error:
5166c2c66affSColin Finck     delete_win_ini("IniFile.ini");
5167c2c66affSColin Finck     DeleteFileA("FileName1");
5168c2c66affSColin Finck     DeleteFileA("FileName2.dll");
5169c2c66affSColin Finck     DeleteFileA("FileName3.dll");
5170c2c66affSColin Finck     DeleteFileA("FileName4.dll");
5171c2c66affSColin Finck     DeleteFileA(msifile);
5172c2c66affSColin Finck }
5173c2c66affSColin Finck 
5174c2c66affSColin Finck /*
5175c2c66affSColin Finck  * MSI AppSearch action on DrLocator table always returns absolute paths.
5176c2c66affSColin Finck  * If a relative path was set, it returns the first absolute path that
5177c2c66affSColin Finck  * matches or an empty string if it didn't find anything.
5178c2c66affSColin Finck  * This helper function replicates this behaviour.
5179c2c66affSColin Finck  */
5180c2c66affSColin Finck static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5181c2c66affSColin Finck {
5182c2c66affSColin Finck     int i, size;
5183c2c66affSColin Finck     DWORD attr, drives;
5184c2c66affSColin Finck 
5185c2c66affSColin Finck     size = lstrlenA(relative);
5186c2c66affSColin Finck     drives = GetLogicalDrives();
5187c2c66affSColin Finck     lstrcpyA(absolute, "A:\\");
5188c2c66affSColin Finck     for (i = 0; i < 26; absolute[0] = '\0', i++)
5189c2c66affSColin Finck     {
5190c2c66affSColin Finck         if (!(drives & (1 << i)))
5191c2c66affSColin Finck             continue;
5192c2c66affSColin Finck 
5193c2c66affSColin Finck         absolute[0] = 'A' + i;
5194c2c66affSColin Finck         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5195c2c66affSColin Finck             continue;
5196c2c66affSColin Finck 
5197c2c66affSColin Finck         lstrcpynA(absolute + 3, relative, size + 1);
5198c2c66affSColin Finck         attr = GetFileAttributesA(absolute);
5199c2c66affSColin Finck         if (attr != INVALID_FILE_ATTRIBUTES &&
5200c2c66affSColin Finck             (attr & FILE_ATTRIBUTE_DIRECTORY))
5201c2c66affSColin Finck         {
5202c2c66affSColin Finck             if (absolute[3 + size - 1] != '\\')
5203c2c66affSColin Finck                 lstrcatA(absolute, "\\");
5204c2c66affSColin Finck             break;
5205c2c66affSColin Finck         }
5206c2c66affSColin Finck         absolute[3] = '\0';
5207c2c66affSColin Finck     }
5208c2c66affSColin Finck }
5209c2c66affSColin Finck 
5210c2c66affSColin Finck static void test_appsearch_drlocator(void)
5211c2c66affSColin Finck {
5212c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
5213c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5214c2c66affSColin Finck     BOOL version;
5215c2c66affSColin Finck     DWORD size;
5216c2c66affSColin Finck     UINT r;
5217c2c66affSColin Finck 
5218c2c66affSColin Finck     version = TRUE;
5219c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5220c2c66affSColin Finck         version = FALSE;
5221c2c66affSColin Finck 
5222c2c66affSColin Finck     DeleteFileA("test.dll");
5223c2c66affSColin Finck 
5224c2c66affSColin Finck     create_test_file("FileName1");
5225c2c66affSColin Finck     CreateDirectoryA("one", NULL);
5226c2c66affSColin Finck     CreateDirectoryA("one\\two", NULL);
5227c2c66affSColin Finck     CreateDirectoryA("one\\two\\three", NULL);
5228c2c66affSColin Finck     create_test_file("one\\two\\three\\FileName2");
5229c2c66affSColin Finck     CreateDirectoryA("another", NULL);
5230c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5231c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5232c2c66affSColin Finck     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5233c2c66affSColin Finck 
5234c2c66affSColin Finck     hdb = create_package_db();
5235c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
5236c2c66affSColin Finck 
5237f860a780SAmine Khaldi     create_appsearch_table(hdb);
5238f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5239f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5240f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5241f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5242f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5243f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5244f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5245f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5246f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5247f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5248f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5249f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5250c2c66affSColin Finck 
5251f860a780SAmine Khaldi     create_drlocator_table(hdb);
5252c2c66affSColin Finck 
5253c2c66affSColin Finck     strcpy(expected, CURR_DIR);
5254c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
5255c2c66affSColin Finck 
5256c2c66affSColin Finck     /* no parent, full path, depth 0, signature */
5257c2c66affSColin Finck     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5258f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5259c2c66affSColin Finck 
5260c2c66affSColin Finck     /* no parent, full path, depth 0, no signature */
5261c2c66affSColin Finck     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5262f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5263c2c66affSColin Finck 
5264c2c66affSColin Finck     /* no parent, relative path, depth 0, no signature */
5265c2c66affSColin Finck     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5266f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5267c2c66affSColin Finck 
5268c2c66affSColin Finck     /* no parent, full path, depth 2, signature */
5269c2c66affSColin Finck     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5270f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5271c2c66affSColin Finck 
5272c2c66affSColin Finck     /* no parent, full path, depth 3, signature */
5273c2c66affSColin Finck     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5274f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5275c2c66affSColin Finck 
5276c2c66affSColin Finck     /* no parent, full path, depth 1, signature is dir */
5277c2c66affSColin Finck     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5278f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5279c2c66affSColin Finck 
5280c2c66affSColin Finck     /* parent is in DrLocator, relative path, depth 0, signature */
5281c2c66affSColin Finck     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5282f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5283c2c66affSColin Finck 
5284c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version */
5285c2c66affSColin Finck     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5286f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5287c2c66affSColin Finck 
5288c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version, ver > max */
5289c2c66affSColin Finck     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5290f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5291c2c66affSColin Finck 
5292c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5293c2c66affSColin Finck     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5294f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5295c2c66affSColin Finck 
5296c2c66affSColin Finck     /* no parent, relative empty path, depth 0, no signature */
5297c2c66affSColin Finck     sprintf(path, "'NewSignature11', '', '', 0");
5298f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5299c2c66affSColin Finck 
5300f860a780SAmine Khaldi     create_reglocator_table(hdb);
5301c2c66affSColin Finck 
5302c2c66affSColin Finck     /* parent */
5303f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5304c2c66affSColin Finck 
5305c2c66affSColin Finck     /* parent is in RegLocator, no path, depth 0, no signature */
5306c2c66affSColin Finck     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5307f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5308c2c66affSColin Finck 
5309f860a780SAmine Khaldi     create_signature_table(hdb);
5310f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5311f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5312f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5313f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5314f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5315f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5316f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5317f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5318c2c66affSColin Finck 
5319c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5320c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5321c2c66affSColin Finck     {
5322c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5323c2c66affSColin Finck         goto error;
5324c2c66affSColin Finck     }
5325c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5326c2c66affSColin Finck 
5327c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5328c2c66affSColin Finck 
5329c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
5330c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5331c2c66affSColin Finck 
5332c2c66affSColin Finck     size = MAX_PATH;
5333c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
5334c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5335c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5336c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5337c2c66affSColin Finck 
5338c2c66affSColin Finck     size = MAX_PATH;
5339c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5340c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5341c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5342c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5343c2c66affSColin Finck 
5344c2c66affSColin Finck     size = MAX_PATH;
5345c2c66affSColin Finck     search_absolute_directory(path, expected + 3);
5346c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5347c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5348c2c66affSColin Finck     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5349c2c66affSColin Finck 
5350c2c66affSColin Finck     size = MAX_PATH;
5351c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5352c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5353c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5354c2c66affSColin Finck 
5355c2c66affSColin Finck     size = MAX_PATH;
5356c2c66affSColin Finck     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5357c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5358c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5359c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5360c2c66affSColin Finck 
5361c2c66affSColin Finck     size = MAX_PATH;
5362c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5363c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5364c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5365c2c66affSColin Finck 
5366c2c66affSColin Finck     size = MAX_PATH;
5367c2c66affSColin Finck     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5368c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5369c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5370c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5371c2c66affSColin Finck 
5372c2c66affSColin Finck     if (version)
5373c2c66affSColin Finck     {
5374c2c66affSColin Finck         size = MAX_PATH;
5375c2c66affSColin Finck         sprintf(path, "%s\\FileName3.dll", expected);
5376c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5377c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5378c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5379c2c66affSColin Finck 
5380c2c66affSColin Finck         size = MAX_PATH;
5381c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5382c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5383c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5384c2c66affSColin Finck 
5385c2c66affSColin Finck         size = MAX_PATH;
5386c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5387c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5388c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5389c2c66affSColin Finck     }
5390c2c66affSColin Finck 
5391c2c66affSColin Finck     size = MAX_PATH;
5392c2c66affSColin Finck     search_absolute_directory(path, "");
5393c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5394c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5395c2c66affSColin Finck     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5396c2c66affSColin Finck 
5397c2c66affSColin Finck     size = MAX_PATH;
5398c2c66affSColin Finck     strcpy(path, "c:\\");
5399c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5400c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5401c2c66affSColin Finck     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5402c2c66affSColin Finck 
5403c2c66affSColin Finck     MsiCloseHandle(hpkg);
5404c2c66affSColin Finck 
5405c2c66affSColin Finck error:
5406c2c66affSColin Finck     DeleteFileA("FileName1");
5407c2c66affSColin Finck     DeleteFileA("FileName3.dll");
5408c2c66affSColin Finck     DeleteFileA("FileName4.dll");
5409c2c66affSColin Finck     DeleteFileA("FileName5.dll");
5410c2c66affSColin Finck     DeleteFileA("one\\two\\three\\FileName2");
5411c2c66affSColin Finck     RemoveDirectoryA("one\\two\\three");
5412c2c66affSColin Finck     RemoveDirectoryA("one\\two");
5413c2c66affSColin Finck     RemoveDirectoryA("one");
5414c2c66affSColin Finck     RemoveDirectoryA("another");
5415c2c66affSColin Finck     DeleteFileA(msifile);
5416c2c66affSColin Finck }
5417c2c66affSColin Finck 
5418c2c66affSColin Finck static void test_featureparents(void)
5419c2c66affSColin Finck {
5420c2c66affSColin Finck     MSIHANDLE hpkg;
5421c2c66affSColin Finck     UINT r;
5422c2c66affSColin Finck     MSIHANDLE hdb;
5423c2c66affSColin Finck 
5424c2c66affSColin Finck     hdb = create_package_db();
5425c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
5426c2c66affSColin Finck 
5427f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5428c2c66affSColin Finck 
5429f860a780SAmine Khaldi     create_feature_table( hdb );
5430f860a780SAmine Khaldi     create_component_table( hdb );
5431f860a780SAmine Khaldi     create_feature_components_table( hdb );
5432f860a780SAmine Khaldi     create_file_table( hdb );
5433c2c66affSColin Finck 
5434c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
5435f860a780SAmine Khaldi     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5436c2c66affSColin Finck 
5437c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
5438f860a780SAmine Khaldi     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5439c2c66affSColin Finck 
5440c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
5441f860a780SAmine Khaldi     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5442c2c66affSColin Finck 
5443c2c66affSColin Finck     /* msidbFeatureAttributesUIDisallowAbsent */
5444f860a780SAmine Khaldi     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5445c2c66affSColin Finck 
5446c2c66affSColin Finck     /* disabled because of install level */
5447f860a780SAmine Khaldi     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5448c2c66affSColin Finck 
5449c2c66affSColin Finck     /* child feature of disabled feature */
5450f860a780SAmine Khaldi     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5451c2c66affSColin Finck 
5452c2c66affSColin Finck     /* component of disabled feature (install level) */
5453f860a780SAmine Khaldi     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5454c2c66affSColin Finck 
5455c2c66affSColin Finck     /* component of disabled child feature (install level) */
5456f860a780SAmine Khaldi     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5457c2c66affSColin Finck 
5458c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5459f860a780SAmine Khaldi     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5460c2c66affSColin Finck 
5461c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5462f860a780SAmine Khaldi     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5463c2c66affSColin Finck 
5464c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5465f860a780SAmine Khaldi     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5466c2c66affSColin Finck 
5467c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5468f860a780SAmine Khaldi     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5469c2c66affSColin Finck 
5470c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5471f860a780SAmine Khaldi     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5472c2c66affSColin Finck 
5473c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5474f860a780SAmine Khaldi     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5475c2c66affSColin Finck 
5476c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5477f860a780SAmine Khaldi     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5478c2c66affSColin Finck 
5479c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5480f860a780SAmine Khaldi     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5481c2c66affSColin Finck 
5482c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5483f860a780SAmine Khaldi     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5484c2c66affSColin Finck 
5485f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5486f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5487f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5488f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5489f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5490f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5491f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'leo'" );
5492f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5493f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'libra'" );
5494f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5495f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5496f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5497f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'canis'" );
5498f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5499f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5500f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5501f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5502c2c66affSColin Finck 
5503f860a780SAmine Khaldi     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5504f860a780SAmine Khaldi     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5505f860a780SAmine Khaldi     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5506f860a780SAmine Khaldi     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5507f860a780SAmine Khaldi     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5508f860a780SAmine Khaldi     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5509f860a780SAmine Khaldi     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5510f860a780SAmine Khaldi     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5511f860a780SAmine Khaldi     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5512f860a780SAmine Khaldi     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5513f860a780SAmine Khaldi     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5514c2c66affSColin Finck 
5515c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
5516c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5517c2c66affSColin Finck     {
5518c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5519c2c66affSColin Finck         DeleteFileA(msifile);
5520c2c66affSColin Finck         return;
5521c2c66affSColin Finck     }
5522c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5523c2c66affSColin Finck 
5524c2c66affSColin Finck     MsiCloseHandle( hdb );
5525c2c66affSColin Finck 
5526c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5527c2c66affSColin Finck 
5528c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
5529c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
5530c2c66affSColin Finck 
5531c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
5532c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
5533c2c66affSColin Finck 
5534c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
5535c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5536c2c66affSColin Finck 
5537c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5538c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5539c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5540c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5541c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5542c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5543c2c66affSColin Finck 
5544c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5545c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5546c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5547c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5548c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5549c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5550c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5551c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5552c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5553c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5554c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5555c2c66affSColin Finck 
5556c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5557c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5558c2c66affSColin Finck 
5559c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5560c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5561c2c66affSColin Finck 
5562c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5563c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5564c2c66affSColin Finck 
5565c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5566c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5567c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5568c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5569c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5570c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5571c2c66affSColin Finck 
5572c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5573c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5574c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5575c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5576c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5577c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5578c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5579c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5580c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5581c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5582c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5583c2c66affSColin Finck 
5584c2c66affSColin Finck     MsiCloseHandle(hpkg);
5585c2c66affSColin Finck     DeleteFileA(msifile);
5586c2c66affSColin Finck }
5587c2c66affSColin Finck 
5588c2c66affSColin Finck static void test_installprops(void)
5589c2c66affSColin Finck {
5590c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
5591c2c66affSColin Finck     CHAR path[MAX_PATH], buf[MAX_PATH];
5592c2c66affSColin Finck     DWORD size, type;
5593c2c66affSColin Finck     LANGID langid;
55943ec0ea99Swinesync     HKEY hkey1, hkey2, pathkey;
5595c2c66affSColin Finck     int res;
5596c2c66affSColin Finck     UINT r;
5597c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
5598c2c66affSColin Finck     SYSTEM_INFO si;
5599c2c66affSColin Finck     INSTALLUILEVEL uilevel;
5600c2c66affSColin Finck 
5601c2c66affSColin Finck     if (is_wow64)
5602c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
5603c2c66affSColin Finck 
5604c2c66affSColin Finck     lstrcpyA(path, CURR_DIR);
5605c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5606c2c66affSColin Finck     lstrcatA(path, msifile);
5607c2c66affSColin Finck 
5608c2c66affSColin Finck     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5609c2c66affSColin Finck 
5610c2c66affSColin Finck     hdb = create_package_db();
5611c2c66affSColin Finck     ok( hdb, "failed to create database\n");
5612c2c66affSColin Finck 
5613c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5614c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5615c2c66affSColin Finck     {
5616c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5617c2c66affSColin Finck         MsiSetInternalUI(uilevel, NULL);
5618c2c66affSColin Finck         DeleteFileA(msifile);
5619c2c66affSColin Finck         return;
5620c2c66affSColin Finck     }
5621c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5622c2c66affSColin Finck 
5623c2c66affSColin Finck     MsiCloseHandle(hdb);
5624c2c66affSColin Finck 
5625c2c66affSColin Finck     buf[0] = 0;
5626c2c66affSColin Finck     size = MAX_PATH;
5627c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5628c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5629c2c66affSColin Finck     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5630c2c66affSColin Finck 
5631c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5632c2c66affSColin Finck 
5633c2c66affSColin Finck     buf[0] = 0;
5634c2c66affSColin Finck     size = MAX_PATH;
5635c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5636c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5637c2c66affSColin Finck     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5638c2c66affSColin Finck 
5639c2c66affSColin Finck     buf[0] = 0;
5640c2c66affSColin Finck     size = MAX_PATH;
5641c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5642c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5643c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5644c2c66affSColin Finck 
5645c2c66affSColin Finck     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5646c2c66affSColin Finck     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
56473ec0ea99Swinesync     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
56483ec0ea99Swinesync         0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &pathkey);
5649c2c66affSColin Finck 
5650c2c66affSColin Finck     size = MAX_PATH;
5651c2c66affSColin Finck     type = REG_SZ;
5652c2c66affSColin Finck     *path = '\0';
5653c2c66affSColin Finck     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5654c2c66affSColin Finck     {
5655c2c66affSColin Finck         size = MAX_PATH;
5656c2c66affSColin Finck         type = REG_SZ;
5657c2c66affSColin Finck         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5658c2c66affSColin Finck     }
5659c2c66affSColin Finck 
5660c2c66affSColin Finck     buf[0] = 0;
5661c2c66affSColin Finck     size = MAX_PATH;
5662c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5663c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5664c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5665c2c66affSColin Finck 
5666c2c66affSColin Finck     size = MAX_PATH;
5667c2c66affSColin Finck     type = REG_SZ;
5668c2c66affSColin Finck     *path = '\0';
5669c2c66affSColin Finck     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5670c2c66affSColin Finck     {
5671c2c66affSColin Finck         size = MAX_PATH;
5672c2c66affSColin Finck         type = REG_SZ;
5673c2c66affSColin Finck         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5674c2c66affSColin Finck     }
5675c2c66affSColin Finck 
5676c2c66affSColin Finck     if (*path)
5677c2c66affSColin Finck     {
5678c2c66affSColin Finck         buf[0] = 0;
5679c2c66affSColin Finck         size = MAX_PATH;
5680c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5681c2c66affSColin Finck         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5682c2c66affSColin Finck         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5683c2c66affSColin Finck     }
5684c2c66affSColin Finck 
5685c2c66affSColin Finck     buf[0] = 0;
5686c2c66affSColin Finck     size = MAX_PATH;
5687c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5688c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5689c2c66affSColin Finck     trace("VersionDatabase = %s\n", buf);
5690c2c66affSColin Finck 
5691c2c66affSColin Finck     buf[0] = 0;
5692c2c66affSColin Finck     size = MAX_PATH;
5693c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5694c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5695c2c66affSColin Finck     trace("VersionMsi = %s\n", buf);
5696c2c66affSColin Finck 
5697c2c66affSColin Finck     buf[0] = 0;
5698c2c66affSColin Finck     size = MAX_PATH;
5699c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5700c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5701c2c66affSColin Finck     trace("Date = %s\n", buf);
5702c2c66affSColin Finck 
5703c2c66affSColin Finck     buf[0] = 0;
5704c2c66affSColin Finck     size = MAX_PATH;
5705c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5706c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5707c2c66affSColin Finck     trace("Time = %s\n", buf);
5708c2c66affSColin Finck 
5709c2c66affSColin Finck     buf[0] = 0;
5710c2c66affSColin Finck     size = MAX_PATH;
5711c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5712c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5713c2c66affSColin Finck     trace("PackageCode = %s\n", buf);
5714c2c66affSColin Finck 
5715c2c66affSColin Finck     buf[0] = 0;
5716c2c66affSColin Finck     size = MAX_PATH;
5717c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5718c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5719c2c66affSColin Finck     trace("ComputerName = %s\n", buf);
5720c2c66affSColin Finck 
5721c2c66affSColin Finck     langid = GetUserDefaultLangID();
5722c2c66affSColin Finck     sprintf(path, "%d", langid);
5723c2c66affSColin Finck 
5724c2c66affSColin Finck     buf[0] = 0;
5725c2c66affSColin Finck     size = MAX_PATH;
5726c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5727c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5728c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5729c2c66affSColin Finck 
5730c2c66affSColin Finck     res = GetSystemMetrics(SM_CXSCREEN);
5731c2c66affSColin Finck     buf[0] = 0;
5732c2c66affSColin Finck     size = MAX_PATH;
5733c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5734c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
57353b835aa0Swinesync     ok(atol(buf) == res, "Expected %d, got %s\n", res, buf);
5736c2c66affSColin Finck 
5737c2c66affSColin Finck     res = GetSystemMetrics(SM_CYSCREEN);
5738c2c66affSColin Finck     buf[0] = 0;
5739c2c66affSColin Finck     size = MAX_PATH;
5740c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5741c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
57423b835aa0Swinesync     ok(atol(buf) == res, "Expected %d, got %s\n", res, buf);
5743c2c66affSColin Finck 
574431139640SAmine Khaldi     buf[0] = 0;
574531139640SAmine Khaldi     size = MAX_PATH;
574631139640SAmine Khaldi     r = MsiGetPropertyA(hpkg, "MsiNetAssemblySupport", buf, &size);
574731139640SAmine Khaldi     if (r == ERROR_SUCCESS) trace( "MsiNetAssemblySupport \"%s\"\n", buf );
574831139640SAmine Khaldi 
5749a4930636Swinesync     GetNativeSystemInfo(&si);
57503ec0ea99Swinesync 
5751c2c66affSColin Finck     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5752c2c66affSColin Finck     {
57533ec0ea99Swinesync         sprintf(buf, "%d", si.wProcessorLevel);
5754461c9cb7Swinesync         check_prop(hpkg, "Intel", buf, 1);
5755461c9cb7Swinesync         check_prop(hpkg, "MsiAMD64", buf, 1);
5756461c9cb7Swinesync         check_prop(hpkg, "Msix64", buf, 1);
57573ec0ea99Swinesync         sprintf(buf, "%d", LOBYTE(LOWORD(GetVersion())) * 100 + HIBYTE(LOWORD(GetVersion())));
5758461c9cb7Swinesync         check_prop(hpkg, "VersionNT64", buf, 1);
5759c2c66affSColin Finck 
5760c2c66affSColin Finck         GetSystemDirectoryA(path, MAX_PATH);
57613ec0ea99Swinesync         strcat(path, "\\");
5762461c9cb7Swinesync         check_prop(hpkg, "System64Folder", path, 0);
5763c2c66affSColin Finck 
5764a4930636Swinesync         GetSystemWow64DirectoryA(path, MAX_PATH);
57653ec0ea99Swinesync         strcat(path, "\\");
5766461c9cb7Swinesync         check_prop(hpkg, "SystemFolder", path, 0);
5767c2c66affSColin Finck 
5768c2c66affSColin Finck         size = MAX_PATH;
57693ec0ea99Swinesync         r = RegQueryValueExA(pathkey, "ProgramFilesDir (x86)", 0, &type, (BYTE *)path, &size);
57703ec0ea99Swinesync         strcat(path, "\\");
5771461c9cb7Swinesync         check_prop(hpkg, "ProgramFilesFolder", path, 0);
5772c2c66affSColin Finck 
5773c2c66affSColin Finck         size = MAX_PATH;
57743ec0ea99Swinesync         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
57753ec0ea99Swinesync         strcat(path, "\\");
5776461c9cb7Swinesync         check_prop(hpkg, "ProgramFiles64Folder", path, 0);
5777c2c66affSColin Finck 
5778c2c66affSColin Finck         size = MAX_PATH;
57793ec0ea99Swinesync         RegQueryValueExA(pathkey, "CommonFilesDir (x86)", 0, &type, (BYTE *)path, &size);
57803ec0ea99Swinesync         strcat(path, "\\");
5781461c9cb7Swinesync         check_prop(hpkg, "CommonFilesFolder", path, 0);
5782c2c66affSColin Finck 
5783c2c66affSColin Finck         size = MAX_PATH;
57843ec0ea99Swinesync         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
57853ec0ea99Swinesync         strcat(path, "\\");
5786461c9cb7Swinesync         check_prop(hpkg, "CommonFiles64Folder", path, 0);
5787c2c66affSColin Finck     }
5788c2c66affSColin Finck     else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5789c2c66affSColin Finck     {
57903ec0ea99Swinesync         sprintf(buf, "%d", si.wProcessorLevel);
5791461c9cb7Swinesync         check_prop(hpkg, "Intel", buf, 1);
5792c2c66affSColin Finck 
5793c2c66affSColin Finck         GetSystemDirectoryA(path, MAX_PATH);
57943ec0ea99Swinesync         strcat(path, "\\");
5795461c9cb7Swinesync         check_prop(hpkg, "SystemFolder", path, 0);
5796c2c66affSColin Finck 
5797c2c66affSColin Finck         size = MAX_PATH;
57983ec0ea99Swinesync         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
57993ec0ea99Swinesync         strcat(path, "\\");
5800461c9cb7Swinesync         check_prop(hpkg, "ProgramFilesFolder", path, 0);
5801c2c66affSColin Finck 
5802c2c66affSColin Finck         size = MAX_PATH;
58033ec0ea99Swinesync         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
58043ec0ea99Swinesync         strcat(path, "\\");
5805461c9cb7Swinesync         check_prop(hpkg, "CommonFilesFolder", path, 0);
5806c2c66affSColin Finck 
5807461c9cb7Swinesync         check_prop(hpkg, "MsiAMD64", "", 1);
5808461c9cb7Swinesync         check_prop(hpkg, "Msix64", "", 1);
5809461c9cb7Swinesync         check_prop(hpkg, "VersionNT64", "", 1);
5810461c9cb7Swinesync         check_prop(hpkg, "System64Folder", "", 0);
5811461c9cb7Swinesync         check_prop(hpkg, "ProgramFiles64Dir", "", 0);
5812461c9cb7Swinesync         check_prop(hpkg, "CommonFiles64Dir", "", 0);
5813c2c66affSColin Finck     }
5814c2c66affSColin Finck 
5815c2c66affSColin Finck     CloseHandle(hkey1);
5816c2c66affSColin Finck     CloseHandle(hkey2);
58173ec0ea99Swinesync     RegCloseKey(pathkey);
5818c2c66affSColin Finck     MsiCloseHandle(hpkg);
5819c2c66affSColin Finck     DeleteFileA(msifile);
5820c2c66affSColin Finck     MsiSetInternalUI(uilevel, NULL);
5821c2c66affSColin Finck }
5822c2c66affSColin Finck 
5823c2c66affSColin Finck static void test_launchconditions(void)
5824c2c66affSColin Finck {
5825c2c66affSColin Finck     MSIHANDLE hpkg;
5826c2c66affSColin Finck     MSIHANDLE hdb;
5827c2c66affSColin Finck     UINT r;
5828c2c66affSColin Finck 
5829c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5830c2c66affSColin Finck 
5831c2c66affSColin Finck     hdb = create_package_db();
5832c2c66affSColin Finck     ok( hdb, "failed to create package database\n" );
5833c2c66affSColin Finck 
5834f860a780SAmine Khaldi     create_launchcondition_table( hdb );
5835c2c66affSColin Finck 
5836f860a780SAmine Khaldi     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5837c2c66affSColin Finck 
5838c2c66affSColin Finck     /* invalid condition */
5839f860a780SAmine Khaldi     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5840c2c66affSColin Finck 
5841c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
5842c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5843c2c66affSColin Finck     {
5844c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5845c2c66affSColin Finck         DeleteFileA(msifile);
5846c2c66affSColin Finck         return;
5847c2c66affSColin Finck     }
5848c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5849c2c66affSColin Finck 
5850c2c66affSColin Finck     MsiCloseHandle( hdb );
5851c2c66affSColin Finck 
5852c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "X", "1" );
5853c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5854c2c66affSColin Finck 
5855c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5856c2c66affSColin Finck 
5857c2c66affSColin Finck     /* invalid conditions are ignored */
5858c2c66affSColin Finck     r = MsiDoActionA( hpkg, "LaunchConditions" );
5859c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5860c2c66affSColin Finck 
5861c2c66affSColin Finck     /* verify LaunchConditions still does some verification */
5862c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "X", "2" );
5863c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5864c2c66affSColin Finck 
5865c2c66affSColin Finck     r = MsiDoActionA( hpkg, "LaunchConditions" );
5866c2c66affSColin Finck     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5867c2c66affSColin Finck 
5868c2c66affSColin Finck     MsiCloseHandle( hpkg );
5869c2c66affSColin Finck     DeleteFileA( msifile );
5870c2c66affSColin Finck }
5871c2c66affSColin Finck 
5872c2c66affSColin Finck static void test_ccpsearch(void)
5873c2c66affSColin Finck {
5874c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
5875c2c66affSColin Finck     CHAR prop[MAX_PATH];
5876c2c66affSColin Finck     DWORD size = MAX_PATH;
5877c2c66affSColin Finck     UINT r;
5878c2c66affSColin Finck 
5879c2c66affSColin Finck     hdb = create_package_db();
5880c2c66affSColin Finck     ok(hdb, "failed to create package database\n");
5881c2c66affSColin Finck 
5882f860a780SAmine Khaldi     create_ccpsearch_table(hdb);
5883f860a780SAmine Khaldi     add_ccpsearch_entry(hdb, "'CCP_random'");
5884f860a780SAmine Khaldi     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5885c2c66affSColin Finck 
5886f860a780SAmine Khaldi     create_reglocator_table(hdb);
5887f860a780SAmine Khaldi     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5888c2c66affSColin Finck 
5889f860a780SAmine Khaldi     create_drlocator_table(hdb);
5890f860a780SAmine Khaldi     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5891c2c66affSColin Finck 
5892f860a780SAmine Khaldi     create_signature_table(hdb);
5893c2c66affSColin Finck 
5894c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5895c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5896c2c66affSColin Finck     {
5897c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5898c2c66affSColin Finck         DeleteFileA(msifile);
5899c2c66affSColin Finck         return;
5900c2c66affSColin Finck     }
5901c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5902c2c66affSColin Finck 
5903c2c66affSColin Finck     MsiCloseHandle(hdb);
5904c2c66affSColin Finck 
5905c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5906c2c66affSColin Finck 
5907c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CCPSearch");
5908c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5909c2c66affSColin Finck 
5910c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5911c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5912c2c66affSColin Finck     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5913c2c66affSColin Finck 
5914c2c66affSColin Finck     MsiCloseHandle(hpkg);
5915c2c66affSColin Finck     DeleteFileA(msifile);
5916c2c66affSColin Finck }
5917c2c66affSColin Finck 
5918c2c66affSColin Finck static void test_complocator(void)
5919c2c66affSColin Finck {
5920c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
5921c2c66affSColin Finck     UINT r;
5922c2c66affSColin Finck     CHAR prop[MAX_PATH];
5923c2c66affSColin Finck     CHAR expected[MAX_PATH];
5924c2c66affSColin Finck     DWORD size = MAX_PATH;
5925c2c66affSColin Finck 
5926c2c66affSColin Finck     hdb = create_package_db();
5927c2c66affSColin Finck     ok(hdb, "failed to create package database\n");
5928c2c66affSColin Finck 
5929f860a780SAmine Khaldi     create_appsearch_table(hdb);
5930f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5931f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5932f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5933f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5934f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5935f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
5936f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
5937f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
5938f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
5939f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
5940f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
5941f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
5942f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
5943f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
5944f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
5945f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
5946c2c66affSColin Finck 
5947f860a780SAmine Khaldi     create_complocator_table(hdb);
5948f860a780SAmine Khaldi     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
5949f860a780SAmine Khaldi     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
5950f860a780SAmine Khaldi     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
5951f860a780SAmine Khaldi     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
5952f860a780SAmine Khaldi     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
5953f860a780SAmine Khaldi     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
5954f860a780SAmine Khaldi     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
5955f860a780SAmine Khaldi     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
5956f860a780SAmine Khaldi     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
5957f860a780SAmine Khaldi     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
5958f860a780SAmine Khaldi     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
5959f860a780SAmine Khaldi     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
5960f860a780SAmine Khaldi     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
5961f860a780SAmine Khaldi     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
5962f860a780SAmine Khaldi     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
5963f860a780SAmine Khaldi     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
5964c2c66affSColin Finck 
5965f860a780SAmine Khaldi     create_signature_table(hdb);
5966f860a780SAmine Khaldi     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
5967f860a780SAmine Khaldi     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
5968f860a780SAmine Khaldi     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
5969f860a780SAmine Khaldi     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
5970f860a780SAmine Khaldi     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
5971f860a780SAmine Khaldi     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
5972f860a780SAmine Khaldi     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
5973f860a780SAmine Khaldi     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
5974c2c66affSColin Finck 
5975c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5976c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5977c2c66affSColin Finck     {
5978c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5979c2c66affSColin Finck         DeleteFileA(msifile);
5980c2c66affSColin Finck         return;
5981c2c66affSColin Finck     }
5982c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5983c2c66affSColin Finck 
5984c2c66affSColin Finck     MsiCloseHandle(hdb);
5985c2c66affSColin Finck 
5986c2c66affSColin Finck     create_test_file("abelisaurus");
5987c2c66affSColin Finck     create_test_file("bactrosaurus");
5988c2c66affSColin Finck     create_test_file("camelotia");
5989c2c66affSColin Finck     create_test_file("diclonius");
5990c2c66affSColin Finck     create_test_file("echinodon");
5991c2c66affSColin Finck     create_test_file("falcarius");
5992c2c66affSColin Finck     create_test_file("gallimimus");
5993c2c66affSColin Finck     create_test_file("hagryphus");
5994c2c66affSColin Finck     CreateDirectoryA("iguanodon", NULL);
5995c2c66affSColin Finck     CreateDirectoryA("jobaria", NULL);
5996c2c66affSColin Finck     CreateDirectoryA("kakuru", NULL);
5997c2c66affSColin Finck     CreateDirectoryA("labocania", NULL);
5998c2c66affSColin Finck     CreateDirectoryA("megaraptor", NULL);
5999c2c66affSColin Finck     CreateDirectoryA("neosodon", NULL);
6000c2c66affSColin Finck     CreateDirectoryA("olorotitan", NULL);
6001c2c66affSColin Finck     CreateDirectoryA("pantydraco", NULL);
6002c2c66affSColin Finck 
6003c2c66affSColin Finck     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
6004c2c66affSColin Finck                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
6005c2c66affSColin Finck     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
6006c2c66affSColin Finck                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
6007c2c66affSColin Finck     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
6008c2c66affSColin Finck                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
6009c2c66affSColin Finck     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
6010c2c66affSColin Finck                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
6011c2c66affSColin Finck     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6012c2c66affSColin Finck                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6013c2c66affSColin Finck     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6014c2c66affSColin Finck                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6015c2c66affSColin Finck     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6016c2c66affSColin Finck                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6017c2c66affSColin Finck     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6018c2c66affSColin Finck                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6019c2c66affSColin Finck 
6020c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6021c2c66affSColin Finck 
6022c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
6023c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6024c2c66affSColin Finck 
6025c2c66affSColin Finck     size = MAX_PATH;
6026c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6027c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6028c2c66affSColin Finck 
6029c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6030c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6031c2c66affSColin Finck     lstrcatA(expected, "abelisaurus");
6032c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6033c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6034c2c66affSColin Finck 
6035c2c66affSColin Finck     size = MAX_PATH;
6036c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6037c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6038c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6039c2c66affSColin Finck 
6040c2c66affSColin Finck     size = MAX_PATH;
6041c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6042c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6043c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6044c2c66affSColin Finck 
6045c2c66affSColin Finck     size = MAX_PATH;
6046c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6047c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6048c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6049c2c66affSColin Finck 
6050c2c66affSColin Finck     size = MAX_PATH;
6051c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6052c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6053c2c66affSColin Finck 
6054c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6055c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6056c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6057c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6058c2c66affSColin Finck 
6059c2c66affSColin Finck     size = MAX_PATH;
6060c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6061c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6062c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6063c2c66affSColin Finck 
6064c2c66affSColin Finck     size = MAX_PATH;
6065c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6066c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6067c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6068c2c66affSColin Finck 
6069c2c66affSColin Finck     size = MAX_PATH;
6070c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6071c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6072c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6073c2c66affSColin Finck 
6074c2c66affSColin Finck     size = MAX_PATH;
6075c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6076c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6077c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6078c2c66affSColin Finck 
6079c2c66affSColin Finck     size = MAX_PATH;
6080c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6081c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6082c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6083c2c66affSColin Finck 
6084c2c66affSColin Finck     size = MAX_PATH;
6085c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6086c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6087c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6088c2c66affSColin Finck 
6089c2c66affSColin Finck     size = MAX_PATH;
6090c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6091c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6092c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6093c2c66affSColin Finck 
6094c2c66affSColin Finck     size = MAX_PATH;
6095c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6096c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6097c2c66affSColin Finck 
6098c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6099c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6100c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6101c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6102c2c66affSColin Finck 
6103c2c66affSColin Finck     size = MAX_PATH;
6104c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6105c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6106c2c66affSColin Finck 
6107c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6108c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6109c2c66affSColin Finck     lstrcatA(expected, "neosodon\\");
6110c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6111c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6112c2c66affSColin Finck 
6113c2c66affSColin Finck     size = MAX_PATH;
6114c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6115c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6116c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6117c2c66affSColin Finck 
6118c2c66affSColin Finck     size = MAX_PATH;
6119c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6120c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6121c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6122c2c66affSColin Finck 
6123c2c66affSColin Finck     MsiCloseHandle(hpkg);
6124c2c66affSColin Finck     DeleteFileA("abelisaurus");
6125c2c66affSColin Finck     DeleteFileA("bactrosaurus");
6126c2c66affSColin Finck     DeleteFileA("camelotia");
6127c2c66affSColin Finck     DeleteFileA("diclonius");
6128c2c66affSColin Finck     DeleteFileA("echinodon");
6129c2c66affSColin Finck     DeleteFileA("falcarius");
6130c2c66affSColin Finck     DeleteFileA("gallimimus");
6131c2c66affSColin Finck     DeleteFileA("hagryphus");
6132c2c66affSColin Finck     RemoveDirectoryA("iguanodon");
6133c2c66affSColin Finck     RemoveDirectoryA("jobaria");
6134c2c66affSColin Finck     RemoveDirectoryA("kakuru");
6135c2c66affSColin Finck     RemoveDirectoryA("labocania");
6136c2c66affSColin Finck     RemoveDirectoryA("megaraptor");
6137c2c66affSColin Finck     RemoveDirectoryA("neosodon");
6138c2c66affSColin Finck     RemoveDirectoryA("olorotitan");
6139c2c66affSColin Finck     RemoveDirectoryA("pantydraco");
6140c2c66affSColin Finck     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6141c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6142c2c66affSColin Finck     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6143c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6144c2c66affSColin Finck     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6145c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6146c2c66affSColin Finck     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6147c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6148c2c66affSColin Finck     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6149c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6150c2c66affSColin Finck     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6151c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6152c2c66affSColin Finck     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6153c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6154c2c66affSColin Finck     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6155c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6156c2c66affSColin Finck     DeleteFileA(msifile);
6157c2c66affSColin Finck }
6158c2c66affSColin Finck 
6159c2c66affSColin Finck static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6160c2c66affSColin Finck {
6161c2c66affSColin Finck     MSIHANDLE summary;
6162c2c66affSColin Finck     UINT r;
6163c2c66affSColin Finck 
6164c2c66affSColin Finck     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6165c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6166c2c66affSColin Finck 
6167c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6168c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6169c2c66affSColin Finck 
6170c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
6171c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6172c2c66affSColin Finck 
6173c2c66affSColin Finck     MsiCloseHandle(summary);
6174c2c66affSColin Finck }
6175c2c66affSColin Finck 
6176c2c66affSColin Finck static void test_MsiGetSourcePath(void)
6177c2c66affSColin Finck {
6178c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
6179c2c66affSColin Finck     CHAR path[MAX_PATH];
6180c2c66affSColin Finck     CHAR cwd[MAX_PATH];
6181c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
6182c2c66affSColin Finck     CHAR sub2[MAX_PATH];
6183c2c66affSColin Finck     DWORD size;
6184c2c66affSColin Finck     UINT r;
6185c2c66affSColin Finck 
6186c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
6187c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6188c2c66affSColin Finck 
6189c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
6190c2c66affSColin Finck     lstrcatA(subsrc, "subsource");
6191c2c66affSColin Finck     lstrcatA(subsrc, "\\");
6192c2c66affSColin Finck 
6193c2c66affSColin Finck     lstrcpyA(sub2, subsrc);
6194c2c66affSColin Finck     lstrcatA(sub2, "sub2");
6195c2c66affSColin Finck     lstrcatA(sub2, "\\");
6196c2c66affSColin Finck 
6197c2c66affSColin Finck     /* uncompressed source */
6198c2c66affSColin Finck 
6199c2c66affSColin Finck     hdb = create_package_db();
6200c2c66affSColin Finck     ok( hdb, "failed to create database\n");
6201c2c66affSColin Finck 
6202c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6203c2c66affSColin Finck 
6204f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6205f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6206f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6207c2c66affSColin Finck 
6208c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
6209c2c66affSColin Finck     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6210c2c66affSColin Finck 
6211c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6212c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6213c2c66affSColin Finck     {
6214c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
6215c2c66affSColin Finck         DeleteFileA(msifile);
6216c2c66affSColin Finck         return;
6217c2c66affSColin Finck     }
6218c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6219c2c66affSColin Finck 
6220c2c66affSColin Finck     MsiCloseHandle(hdb);
6221c2c66affSColin Finck 
6222c2c66affSColin Finck     /* invalid database handle */
6223c2c66affSColin Finck     size = MAX_PATH;
6224c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6225c2c66affSColin Finck     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6226c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
6227c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6228c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6229c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6230c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6231c2c66affSColin Finck 
6232c2c66affSColin Finck     /* NULL szFolder */
6233c2c66affSColin Finck     size = MAX_PATH;
6234c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6235c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6236c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
6237c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6238c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6239c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6240c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6241c2c66affSColin Finck 
6242c2c66affSColin Finck     /* empty szFolder */
6243c2c66affSColin Finck     size = MAX_PATH;
6244c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6245c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "", path, &size);
6246c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6247c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6248c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6249c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6250c2c66affSColin Finck 
6251c2c66affSColin Finck     /* try TARGETDIR */
6252c2c66affSColin Finck     size = MAX_PATH;
6253c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6254c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6255c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6256c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6257c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6258c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6259c2c66affSColin Finck 
6260c2c66affSColin Finck     size = MAX_PATH;
6261c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6262c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6263c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6264c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6265c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6266c2c66affSColin Finck 
6267c2c66affSColin Finck     size = MAX_PATH;
6268c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6269c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6270c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6271c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6272c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6273c2c66affSColin Finck 
6274c2c66affSColin Finck     /* try SourceDir */
6275c2c66affSColin Finck     size = MAX_PATH;
6276c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6277c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6278c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6279c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6280c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6281c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6282c2c66affSColin Finck 
6283c2c66affSColin Finck     /* try SOURCEDIR */
6284c2c66affSColin Finck     size = MAX_PATH;
6285c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6286c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6287c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6288c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6289c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6290c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6291c2c66affSColin Finck 
6292c2c66affSColin Finck     /* source path does not exist, but the property exists */
6293c2c66affSColin Finck     size = MAX_PATH;
6294c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6295c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6296c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6297c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6298c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6299c2c66affSColin Finck 
6300c2c66affSColin Finck     size = MAX_PATH;
6301c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6302c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6303c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6304c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6305c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6306c2c66affSColin Finck 
6307c2c66affSColin Finck     /* try SubDir */
6308c2c66affSColin Finck     size = MAX_PATH;
6309c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6310c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6311c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6312c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6313c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6314c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6315c2c66affSColin Finck 
6316c2c66affSColin Finck     /* try SubDir2 */
6317c2c66affSColin Finck     size = MAX_PATH;
6318c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6319c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6320c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6321c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6322c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6323c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6324c2c66affSColin Finck 
6325c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6326c2c66affSColin Finck 
6327c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6328c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "cost init failed\n");
6329c2c66affSColin Finck 
6330c2c66affSColin Finck     /* try TARGETDIR after CostInitialize */
6331c2c66affSColin Finck     size = MAX_PATH;
6332c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6333c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6334c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6335c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6336c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6337c2c66affSColin Finck 
6338c2c66affSColin Finck     /* try SourceDir after CostInitialize */
6339c2c66affSColin Finck     size = MAX_PATH;
6340c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6341c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6342c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6343c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6344c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6345c2c66affSColin Finck 
6346c2c66affSColin Finck     /* try SOURCEDIR after CostInitialize */
6347c2c66affSColin Finck     size = MAX_PATH;
6348c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6349c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6350c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6351c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6352c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6353c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6354c2c66affSColin Finck 
6355c2c66affSColin Finck     /* source path does not exist, but the property exists */
6356c2c66affSColin Finck     size = MAX_PATH;
6357c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6358c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6359c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6360c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6361c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6362c2c66affSColin Finck 
6363c2c66affSColin Finck     size = MAX_PATH;
6364c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6365c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6366c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6367c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6368c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6369c2c66affSColin Finck 
6370c2c66affSColin Finck     /* try SubDir after CostInitialize */
6371c2c66affSColin Finck     size = MAX_PATH;
6372c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6373c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6374c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6375c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6376c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6377c2c66affSColin Finck 
6378c2c66affSColin Finck     /* try SubDir2 after CostInitialize */
6379c2c66affSColin Finck     size = MAX_PATH;
6380c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6381c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6382c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6383c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6384c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6385c2c66affSColin Finck 
6386c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
6387c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6388c2c66affSColin Finck 
6389c2c66affSColin Finck     /* try TARGETDIR after ResolveSource */
6390c2c66affSColin Finck     size = MAX_PATH;
6391c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6392c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6393c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6394c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6395c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6396c2c66affSColin Finck 
6397c2c66affSColin Finck     /* try SourceDir after ResolveSource */
6398c2c66affSColin Finck     size = MAX_PATH;
6399c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6400c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6401c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6402c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6403c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6404c2c66affSColin Finck 
6405c2c66affSColin Finck     /* try SOURCEDIR after ResolveSource */
6406c2c66affSColin Finck     size = MAX_PATH;
6407c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6408c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6409c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6410c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6411c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6412c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6413c2c66affSColin Finck 
6414c2c66affSColin Finck     /* source path does not exist, but the property exists */
6415c2c66affSColin Finck     size = MAX_PATH;
6416c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6417c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6418c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6419c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6420c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6421c2c66affSColin Finck 
6422c2c66affSColin Finck     size = MAX_PATH;
6423c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6424c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6425c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6426c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6427c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6428c2c66affSColin Finck 
6429c2c66affSColin Finck     /* try SubDir after ResolveSource */
6430c2c66affSColin Finck     size = MAX_PATH;
6431c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6432c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6433c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6434c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6435c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6436c2c66affSColin Finck 
6437c2c66affSColin Finck     /* try SubDir2 after ResolveSource */
6438c2c66affSColin Finck     size = MAX_PATH;
6439c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6440c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6441c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6442c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6443c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6444c2c66affSColin Finck 
6445c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
6446c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6447c2c66affSColin Finck 
6448c2c66affSColin Finck     /* try TARGETDIR after FileCost */
6449c2c66affSColin Finck     size = MAX_PATH;
6450c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6451c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6452c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6453c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6454c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6455c2c66affSColin Finck 
6456c2c66affSColin Finck     /* try SourceDir after FileCost */
6457c2c66affSColin Finck     size = MAX_PATH;
6458c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6459c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6460c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6461c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6462c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6463c2c66affSColin Finck 
6464c2c66affSColin Finck     /* try SOURCEDIR after FileCost */
6465c2c66affSColin Finck     size = MAX_PATH;
6466c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6467c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6468c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6469c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6470c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6471c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6472c2c66affSColin Finck 
6473c2c66affSColin Finck     /* source path does not exist, but the property exists */
6474c2c66affSColin Finck     size = MAX_PATH;
6475c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6476c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6477c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6478c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6479c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6480c2c66affSColin Finck 
6481c2c66affSColin Finck     size = MAX_PATH;
6482c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6483c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6484c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6485c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6486c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6487c2c66affSColin Finck 
6488c2c66affSColin Finck     /* try SubDir after FileCost */
6489c2c66affSColin Finck     size = MAX_PATH;
6490c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6491c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6492c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6493c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6494c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6495c2c66affSColin Finck 
6496c2c66affSColin Finck     /* try SubDir2 after FileCost */
6497c2c66affSColin Finck     size = MAX_PATH;
6498c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6499c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6500c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6501c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6502c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6503c2c66affSColin Finck 
6504c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
6505c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6506c2c66affSColin Finck 
6507c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6508c2c66affSColin Finck     size = MAX_PATH;
6509c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6510c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6511c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6512c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6513c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6514c2c66affSColin Finck 
6515c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6516c2c66affSColin Finck     size = MAX_PATH;
6517c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6518c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6519c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6520c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6521c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6522c2c66affSColin Finck 
6523c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6524c2c66affSColin Finck     size = MAX_PATH;
6525c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6526c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6527c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6528c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6529c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6530c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6531c2c66affSColin Finck 
6532c2c66affSColin Finck     /* source path does not exist, but the property exists */
6533c2c66affSColin Finck     size = MAX_PATH;
6534c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6535c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6536c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6537c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6538c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6539c2c66affSColin Finck 
6540c2c66affSColin Finck     size = MAX_PATH;
6541c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6542c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6543c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6544c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6545c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6546c2c66affSColin Finck 
6547c2c66affSColin Finck     /* try SubDir after CostFinalize */
6548c2c66affSColin Finck     size = MAX_PATH;
6549c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6550c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6551c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6552c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6553c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6554c2c66affSColin Finck 
6555c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6556c2c66affSColin Finck     size = MAX_PATH;
6557c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6558c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6559c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6560c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6561c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6562c2c66affSColin Finck 
6563c2c66affSColin Finck     /* nonexistent directory */
6564c2c66affSColin Finck     size = MAX_PATH;
6565c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6566c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6567c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6568c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6569c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6570c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6571c2c66affSColin Finck 
6572c2c66affSColin Finck     /* NULL szPathBuf */
6573c2c66affSColin Finck     size = MAX_PATH;
6574c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6575c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6576c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6577c2c66affSColin Finck 
6578c2c66affSColin Finck     /* NULL pcchPathBuf */
6579c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6580c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6581c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
6582c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6583c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6584c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6585c2c66affSColin Finck 
6586c2c66affSColin Finck     /* pcchPathBuf is 0 */
6587c2c66affSColin Finck     size = 0;
6588c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6589c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6590c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6591c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6592c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6593c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6594c2c66affSColin Finck 
6595c2c66affSColin Finck     /* pcchPathBuf does not have room for NULL terminator */
6596c2c66affSColin Finck     size = lstrlenA(cwd);
6597c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6598c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6599c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6600c2c66affSColin Finck     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6601c2c66affSColin Finck        "Expected path with no backslash, got \"%s\"\n", path);
6602c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6603c2c66affSColin Finck 
6604c2c66affSColin Finck     /* pcchPathBuf has room for NULL terminator */
6605c2c66affSColin Finck     size = lstrlenA(cwd) + 1;
6606c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6607c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6608c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6609c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6610c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6611c2c66affSColin Finck 
6612c2c66affSColin Finck     /* remove property */
6613c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6614c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6615c2c66affSColin Finck 
6616c2c66affSColin Finck     /* try SourceDir again */
6617c2c66affSColin Finck     size = MAX_PATH;
6618c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6619c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6620c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6621c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6622c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6623c2c66affSColin Finck 
6624c2c66affSColin Finck     /* set property to a valid directory */
6625c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6626c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6627c2c66affSColin Finck 
6628c2c66affSColin Finck     /* try SOURCEDIR again */
6629c2c66affSColin Finck     size = MAX_PATH;
6630c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6631c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6632c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6633c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6634c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6635c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6636c2c66affSColin Finck 
6637c2c66affSColin Finck     MsiCloseHandle(hpkg);
6638c2c66affSColin Finck 
6639c2c66affSColin Finck     /* compressed source */
6640c2c66affSColin Finck 
6641c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6642c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6643c2c66affSColin Finck 
6644c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6645c2c66affSColin Finck 
6646c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6647c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6648c2c66affSColin Finck 
6649c2c66affSColin Finck     /* try TARGETDIR */
6650c2c66affSColin Finck     size = MAX_PATH;
6651c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6652c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6653c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6654c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6655c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6656c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6657c2c66affSColin Finck 
6658c2c66affSColin Finck     /* try SourceDir */
6659c2c66affSColin Finck     size = MAX_PATH;
6660c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6661c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6662c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6663c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6664c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6665c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6666c2c66affSColin Finck 
6667c2c66affSColin Finck     /* try SOURCEDIR */
6668c2c66affSColin Finck     size = MAX_PATH;
6669c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6670c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6671c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6672c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6673c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6674c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6675c2c66affSColin Finck 
6676c2c66affSColin Finck     /* source path nor the property exist */
6677c2c66affSColin Finck     size = MAX_PATH;
6678c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6679c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6680c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6681c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6682c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6683c2c66affSColin Finck 
6684c2c66affSColin Finck     size = MAX_PATH;
6685c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6686c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6687c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6688c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6689c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6690c2c66affSColin Finck 
6691c2c66affSColin Finck     /* try SubDir */
6692c2c66affSColin Finck     size = MAX_PATH;
6693c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6694c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6695c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6696c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6697c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6698c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6699c2c66affSColin Finck 
6700c2c66affSColin Finck     /* try SubDir2 */
6701c2c66affSColin Finck     size = MAX_PATH;
6702c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6703c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6704c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6705c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6706c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6707c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6708c2c66affSColin Finck 
6709c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6710c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6711c2c66affSColin Finck 
6712c2c66affSColin Finck     /* try TARGETDIR after CostInitialize */
6713c2c66affSColin Finck     size = MAX_PATH;
6714c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6715c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6716c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6717c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6718c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6719c2c66affSColin Finck 
6720c2c66affSColin Finck     /* try SourceDir after CostInitialize */
6721c2c66affSColin Finck     size = MAX_PATH;
6722c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6723c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6724c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6725c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6726c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6727c2c66affSColin Finck 
6728c2c66affSColin Finck     /* try SOURCEDIR after CostInitialize */
6729c2c66affSColin Finck     size = MAX_PATH;
6730c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6731c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6732c2c66affSColin Finck     todo_wine
6733c2c66affSColin Finck     {
6734c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6735c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6736c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6737c2c66affSColin Finck     }
6738c2c66affSColin Finck 
6739c2c66affSColin Finck     /* source path does not exist, but the property exists */
6740c2c66affSColin Finck     size = MAX_PATH;
6741c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6742c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6743c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6744c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6745c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6746c2c66affSColin Finck 
6747c2c66affSColin Finck     size = MAX_PATH;
6748c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6749c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6750c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6751c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6752c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6753c2c66affSColin Finck 
6754c2c66affSColin Finck     /* try SubDir after CostInitialize */
6755c2c66affSColin Finck     size = MAX_PATH;
6756c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6757c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6758c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6759c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6760c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6761c2c66affSColin Finck 
6762c2c66affSColin Finck     /* try SubDir2 after CostInitialize */
6763c2c66affSColin Finck     size = MAX_PATH;
6764c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6765c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6766c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6767c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6768c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6769c2c66affSColin Finck 
6770c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
6771c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6772c2c66affSColin Finck 
6773c2c66affSColin Finck     /* try TARGETDIR after ResolveSource */
6774c2c66affSColin Finck     size = MAX_PATH;
6775c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6776c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6777c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6778c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6779c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6780c2c66affSColin Finck 
6781c2c66affSColin Finck     /* try SourceDir after ResolveSource */
6782c2c66affSColin Finck     size = MAX_PATH;
6783c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6784c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6785c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6786c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6787c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6788c2c66affSColin Finck 
6789c2c66affSColin Finck     /* try SOURCEDIR after ResolveSource */
6790c2c66affSColin Finck     size = MAX_PATH;
6791c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6792c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6793c2c66affSColin Finck     todo_wine
6794c2c66affSColin Finck     {
6795c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6796c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6797c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6798c2c66affSColin Finck     }
6799c2c66affSColin Finck 
6800c2c66affSColin Finck     /* source path and the property exist */
6801c2c66affSColin Finck     size = MAX_PATH;
6802c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6803c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6804c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6805c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6806c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6807c2c66affSColin Finck 
6808c2c66affSColin Finck     size = MAX_PATH;
6809c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6810c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6811c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6812c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6813c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6814c2c66affSColin Finck 
6815c2c66affSColin Finck     /* try SubDir after ResolveSource */
6816c2c66affSColin Finck     size = MAX_PATH;
6817c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6818c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6819c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6820c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6821c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6822c2c66affSColin Finck 
6823c2c66affSColin Finck     /* try SubDir2 after ResolveSource */
6824c2c66affSColin Finck     size = MAX_PATH;
6825c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6826c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6827c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6828c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6829c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6830c2c66affSColin Finck 
6831c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
6832c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6833c2c66affSColin Finck 
6834c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6835c2c66affSColin Finck     size = MAX_PATH;
6836c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6837c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6838c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6839c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6840c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6841c2c66affSColin Finck 
6842c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6843c2c66affSColin Finck     size = MAX_PATH;
6844c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6845c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6846c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6847c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6848c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6849c2c66affSColin Finck 
6850c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6851c2c66affSColin Finck     size = MAX_PATH;
6852c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6853c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6854c2c66affSColin Finck     todo_wine
6855c2c66affSColin Finck     {
6856c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6857c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6858c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6859c2c66affSColin Finck     }
6860c2c66affSColin Finck 
6861c2c66affSColin Finck     /* source path and the property exist */
6862c2c66affSColin Finck     size = MAX_PATH;
6863c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6864c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6865c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6866c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6867c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6868c2c66affSColin Finck 
6869c2c66affSColin Finck     size = MAX_PATH;
6870c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6871c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6872c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6873c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6874c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6875c2c66affSColin Finck 
6876c2c66affSColin Finck     /* try SubDir after CostFinalize */
6877c2c66affSColin Finck     size = MAX_PATH;
6878c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6879c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6880c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6881c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6882c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6883c2c66affSColin Finck 
6884c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6885c2c66affSColin Finck     size = MAX_PATH;
6886c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6887c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6888c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6889c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6890c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6891c2c66affSColin Finck 
6892c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
6893c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6894c2c66affSColin Finck 
6895c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6896c2c66affSColin Finck     size = MAX_PATH;
6897c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6898c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6899c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6900c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6901c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6902c2c66affSColin Finck 
6903c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6904c2c66affSColin Finck     size = MAX_PATH;
6905c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6906c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6907c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6908c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6909c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6910c2c66affSColin Finck 
6911c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6912c2c66affSColin Finck     size = MAX_PATH;
6913c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6914c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6915c2c66affSColin Finck     todo_wine
6916c2c66affSColin Finck     {
6917c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6918c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6919c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6920c2c66affSColin Finck     }
6921c2c66affSColin Finck 
6922c2c66affSColin Finck     /* source path and the property exist */
6923c2c66affSColin Finck     size = MAX_PATH;
6924c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6925c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6926c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6927c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6928c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6929c2c66affSColin Finck 
6930c2c66affSColin Finck     size = MAX_PATH;
6931c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6932c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6933c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6934c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6935c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6936c2c66affSColin Finck 
6937c2c66affSColin Finck     /* try SubDir after CostFinalize */
6938c2c66affSColin Finck     size = MAX_PATH;
6939c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6940c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6941c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6942c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6943c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6944c2c66affSColin Finck 
6945c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6946c2c66affSColin Finck     size = MAX_PATH;
6947c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6948c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6949c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6950c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6951c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6952c2c66affSColin Finck 
6953c2c66affSColin Finck     MsiCloseHandle(hpkg);
6954c2c66affSColin Finck     DeleteFileA(msifile);
6955c2c66affSColin Finck }
6956c2c66affSColin Finck 
6957c2c66affSColin Finck static void test_shortlongsource(void)
6958c2c66affSColin Finck {
6959c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
6960c2c66affSColin Finck     CHAR path[MAX_PATH];
6961c2c66affSColin Finck     CHAR cwd[MAX_PATH];
6962c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
6963c2c66affSColin Finck     DWORD size;
6964c2c66affSColin Finck     UINT r;
6965c2c66affSColin Finck 
6966c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
6967c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6968c2c66affSColin Finck 
6969c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
6970c2c66affSColin Finck     lstrcatA(subsrc, "long");
6971c2c66affSColin Finck     lstrcatA(subsrc, "\\");
6972c2c66affSColin Finck 
6973c2c66affSColin Finck     /* long file names */
6974c2c66affSColin Finck 
6975c2c66affSColin Finck     hdb = create_package_db();
6976c2c66affSColin Finck     ok( hdb, "failed to create database\n");
6977c2c66affSColin Finck 
6978c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6979c2c66affSColin Finck 
6980f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6981f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
6982c2c66affSColin Finck 
6983c2c66affSColin Finck     /* CostInitialize:short */
6984f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
6985c2c66affSColin Finck 
6986c2c66affSColin Finck     /* CostInitialize:long */
6987f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
6988c2c66affSColin Finck 
6989c2c66affSColin Finck     /* FileCost:short */
6990f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
6991c2c66affSColin Finck 
6992c2c66affSColin Finck     /* FileCost:long */
6993f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
6994c2c66affSColin Finck 
6995c2c66affSColin Finck     /* CostFinalize:short */
6996f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
6997c2c66affSColin Finck 
6998c2c66affSColin Finck     /* CostFinalize:long */
6999f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
7000c2c66affSColin Finck 
7001f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
7002f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
7003c2c66affSColin Finck 
7004c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
7005c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7006c2c66affSColin Finck     {
7007c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7008c2c66affSColin Finck         DeleteFileA(msifile);
7009c2c66affSColin Finck         return;
7010c2c66affSColin Finck     }
7011c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7012c2c66affSColin Finck 
7013c2c66affSColin Finck     MsiCloseHandle(hdb);
7014c2c66affSColin Finck 
7015c2c66affSColin Finck     CreateDirectoryA("one", NULL);
7016c2c66affSColin Finck     CreateDirectoryA("four", NULL);
7017c2c66affSColin Finck 
7018c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7019c2c66affSColin Finck 
7020c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7021c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7022c2c66affSColin Finck 
7023c2c66affSColin Finck     CreateDirectoryA("five", NULL);
7024c2c66affSColin Finck     CreateDirectoryA("eight", NULL);
7025c2c66affSColin Finck 
7026c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7027c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7028c2c66affSColin Finck 
7029c2c66affSColin Finck     CreateDirectoryA("nine", NULL);
7030c2c66affSColin Finck     CreateDirectoryA("twelve", NULL);
7031c2c66affSColin Finck 
7032c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7033c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7034c2c66affSColin Finck 
7035c2c66affSColin Finck     /* neither short nor long source directories exist */
7036c2c66affSColin Finck     size = MAX_PATH;
7037c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7038c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7039c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7040c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7041c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7042c2c66affSColin Finck 
7043c2c66affSColin Finck     CreateDirectoryA("short", NULL);
7044c2c66affSColin Finck 
7045c2c66affSColin Finck     /* short source directory exists */
7046c2c66affSColin Finck     size = MAX_PATH;
7047c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7048c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7049c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7050c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7051c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7052c2c66affSColin Finck 
7053c2c66affSColin Finck     CreateDirectoryA("long", NULL);
7054c2c66affSColin Finck 
7055c2c66affSColin Finck     /* both short and long source directories exist */
7056c2c66affSColin Finck     size = MAX_PATH;
7057c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7058c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7059c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7060c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7061c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7062c2c66affSColin Finck 
7063c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7064c2c66affSColin Finck     lstrcatA(subsrc, "two");
7065c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7066c2c66affSColin Finck 
7067c2c66affSColin Finck     /* short dir exists before CostInitialize */
7068c2c66affSColin Finck     size = MAX_PATH;
7069c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7070c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7071c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7072c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7073c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7074c2c66affSColin Finck 
7075c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7076c2c66affSColin Finck     lstrcatA(subsrc, "four");
7077c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7078c2c66affSColin Finck 
7079c2c66affSColin Finck     /* long dir exists before CostInitialize */
7080c2c66affSColin Finck     size = MAX_PATH;
7081c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7082c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7083c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7084c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7085c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7086c2c66affSColin Finck 
7087c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7088c2c66affSColin Finck     lstrcatA(subsrc, "six");
7089c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7090c2c66affSColin Finck 
7091c2c66affSColin Finck     /* short dir exists before FileCost */
7092c2c66affSColin Finck     size = MAX_PATH;
7093c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7094c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7095c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7096c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7097c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7098c2c66affSColin Finck 
7099c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7100c2c66affSColin Finck     lstrcatA(subsrc, "eight");
7101c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7102c2c66affSColin Finck 
7103c2c66affSColin Finck     /* long dir exists before FileCost */
7104c2c66affSColin Finck     size = MAX_PATH;
7105c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7106c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7107c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7108c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7109c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7110c2c66affSColin Finck 
7111c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7112c2c66affSColin Finck     lstrcatA(subsrc, "ten");
7113c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7114c2c66affSColin Finck 
7115c2c66affSColin Finck     /* short dir exists before CostFinalize */
7116c2c66affSColin Finck     size = MAX_PATH;
7117c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7118c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7119c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7120c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7121c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7122c2c66affSColin Finck 
7123c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7124c2c66affSColin Finck     lstrcatA(subsrc, "twelve");
7125c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7126c2c66affSColin Finck 
7127c2c66affSColin Finck     /* long dir exists before CostFinalize */
7128c2c66affSColin Finck     size = MAX_PATH;
7129c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7130c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7131c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7132c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7133c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7134c2c66affSColin Finck 
7135c2c66affSColin Finck     MsiCloseHandle(hpkg);
7136c2c66affSColin Finck     RemoveDirectoryA("short");
7137c2c66affSColin Finck     RemoveDirectoryA("long");
7138c2c66affSColin Finck     RemoveDirectoryA("one");
7139c2c66affSColin Finck     RemoveDirectoryA("four");
7140c2c66affSColin Finck     RemoveDirectoryA("five");
7141c2c66affSColin Finck     RemoveDirectoryA("eight");
7142c2c66affSColin Finck     RemoveDirectoryA("nine");
7143c2c66affSColin Finck     RemoveDirectoryA("twelve");
7144c2c66affSColin Finck 
7145c2c66affSColin Finck     /* short file names */
7146c2c66affSColin Finck 
7147c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7148c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7149c2c66affSColin Finck 
7150c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7151c2c66affSColin Finck 
7152c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
7153c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7154c2c66affSColin Finck 
7155c2c66affSColin Finck     MsiCloseHandle(hdb);
7156c2c66affSColin Finck 
7157c2c66affSColin Finck     CreateDirectoryA("one", NULL);
7158c2c66affSColin Finck     CreateDirectoryA("four", NULL);
7159c2c66affSColin Finck 
7160c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7161c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7162c2c66affSColin Finck 
7163c2c66affSColin Finck     CreateDirectoryA("five", NULL);
7164c2c66affSColin Finck     CreateDirectoryA("eight", NULL);
7165c2c66affSColin Finck 
7166c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7167c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7168c2c66affSColin Finck 
7169c2c66affSColin Finck     CreateDirectoryA("nine", NULL);
7170c2c66affSColin Finck     CreateDirectoryA("twelve", NULL);
7171c2c66affSColin Finck 
7172c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7173c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7174c2c66affSColin Finck 
7175c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7176c2c66affSColin Finck     lstrcatA(subsrc, "short");
7177c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7178c2c66affSColin Finck 
7179c2c66affSColin Finck     /* neither short nor long source directories exist */
7180c2c66affSColin Finck     size = MAX_PATH;
7181c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7182c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7183c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7184c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7185c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7186c2c66affSColin Finck 
7187c2c66affSColin Finck     CreateDirectoryA("short", NULL);
7188c2c66affSColin Finck 
7189c2c66affSColin Finck     /* short source directory exists */
7190c2c66affSColin Finck     size = MAX_PATH;
7191c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7192c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7193c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7194c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7195c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7196c2c66affSColin Finck 
7197c2c66affSColin Finck     CreateDirectoryA("long", NULL);
7198c2c66affSColin Finck 
7199c2c66affSColin Finck     /* both short and long source directories exist */
7200c2c66affSColin Finck     size = MAX_PATH;
7201c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7202c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7203c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7204c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7205c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7206c2c66affSColin Finck 
7207c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7208c2c66affSColin Finck     lstrcatA(subsrc, "one");
7209c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7210c2c66affSColin Finck 
7211c2c66affSColin Finck     /* short dir exists before CostInitialize */
7212c2c66affSColin Finck     size = MAX_PATH;
7213c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7214c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7215c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7216c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7217c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7218c2c66affSColin Finck 
7219c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7220c2c66affSColin Finck     lstrcatA(subsrc, "three");
7221c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7222c2c66affSColin Finck 
7223c2c66affSColin Finck     /* long dir exists before CostInitialize */
7224c2c66affSColin Finck     size = MAX_PATH;
7225c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7226c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7227c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7228c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7229c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7230c2c66affSColin Finck 
7231c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7232c2c66affSColin Finck     lstrcatA(subsrc, "five");
7233c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7234c2c66affSColin Finck 
7235c2c66affSColin Finck     /* short dir exists before FileCost */
7236c2c66affSColin Finck     size = MAX_PATH;
7237c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7238c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7239c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7240c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7241c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7242c2c66affSColin Finck 
7243c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7244c2c66affSColin Finck     lstrcatA(subsrc, "seven");
7245c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7246c2c66affSColin Finck 
7247c2c66affSColin Finck     /* long dir exists before FileCost */
7248c2c66affSColin Finck     size = MAX_PATH;
7249c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7250c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7251c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7252c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7253c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7254c2c66affSColin Finck 
7255c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7256c2c66affSColin Finck     lstrcatA(subsrc, "nine");
7257c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7258c2c66affSColin Finck 
7259c2c66affSColin Finck     /* short dir exists before CostFinalize */
7260c2c66affSColin Finck     size = MAX_PATH;
7261c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7262c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7263c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7264c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7265c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7266c2c66affSColin Finck 
7267c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7268c2c66affSColin Finck     lstrcatA(subsrc, "eleven");
7269c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7270c2c66affSColin Finck 
7271c2c66affSColin Finck     /* long dir exists before CostFinalize */
7272c2c66affSColin Finck     size = MAX_PATH;
7273c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7274c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7275c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7276c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7277c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7278c2c66affSColin Finck 
7279c2c66affSColin Finck     MsiCloseHandle(hpkg);
7280c2c66affSColin Finck     RemoveDirectoryA("short");
7281c2c66affSColin Finck     RemoveDirectoryA("long");
7282c2c66affSColin Finck     RemoveDirectoryA("one");
7283c2c66affSColin Finck     RemoveDirectoryA("four");
7284c2c66affSColin Finck     RemoveDirectoryA("five");
7285c2c66affSColin Finck     RemoveDirectoryA("eight");
7286c2c66affSColin Finck     RemoveDirectoryA("nine");
7287c2c66affSColin Finck     RemoveDirectoryA("twelve");
7288c2c66affSColin Finck     DeleteFileA(msifile);
7289c2c66affSColin Finck }
7290c2c66affSColin Finck 
7291c2c66affSColin Finck static void test_sourcedir(void)
7292c2c66affSColin Finck {
7293c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
7294c2c66affSColin Finck     CHAR package[12];
7295c2c66affSColin Finck     CHAR path[MAX_PATH];
7296c2c66affSColin Finck     CHAR cwd[MAX_PATH];
7297c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
7298c2c66affSColin Finck     DWORD size;
7299c2c66affSColin Finck     UINT r;
7300c2c66affSColin Finck 
7301c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
7302c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7303c2c66affSColin Finck 
7304c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7305c2c66affSColin Finck     lstrcatA(subsrc, "long");
7306c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7307c2c66affSColin Finck 
7308c2c66affSColin Finck     hdb = create_package_db();
7309c2c66affSColin Finck     ok( hdb, "failed to create database\n");
7310c2c66affSColin Finck 
7311f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7312c2c66affSColin Finck 
7313c2c66affSColin Finck     sprintf(package, "#%u", hdb);
7314c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
7315c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7316c2c66affSColin Finck     {
7317c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7318c2c66affSColin Finck         goto error;
7319c2c66affSColin Finck     }
7320c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7321c2c66affSColin Finck 
7322c2c66affSColin Finck     /* properties only */
7323c2c66affSColin Finck 
7324c2c66affSColin Finck     /* SourceDir prop */
7325c2c66affSColin Finck     size = MAX_PATH;
7326c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7327c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7328c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7329c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7330c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7331c2c66affSColin Finck 
7332c2c66affSColin Finck     /* SOURCEDIR prop */
7333c2c66affSColin Finck     size = MAX_PATH;
7334c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7335c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7336c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7337c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7338c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7339c2c66affSColin Finck 
7340c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7341c2c66affSColin Finck 
7342c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7343c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7344c2c66affSColin Finck 
7345c2c66affSColin Finck     /* SourceDir after CostInitialize */
7346c2c66affSColin Finck     size = MAX_PATH;
7347c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7348c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7349c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7350c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7351c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7352c2c66affSColin Finck 
7353c2c66affSColin Finck     /* SOURCEDIR after CostInitialize */
7354c2c66affSColin Finck     size = MAX_PATH;
7355c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7356c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7357c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7358c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7359c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7360c2c66affSColin Finck 
7361c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7362c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7363c2c66affSColin Finck 
7364c2c66affSColin Finck     /* SourceDir after FileCost */
7365c2c66affSColin Finck     size = MAX_PATH;
7366c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7367c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7368c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7369c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7370c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7371c2c66affSColin Finck 
7372c2c66affSColin Finck     /* SOURCEDIR after FileCost */
7373c2c66affSColin Finck     size = MAX_PATH;
7374c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7375c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7376c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7377c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7378c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7379c2c66affSColin Finck 
7380c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7381c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7382c2c66affSColin Finck 
7383c2c66affSColin Finck     /* SourceDir after CostFinalize */
7384c2c66affSColin Finck     size = MAX_PATH;
7385c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7386c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7387c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7388c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7389c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7390c2c66affSColin Finck 
7391c2c66affSColin Finck     /* SOURCEDIR after CostFinalize */
7392c2c66affSColin Finck     size = MAX_PATH;
7393c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7394c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7395c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7396c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7397c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7398c2c66affSColin Finck 
7399c2c66affSColin Finck     size = MAX_PATH;
7400c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7401c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7402c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7403c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7404c2c66affSColin Finck     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7405c2c66affSColin Finck 
7406c2c66affSColin Finck     /* SOURCEDIR after calling MsiGetSourcePath */
7407c2c66affSColin Finck     size = MAX_PATH;
7408c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7409c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7410c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7411c2c66affSColin Finck     todo_wine {
7412c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7413c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7414c2c66affSColin Finck     }
7415c2c66affSColin Finck 
7416c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
7417c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7418c2c66affSColin Finck 
7419c2c66affSColin Finck     /* SourceDir after ResolveSource */
7420c2c66affSColin Finck     size = MAX_PATH;
7421c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7422c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7423c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7424c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7425c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7426c2c66affSColin Finck 
7427c2c66affSColin Finck     /* SOURCEDIR after ResolveSource */
7428c2c66affSColin Finck     size = MAX_PATH;
7429c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7430c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7431c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7432c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7433c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7434c2c66affSColin Finck 
7435c2c66affSColin Finck     /* random casing */
7436c2c66affSColin Finck     size = MAX_PATH;
7437c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7438c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7439c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7440c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7441c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7442c2c66affSColin Finck 
7443c2c66affSColin Finck     MsiCloseHandle(hpkg);
7444c2c66affSColin Finck 
7445c2c66affSColin Finck     /* reset the package state */
7446c2c66affSColin Finck     sprintf(package, "#%i", hdb);
7447c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
7448c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7449c2c66affSColin Finck 
7450c2c66affSColin Finck     /* test how MsiGetSourcePath affects the properties */
7451c2c66affSColin Finck 
7452c2c66affSColin Finck     /* SourceDir prop */
7453c2c66affSColin Finck     size = MAX_PATH;
7454c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7455c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7456c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7457c2c66affSColin Finck     todo_wine
7458c2c66affSColin Finck     {
7459c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7460c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7461c2c66affSColin Finck     }
7462c2c66affSColin Finck 
7463c2c66affSColin Finck     size = MAX_PATH;
7464c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7465c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7466c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7467c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7468c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7469c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7470c2c66affSColin Finck 
7471c2c66affSColin Finck     /* SourceDir after MsiGetSourcePath */
7472c2c66affSColin Finck     size = MAX_PATH;
7473c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7474c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7475c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7476c2c66affSColin Finck     todo_wine
7477c2c66affSColin Finck     {
7478c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7479c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7480c2c66affSColin Finck     }
7481c2c66affSColin Finck 
7482c2c66affSColin Finck     /* SOURCEDIR prop */
7483c2c66affSColin Finck     size = MAX_PATH;
7484c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7485c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7486c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7487c2c66affSColin Finck     todo_wine
7488c2c66affSColin Finck     {
7489c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7490c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7491c2c66affSColin Finck     }
7492c2c66affSColin Finck 
7493c2c66affSColin Finck     size = MAX_PATH;
7494c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7495c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7496c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7497c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7498c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7499c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7500c2c66affSColin Finck 
7501c2c66affSColin Finck     /* SOURCEDIR prop after MsiGetSourcePath */
7502c2c66affSColin Finck     size = MAX_PATH;
7503c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7504c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7505c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7506c2c66affSColin Finck     todo_wine
7507c2c66affSColin Finck     {
7508c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7509c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7510c2c66affSColin Finck     }
7511c2c66affSColin Finck 
7512c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7513c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7514c2c66affSColin Finck 
7515c2c66affSColin Finck     /* SourceDir after CostInitialize */
7516c2c66affSColin Finck     size = MAX_PATH;
7517c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7518c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7519c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7520c2c66affSColin Finck     todo_wine
7521c2c66affSColin Finck     {
7522c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7523c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7524c2c66affSColin Finck     }
7525c2c66affSColin Finck 
7526c2c66affSColin Finck     size = MAX_PATH;
7527c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7528c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7529c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7530c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7531c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7532c2c66affSColin Finck 
7533c2c66affSColin Finck     /* SourceDir after MsiGetSourcePath */
7534c2c66affSColin Finck     size = MAX_PATH;
7535c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7536c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7537c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7538c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7539c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7540c2c66affSColin Finck 
7541c2c66affSColin Finck     /* SOURCEDIR after CostInitialize */
7542c2c66affSColin Finck     size = MAX_PATH;
7543c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7544c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7545c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7546c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7547c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7548c2c66affSColin Finck 
7549c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7550c2c66affSColin Finck     size = MAX_PATH;
7551c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7552c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7553c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7554c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7555c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7556c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7557c2c66affSColin Finck 
7558c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7559c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7560c2c66affSColin Finck 
7561c2c66affSColin Finck     /* SourceDir after FileCost */
7562c2c66affSColin Finck     size = MAX_PATH;
7563c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7564c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7565c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7566c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7567c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7568c2c66affSColin Finck 
7569c2c66affSColin Finck     /* SOURCEDIR after FileCost */
7570c2c66affSColin Finck     size = MAX_PATH;
7571c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7572c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7573c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7574c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7575c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7576c2c66affSColin Finck 
7577c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7578c2c66affSColin Finck     size = MAX_PATH;
7579c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7580c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7581c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7582c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7583c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7584c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7585c2c66affSColin Finck 
7586c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7587c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7588c2c66affSColin Finck 
7589c2c66affSColin Finck     /* SourceDir after CostFinalize */
7590c2c66affSColin Finck     size = MAX_PATH;
7591c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7592c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7593c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7594c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7595c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7596c2c66affSColin Finck 
7597c2c66affSColin Finck     /* SOURCEDIR after CostFinalize */
7598c2c66affSColin Finck     size = MAX_PATH;
7599c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7600c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7601c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7602c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7603c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7604c2c66affSColin Finck 
7605c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7606c2c66affSColin Finck     size = MAX_PATH;
7607c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7608c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7609c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7610c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7611c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7612c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7613c2c66affSColin Finck 
7614c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
7615c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7616c2c66affSColin Finck 
7617c2c66affSColin Finck     /* SourceDir after ResolveSource */
7618c2c66affSColin Finck     size = MAX_PATH;
7619c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7620c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7621c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7622c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7623c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7624c2c66affSColin Finck 
7625c2c66affSColin Finck     /* SOURCEDIR after ResolveSource */
7626c2c66affSColin Finck     size = MAX_PATH;
7627c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7628c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7629c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7630c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7631c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7632c2c66affSColin Finck 
7633c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7634c2c66affSColin Finck     size = MAX_PATH;
7635c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7636c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7637c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7638c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7639c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7640c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7641c2c66affSColin Finck 
7642c2c66affSColin Finck     MsiCloseHandle(hpkg);
7643c2c66affSColin Finck 
7644c2c66affSColin Finck error:
7645c2c66affSColin Finck     MsiCloseHandle(hdb);
7646c2c66affSColin Finck     DeleteFileA(msifile);
7647c2c66affSColin Finck }
7648c2c66affSColin Finck 
7649c2c66affSColin Finck struct access_res
7650c2c66affSColin Finck {
7651c2c66affSColin Finck     BOOL gothandle;
7652c2c66affSColin Finck     DWORD lasterr;
7653c2c66affSColin Finck     BOOL ignore;
7654c2c66affSColin Finck };
7655c2c66affSColin Finck 
7656c2c66affSColin Finck static const struct access_res create[16] =
7657c2c66affSColin Finck {
7658c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7659c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7660c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7661c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7662c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7663c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7664c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7665c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7666c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7667c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7668c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7669c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7670c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7671c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7672c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7673c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE }
7674c2c66affSColin Finck };
7675c2c66affSColin Finck 
7676c2c66affSColin Finck static const struct access_res create_commit[16] =
7677c2c66affSColin Finck {
7678c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7679c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7680c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7681c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7682c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7683c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7684c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7685c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7686c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7687c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7688c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7689c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7690c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7691c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7692c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7693c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE }
7694c2c66affSColin Finck };
7695c2c66affSColin Finck 
7696c2c66affSColin Finck static const struct access_res create_close[16] =
7697c2c66affSColin Finck {
7698c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7699c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7700c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7701c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7702c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7703c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7704c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7705c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7706c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7707c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7708c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7709c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7710c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7711c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7712c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7713c2c66affSColin Finck     { TRUE, ERROR_SUCCESS }
7714c2c66affSColin Finck };
7715c2c66affSColin Finck 
7716c2c66affSColin Finck static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7717c2c66affSColin Finck {
7718c2c66affSColin Finck     DWORD access = 0, share = 0;
7719c2c66affSColin Finck     DWORD lasterr;
7720c2c66affSColin Finck     HANDLE hfile;
7721c2c66affSColin Finck     int i, j, idx = 0;
7722c2c66affSColin Finck 
7723c2c66affSColin Finck     for (i = 0; i < 4; i++)
7724c2c66affSColin Finck     {
7725c2c66affSColin Finck         if (i == 0) access = 0;
7726c2c66affSColin Finck         if (i == 1) access = GENERIC_READ;
7727c2c66affSColin Finck         if (i == 2) access = GENERIC_WRITE;
7728c2c66affSColin Finck         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7729c2c66affSColin Finck 
7730c2c66affSColin Finck         for (j = 0; j < 4; j++)
7731c2c66affSColin Finck         {
7732c2c66affSColin Finck             if (ares[idx].ignore)
7733c2c66affSColin Finck                 continue;
7734c2c66affSColin Finck 
7735c2c66affSColin Finck             if (j == 0) share = 0;
7736c2c66affSColin Finck             if (j == 1) share = FILE_SHARE_READ;
7737c2c66affSColin Finck             if (j == 2) share = FILE_SHARE_WRITE;
7738c2c66affSColin Finck             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7739c2c66affSColin Finck 
7740c2c66affSColin Finck             SetLastError(0xdeadbeef);
7741c2c66affSColin Finck             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7742c2c66affSColin Finck                                 FILE_ATTRIBUTE_NORMAL, 0);
7743c2c66affSColin Finck             lasterr = GetLastError();
7744c2c66affSColin Finck 
7745c2c66affSColin Finck             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7746c2c66affSColin Finck                "(%d, handle, %d): Expected %d, got %d\n",
7747c2c66affSColin Finck                line, idx, ares[idx].gothandle,
7748c2c66affSColin Finck                (hfile != INVALID_HANDLE_VALUE));
7749c2c66affSColin Finck 
7750c2c66affSColin Finck             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
7751c2c66affSColin Finck                line, idx, ares[idx].lasterr, lasterr);
7752c2c66affSColin Finck 
7753c2c66affSColin Finck             CloseHandle(hfile);
7754c2c66affSColin Finck             idx++;
7755c2c66affSColin Finck         }
7756c2c66affSColin Finck     }
7757c2c66affSColin Finck }
7758c2c66affSColin Finck 
7759c2c66affSColin Finck #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7760c2c66affSColin Finck 
7761c2c66affSColin Finck static void test_access(void)
7762c2c66affSColin Finck {
7763c2c66affSColin Finck     MSIHANDLE hdb;
7764c2c66affSColin Finck     UINT r;
7765c2c66affSColin Finck 
7766c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7767c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7768c2c66affSColin Finck 
7769c2c66affSColin Finck     test_file_access(msifile, create);
7770c2c66affSColin Finck 
7771c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7772c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7773c2c66affSColin Finck 
7774c2c66affSColin Finck     test_file_access(msifile, create_commit);
7775c2c66affSColin Finck     MsiCloseHandle(hdb);
7776c2c66affSColin Finck 
7777c2c66affSColin Finck     test_file_access(msifile, create_close);
7778c2c66affSColin Finck     DeleteFileA(msifile);
7779c2c66affSColin Finck 
7780c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7781c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7782c2c66affSColin Finck 
7783c2c66affSColin Finck     test_file_access(msifile, create);
7784c2c66affSColin Finck 
7785c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7786c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7787c2c66affSColin Finck 
7788c2c66affSColin Finck     test_file_access(msifile, create_commit);
7789c2c66affSColin Finck     MsiCloseHandle(hdb);
7790c2c66affSColin Finck 
7791c2c66affSColin Finck     test_file_access(msifile, create_close);
7792c2c66affSColin Finck     DeleteFileA(msifile);
7793c2c66affSColin Finck }
7794c2c66affSColin Finck 
7795c2c66affSColin Finck static void test_emptypackage(void)
7796c2c66affSColin Finck {
7797c2c66affSColin Finck     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7798c2c66affSColin Finck     MSIHANDLE hview = 0, hrec = 0;
7799c2c66affSColin Finck     MSICONDITION condition;
7800c2c66affSColin Finck     CHAR buffer[MAX_PATH];
7801c2c66affSColin Finck     DWORD size;
7802c2c66affSColin Finck     UINT r;
7803c2c66affSColin Finck 
7804c2c66affSColin Finck     r = MsiOpenPackageA("", &hpkg);
7805c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7806c2c66affSColin Finck     {
7807c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7808c2c66affSColin Finck         return;
7809c2c66affSColin Finck     }
7810c2c66affSColin Finck     todo_wine
7811c2c66affSColin Finck     {
7812c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7813c2c66affSColin Finck     }
7814c2c66affSColin Finck 
7815c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
7816c2c66affSColin Finck     todo_wine
7817c2c66affSColin Finck     {
7818c2c66affSColin Finck         ok(hdb != 0, "Expected a valid database handle\n");
7819c2c66affSColin Finck     }
7820c2c66affSColin Finck 
7821c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7822c2c66affSColin Finck     todo_wine
7823c2c66affSColin Finck     {
7824c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7825c2c66affSColin Finck     }
7826c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7827c2c66affSColin Finck     todo_wine
7828c2c66affSColin Finck     {
7829c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7830c2c66affSColin Finck     }
7831c2c66affSColin Finck 
7832c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7833c2c66affSColin Finck     todo_wine
7834c2c66affSColin Finck     {
7835c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7836c2c66affSColin Finck     }
7837c2c66affSColin Finck 
7838c2c66affSColin Finck     buffer[0] = 0;
7839c2c66affSColin Finck     size = MAX_PATH;
7840c2c66affSColin Finck     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7841c2c66affSColin Finck     todo_wine
7842c2c66affSColin Finck     {
7843c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7844c2c66affSColin Finck         ok(!lstrcmpA(buffer, "_Property"),
7845c2c66affSColin Finck            "Expected \"_Property\", got \"%s\"\n", buffer);
7846c2c66affSColin Finck     }
7847c2c66affSColin Finck 
7848c2c66affSColin Finck     MsiCloseHandle(hrec);
7849c2c66affSColin Finck 
7850c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7851c2c66affSColin Finck     todo_wine
7852c2c66affSColin Finck     {
7853c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7854c2c66affSColin Finck     }
7855c2c66affSColin Finck 
7856c2c66affSColin Finck     size = MAX_PATH;
7857c2c66affSColin Finck     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7858c2c66affSColin Finck     todo_wine
7859c2c66affSColin Finck     {
7860c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7861c2c66affSColin Finck         ok(!lstrcmpA(buffer, "#_FolderCache"),
7862c2c66affSColin Finck            "Expected \"_Property\", got \"%s\"\n", buffer);
7863c2c66affSColin Finck     }
7864c2c66affSColin Finck 
7865c2c66affSColin Finck     MsiCloseHandle(hrec);
7866c2c66affSColin Finck     MsiViewClose(hview);
7867c2c66affSColin Finck     MsiCloseHandle(hview);
7868c2c66affSColin Finck 
7869c2c66affSColin Finck     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7870c2c66affSColin Finck     todo_wine
7871c2c66affSColin Finck     {
7872c2c66affSColin Finck         ok(condition == MSICONDITION_FALSE,
7873c2c66affSColin Finck            "Expected MSICONDITION_FALSE, got %d\n", condition);
7874c2c66affSColin Finck     }
7875c2c66affSColin Finck 
7876c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7877c2c66affSColin Finck     todo_wine
7878c2c66affSColin Finck     {
7879c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7880c2c66affSColin Finck     }
7881c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7882c2c66affSColin Finck     todo_wine
7883c2c66affSColin Finck     {
7884c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7885c2c66affSColin Finck     }
7886c2c66affSColin Finck 
7887c2c66affSColin Finck     /* _Property table is not empty */
7888c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7889c2c66affSColin Finck     todo_wine
7890c2c66affSColin Finck     {
7891c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7892c2c66affSColin Finck     }
7893c2c66affSColin Finck 
7894c2c66affSColin Finck     MsiCloseHandle(hrec);
7895c2c66affSColin Finck     MsiViewClose(hview);
7896c2c66affSColin Finck     MsiCloseHandle(hview);
7897c2c66affSColin Finck 
7898c2c66affSColin Finck     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7899c2c66affSColin Finck     todo_wine
7900c2c66affSColin Finck     {
7901c2c66affSColin Finck         ok(condition == MSICONDITION_FALSE,
7902c2c66affSColin Finck            "Expected MSICONDITION_FALSE, got %d\n", condition);
7903c2c66affSColin Finck     }
7904c2c66affSColin Finck 
7905c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7906c2c66affSColin Finck     todo_wine
7907c2c66affSColin Finck     {
7908c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7909c2c66affSColin Finck     }
7910c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7911c2c66affSColin Finck     todo_wine
7912c2c66affSColin Finck     {
7913c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7914c2c66affSColin Finck     }
7915c2c66affSColin Finck 
7916c2c66affSColin Finck     /* #_FolderCache is not empty */
7917c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7918c2c66affSColin Finck     todo_wine
7919c2c66affSColin Finck     {
7920c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7921c2c66affSColin Finck     }
7922c2c66affSColin Finck 
7923c2c66affSColin Finck     MsiCloseHandle(hrec);
7924c2c66affSColin Finck     MsiViewClose(hview);
7925c2c66affSColin Finck     MsiCloseHandle(hview);
7926c2c66affSColin Finck 
7927c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7928c2c66affSColin Finck     todo_wine
7929c2c66affSColin Finck     {
7930c2c66affSColin Finck         ok(r == ERROR_BAD_QUERY_SYNTAX,
7931c2c66affSColin Finck            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7932c2c66affSColin Finck     }
7933c2c66affSColin Finck 
7934c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7935c2c66affSColin Finck     todo_wine
7936c2c66affSColin Finck     {
7937c2c66affSColin Finck         ok(r == ERROR_BAD_QUERY_SYNTAX,
7938c2c66affSColin Finck            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7939c2c66affSColin Finck     }
7940c2c66affSColin Finck 
7941c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
7942c2c66affSColin Finck     todo_wine
7943c2c66affSColin Finck     {
7944c2c66affSColin Finck         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
7945c2c66affSColin Finck            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
7946c2c66affSColin Finck     }
7947c2c66affSColin Finck 
7948c2c66affSColin Finck     MsiCloseHandle(hsuminfo);
7949c2c66affSColin Finck 
7950c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7951c2c66affSColin Finck     todo_wine
7952c2c66affSColin Finck     {
7953c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7954c2c66affSColin Finck     }
7955c2c66affSColin Finck 
7956c2c66affSColin Finck     MsiCloseHandle(hdb);
7957c2c66affSColin Finck     MsiCloseHandle(hpkg);
7958c2c66affSColin Finck }
7959c2c66affSColin Finck 
7960c2c66affSColin Finck static void test_MsiGetProductProperty(void)
7961c2c66affSColin Finck {
7962c2c66affSColin Finck     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
7963c2c66affSColin Finck     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
7964c2c66affSColin Finck     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
7965c2c66affSColin Finck     static const WCHAR appleW[] = {'a','p','p','l','e',0};
7966c2c66affSColin Finck     static const WCHAR emptyW[] = {0};
7967c2c66affSColin Finck     WCHAR valW[MAX_PATH];
7968c2c66affSColin Finck     MSIHANDLE hprod, hdb;
7969c2c66affSColin Finck     CHAR val[MAX_PATH];
7970c2c66affSColin Finck     CHAR path[MAX_PATH];
7971c2c66affSColin Finck     CHAR query[MAX_PATH];
7972c2c66affSColin Finck     CHAR keypath[MAX_PATH*2];
7973c2c66affSColin Finck     CHAR prodcode[MAX_PATH];
7974c2c66affSColin Finck     WCHAR prodcodeW[MAX_PATH];
7975c2c66affSColin Finck     CHAR prod_squashed[MAX_PATH];
7976c2c66affSColin Finck     WCHAR prod_squashedW[MAX_PATH];
7977c2c66affSColin Finck     HKEY prodkey, userkey, props;
7978c2c66affSColin Finck     DWORD size;
7979c2c66affSColin Finck     LONG res;
7980c2c66affSColin Finck     UINT r;
7981c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
7982c2c66affSColin Finck 
7983c2c66affSColin Finck     GetCurrentDirectoryA(MAX_PATH, path);
7984c2c66affSColin Finck     lstrcatA(path, "\\");
7985c2c66affSColin Finck 
7986c2c66affSColin Finck     create_test_guid(prodcode, prod_squashed);
7987c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
7988c2c66affSColin Finck     squash_guid(prodcodeW, prod_squashedW);
7989c2c66affSColin Finck 
7990c2c66affSColin Finck     if (is_wow64)
7991c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
7992c2c66affSColin Finck 
7993c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7994c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7995c2c66affSColin Finck 
7996c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7997c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7998c2c66affSColin Finck 
7999c2c66affSColin Finck     r = set_summary_info(hdb);
8000c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8001c2c66affSColin Finck 
8002c2c66affSColin Finck     r = run_query(hdb,
8003c2c66affSColin Finck             "CREATE TABLE `Directory` ( "
8004c2c66affSColin Finck             "`Directory` CHAR(255) NOT NULL, "
8005c2c66affSColin Finck             "`Directory_Parent` CHAR(255), "
8006c2c66affSColin Finck             "`DefaultDir` CHAR(255) NOT NULL "
8007c2c66affSColin Finck             "PRIMARY KEY `Directory`)");
8008c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8009c2c66affSColin Finck 
8010f860a780SAmine Khaldi     create_property_table(hdb);
8011c2c66affSColin Finck 
8012f860a780SAmine Khaldi     sprintf(query, "'ProductCode', '%s'", prodcode);
8013f860a780SAmine Khaldi     r = add_property_entry(hdb, query);
8014c2c66affSColin Finck 
8015c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
8016c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8017c2c66affSColin Finck 
8018c2c66affSColin Finck     MsiCloseHandle(hdb);
8019c2c66affSColin Finck 
8020c2c66affSColin Finck     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8021c2c66affSColin Finck     lstrcatA(keypath, prod_squashed);
8022c2c66affSColin Finck 
8023c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8024c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
8025c2c66affSColin Finck     {
8026c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8027c2c66affSColin Finck         DeleteFileA(msifile);
8028c2c66affSColin Finck         return;
8029c2c66affSColin Finck     }
8030c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8031c2c66affSColin Finck 
8032c2c66affSColin Finck     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8033c2c66affSColin Finck     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8034c2c66affSColin Finck     lstrcatA(keypath, prod_squashed);
8035c2c66affSColin Finck 
8036c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8037c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
8038c2c66affSColin Finck     {
8039c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8040c2c66affSColin Finck         RegDeleteKeyA(prodkey, "");
8041c2c66affSColin Finck         RegCloseKey(prodkey);
8042c2c66affSColin Finck         return;
8043c2c66affSColin Finck     }
8044c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8045c2c66affSColin Finck 
8046c2c66affSColin Finck     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8047c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8048c2c66affSColin Finck 
8049c2c66affSColin Finck     lstrcpyA(val, path);
8050c2c66affSColin Finck     lstrcatA(val, "\\");
8051c2c66affSColin Finck     lstrcatA(val, msifile);
8052c2c66affSColin Finck     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8053c2c66affSColin Finck                          (const BYTE *)val, lstrlenA(val) + 1);
8054c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8055c2c66affSColin Finck 
8056c2c66affSColin Finck     hprod = 0xdeadbeef;
8057c2c66affSColin Finck     r = MsiOpenProductA(prodcode, &hprod);
8058c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8059c2c66affSColin Finck     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8060c2c66affSColin Finck 
8061c2c66affSColin Finck     /* hProduct is invalid */
8062c2c66affSColin Finck     size = MAX_PATH;
8063c2c66affSColin Finck     lstrcpyA(val, "apple");
8064c2c66affSColin Finck     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8065c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8066c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8067c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8068c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8069c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8070c2c66affSColin Finck 
8071c2c66affSColin Finck     size = MAX_PATH;
8072c2c66affSColin Finck     lstrcpyW(valW, appleW);
8073c2c66affSColin Finck     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8074c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8075c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8076c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8077c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8078c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8079c2c66affSColin Finck 
8080c2c66affSColin Finck     /* szProperty is NULL */
8081c2c66affSColin Finck     size = MAX_PATH;
8082c2c66affSColin Finck     lstrcpyA(val, "apple");
8083c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8084c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8085c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8086c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8087c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8088c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8089c2c66affSColin Finck 
8090c2c66affSColin Finck     size = MAX_PATH;
8091c2c66affSColin Finck     lstrcpyW(valW, appleW);
8092c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8093c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8094c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8095c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8096c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8097c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8098c2c66affSColin Finck 
8099c2c66affSColin Finck     /* szProperty is empty */
8100c2c66affSColin Finck     size = MAX_PATH;
8101c2c66affSColin Finck     lstrcpyA(val, "apple");
8102c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "", val, &size);
8103c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8104c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8105c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8106c2c66affSColin Finck 
8107c2c66affSColin Finck     size = MAX_PATH;
8108c2c66affSColin Finck     lstrcpyW(valW, appleW);
8109c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8110c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8111c2c66affSColin Finck     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8112c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8113c2c66affSColin Finck 
8114c2c66affSColin Finck     /* get the property */
8115c2c66affSColin Finck     size = MAX_PATH;
8116c2c66affSColin Finck     lstrcpyA(val, "apple");
8117c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8118c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8119c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8120c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8121c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8122c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8123c2c66affSColin Finck 
8124c2c66affSColin Finck     size = MAX_PATH;
8125c2c66affSColin Finck     lstrcpyW(valW, appleW);
8126c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8127c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8128c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8129c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8130c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8131c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8132c2c66affSColin Finck 
8133c2c66affSColin Finck     /* lpValueBuf is NULL */
8134c2c66affSColin Finck     size = MAX_PATH;
8135c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8136c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8137c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8138c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8139c2c66affSColin Finck 
8140c2c66affSColin Finck     size = MAX_PATH;
8141c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8142c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8143c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8144c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8145c2c66affSColin Finck 
8146c2c66affSColin Finck     /* pcchValueBuf is NULL */
8147c2c66affSColin Finck     lstrcpyA(val, "apple");
8148c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8149c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8150c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8151c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8152c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8153c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8154c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8155c2c66affSColin Finck 
8156c2c66affSColin Finck     lstrcpyW(valW, appleW);
8157c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8158c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8159c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8160c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8161c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8162c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8163c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8164c2c66affSColin Finck 
8165c2c66affSColin Finck     /* pcchValueBuf is too small */
8166c2c66affSColin Finck     size = 4;
8167c2c66affSColin Finck     lstrcpyA(val, "apple");
8168c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8169c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8170c2c66affSColin Finck     ok(!strncmp(val, prodcode, 3),
8171c2c66affSColin Finck        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8172c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8173c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8174c2c66affSColin Finck 
8175c2c66affSColin Finck     size = 4;
8176c2c66affSColin Finck     lstrcpyW(valW, appleW);
8177c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8178c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8179c2c66affSColin Finck     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8180c2c66affSColin Finck        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8181c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8182c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8183c2c66affSColin Finck 
8184c2c66affSColin Finck     /* pcchValueBuf does not leave room for NULL terminator */
8185c2c66affSColin Finck     size = lstrlenA(prodcode);
8186c2c66affSColin Finck     lstrcpyA(val, "apple");
8187c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8188c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8189c2c66affSColin Finck     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8190c2c66affSColin Finck        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8191c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8192c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8193c2c66affSColin Finck 
8194c2c66affSColin Finck     size = lstrlenW(prodcodeW);
8195c2c66affSColin Finck     lstrcpyW(valW, appleW);
8196c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8197c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8198c2c66affSColin Finck     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8199c2c66affSColin Finck        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8200c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8201c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8202c2c66affSColin Finck 
8203c2c66affSColin Finck     /* pcchValueBuf has enough room for NULL terminator */
8204c2c66affSColin Finck     size = lstrlenA(prodcode) + 1;
8205c2c66affSColin Finck     lstrcpyA(val, "apple");
8206c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8207c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8208c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8209c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8210c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8211c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8212c2c66affSColin Finck 
8213c2c66affSColin Finck     size = lstrlenW(prodcodeW) + 1;
8214c2c66affSColin Finck     lstrcpyW(valW, appleW);
8215c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8216c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8217c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8218c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8219c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8220c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8221c2c66affSColin Finck 
8222c2c66affSColin Finck     /* nonexistent property */
8223c2c66affSColin Finck     size = MAX_PATH;
8224c2c66affSColin Finck     lstrcpyA(val, "apple");
8225c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8226c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8227c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8228c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8229c2c66affSColin Finck 
8230c2c66affSColin Finck     size = MAX_PATH;
8231c2c66affSColin Finck     lstrcpyW(valW, appleW);
8232c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8233c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8234c2c66affSColin Finck     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8235c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8236c2c66affSColin Finck 
8237c2c66affSColin Finck     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8238c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8239c2c66affSColin Finck 
8240c2c66affSColin Finck     /* non-product property set */
8241c2c66affSColin Finck     size = MAX_PATH;
8242c2c66affSColin Finck     lstrcpyA(val, "apple");
8243c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8244c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8245c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8246c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8247c2c66affSColin Finck 
8248c2c66affSColin Finck     size = MAX_PATH;
8249c2c66affSColin Finck     lstrcpyW(valW, appleW);
8250c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8251c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8252c2c66affSColin Finck     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8253c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8254c2c66affSColin Finck 
8255c2c66affSColin Finck     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8256c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8257c2c66affSColin Finck 
8258c2c66affSColin Finck     /* non-product property that is also a product property set */
8259c2c66affSColin Finck     size = MAX_PATH;
8260c2c66affSColin Finck     lstrcpyA(val, "apple");
8261c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8262c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8263c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8264c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8265c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8266c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8267c2c66affSColin Finck 
8268c2c66affSColin Finck     size = MAX_PATH;
8269c2c66affSColin Finck     lstrcpyW(valW, appleW);
8270c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8271c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8272c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8273c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8274c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8275c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8276c2c66affSColin Finck 
8277c2c66affSColin Finck     MsiCloseHandle(hprod);
8278c2c66affSColin Finck 
8279c2c66affSColin Finck     RegDeleteValueA(props, "LocalPackage");
8280c2c66affSColin Finck     delete_key(props, "", access);
8281c2c66affSColin Finck     RegCloseKey(props);
8282c2c66affSColin Finck     delete_key(userkey, "", access);
8283c2c66affSColin Finck     RegCloseKey(userkey);
8284c2c66affSColin Finck     delete_key(prodkey, "", access);
8285c2c66affSColin Finck     RegCloseKey(prodkey);
8286c2c66affSColin Finck     DeleteFileA(msifile);
8287c2c66affSColin Finck }
8288c2c66affSColin Finck 
8289c2c66affSColin Finck static void test_MsiSetProperty(void)
8290c2c66affSColin Finck {
8291c2c66affSColin Finck     MSIHANDLE hpkg, hdb, hrec;
8292c2c66affSColin Finck     CHAR buf[MAX_PATH];
8293c2c66affSColin Finck     LPCSTR query;
8294c2c66affSColin Finck     DWORD size;
8295c2c66affSColin Finck     UINT r;
8296c2c66affSColin Finck 
8297c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
8298c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8299c2c66affSColin Finck     {
8300c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8301c2c66affSColin Finck         DeleteFileA(msifile);
8302c2c66affSColin Finck         return;
8303c2c66affSColin Finck     }
8304c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8305c2c66affSColin Finck 
8306c2c66affSColin Finck     /* invalid hInstall */
8307c2c66affSColin Finck     r = MsiSetPropertyA(0, "Prop", "Val");
8308c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8309c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8310c2c66affSColin Finck 
8311c2c66affSColin Finck     /* invalid hInstall */
8312c2c66affSColin Finck     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8313c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8314c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8315c2c66affSColin Finck 
8316c2c66affSColin Finck     /* szName is NULL */
8317c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, NULL, "Val");
8318c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8319c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8320c2c66affSColin Finck 
8321c2c66affSColin Finck     /* both szName and szValue are NULL */
8322c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, NULL, NULL);
8323c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8324c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8325c2c66affSColin Finck 
8326c2c66affSColin Finck     /* szName is empty */
8327c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "", "Val");
8328c2c66affSColin Finck     ok(r == ERROR_FUNCTION_FAILED,
8329c2c66affSColin Finck        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8330c2c66affSColin Finck 
8331c2c66affSColin Finck     /* szName is empty and szValue is NULL */
8332c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "", NULL);
8333c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8334c2c66affSColin Finck 
8335c2c66affSColin Finck     /* set a property */
8336c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8337c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8338c2c66affSColin Finck 
8339c2c66affSColin Finck     /* get the property */
8340c2c66affSColin Finck     size = MAX_PATH;
8341c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8342c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8343c2c66affSColin Finck     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8344c2c66affSColin Finck     ok(size == 3, "Expected 3, got %d\n", size);
8345c2c66affSColin Finck 
8346c2c66affSColin Finck     /* update the property */
8347c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8348c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8349c2c66affSColin Finck 
8350c2c66affSColin Finck     /* get the property */
8351c2c66affSColin Finck     size = MAX_PATH;
8352c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8353c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8354c2c66affSColin Finck     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8355c2c66affSColin Finck     ok(size == 4, "Expected 4, got %d\n", size);
8356c2c66affSColin Finck 
8357c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
8358c2c66affSColin Finck     ok(hdb != 0, "Expected a valid database handle\n");
8359c2c66affSColin Finck 
8360c2c66affSColin Finck     /* set prop is not in the _Property table */
8361c2c66affSColin Finck     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8362c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
8363c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX,
8364c2c66affSColin Finck        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8365c2c66affSColin Finck 
8366c2c66affSColin Finck     /* set prop is not in the Property table */
8367c2c66affSColin Finck     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8368c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
8369c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX,
8370c2c66affSColin Finck        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8371c2c66affSColin Finck 
8372c2c66affSColin Finck     MsiCloseHandle(hdb);
8373c2c66affSColin Finck 
8374c2c66affSColin Finck     /* szValue is an empty string */
8375c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "");
8376c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8377c2c66affSColin Finck 
8378c2c66affSColin Finck     /* try to get the property */
8379c2c66affSColin Finck     size = MAX_PATH;
8380c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8381c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8382c2c66affSColin Finck     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8383c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8384c2c66affSColin Finck 
8385c2c66affSColin Finck     /* reset the property */
8386c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8387c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8388c2c66affSColin Finck 
8389c2c66affSColin Finck     /* delete the property */
8390c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8391c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8392c2c66affSColin Finck 
8393c2c66affSColin Finck     /* try to get the property */
8394c2c66affSColin Finck     size = MAX_PATH;
8395c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8396c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8397c2c66affSColin Finck     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8398c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8399c2c66affSColin Finck 
8400c2c66affSColin Finck     MsiCloseHandle(hpkg);
8401c2c66affSColin Finck     DeleteFileA(msifile);
8402c2c66affSColin Finck }
8403c2c66affSColin Finck 
8404c2c66affSColin Finck static void test_MsiApplyMultiplePatches(void)
8405c2c66affSColin Finck {
8406c2c66affSColin Finck     UINT r, type = GetDriveTypeW(NULL);
8407c2c66affSColin Finck 
84082f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8409c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8410c2c66affSColin Finck 
84112f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8412c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8413c2c66affSColin Finck 
84142f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8415c2c66affSColin Finck     if (type == DRIVE_FIXED)
8416c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8417c2c66affSColin Finck     else
8418c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8419c2c66affSColin Finck 
84202f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8421c2c66affSColin Finck     if (type == DRIVE_FIXED)
8422c2c66affSColin Finck         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8423c2c66affSColin Finck     else
8424c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8425c2c66affSColin Finck 
84262f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8427c2c66affSColin Finck     if (type == DRIVE_FIXED)
8428c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8429c2c66affSColin Finck     else
8430c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8431c2c66affSColin Finck 
84322f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8433c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8434c2c66affSColin Finck 
84352f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8436c2c66affSColin Finck     if (type == DRIVE_FIXED)
8437c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8438c2c66affSColin Finck     else
8439c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8440c2c66affSColin Finck 
84412f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8442c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8443c2c66affSColin Finck 
84442f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8445c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8446c2c66affSColin Finck }
8447c2c66affSColin Finck 
8448c2c66affSColin Finck static void test_MsiApplyPatch(void)
8449c2c66affSColin Finck {
8450c2c66affSColin Finck     UINT r;
8451c2c66affSColin Finck 
8452c2c66affSColin Finck     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8453c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8454c2c66affSColin Finck 
8455c2c66affSColin Finck     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8456c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8457c2c66affSColin Finck }
8458c2c66affSColin Finck 
8459818a84ddSwinesync static void test_costs(void)
8460c2c66affSColin Finck {
8461c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
8462c2c66affSColin Finck     char package[12], drive[3];
8463c2c66affSColin Finck     DWORD len;
8464c2c66affSColin Finck     UINT r;
8465c2c66affSColin Finck     int cost, temp;
8466c2c66affSColin Finck 
8467c2c66affSColin Finck     hdb = create_package_db();
8468c2c66affSColin Finck     ok( hdb, "failed to create database\n" );
8469c2c66affSColin Finck 
8470f860a780SAmine Khaldi     create_property_table( hdb );
8471f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8472f860a780SAmine Khaldi     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8473f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8474c2c66affSColin Finck 
8475f860a780SAmine Khaldi     create_media_table( hdb );
8476f860a780SAmine Khaldi     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8477c2c66affSColin Finck 
8478f860a780SAmine Khaldi     create_file_table( hdb );
8479f860a780SAmine Khaldi     add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8480c2c66affSColin Finck 
8481f860a780SAmine Khaldi     create_component_table( hdb );
8482f860a780SAmine Khaldi     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8483f860a780SAmine Khaldi     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8484c2c66affSColin Finck 
8485f860a780SAmine Khaldi     create_feature_table( hdb );
8486f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8487f860a780SAmine Khaldi     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8488c2c66affSColin Finck 
8489f860a780SAmine Khaldi     create_feature_components_table( hdb );
8490f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'one'" );
8491f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'two'" );
8492c2c66affSColin Finck 
8493f860a780SAmine Khaldi     create_install_execute_sequence_table( hdb );
8494f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8495f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8496f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8497f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8498c2c66affSColin Finck 
8499f860a780SAmine Khaldi     r = MsiDatabaseCommit( hdb );
8500f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8501c2c66affSColin Finck 
8502c2c66affSColin Finck     sprintf( package, "#%u", hdb );
8503c2c66affSColin Finck     r = MsiOpenPackageA( package, &hpkg );
8504c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8505c2c66affSColin Finck     {
8506c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8507c2c66affSColin Finck         goto error;
8508c2c66affSColin Finck     }
8509c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8510c2c66affSColin Finck 
8511c2c66affSColin Finck     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8512c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8513c2c66affSColin Finck 
8514c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8515c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8516c2c66affSColin Finck 
8517c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8518c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8519c2c66affSColin Finck 
8520c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8521c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8522c2c66affSColin Finck 
8523c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8524c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8525c2c66affSColin Finck 
8526c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8527c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8528c2c66affSColin Finck 
8529c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8530c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8531c2c66affSColin Finck 
8532c2c66affSColin Finck     len = sizeof(drive);
8533c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8534c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8535c2c66affSColin Finck 
8536c2c66affSColin Finck     len = sizeof(drive);
8537c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8538c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8539c2c66affSColin Finck 
8540c2c66affSColin Finck     len = sizeof(drive);
8541c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8542c2c66affSColin Finck     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8543c2c66affSColin Finck 
8544c2c66affSColin Finck     len = sizeof(drive);
8545c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8546c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8547c2c66affSColin Finck 
8548c2c66affSColin Finck     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8549c2c66affSColin Finck 
8550c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize" );
8551c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8552c2c66affSColin Finck 
8553c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost" );
8554c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8555c2c66affSColin Finck 
8556c2c66affSColin Finck     len = sizeof(drive);
8557c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8558c2c66affSColin Finck     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8559c2c66affSColin Finck 
8560c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize" );
8561c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8562c2c66affSColin Finck 
8563c2c66affSColin Finck     /* contrary to what msdn says InstallValidate must be called too */
8564c2c66affSColin Finck     len = sizeof(drive);
8565c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8566c2c66affSColin Finck     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8567c2c66affSColin Finck 
8568c2c66affSColin Finck     r = MsiDoActionA( hpkg, "InstallValidate" );
8569c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8570c2c66affSColin Finck 
8571c2c66affSColin Finck     len = 0;
8572c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8573c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8574c2c66affSColin Finck 
8575c2c66affSColin Finck     len = 0;
8576c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8577c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8578c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8579c2c66affSColin Finck 
8580c2c66affSColin Finck     len = 2;
8581c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8582c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8583c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8584c2c66affSColin Finck 
8585c2c66affSColin Finck     len = 2;
8586c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8587c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8588c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8589c2c66affSColin Finck 
8590c2c66affSColin Finck     /* install state doesn't seem to matter */
8591c2c66affSColin Finck     len = sizeof(drive);
8592c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8593c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8594c2c66affSColin Finck 
8595c2c66affSColin Finck     len = sizeof(drive);
8596c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8597c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8598c2c66affSColin Finck 
8599c2c66affSColin Finck     len = sizeof(drive);
8600c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8601c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8602c2c66affSColin Finck 
8603c2c66affSColin Finck     len = sizeof(drive);
8604c2c66affSColin Finck     drive[0] = 0;
8605c2c66affSColin Finck     cost = temp = 0xdead;
8606c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8607c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8608c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8609c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8610c2c66affSColin Finck     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
8611c2c66affSColin Finck     ok( !temp, "expected temp == 0, got %d\n", temp );
8612c2c66affSColin Finck 
8613c2c66affSColin Finck     len = sizeof(drive);
8614c2c66affSColin Finck     drive[0] = 0;
8615c2c66affSColin Finck     cost = temp = 0xdead;
8616c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8617c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8618c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8619c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8620c2c66affSColin Finck     ok( !cost, "expected cost == 0, got %d\n", cost );
8621c2c66affSColin Finck     ok( !temp, "expected temp == 0, got %d\n", temp );
8622c2c66affSColin Finck 
8623c2c66affSColin Finck     len = sizeof(drive);
8624c2c66affSColin Finck     drive[0] = 0;
8625c2c66affSColin Finck     cost = temp = 0xdead;
8626c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8627c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8628c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8629c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8630c2c66affSColin Finck     ok( !cost, "expected cost == 0, got %d\n", cost );
8631c2c66affSColin Finck     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8632c2c66affSColin Finck 
8633c2c66affSColin Finck     /* increased index */
8634c2c66affSColin Finck     len = sizeof(drive);
8635c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8636c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8637c2c66affSColin Finck 
8638c2c66affSColin Finck     len = sizeof(drive);
8639c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8640c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8641c2c66affSColin Finck 
8642818a84ddSwinesync     /* test MsiGetFeatureCost */
8643818a84ddSwinesync     cost = 0xdead;
8644818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, NULL, MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8645818a84ddSwinesync     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8646818a84ddSwinesync     ok( cost == 0xdead, "got %d\n", cost );
8647818a84ddSwinesync 
8648818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, NULL );
8649818a84ddSwinesync     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8650818a84ddSwinesync 
8651818a84ddSwinesync     cost = 0xdead;
8652818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8653818a84ddSwinesync     ok( !r, "got %u\n", r);
8654818a84ddSwinesync     ok( cost == 8, "got %d\n", cost );
8655818a84ddSwinesync 
8656c2c66affSColin Finck     MsiCloseHandle( hpkg );
8657c2c66affSColin Finck error:
8658c2c66affSColin Finck     MsiCloseHandle( hdb );
8659c2c66affSColin Finck     DeleteFileA( msifile );
8660c2c66affSColin Finck }
8661c2c66affSColin Finck 
8662c2c66affSColin Finck static void test_MsiDatabaseCommit(void)
8663c2c66affSColin Finck {
8664c2c66affSColin Finck     UINT r;
8665c2c66affSColin Finck     MSIHANDLE hdb, hpkg = 0;
8666c2c66affSColin Finck     char buf[32], package[12];
8667c2c66affSColin Finck     DWORD sz;
8668c2c66affSColin Finck 
8669c2c66affSColin Finck     hdb = create_package_db();
8670c2c66affSColin Finck     ok( hdb, "failed to create database\n" );
8671c2c66affSColin Finck 
8672f860a780SAmine Khaldi     create_property_table( hdb );
8673c2c66affSColin Finck 
8674c2c66affSColin Finck     sprintf( package, "#%u", hdb );
8675c2c66affSColin Finck     r = MsiOpenPackageA( package, &hpkg );
8676c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8677c2c66affSColin Finck     {
8678c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8679c2c66affSColin Finck         goto error;
8680c2c66affSColin Finck     }
8681c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "got %u\n", r );
8682c2c66affSColin Finck 
8683c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8684c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "got %u\n", r );
8685c2c66affSColin Finck 
8686c2c66affSColin Finck     buf[0] = 0;
8687c2c66affSColin Finck     sz = sizeof(buf);
8688c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8689c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8690c2c66affSColin Finck     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8691c2c66affSColin Finck 
8692c2c66affSColin Finck     r = MsiDatabaseCommit( hdb );
8693c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8694c2c66affSColin Finck 
8695c2c66affSColin Finck     buf[0] = 0;
8696c2c66affSColin Finck     sz = sizeof(buf);
8697c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8698c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8699c2c66affSColin Finck     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8700c2c66affSColin Finck 
8701c2c66affSColin Finck     MsiCloseHandle( hpkg );
8702c2c66affSColin Finck error:
8703c2c66affSColin Finck     MsiCloseHandle( hdb );
8704c2c66affSColin Finck     DeleteFileA( msifile );
8705c2c66affSColin Finck }
8706c2c66affSColin Finck 
87072f8e6f71SAmine Khaldi static int externalui_ran;
87082f8e6f71SAmine Khaldi 
87092f8e6f71SAmine Khaldi static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
87102f8e6f71SAmine Khaldi {
87112f8e6f71SAmine Khaldi     externalui_ran = 1;
87122f8e6f71SAmine Khaldi     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
87132f8e6f71SAmine Khaldi     return 0;
87142f8e6f71SAmine Khaldi }
87152f8e6f71SAmine Khaldi 
87162f8e6f71SAmine Khaldi static int externalui_record_ran;
87172f8e6f71SAmine Khaldi 
87182f8e6f71SAmine Khaldi static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
87192f8e6f71SAmine Khaldi {
87202f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
87212f8e6f71SAmine Khaldi     UINT r;
87222f8e6f71SAmine Khaldi     externalui_record_ran = 1;
87232f8e6f71SAmine Khaldi     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
87242f8e6f71SAmine Khaldi     r = MsiRecordGetFieldCount(hrecord);
87252f8e6f71SAmine Khaldi     ok(r == 1, "expected 1, got %u\n", r);
87262f8e6f71SAmine Khaldi     r = MsiRecordGetInteger(hrecord, 1);
87272f8e6f71SAmine Khaldi     ok(r == 12345, "expected 12345, got %u\n", r);
87282f8e6f71SAmine Khaldi     return retval;
87292f8e6f71SAmine Khaldi }
87302f8e6f71SAmine Khaldi 
87312f8e6f71SAmine Khaldi static void test_externalui(void)
87322f8e6f71SAmine Khaldi {
87332f8e6f71SAmine Khaldi     /* test that external UI handlers work correctly */
87342f8e6f71SAmine Khaldi 
87352f8e6f71SAmine Khaldi     INSTALLUI_HANDLERA prev;
87362f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev_record;
87372f8e6f71SAmine Khaldi     MSIHANDLE hpkg, hrecord;
87382f8e6f71SAmine Khaldi     UINT r;
87392f8e6f71SAmine Khaldi     INT retval = 0;
87402f8e6f71SAmine Khaldi 
87412f8e6f71SAmine Khaldi     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
87422f8e6f71SAmine Khaldi 
87432f8e6f71SAmine Khaldi     r = package_from_db(create_package_db(), &hpkg);
87442f8e6f71SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
87452f8e6f71SAmine Khaldi     {
87462f8e6f71SAmine Khaldi         skip("Not enough rights to perform tests\n");
87472f8e6f71SAmine Khaldi         DeleteFileA(msifile);
87482f8e6f71SAmine Khaldi         return;
87492f8e6f71SAmine Khaldi     }
87502f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
87512f8e6f71SAmine Khaldi 
87522f8e6f71SAmine Khaldi     hrecord = MsiCreateRecord(1);
87532f8e6f71SAmine Khaldi     ok(hrecord, "Expected a valid record\n");
87542f8e6f71SAmine Khaldi     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
87552f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
87562f8e6f71SAmine Khaldi     r = MsiRecordSetInteger(hrecord, 1, 12345);
87572f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
87582f8e6f71SAmine Khaldi 
87592f8e6f71SAmine Khaldi     externalui_ran = 0;
87602f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87612f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87622f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87632f8e6f71SAmine Khaldi 
87642f8e6f71SAmine Khaldi     prev = MsiSetExternalUIA(prev, 0, NULL);
87652f8e6f71SAmine Khaldi     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
87662f8e6f71SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
87672f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
87682f8e6f71SAmine Khaldi 
87692f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87702f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87712f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87722f8e6f71SAmine Khaldi     ok(externalui_ran == 0, "external UI callback should not have run\n");
87732f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87742f8e6f71SAmine Khaldi 
87752f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
87762f8e6f71SAmine Khaldi 
87772f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87782f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87792f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87802f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87812f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87822f8e6f71SAmine Khaldi 
87832f8e6f71SAmine Khaldi     retval = 1;
87842f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87852f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87862f8e6f71SAmine Khaldi     ok(r == 1, "expected 1, got %u\n", r);
87872f8e6f71SAmine Khaldi     ok(externalui_ran == 0, "external UI callback should not have run\n");
87882f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87892f8e6f71SAmine Khaldi 
87902f8e6f71SAmine Khaldi     /* filter and context should be kept separately */
87912f8e6f71SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
87922f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
87932f8e6f71SAmine Khaldi 
87942f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87952f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87962f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87972f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87982f8e6f71SAmine Khaldi     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
87992f8e6f71SAmine Khaldi 
88002f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
88012f8e6f71SAmine Khaldi     DeleteFileA(msifile);
88022f8e6f71SAmine Khaldi }
88032f8e6f71SAmine Khaldi 
88042f8e6f71SAmine Khaldi struct externalui_message {
88052f8e6f71SAmine Khaldi     UINT message;
88062f8e6f71SAmine Khaldi     int field_count;
88072f8e6f71SAmine Khaldi     char field[4][100];
88082f8e6f71SAmine Khaldi     int match[4]; /* should we test for a match */
88092f8e6f71SAmine Khaldi     int optional;
88102f8e6f71SAmine Khaldi };
88112f8e6f71SAmine Khaldi 
88122f8e6f71SAmine Khaldi static struct externalui_message *sequence;
88132f8e6f71SAmine Khaldi static int sequence_count, sequence_size;
88142f8e6f71SAmine Khaldi 
88152f8e6f71SAmine Khaldi static void add_message(const struct externalui_message *msg)
88162f8e6f71SAmine Khaldi {
88172f8e6f71SAmine Khaldi     if (!sequence)
88182f8e6f71SAmine Khaldi     {
88192f8e6f71SAmine Khaldi         sequence_size = 10;
88202f8e6f71SAmine Khaldi         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
88212f8e6f71SAmine Khaldi     }
88222f8e6f71SAmine Khaldi     if (sequence_count == sequence_size)
88232f8e6f71SAmine Khaldi     {
88242f8e6f71SAmine Khaldi         sequence_size *= 2;
88252f8e6f71SAmine Khaldi         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
88262f8e6f71SAmine Khaldi     }
88272f8e6f71SAmine Khaldi 
88282f8e6f71SAmine Khaldi     assert(sequence);
88292f8e6f71SAmine Khaldi 
88302f8e6f71SAmine Khaldi     sequence[sequence_count++] = *msg;
88312f8e6f71SAmine Khaldi }
88322f8e6f71SAmine Khaldi 
88332f8e6f71SAmine Khaldi static void flush_sequence(void)
88342f8e6f71SAmine Khaldi {
88352f8e6f71SAmine Khaldi     HeapFree(GetProcessHeap(), 0, sequence);
88362f8e6f71SAmine Khaldi     sequence = NULL;
88372f8e6f71SAmine Khaldi     sequence_count = sequence_size = 0;
88382f8e6f71SAmine Khaldi }
88392f8e6f71SAmine Khaldi 
88402f8e6f71SAmine Khaldi static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
88412f8e6f71SAmine Khaldi                          const char *file, int line)
88422f8e6f71SAmine Khaldi {
88432f8e6f71SAmine Khaldi     static const struct externalui_message end_of_sequence = {0};
88442f8e6f71SAmine Khaldi     const struct externalui_message *actual;
88452f8e6f71SAmine Khaldi     int failcount = 0;
88462f8e6f71SAmine Khaldi     int i;
88472f8e6f71SAmine Khaldi 
88482f8e6f71SAmine Khaldi     add_message(&end_of_sequence);
88492f8e6f71SAmine Khaldi 
88502f8e6f71SAmine Khaldi     actual = sequence;
88512f8e6f71SAmine Khaldi 
88522f8e6f71SAmine Khaldi     while (expected->message && actual->message)
88532f8e6f71SAmine Khaldi     {
88542f8e6f71SAmine Khaldi         if (expected->message == actual->message)
88552f8e6f71SAmine Khaldi         {
8856f860a780SAmine Khaldi             if (expected->field_count < actual->field_count)
88572f8e6f71SAmine Khaldi             {
88582f8e6f71SAmine Khaldi                 todo_wine_if (todo)
88592f8e6f71SAmine Khaldi                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
88602f8e6f71SAmine Khaldi                                      context, expected->message, expected->field_count, actual->field_count);
88612f8e6f71SAmine Khaldi                 failcount++;
88622f8e6f71SAmine Khaldi             }
88632f8e6f71SAmine Khaldi 
88642f8e6f71SAmine Khaldi             for (i = 0; i <= actual->field_count; i++)
88652f8e6f71SAmine Khaldi             {
88662f8e6f71SAmine Khaldi                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
88672f8e6f71SAmine Khaldi                 {
88682f8e6f71SAmine Khaldi                     todo_wine_if (todo)
88692f8e6f71SAmine Khaldi                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
88702f8e6f71SAmine Khaldi                                          context, expected->message, i, expected->field[i], actual->field[i]);
88712f8e6f71SAmine Khaldi                     failcount++;
88722f8e6f71SAmine Khaldi                 }
88732f8e6f71SAmine Khaldi             }
88742f8e6f71SAmine Khaldi 
88752f8e6f71SAmine Khaldi             expected++;
88762f8e6f71SAmine Khaldi             actual++;
88772f8e6f71SAmine Khaldi         }
8878f860a780SAmine Khaldi         else if (expected->optional)
8879f860a780SAmine Khaldi         {
8880f860a780SAmine Khaldi             expected++;
8881f860a780SAmine Khaldi         }
88822f8e6f71SAmine Khaldi         else
88832f8e6f71SAmine Khaldi         {
88842f8e6f71SAmine Khaldi             todo_wine_if (todo)
88852f8e6f71SAmine Khaldi                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
88862f8e6f71SAmine Khaldi                                  context, expected->message, actual->message);
88872f8e6f71SAmine Khaldi             failcount++;
88882f8e6f71SAmine Khaldi             if (todo)
88892f8e6f71SAmine Khaldi                 goto done;
88902f8e6f71SAmine Khaldi             expected++;
88912f8e6f71SAmine Khaldi             actual++;
88922f8e6f71SAmine Khaldi         }
88932f8e6f71SAmine Khaldi     }
88942f8e6f71SAmine Khaldi 
88952f8e6f71SAmine Khaldi     if (expected->message || actual->message)
88962f8e6f71SAmine Khaldi     {
88972f8e6f71SAmine Khaldi         todo_wine_if (todo)
88982f8e6f71SAmine Khaldi             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
88992f8e6f71SAmine Khaldi                              context, expected->message, actual->message);
89002f8e6f71SAmine Khaldi         failcount++;
89012f8e6f71SAmine Khaldi     }
89022f8e6f71SAmine Khaldi 
89032f8e6f71SAmine Khaldi     if(todo && !failcount) /* succeeded yet marked todo */
89042f8e6f71SAmine Khaldi     {
89052f8e6f71SAmine Khaldi         todo_wine
89062f8e6f71SAmine Khaldi             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
89072f8e6f71SAmine Khaldi     }
89082f8e6f71SAmine Khaldi 
89092f8e6f71SAmine Khaldi done:
89102f8e6f71SAmine Khaldi     flush_sequence();
89112f8e6f71SAmine Khaldi }
89122f8e6f71SAmine Khaldi 
89132f8e6f71SAmine Khaldi #define ok_sequence(exp, contx, todo) \
89142f8e6f71SAmine Khaldi         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
89152f8e6f71SAmine Khaldi 
8916f860a780SAmine Khaldi /* don't use PROGRESS, which is timing-dependent,
8917f860a780SAmine Khaldi  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8918f860a780SAmine Khaldi static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8919f860a780SAmine Khaldi     INSTALLLOGMODE_FATALEXIT |
8920f860a780SAmine Khaldi     INSTALLLOGMODE_ERROR |
8921f860a780SAmine Khaldi     INSTALLLOGMODE_WARNING |
8922f860a780SAmine Khaldi     INSTALLLOGMODE_USER |
8923f860a780SAmine Khaldi     INSTALLLOGMODE_INFO |
8924f860a780SAmine Khaldi     INSTALLLOGMODE_FILESINUSE |
8925f860a780SAmine Khaldi     INSTALLLOGMODE_RESOLVESOURCE |
8926f860a780SAmine Khaldi     INSTALLLOGMODE_OUTOFDISKSPACE |
8927f860a780SAmine Khaldi     INSTALLLOGMODE_ACTIONSTART |
8928f860a780SAmine Khaldi     INSTALLLOGMODE_ACTIONDATA |
8929f860a780SAmine Khaldi     INSTALLLOGMODE_COMMONDATA |
8930f860a780SAmine Khaldi     INSTALLLOGMODE_INITIALIZE |
8931f860a780SAmine Khaldi     INSTALLLOGMODE_TERMINATE |
8932f860a780SAmine Khaldi     INSTALLLOGMODE_RMFILESINUSE |
8933f860a780SAmine Khaldi     INSTALLLOGMODE_INSTALLSTART |
8934f860a780SAmine Khaldi     INSTALLLOGMODE_INSTALLEND;
8935f860a780SAmine Khaldi 
89362f8e6f71SAmine Khaldi static const struct externalui_message empty_sequence[] = {
89372f8e6f71SAmine Khaldi     {0}
89382f8e6f71SAmine Khaldi };
89392f8e6f71SAmine Khaldi 
89402f8e6f71SAmine Khaldi static const struct externalui_message openpackage_nonexistent_sequence[] = {
89412f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
89422f8e6f71SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
89432f8e6f71SAmine Khaldi     {0}
89442f8e6f71SAmine Khaldi };
89452f8e6f71SAmine Khaldi 
89462f8e6f71SAmine Khaldi static const struct externalui_message openpackage_sequence[] = {
89472f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
89482f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
89492f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
89502f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
89512f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
89522f8e6f71SAmine Khaldi     {0}
89532f8e6f71SAmine Khaldi };
89542f8e6f71SAmine Khaldi 
89552f8e6f71SAmine Khaldi static const struct externalui_message processmessage_info_sequence[] = {
89562f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
89572f8e6f71SAmine Khaldi     {0}
89582f8e6f71SAmine Khaldi };
89592f8e6f71SAmine Khaldi 
89602f8e6f71SAmine Khaldi static const struct externalui_message processmessage_actionstart_sequence[] = {
89612f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
89622f8e6f71SAmine Khaldi     {0}
89632f8e6f71SAmine Khaldi };
89642f8e6f71SAmine Khaldi 
89652f8e6f71SAmine Khaldi static const struct externalui_message processmessage_actiondata_sequence[] = {
89662f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
89672f8e6f71SAmine Khaldi     {0}
89682f8e6f71SAmine Khaldi };
89692f8e6f71SAmine Khaldi 
89702f8e6f71SAmine Khaldi static const struct externalui_message processmessage_error_sequence[] = {
89712f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
89722f8e6f71SAmine Khaldi     {0}
89732f8e6f71SAmine Khaldi };
89742f8e6f71SAmine Khaldi 
89752f8e6f71SAmine Khaldi static const struct externalui_message processmessage_internal_error_sequence[] = {
89762f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
89772f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
89782f8e6f71SAmine Khaldi     {0}
89792f8e6f71SAmine Khaldi };
89802f8e6f71SAmine Khaldi 
89812f8e6f71SAmine Khaldi static const struct externalui_message processmessage_error_format_sequence[] = {
89822f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
89832f8e6f71SAmine Khaldi     {0}
89842f8e6f71SAmine Khaldi };
89852f8e6f71SAmine Khaldi 
89862f8e6f71SAmine Khaldi static const struct externalui_message doaction_costinitialize_sequence[] = {
89872f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
89882f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
89892f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
89902f8e6f71SAmine Khaldi     {0}
89912f8e6f71SAmine Khaldi };
89922f8e6f71SAmine Khaldi 
89932f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_sequence[] = {
89942f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
89952f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
89962f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
89972f8e6f71SAmine Khaldi     {0}
89982f8e6f71SAmine Khaldi };
89992f8e6f71SAmine Khaldi 
90002f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_fullui_sequence[] = {
90012f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
90022f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
90032f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
90042f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
90052f8e6f71SAmine Khaldi     {0}
90062f8e6f71SAmine Khaldi };
90072f8e6f71SAmine Khaldi 
90082f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_cancel_sequence[] = {
90092f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
90102f8e6f71SAmine Khaldi     {0}
90112f8e6f71SAmine Khaldi };
90122f8e6f71SAmine Khaldi 
90132f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
90142f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
90152f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
90162f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
90172f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
90182f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
90192f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
90202f8e6f71SAmine Khaldi     {0}
90212f8e6f71SAmine Khaldi };
90222f8e6f71SAmine Khaldi 
90232f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_sequence[] = {
90242f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90252f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
90262f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90272f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
90282f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
90292f8e6f71SAmine Khaldi     {0}
90302f8e6f71SAmine Khaldi };
90312f8e6f71SAmine Khaldi 
90322f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_error_sequence[] = {
90332f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
90342f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
90352f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
90362f8e6f71SAmine Khaldi     {0}
90372f8e6f71SAmine Khaldi };
90382f8e6f71SAmine Khaldi 
90392f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_3_sequence[] = {
90402f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90412f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
90422f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90432f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
90442f8e6f71SAmine Khaldi     {0}
90452f8e6f71SAmine Khaldi };
90462f8e6f71SAmine Khaldi 
90472f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_12345_sequence[] = {
90482f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90492f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
90502f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90512f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
90522f8e6f71SAmine Khaldi     {0}
90532f8e6f71SAmine Khaldi };
90542f8e6f71SAmine Khaldi 
90552f8e6f71SAmine Khaldi static const struct externalui_message closehandle_sequence[] = {
90562f8e6f71SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
90572f8e6f71SAmine Khaldi     {0}
90582f8e6f71SAmine Khaldi };
90592f8e6f71SAmine Khaldi 
90602f8e6f71SAmine Khaldi static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
90612f8e6f71SAmine Khaldi {
90622f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
90632f8e6f71SAmine Khaldi     struct externalui_message msg;
90642f8e6f71SAmine Khaldi 
90652f8e6f71SAmine Khaldi     msg.message = message;
90662f8e6f71SAmine Khaldi     msg.field_count = 0;
90672f8e6f71SAmine Khaldi     strcpy(msg.field[0], string);
90682f8e6f71SAmine Khaldi     add_message(&msg);
90692f8e6f71SAmine Khaldi 
90702f8e6f71SAmine Khaldi     return retval;
90712f8e6f71SAmine Khaldi }
90722f8e6f71SAmine Khaldi 
90732f8e6f71SAmine Khaldi static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
90742f8e6f71SAmine Khaldi {
90752f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
90762f8e6f71SAmine Khaldi     struct externalui_message msg;
9077f860a780SAmine Khaldi     char buffer[256];
9078f860a780SAmine Khaldi     DWORD length;
9079f860a780SAmine Khaldi     UINT r;
90802f8e6f71SAmine Khaldi     int i;
90812f8e6f71SAmine Khaldi 
90822f8e6f71SAmine Khaldi     msg.message = message;
90832f8e6f71SAmine Khaldi     if (message == INSTALLMESSAGE_TERMINATE)
90842f8e6f71SAmine Khaldi     {
90852f8e6f71SAmine Khaldi         /* trying to access the record seems to hang on some versions of Windows */
90862f8e6f71SAmine Khaldi         msg.field_count = -1;
90872f8e6f71SAmine Khaldi         add_message(&msg);
90882f8e6f71SAmine Khaldi         return 1;
90892f8e6f71SAmine Khaldi     }
90902f8e6f71SAmine Khaldi     msg.field_count = MsiRecordGetFieldCount(hrecord);
90912f8e6f71SAmine Khaldi     for (i = 0; i <= msg.field_count; i++)
90922f8e6f71SAmine Khaldi     {
9093f860a780SAmine Khaldi         length = sizeof(buffer);
9094f860a780SAmine Khaldi         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
9095f860a780SAmine Khaldi         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
90962f8e6f71SAmine Khaldi         memcpy(msg.field[i], buffer, min(100, length+1));
90972f8e6f71SAmine Khaldi     }
90982f8e6f71SAmine Khaldi 
9099f860a780SAmine Khaldi     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
9100f860a780SAmine Khaldi     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
9101f860a780SAmine Khaldi         return retval;
9102f860a780SAmine Khaldi 
91032f8e6f71SAmine Khaldi     add_message(&msg);
91042f8e6f71SAmine Khaldi 
91052f8e6f71SAmine Khaldi     return retval;
91062f8e6f71SAmine Khaldi }
91072f8e6f71SAmine Khaldi 
91082f8e6f71SAmine Khaldi static void test_externalui_message(void)
91092f8e6f71SAmine Khaldi {
91102f8e6f71SAmine Khaldi     /* test that events trigger the correct sequence of messages */
91112f8e6f71SAmine Khaldi 
91122f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
91132f8e6f71SAmine Khaldi     MSIHANDLE hdb, hpkg, hrecord;
91142f8e6f71SAmine Khaldi     INT retval = 1;
91152f8e6f71SAmine Khaldi     UINT r;
91162f8e6f71SAmine Khaldi 
91172f8e6f71SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
91182f8e6f71SAmine Khaldi 
91192f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9120f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
91212f8e6f71SAmine Khaldi 
91222f8e6f71SAmine Khaldi     flush_sequence();
91232f8e6f71SAmine Khaldi 
91242f8e6f71SAmine Khaldi     CoInitialize(NULL);
91252f8e6f71SAmine Khaldi 
91262f8e6f71SAmine Khaldi     hdb = create_package_db();
91272f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
91282f8e6f71SAmine Khaldi 
91292f8e6f71SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
91302f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
91312f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
91322f8e6f71SAmine Khaldi 
91332f8e6f71SAmine Khaldi     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
91342f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
91352f8e6f71SAmine Khaldi     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
91362f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
91372f8e6f71SAmine Khaldi 
9138f860a780SAmine Khaldi     create_actiontext_table(hdb);
9139f860a780SAmine Khaldi     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9140f860a780SAmine Khaldi     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
91412f8e6f71SAmine Khaldi 
91422f8e6f71SAmine Khaldi     r = MsiOpenPackageA(NULL, &hpkg);
91432f8e6f71SAmine Khaldi     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
91442f8e6f71SAmine Khaldi     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
91452f8e6f71SAmine Khaldi 
91462f8e6f71SAmine Khaldi     r = MsiOpenPackageA("nonexistent", &hpkg);
91472f8e6f71SAmine Khaldi     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
91482f8e6f71SAmine Khaldi     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
91492f8e6f71SAmine Khaldi 
91502f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
91512f8e6f71SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
91522f8e6f71SAmine Khaldi     {
91532f8e6f71SAmine Khaldi         skip("Not enough rights to perform tests\n");
91542f8e6f71SAmine Khaldi         DeleteFileA(msifile);
91552f8e6f71SAmine Khaldi         return;
91562f8e6f71SAmine Khaldi     }
91572f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
91582f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
91592f8e6f71SAmine Khaldi 
91602f8e6f71SAmine Khaldi     /* Test MsiProcessMessage */
91612f8e6f71SAmine Khaldi     hrecord = MsiCreateRecord(3);
91622f8e6f71SAmine Khaldi     ok(hrecord, "failed to create record\n");
91632f8e6f71SAmine Khaldi 
91642f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "zero");
91652f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "one");
91662f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "two");
91672f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "three");
91682f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
91692f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91702f8e6f71SAmine Khaldi     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
91712f8e6f71SAmine Khaldi 
91722f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "name");
91732f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "description");
91742f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "template");
91752f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
91762f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91772f8e6f71SAmine Khaldi     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
91782f8e6f71SAmine Khaldi 
91792f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "apple");
91802f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "cherry");
91812f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "banana");
91822f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "guava");
91832f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
91842f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91852f8e6f71SAmine Khaldi     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
91862f8e6f71SAmine Khaldi 
91872f8e6f71SAmine Khaldi     /* non-internal error */
91882f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, NULL);
91892f8e6f71SAmine Khaldi     MsiRecordSetInteger(hrecord, 1, 1311);
91902f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
91912f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91922f8e6f71SAmine Khaldi     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
91932f8e6f71SAmine Khaldi 
91942f8e6f71SAmine Khaldi     /* internal error */
91952f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, NULL);
91962f8e6f71SAmine Khaldi     MsiRecordSetInteger(hrecord, 1, 2726);
91972f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
91982f8e6f71SAmine Khaldi     ok(r == 0, "Expected 0, got %d\n", r);
91992f8e6f71SAmine Khaldi     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
92002f8e6f71SAmine Khaldi 
92012f8e6f71SAmine Khaldi     /* with format field */
92022f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "starfruit");
92032f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
92042f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
92052f8e6f71SAmine Khaldi     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
92062f8e6f71SAmine Khaldi 
92072f8e6f71SAmine Khaldi     /* Test a standard action */
92082f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "CostInitialize");
92092f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92102f8e6f71SAmine Khaldi     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
92112f8e6f71SAmine Khaldi 
92122f8e6f71SAmine Khaldi     /* Test a custom action */
92132f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92142f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92152f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
92162f8e6f71SAmine Khaldi 
92172f8e6f71SAmine Khaldi     /* close the package */
92182f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
92192f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
92202f8e6f71SAmine Khaldi 
92212f8e6f71SAmine Khaldi     /* Test dialogs */
92222f8e6f71SAmine Khaldi     hdb = create_package_db();
92232f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
92242f8e6f71SAmine Khaldi 
92252f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
92262f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92272f8e6f71SAmine Khaldi 
9228f860a780SAmine Khaldi     create_dialog_table(hdb);
9229f860a780SAmine Khaldi     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
92302f8e6f71SAmine Khaldi 
9231f860a780SAmine Khaldi     create_control_table(hdb);
9232f860a780SAmine Khaldi     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
92332f8e6f71SAmine Khaldi 
92342f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
92352f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
92362f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
92372f8e6f71SAmine Khaldi 
92382f8e6f71SAmine Khaldi     /* Test a custom action */
92392f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92402f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92412f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
92422f8e6f71SAmine Khaldi 
92432f8e6f71SAmine Khaldi     retval = 2;
92442f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92452f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
92462f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
92472f8e6f71SAmine Khaldi 
92482f8e6f71SAmine Khaldi     retval = 0;
92492f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92502f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92512f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
92522f8e6f71SAmine Khaldi 
92532f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92542f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92552f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
92562f8e6f71SAmine Khaldi 
92572f8e6f71SAmine Khaldi     retval = -1;
92582f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "error");
92592f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92602f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
92612f8e6f71SAmine Khaldi 
92622f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "error");
92632f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92642f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
92652f8e6f71SAmine Khaldi 
92662f8e6f71SAmine Khaldi     retval = -2;
92672f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92682f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92692f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
92702f8e6f71SAmine Khaldi 
92712f8e6f71SAmine Khaldi     retval = 3;
92722f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92732f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
92742f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
92752f8e6f71SAmine Khaldi 
92762f8e6f71SAmine Khaldi     retval = 12345;
92772f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92782f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
92792f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
92802f8e6f71SAmine Khaldi 
92812f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
92822f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
92832f8e6f71SAmine Khaldi 
92842f8e6f71SAmine Khaldi     MsiCloseHandle(hrecord);
92852f8e6f71SAmine Khaldi     CoUninitialize();
92862f8e6f71SAmine Khaldi     DeleteFileA(msifile);
92872f8e6f71SAmine Khaldi     DeleteFileA("forcecodepage.idt");
92882f8e6f71SAmine Khaldi }
92892f8e6f71SAmine Khaldi 
92902f8e6f71SAmine Khaldi static const struct externalui_message controlevent_spawn_sequence[] = {
92912f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
92922f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
92932f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
92942f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
92952f8e6f71SAmine Khaldi 
92962f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
92972f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
92982f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
92992f8e6f71SAmine Khaldi 
93002f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
93012f8e6f71SAmine Khaldi 
93022f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
93032f8e6f71SAmine Khaldi     {0}
93042f8e6f71SAmine Khaldi };
93052f8e6f71SAmine Khaldi 
93062f8e6f71SAmine Khaldi static const struct externalui_message controlevent_spawn2_sequence[] = {
93072f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
93082f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
93092f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
93102f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
93112f8e6f71SAmine Khaldi 
93122f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
93132f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
93142f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
93152f8e6f71SAmine Khaldi 
93162f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
93172f8e6f71SAmine Khaldi 
93182f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
93192f8e6f71SAmine Khaldi     {0}
93202f8e6f71SAmine Khaldi };
93212f8e6f71SAmine Khaldi 
93222f8e6f71SAmine Khaldi static void test_controlevent(void)
93232f8e6f71SAmine Khaldi {
93242f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
93252f8e6f71SAmine Khaldi     MSIHANDLE hdb, hpkg;
93262f8e6f71SAmine Khaldi     UINT r;
93272f8e6f71SAmine Khaldi 
93282f8e6f71SAmine Khaldi     if (!winetest_interactive)
93292f8e6f71SAmine Khaldi     {
93302f8e6f71SAmine Khaldi         skip("interactive ControlEvent tests\n");
93312f8e6f71SAmine Khaldi         return;
93322f8e6f71SAmine Khaldi     }
93332f8e6f71SAmine Khaldi 
93342f8e6f71SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
93352f8e6f71SAmine Khaldi 
93362f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9337f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
93382f8e6f71SAmine Khaldi 
93392f8e6f71SAmine Khaldi     flush_sequence();
93402f8e6f71SAmine Khaldi 
93412f8e6f71SAmine Khaldi     CoInitialize(NULL);
93422f8e6f71SAmine Khaldi 
93432f8e6f71SAmine Khaldi     hdb = create_package_db();
93442f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
93452f8e6f71SAmine Khaldi 
93462f8e6f71SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
93472f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
93482f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
93492f8e6f71SAmine Khaldi 
9350f860a780SAmine Khaldi     create_dialog_table(hdb);
9351f860a780SAmine Khaldi     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9352f860a780SAmine Khaldi     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9353f860a780SAmine Khaldi     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9354f860a780SAmine Khaldi     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
93552f8e6f71SAmine Khaldi 
9356f860a780SAmine Khaldi     create_control_table(hdb);
9357f860a780SAmine Khaldi     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9358f860a780SAmine Khaldi     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9359f860a780SAmine Khaldi     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9360f860a780SAmine Khaldi     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
93612f8e6f71SAmine Khaldi 
9362f860a780SAmine Khaldi     create_controlevent_table(hdb);
9363f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9364f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
93652f8e6f71SAmine Khaldi 
9366f860a780SAmine Khaldi     create_custom_action_table(hdb);
9367f860a780SAmine Khaldi     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
93682f8e6f71SAmine Khaldi 
93692f8e6f71SAmine Khaldi     /* SpawnDialog and EndDialog should trigger after all other events */
9370f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9371f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
93722f8e6f71SAmine Khaldi 
93732f8e6f71SAmine Khaldi     /* Multiple dialog events cause only the last one to be triggered */
9374f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9375f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9376f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
93772f8e6f71SAmine Khaldi 
93782f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
93792f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
93802f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
93812f8e6f71SAmine Khaldi 
93822f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "spawn");
93832f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
93842f8e6f71SAmine Khaldi     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
93852f8e6f71SAmine Khaldi 
93862f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "spawn2");
93872f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
93882f8e6f71SAmine Khaldi     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
93892f8e6f71SAmine Khaldi 
93902f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
93912f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
93922f8e6f71SAmine Khaldi 
93932f8e6f71SAmine Khaldi     CoUninitialize();
93942f8e6f71SAmine Khaldi     DeleteFileA(msifile);
93952f8e6f71SAmine Khaldi     DeleteFileA("forcecodepage.idt");
93962f8e6f71SAmine Khaldi }
93972f8e6f71SAmine Khaldi 
9398f860a780SAmine Khaldi static const struct externalui_message toplevel_install_sequence[] = {
9399f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9400f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9401f860a780SAmine Khaldi 
9402f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9403f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9404f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9405f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9406f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9407f860a780SAmine Khaldi 
9408f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9409f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9410f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9411f860a780SAmine Khaldi 
9412f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9413f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9414f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9415f860a780SAmine Khaldi 
9416f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9417f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9418f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9419f860a780SAmine Khaldi 
9420f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9421f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9422f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9423f860a780SAmine Khaldi 
9424f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9425f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9426f860a780SAmine Khaldi 
9427f860a780SAmine Khaldi     /* property dump */
9428f860a780SAmine Khaldi 
9429f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9430f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9431f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9432f860a780SAmine Khaldi     {0}
9433f860a780SAmine Khaldi };
9434f860a780SAmine Khaldi 
9435f860a780SAmine Khaldi static const struct externalui_message toplevel_install_ui_sequence[] = {
9436f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9437f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9438f860a780SAmine Khaldi 
9439f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9440f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9441f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9442f860a780SAmine Khaldi 
9443f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9444f860a780SAmine Khaldi     {0}
9445f860a780SAmine Khaldi };
9446f860a780SAmine Khaldi 
9447f860a780SAmine Khaldi static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9448f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9449f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9450f860a780SAmine Khaldi 
9451f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9452f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9453f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9454f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9455f860a780SAmine Khaldi 
9456f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9457f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9458f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9459f860a780SAmine Khaldi 
9460f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9461f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9462f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9463f860a780SAmine Khaldi 
9464f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9465f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9466f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9467f860a780SAmine Khaldi 
9468f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9469f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9470f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9471f860a780SAmine Khaldi 
9472f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9473f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9474f860a780SAmine Khaldi 
9475f860a780SAmine Khaldi     /* property dump */
9476f860a780SAmine Khaldi 
9477f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9478f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9479f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9480f860a780SAmine Khaldi     {0}
9481f860a780SAmine Khaldi };
9482f860a780SAmine Khaldi 
9483f860a780SAmine Khaldi static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9484f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9485f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9486f860a780SAmine Khaldi 
9487f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9488f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9489f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9490f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9491f860a780SAmine Khaldi 
9492f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9493f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9494f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9495f860a780SAmine Khaldi 
9496f860a780SAmine Khaldi     /* property dump */
9497f860a780SAmine Khaldi 
9498f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9499f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9500f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9501f860a780SAmine Khaldi     {0}
9502f860a780SAmine Khaldi };
9503f860a780SAmine Khaldi 
9504f860a780SAmine Khaldi static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9505f860a780SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
9506f860a780SAmine Khaldi 
9507f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9508f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9509f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9510f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9511f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9512f860a780SAmine Khaldi 
9513f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9514f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9515f860a780SAmine Khaldi 
9516f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9517f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9518f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9519f860a780SAmine Khaldi 
9520f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9521f860a780SAmine Khaldi 
9522f860a780SAmine Khaldi     /* property dump */
9523f860a780SAmine Khaldi 
9524f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9525f860a780SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
9526f860a780SAmine Khaldi     {0}
9527f860a780SAmine Khaldi };
9528f860a780SAmine Khaldi 
9529f860a780SAmine Khaldi static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9530f860a780SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
9531f860a780SAmine Khaldi 
9532f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9533f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9534f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9535f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9536f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9537f860a780SAmine Khaldi 
9538f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9539f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9540f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9541f860a780SAmine Khaldi 
9542f860a780SAmine Khaldi     /* property dump */
9543f860a780SAmine Khaldi 
9544f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9545f860a780SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
9546f860a780SAmine Khaldi     {0}
9547f860a780SAmine Khaldi };
9548f860a780SAmine Khaldi 
9549f860a780SAmine Khaldi /* tests involving top-level actions: INSTALL, ExecuteAction */
9550f860a780SAmine Khaldi static void test_top_level_action(void)
9551f860a780SAmine Khaldi {
9552f860a780SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
9553f860a780SAmine Khaldi     MSIHANDLE hdb, hpkg;
9554f860a780SAmine Khaldi     UINT r;
9555f860a780SAmine Khaldi     char msifile_absolute[MAX_PATH];
9556f860a780SAmine Khaldi 
9557f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9558f860a780SAmine Khaldi 
9559f860a780SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9560f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9561f860a780SAmine Khaldi 
9562f860a780SAmine Khaldi     flush_sequence();
9563f860a780SAmine Khaldi 
9564f860a780SAmine Khaldi     CoInitialize(NULL);
9565f860a780SAmine Khaldi 
9566f860a780SAmine Khaldi     hdb = create_package_db();
9567f860a780SAmine Khaldi     ok(hdb, "failed to create database\n");
9568f860a780SAmine Khaldi 
9569f860a780SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9570f860a780SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9571f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9572f860a780SAmine Khaldi 
9573f860a780SAmine Khaldi     create_property_table(hdb);
9574f860a780SAmine Khaldi     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9575f860a780SAmine Khaldi 
9576f860a780SAmine Khaldi     create_install_execute_sequence_table(hdb);
9577f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9578f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9579f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9580f860a780SAmine Khaldi 
9581f860a780SAmine Khaldi     create_install_ui_sequence_table(hdb);
9582f860a780SAmine Khaldi     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9583f860a780SAmine Khaldi 
9584f860a780SAmine Khaldi     MsiDatabaseCommit(hdb);
9585f860a780SAmine Khaldi 
9586f860a780SAmine Khaldi     /* for some reason we have to open the package from file using an absolute path */
9587f860a780SAmine Khaldi     MsiCloseHandle(hdb);
9588f860a780SAmine Khaldi     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9589f860a780SAmine Khaldi     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9590f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9591f860a780SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9592f860a780SAmine Khaldi 
9593f860a780SAmine Khaldi     /* test INSTALL */
9594f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "INSTALL");
9595f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9596f860a780SAmine Khaldi     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9597f860a780SAmine Khaldi 
9598f860a780SAmine Khaldi     /* test INSTALL with reduced+ UI */
9599f860a780SAmine Khaldi     /* for some reason we need to re-open the package to change the internal UI */
9600f860a780SAmine Khaldi     MsiCloseHandle(hpkg);
9601f860a780SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9602f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9603f860a780SAmine Khaldi     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9604f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9605f860a780SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9606f860a780SAmine Khaldi 
9607f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "INSTALL");
9608f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9609f860a780SAmine Khaldi     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9610f860a780SAmine Khaldi 
9611f860a780SAmine Khaldi     /* test ExecuteAction with EXECUTEACTION property unset */
9612f860a780SAmine Khaldi     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9613f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "ExecuteAction");
9614f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9615f860a780SAmine Khaldi     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9616f860a780SAmine Khaldi 
9617f860a780SAmine Khaldi     /* test ExecuteAction with EXECUTEACTION property set */
9618f860a780SAmine Khaldi     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9619f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "ExecuteAction");
9620f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9621f860a780SAmine Khaldi     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9622f860a780SAmine Khaldi 
9623f860a780SAmine Khaldi     MsiCloseHandle(hpkg);
9624f860a780SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9625f860a780SAmine Khaldi 
9626f860a780SAmine Khaldi     /* test MsiInstallProduct() */
9627f860a780SAmine Khaldi     r = MsiInstallProductA(msifile_absolute, NULL);
9628f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9629f860a780SAmine Khaldi     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9630f860a780SAmine Khaldi 
9631f860a780SAmine Khaldi     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9632f860a780SAmine Khaldi     todo_wine
9633f860a780SAmine Khaldi     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9634f860a780SAmine Khaldi     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9635f860a780SAmine Khaldi 
9636f860a780SAmine Khaldi     CoUninitialize();
9637f860a780SAmine Khaldi     DeleteFileA(msifile);
9638f860a780SAmine Khaldi     DeleteFileA("forcecodepage.idt");
9639f860a780SAmine Khaldi }
9640f860a780SAmine Khaldi 
9641c2c66affSColin Finck START_TEST(package)
9642c2c66affSColin Finck {
9643*2b92436dSwinesync     char temp_path[MAX_PATH], prev_path[MAX_PATH];
9644c2c66affSColin Finck     STATEMGRSTATUS status;
9645c2c66affSColin Finck     BOOL ret = FALSE;
9646*2b92436dSwinesync     DWORD len;
9647c2c66affSColin Finck 
9648c2c66affSColin Finck     init_functionpointers();
9649c2c66affSColin Finck 
9650c2c66affSColin Finck     if (pIsWow64Process)
9651c2c66affSColin Finck         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9652c2c66affSColin Finck 
9653*2b92436dSwinesync     GetCurrentDirectoryA(MAX_PATH, prev_path);
9654*2b92436dSwinesync     GetTempPathA(MAX_PATH, temp_path);
9655*2b92436dSwinesync     SetCurrentDirectoryA(temp_path);
9656*2b92436dSwinesync 
9657*2b92436dSwinesync     lstrcpyA(CURR_DIR, temp_path);
9658*2b92436dSwinesync     len = lstrlenA(CURR_DIR);
9659*2b92436dSwinesync 
9660*2b92436dSwinesync     if (len && (CURR_DIR[len - 1] == '\\'))
9661*2b92436dSwinesync         CURR_DIR[len - 1] = 0;
9662c2c66affSColin Finck 
9663c2c66affSColin Finck     /* Create a restore point ourselves so we circumvent the multitude of restore points
9664c2c66affSColin Finck      * that would have been created by all the installation and removal tests.
9665c2c66affSColin Finck      *
9666c2c66affSColin Finck      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9667c2c66affSColin Finck      * creation of restore points.
9668c2c66affSColin Finck      */
9669c2c66affSColin Finck     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9670c2c66affSColin Finck     {
9671c2c66affSColin Finck         memset(&status, 0, sizeof(status));
9672c2c66affSColin Finck         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9673c2c66affSColin Finck     }
9674c2c66affSColin Finck 
9675c2c66affSColin Finck     test_createpackage();
9676c2c66affSColin Finck     test_doaction();
9677c2c66affSColin Finck     test_gettargetpath_bad();
9678c2c66affSColin Finck     test_settargetpath();
9679c2c66affSColin Finck     test_props();
9680c2c66affSColin Finck     test_property_table();
9681c2c66affSColin Finck     test_condition();
9682c2c66affSColin Finck     test_msipackage();
9683c2c66affSColin Finck     test_formatrecord2();
9684f860a780SAmine Khaldi     test_formatrecord_tables();
9685c2c66affSColin Finck     test_states();
9686c2c66affSColin Finck     test_removefiles();
9687c2c66affSColin Finck     test_appsearch();
9688c2c66affSColin Finck     test_appsearch_complocator();
9689c2c66affSColin Finck     test_appsearch_reglocator();
9690c2c66affSColin Finck     test_appsearch_inilocator();
9691c2c66affSColin Finck     test_appsearch_drlocator();
9692c2c66affSColin Finck     test_featureparents();
9693c2c66affSColin Finck     test_installprops();
9694c2c66affSColin Finck     test_launchconditions();
9695c2c66affSColin Finck     test_ccpsearch();
9696c2c66affSColin Finck     test_complocator();
9697c2c66affSColin Finck     test_MsiGetSourcePath();
9698c2c66affSColin Finck     test_shortlongsource();
9699c2c66affSColin Finck     test_sourcedir();
9700c2c66affSColin Finck     test_access();
9701c2c66affSColin Finck     test_emptypackage();
9702c2c66affSColin Finck     test_MsiGetProductProperty();
9703c2c66affSColin Finck     test_MsiSetProperty();
9704c2c66affSColin Finck     test_MsiApplyMultiplePatches();
9705c2c66affSColin Finck     test_MsiApplyPatch();
9706818a84ddSwinesync     test_costs();
9707c2c66affSColin Finck     test_MsiDatabaseCommit();
97082f8e6f71SAmine Khaldi     test_externalui();
97092f8e6f71SAmine Khaldi     test_externalui_message();
97102f8e6f71SAmine Khaldi     test_controlevent();
9711f860a780SAmine Khaldi     test_top_level_action();
9712c2c66affSColin Finck 
9713c2c66affSColin Finck     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9714c2c66affSColin Finck     {
9715c2c66affSColin Finck         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9716c2c66affSColin Finck         if (ret)
9717c2c66affSColin Finck             remove_restore_point(status.llSequenceNumber);
9718c2c66affSColin Finck     }
9719*2b92436dSwinesync 
9720*2b92436dSwinesync     SetCurrentDirectoryA(prev_path);
9721c2c66affSColin Finck }
9722