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>
32c2c66affSColin Finck 
3331139640SAmine Khaldi #include "wine/test.h"
3431139640SAmine Khaldi 
35c2c66affSColin Finck static BOOL is_wow64;
36c2c66affSColin Finck static const char msifile[] = "winetest-package.msi";
37c2c66affSColin Finck static const WCHAR msifileW[] =
38c2c66affSColin Finck     {'w','i','n','e','t','e','s','t','-','p','a','c','k','a','g','e','.','m','s','i',0};
39c2c66affSColin Finck static char CURR_DIR[MAX_PATH];
40c2c66affSColin Finck 
41c2c66affSColin Finck static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42c2c66affSColin Finck static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
43c2c66affSColin Finck 
44c2c66affSColin Finck static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
45c2c66affSColin Finck static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
46c2c66affSColin Finck static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
47c2c66affSColin Finck static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
48c2c66affSColin Finck static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
49c2c66affSColin Finck static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
50c2c66affSColin Finck static void (WINAPI *pGetSystemInfo)(LPSYSTEM_INFO);
51c2c66affSColin Finck static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
52c2c66affSColin Finck static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR, UINT);
53c2c66affSColin Finck 
54c2c66affSColin Finck static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
55c2c66affSColin Finck static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
56c2c66affSColin Finck 
57c2c66affSColin Finck static void init_functionpointers(void)
58c2c66affSColin Finck {
59c2c66affSColin Finck     HMODULE hmsi = GetModuleHandleA("msi.dll");
60c2c66affSColin Finck     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
61c2c66affSColin Finck     HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
62c2c66affSColin Finck     HMODULE hshell32 = GetModuleHandleA("shell32.dll");
63c2c66affSColin Finck     HMODULE hsrclient;
64c2c66affSColin Finck 
65c2c66affSColin Finck #define GET_PROC(mod, func) \
66c2c66affSColin Finck     p ## func = (void*)GetProcAddress(mod, #func);
67c2c66affSColin Finck 
68c2c66affSColin Finck     GET_PROC(hmsi, MsiGetComponentPathExA);
69c2c66affSColin Finck     GET_PROC(hshell32, SHGetFolderPathA);
70c2c66affSColin Finck 
71c2c66affSColin Finck     GET_PROC(hadvapi32, CheckTokenMembership);
72c2c66affSColin Finck     GET_PROC(hadvapi32, ConvertSidToStringSidA);
73c2c66affSColin Finck     GET_PROC(hadvapi32, OpenProcessToken);
74c2c66affSColin Finck     GET_PROC(hadvapi32, RegDeleteKeyExA)
75c2c66affSColin Finck     GET_PROC(hadvapi32, RegDeleteKeyExW)
76c2c66affSColin Finck     GET_PROC(hkernel32, IsWow64Process)
77c2c66affSColin Finck     GET_PROC(hkernel32, GetNativeSystemInfo)
78c2c66affSColin Finck     GET_PROC(hkernel32, GetSystemInfo)
79c2c66affSColin Finck     GET_PROC(hkernel32, GetSystemWow64DirectoryA)
80c2c66affSColin Finck 
81c2c66affSColin Finck     hsrclient = LoadLibraryA("srclient.dll");
82c2c66affSColin Finck     GET_PROC(hsrclient, SRRemoveRestorePoint);
83c2c66affSColin Finck     GET_PROC(hsrclient, SRSetRestorePointA);
84c2c66affSColin Finck #undef GET_PROC
85c2c66affSColin Finck }
86c2c66affSColin Finck 
87c2c66affSColin Finck static BOOL is_process_limited(void)
88c2c66affSColin Finck {
89c2c66affSColin Finck     SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
90c2c66affSColin Finck     PSID Group = NULL;
91c2c66affSColin Finck     BOOL IsInGroup;
92c2c66affSColin Finck     HANDLE token;
93c2c66affSColin Finck 
94c2c66affSColin Finck     if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
95c2c66affSColin Finck 
96c2c66affSColin Finck     if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
97c2c66affSColin Finck                                   DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
98c2c66affSColin Finck         !pCheckTokenMembership(NULL, Group, &IsInGroup))
99c2c66affSColin Finck     {
100c2c66affSColin Finck         trace("Could not check if the current user is an administrator\n");
101c2c66affSColin Finck         FreeSid(Group);
102c2c66affSColin Finck         return FALSE;
103c2c66affSColin Finck     }
104c2c66affSColin Finck     FreeSid(Group);
105c2c66affSColin Finck 
106c2c66affSColin Finck     if (!IsInGroup)
107c2c66affSColin Finck     {
108c2c66affSColin Finck         if (!AllocateAndInitializeSid(&NtAuthority, 2,
109c2c66affSColin Finck                                       SECURITY_BUILTIN_DOMAIN_RID,
110c2c66affSColin Finck                                       DOMAIN_ALIAS_RID_POWER_USERS,
111c2c66affSColin Finck                                       0, 0, 0, 0, 0, 0, &Group) ||
112c2c66affSColin Finck             !pCheckTokenMembership(NULL, Group, &IsInGroup))
113c2c66affSColin Finck         {
114c2c66affSColin Finck             trace("Could not check if the current user is a power user\n");
115c2c66affSColin Finck             return FALSE;
116c2c66affSColin Finck         }
117c2c66affSColin Finck         if (!IsInGroup)
118c2c66affSColin Finck         {
119c2c66affSColin Finck             /* Only administrators and power users can be powerful */
120c2c66affSColin Finck             return TRUE;
121c2c66affSColin Finck         }
122c2c66affSColin Finck     }
123c2c66affSColin Finck 
124c2c66affSColin Finck     if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
125c2c66affSColin Finck     {
126c2c66affSColin Finck         BOOL ret;
127c2c66affSColin Finck         TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
128c2c66affSColin Finck         DWORD size;
129c2c66affSColin Finck 
130c2c66affSColin Finck         ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
131c2c66affSColin Finck         CloseHandle(token);
132c2c66affSColin Finck         return (ret && type == TokenElevationTypeLimited);
133c2c66affSColin Finck     }
134c2c66affSColin Finck     return FALSE;
135c2c66affSColin Finck }
136c2c66affSColin Finck 
137c2c66affSColin Finck static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
138c2c66affSColin Finck {
139c2c66affSColin Finck     if (pRegDeleteKeyExA)
140c2c66affSColin Finck         return pRegDeleteKeyExA( key, subkey, access, 0 );
141c2c66affSColin Finck     return RegDeleteKeyA( key, subkey );
142c2c66affSColin Finck }
143c2c66affSColin Finck 
144c2c66affSColin Finck static char *get_user_sid(void)
145c2c66affSColin Finck {
146c2c66affSColin Finck     HANDLE token;
147c2c66affSColin Finck     DWORD size = 0;
148c2c66affSColin Finck     TOKEN_USER *user;
149c2c66affSColin Finck     char *usersid = NULL;
150c2c66affSColin Finck 
151c2c66affSColin Finck     if (!pConvertSidToStringSidA)
152c2c66affSColin Finck     {
153c2c66affSColin Finck         win_skip("ConvertSidToStringSidA is not available\n");
154c2c66affSColin Finck         return NULL;
155c2c66affSColin Finck     }
156c2c66affSColin Finck     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
157c2c66affSColin Finck     GetTokenInformation(token, TokenUser, NULL, size, &size);
158c2c66affSColin Finck 
159c2c66affSColin Finck     user = HeapAlloc(GetProcessHeap(), 0, size);
160c2c66affSColin Finck     GetTokenInformation(token, TokenUser, user, size, &size);
161c2c66affSColin Finck     pConvertSidToStringSidA(user->User.Sid, &usersid);
162c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, user);
163c2c66affSColin Finck 
164c2c66affSColin Finck     CloseHandle(token);
165c2c66affSColin Finck     return usersid;
166c2c66affSColin Finck }
167c2c66affSColin Finck 
168c2c66affSColin Finck /* RegDeleteTreeW from dlls/advapi32/registry.c */
169c2c66affSColin Finck static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
170c2c66affSColin Finck {
171c2c66affSColin Finck     LONG ret;
172c2c66affSColin Finck     DWORD dwMaxSubkeyLen, dwMaxValueLen;
173c2c66affSColin Finck     DWORD dwMaxLen, dwSize;
174c2c66affSColin Finck     WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
175c2c66affSColin Finck     HKEY hSubKey = hKey;
176c2c66affSColin Finck 
177c2c66affSColin Finck     if(lpszSubKey)
178c2c66affSColin Finck     {
179c2c66affSColin Finck         ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
180c2c66affSColin Finck         if (ret) return ret;
181c2c66affSColin Finck     }
182c2c66affSColin Finck 
183c2c66affSColin Finck     ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
184c2c66affSColin Finck             &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
185c2c66affSColin Finck     if (ret) goto cleanup;
186c2c66affSColin Finck 
187c2c66affSColin Finck     dwMaxSubkeyLen++;
188c2c66affSColin Finck     dwMaxValueLen++;
189c2c66affSColin Finck     dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
190c2c66affSColin Finck     if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
191c2c66affSColin Finck     {
192c2c66affSColin Finck         /* Name too big: alloc a buffer for it */
193c2c66affSColin Finck         if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
194c2c66affSColin Finck         {
195c2c66affSColin Finck             ret = ERROR_NOT_ENOUGH_MEMORY;
196c2c66affSColin Finck             goto cleanup;
197c2c66affSColin Finck         }
198c2c66affSColin Finck     }
199c2c66affSColin Finck 
200c2c66affSColin Finck     /* Recursively delete all the subkeys */
201c2c66affSColin Finck     while (TRUE)
202c2c66affSColin Finck     {
203c2c66affSColin Finck         dwSize = dwMaxLen;
204c2c66affSColin Finck         if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
205c2c66affSColin Finck                           NULL, NULL, NULL)) break;
206c2c66affSColin Finck 
207c2c66affSColin Finck         ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
208c2c66affSColin Finck         if (ret) goto cleanup;
209c2c66affSColin Finck     }
210c2c66affSColin Finck 
211c2c66affSColin Finck     if (lpszSubKey)
212c2c66affSColin Finck     {
213c2c66affSColin Finck         if (pRegDeleteKeyExW)
214c2c66affSColin Finck             ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
215c2c66affSColin Finck         else
216c2c66affSColin Finck             ret = RegDeleteKeyW(hKey, lpszSubKey);
217c2c66affSColin Finck     }
218c2c66affSColin Finck     else
219c2c66affSColin Finck         while (TRUE)
220c2c66affSColin Finck         {
221c2c66affSColin Finck             dwSize = dwMaxLen;
222c2c66affSColin Finck             if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
223c2c66affSColin Finck                   NULL, NULL, NULL, NULL)) break;
224c2c66affSColin Finck 
225c2c66affSColin Finck             ret = RegDeleteValueW(hKey, lpszName);
226c2c66affSColin Finck             if (ret) goto cleanup;
227c2c66affSColin Finck         }
228c2c66affSColin Finck 
229c2c66affSColin Finck cleanup:
230c2c66affSColin Finck     if (lpszName != szNameBuf)
231c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, lpszName);
232c2c66affSColin Finck     if(lpszSubKey)
233c2c66affSColin Finck         RegCloseKey(hSubKey);
234c2c66affSColin Finck     return ret;
235c2c66affSColin Finck }
236c2c66affSColin Finck 
237c2c66affSColin Finck static BOOL squash_guid(LPCWSTR in, LPWSTR out)
238c2c66affSColin Finck {
239c2c66affSColin Finck     DWORD i,n=1;
240c2c66affSColin Finck     GUID guid;
241c2c66affSColin Finck 
242c2c66affSColin Finck     if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
243c2c66affSColin Finck         return FALSE;
244c2c66affSColin Finck 
245c2c66affSColin Finck     for(i=0; i<8; i++)
246c2c66affSColin Finck         out[7-i] = in[n++];
247c2c66affSColin Finck     n++;
248c2c66affSColin Finck     for(i=0; i<4; i++)
249c2c66affSColin Finck         out[11-i] = in[n++];
250c2c66affSColin Finck     n++;
251c2c66affSColin Finck     for(i=0; i<4; i++)
252c2c66affSColin Finck         out[15-i] = in[n++];
253c2c66affSColin Finck     n++;
254c2c66affSColin Finck     for(i=0; i<2; i++)
255c2c66affSColin Finck     {
256c2c66affSColin Finck         out[17+i*2] = in[n++];
257c2c66affSColin Finck         out[16+i*2] = in[n++];
258c2c66affSColin Finck     }
259c2c66affSColin Finck     n++;
260c2c66affSColin Finck     for( ; i<8; i++)
261c2c66affSColin Finck     {
262c2c66affSColin Finck         out[17+i*2] = in[n++];
263c2c66affSColin Finck         out[16+i*2] = in[n++];
264c2c66affSColin Finck     }
265c2c66affSColin Finck     out[32]=0;
266c2c66affSColin Finck     return TRUE;
267c2c66affSColin Finck }
268c2c66affSColin Finck 
269c2c66affSColin Finck static void create_test_guid(LPSTR prodcode, LPSTR squashed)
270c2c66affSColin Finck {
271c2c66affSColin Finck     WCHAR guidW[MAX_PATH];
272c2c66affSColin Finck     WCHAR squashedW[MAX_PATH];
273c2c66affSColin Finck     GUID guid;
274c2c66affSColin Finck     HRESULT hr;
275c2c66affSColin Finck     int size;
276c2c66affSColin Finck 
277c2c66affSColin Finck     hr = CoCreateGuid(&guid);
278c2c66affSColin Finck     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
279c2c66affSColin Finck 
280c2c66affSColin Finck     size = StringFromGUID2(&guid, guidW, MAX_PATH);
281c2c66affSColin Finck     ok(size == 39, "Expected 39, got %d\n", hr);
282c2c66affSColin Finck 
283c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
284c2c66affSColin Finck     squash_guid(guidW, squashedW);
285c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
286c2c66affSColin Finck }
287c2c66affSColin Finck 
288c2c66affSColin Finck static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
289c2c66affSColin Finck                                LPCSTR guid, LPSTR usersid, BOOL dir)
290c2c66affSColin Finck {
291c2c66affSColin Finck     WCHAR guidW[MAX_PATH];
292c2c66affSColin Finck     WCHAR squashedW[MAX_PATH];
293c2c66affSColin Finck     CHAR squashed[MAX_PATH];
294c2c66affSColin Finck     CHAR comppath[MAX_PATH];
295c2c66affSColin Finck     CHAR prodpath[MAX_PATH];
296c2c66affSColin Finck     CHAR path[MAX_PATH];
297c2c66affSColin Finck     LPCSTR prod = NULL;
298c2c66affSColin Finck     HKEY hkey;
299c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
300c2c66affSColin Finck 
301c2c66affSColin Finck     if (is_wow64)
302c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
303c2c66affSColin Finck 
304c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
305c2c66affSColin Finck     squash_guid(guidW, squashedW);
306c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
307c2c66affSColin Finck 
308c2c66affSColin Finck     if (context == MSIINSTALLCONTEXT_MACHINE)
309c2c66affSColin Finck     {
310c2c66affSColin Finck         prod = "3D0DAE300FACA1300AD792060BCDAA92";
311c2c66affSColin Finck         sprintf(comppath,
312c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
313c2c66affSColin Finck                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
314c2c66affSColin Finck         lstrcpyA(prodpath,
315c2c66affSColin Finck                  "SOFTWARE\\Classes\\Installer\\"
316c2c66affSColin Finck                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
317c2c66affSColin Finck     }
318c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
319c2c66affSColin Finck     {
320c2c66affSColin Finck         prod = "7D2F387510109040002000060BECB6AB";
321c2c66affSColin Finck         sprintf(comppath,
322c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
323c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
324c2c66affSColin Finck         sprintf(prodpath,
325c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
326c2c66affSColin Finck                 "Installer\\%s\\Installer\\Products\\"
327c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
328c2c66affSColin Finck     }
329c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
330c2c66affSColin Finck     {
331c2c66affSColin Finck         prod = "7D2F387510109040002000060BECB6AB";
332c2c66affSColin Finck         sprintf(comppath,
333c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
334c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
335c2c66affSColin Finck         sprintf(prodpath,
336c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
337c2c66affSColin Finck                 "Installer\\Managed\\%s\\Installer\\Products\\"
338c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
339c2c66affSColin Finck     }
340c2c66affSColin Finck 
341c2c66affSColin Finck     RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
342c2c66affSColin Finck 
343c2c66affSColin Finck     lstrcpyA(path, CURR_DIR);
344c2c66affSColin Finck     lstrcatA(path, "\\");
345c2c66affSColin Finck     if (!dir) lstrcatA(path, filename);
346c2c66affSColin Finck 
347c2c66affSColin Finck     RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
348c2c66affSColin Finck     RegCloseKey(hkey);
349c2c66affSColin Finck 
350c2c66affSColin Finck     RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
351c2c66affSColin Finck     RegCloseKey(hkey);
352c2c66affSColin Finck }
353c2c66affSColin Finck 
354c2c66affSColin Finck static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
355c2c66affSColin Finck {
356c2c66affSColin Finck     WCHAR guidW[MAX_PATH];
357c2c66affSColin Finck     WCHAR squashedW[MAX_PATH];
358c2c66affSColin Finck     WCHAR substrW[MAX_PATH];
359c2c66affSColin Finck     CHAR squashed[MAX_PATH];
360c2c66affSColin Finck     CHAR comppath[MAX_PATH];
361c2c66affSColin Finck     CHAR prodpath[MAX_PATH];
362c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
363c2c66affSColin Finck 
364c2c66affSColin Finck     if (is_wow64)
365c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
366c2c66affSColin Finck 
367c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
368c2c66affSColin Finck     squash_guid(guidW, squashedW);
369c2c66affSColin Finck     WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
370c2c66affSColin Finck 
371c2c66affSColin Finck     if (context == MSIINSTALLCONTEXT_MACHINE)
372c2c66affSColin Finck     {
373c2c66affSColin Finck         sprintf(comppath,
374c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
375c2c66affSColin Finck                 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
376c2c66affSColin Finck         lstrcpyA(prodpath,
377c2c66affSColin Finck                  "SOFTWARE\\Classes\\Installer\\"
378c2c66affSColin Finck                  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
379c2c66affSColin Finck     }
380c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
381c2c66affSColin Finck     {
382c2c66affSColin Finck         sprintf(comppath,
383c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
384c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
385c2c66affSColin Finck         sprintf(prodpath,
386c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
387c2c66affSColin Finck                 "Installer\\%s\\Installer\\Products\\"
388c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
389c2c66affSColin Finck     }
390c2c66affSColin Finck     else if (context == MSIINSTALLCONTEXT_USERMANAGED)
391c2c66affSColin Finck     {
392c2c66affSColin Finck         sprintf(comppath,
393c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
394c2c66affSColin Finck                 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
395c2c66affSColin Finck         sprintf(prodpath,
396c2c66affSColin Finck                 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
397c2c66affSColin Finck                 "Installer\\Managed\\%s\\Installer\\Products\\"
398c2c66affSColin Finck                 "7D2F387510109040002000060BECB6AB", usersid);
399c2c66affSColin Finck     }
400c2c66affSColin Finck 
401c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
402c2c66affSColin Finck     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
403c2c66affSColin Finck 
404c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
405c2c66affSColin Finck     package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
406c2c66affSColin Finck }
407c2c66affSColin Finck 
408c2c66affSColin Finck static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
409c2c66affSColin Finck {
410c2c66affSColin Finck     MSIHANDLE hview = 0;
411c2c66affSColin Finck     UINT r, ret;
412c2c66affSColin Finck 
413c2c66affSColin Finck     /* open a select query */
414c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, query, &hview);
415c2c66affSColin Finck     if (r != ERROR_SUCCESS)
416c2c66affSColin Finck         return r;
417c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
418c2c66affSColin Finck     if (r != ERROR_SUCCESS)
419c2c66affSColin Finck         return r;
420c2c66affSColin Finck     ret = MsiViewFetch(hview, phrec);
421c2c66affSColin Finck     r = MsiViewClose(hview);
422c2c66affSColin Finck     if (r != ERROR_SUCCESS)
423c2c66affSColin Finck         return r;
424c2c66affSColin Finck     r = MsiCloseHandle(hview);
425c2c66affSColin Finck     if (r != ERROR_SUCCESS)
426c2c66affSColin Finck         return r;
427c2c66affSColin Finck     return ret;
428c2c66affSColin Finck }
429c2c66affSColin Finck 
430c2c66affSColin Finck static UINT run_query( MSIHANDLE hdb, const char *query )
431c2c66affSColin Finck {
432c2c66affSColin Finck     MSIHANDLE hview = 0;
433c2c66affSColin Finck     UINT r;
434c2c66affSColin Finck 
435c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, query, &hview);
436c2c66affSColin Finck     if( r != ERROR_SUCCESS )
437c2c66affSColin Finck         return r;
438c2c66affSColin Finck 
439c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
440c2c66affSColin Finck     if( r == ERROR_SUCCESS )
441c2c66affSColin Finck         r = MsiViewClose(hview);
442c2c66affSColin Finck     MsiCloseHandle(hview);
443c2c66affSColin Finck     return r;
444c2c66affSColin Finck }
445c2c66affSColin Finck 
446c2c66affSColin Finck static UINT create_component_table( MSIHANDLE hdb )
447c2c66affSColin Finck {
448f860a780SAmine Khaldi     UINT r = run_query( hdb,
449c2c66affSColin Finck             "CREATE TABLE `Component` ( "
450c2c66affSColin Finck             "`Component` CHAR(72) NOT NULL, "
451c2c66affSColin Finck             "`ComponentId` CHAR(38), "
452c2c66affSColin Finck             "`Directory_` CHAR(72) NOT NULL, "
453c2c66affSColin Finck             "`Attributes` SHORT NOT NULL, "
454c2c66affSColin Finck             "`Condition` CHAR(255), "
455c2c66affSColin Finck             "`KeyPath` CHAR(72) "
456c2c66affSColin Finck             "PRIMARY KEY `Component`)" );
457f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
458f860a780SAmine Khaldi     return r;
459c2c66affSColin Finck }
460c2c66affSColin Finck 
461c2c66affSColin Finck static UINT create_feature_table( MSIHANDLE hdb )
462c2c66affSColin Finck {
463f860a780SAmine Khaldi     UINT r = run_query( hdb,
464c2c66affSColin Finck             "CREATE TABLE `Feature` ( "
465c2c66affSColin Finck             "`Feature` CHAR(38) NOT NULL, "
466c2c66affSColin Finck             "`Feature_Parent` CHAR(38), "
467c2c66affSColin Finck             "`Title` CHAR(64), "
468c2c66affSColin Finck             "`Description` CHAR(255), "
469c2c66affSColin Finck             "`Display` SHORT NOT NULL, "
470c2c66affSColin Finck             "`Level` SHORT NOT NULL, "
471c2c66affSColin Finck             "`Directory_` CHAR(72), "
472c2c66affSColin Finck             "`Attributes` SHORT NOT NULL "
473c2c66affSColin Finck             "PRIMARY KEY `Feature`)" );
474f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
475f860a780SAmine Khaldi     return r;
476c2c66affSColin Finck }
477c2c66affSColin Finck 
478c2c66affSColin Finck static UINT create_feature_components_table( MSIHANDLE hdb )
479c2c66affSColin Finck {
480f860a780SAmine Khaldi     UINT r = run_query( hdb,
481c2c66affSColin Finck             "CREATE TABLE `FeatureComponents` ( "
482c2c66affSColin Finck             "`Feature_` CHAR(38) NOT NULL, "
483c2c66affSColin Finck             "`Component_` CHAR(72) NOT NULL "
484c2c66affSColin Finck             "PRIMARY KEY `Feature_`, `Component_` )" );
485f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
486f860a780SAmine Khaldi     return r;
487c2c66affSColin Finck }
488c2c66affSColin Finck 
489c2c66affSColin Finck static UINT create_file_table( MSIHANDLE hdb )
490c2c66affSColin Finck {
491f860a780SAmine Khaldi     UINT r = run_query( hdb,
492c2c66affSColin Finck             "CREATE TABLE `File` ("
493c2c66affSColin Finck             "`File` CHAR(72) NOT NULL, "
494c2c66affSColin Finck             "`Component_` CHAR(72) NOT NULL, "
495c2c66affSColin Finck             "`FileName` CHAR(255) NOT NULL, "
496c2c66affSColin Finck             "`FileSize` LONG NOT NULL, "
497c2c66affSColin Finck             "`Version` CHAR(72), "
498c2c66affSColin Finck             "`Language` CHAR(20), "
499c2c66affSColin Finck             "`Attributes` SHORT, "
500c2c66affSColin Finck             "`Sequence` SHORT NOT NULL "
501c2c66affSColin Finck             "PRIMARY KEY `File`)" );
502f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
503f860a780SAmine Khaldi     return r;
504c2c66affSColin Finck }
505c2c66affSColin Finck 
506c2c66affSColin Finck static UINT create_remove_file_table( MSIHANDLE hdb )
507c2c66affSColin Finck {
508f860a780SAmine Khaldi     UINT r = run_query( hdb,
509c2c66affSColin Finck             "CREATE TABLE `RemoveFile` ("
510c2c66affSColin Finck             "`FileKey` CHAR(72) NOT NULL, "
511c2c66affSColin Finck             "`Component_` CHAR(72) NOT NULL, "
512c2c66affSColin Finck             "`FileName` CHAR(255) LOCALIZABLE, "
513c2c66affSColin Finck             "`DirProperty` CHAR(72) NOT NULL, "
514c2c66affSColin Finck             "`InstallMode` SHORT NOT NULL "
515c2c66affSColin Finck             "PRIMARY KEY `FileKey`)" );
516f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
517f860a780SAmine Khaldi     return r;
518c2c66affSColin Finck }
519c2c66affSColin Finck 
520c2c66affSColin Finck static UINT create_appsearch_table( MSIHANDLE hdb )
521c2c66affSColin Finck {
522f860a780SAmine Khaldi     UINT r = run_query( hdb,
523c2c66affSColin Finck             "CREATE TABLE `AppSearch` ("
524c2c66affSColin Finck             "`Property` CHAR(72) NOT NULL, "
525c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL "
526c2c66affSColin Finck             "PRIMARY KEY `Property`, `Signature_`)" );
527f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
528f860a780SAmine Khaldi     return r;
529c2c66affSColin Finck }
530c2c66affSColin Finck 
531c2c66affSColin Finck static UINT create_reglocator_table( MSIHANDLE hdb )
532c2c66affSColin Finck {
533f860a780SAmine Khaldi     UINT r = run_query( hdb,
534c2c66affSColin Finck             "CREATE TABLE `RegLocator` ("
535c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
536c2c66affSColin Finck             "`Root` SHORT NOT NULL, "
537c2c66affSColin Finck             "`Key` CHAR(255) NOT NULL, "
538c2c66affSColin Finck             "`Name` CHAR(255), "
539c2c66affSColin Finck             "`Type` SHORT "
540c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
541f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
542f860a780SAmine Khaldi     return r;
543c2c66affSColin Finck }
544c2c66affSColin Finck 
545c2c66affSColin Finck static UINT create_signature_table( MSIHANDLE hdb )
546c2c66affSColin Finck {
547f860a780SAmine Khaldi     UINT r = run_query( hdb,
548c2c66affSColin Finck             "CREATE TABLE `Signature` ("
549c2c66affSColin Finck             "`Signature` CHAR(72) NOT NULL, "
550c2c66affSColin Finck             "`FileName` CHAR(255) NOT NULL, "
551c2c66affSColin Finck             "`MinVersion` CHAR(20), "
552c2c66affSColin Finck             "`MaxVersion` CHAR(20), "
553c2c66affSColin Finck             "`MinSize` LONG, "
554c2c66affSColin Finck             "`MaxSize` LONG, "
555c2c66affSColin Finck             "`MinDate` LONG, "
556c2c66affSColin Finck             "`MaxDate` LONG, "
557c2c66affSColin Finck             "`Languages` CHAR(255) "
558c2c66affSColin Finck             "PRIMARY KEY `Signature`)" );
559f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
560f860a780SAmine Khaldi     return r;
561c2c66affSColin Finck }
562c2c66affSColin Finck 
563c2c66affSColin Finck static UINT create_launchcondition_table( MSIHANDLE hdb )
564c2c66affSColin Finck {
565f860a780SAmine Khaldi     UINT r = run_query( hdb,
566c2c66affSColin Finck             "CREATE TABLE `LaunchCondition` ("
567c2c66affSColin Finck             "`Condition` CHAR(255) NOT NULL, "
568c2c66affSColin Finck             "`Description` CHAR(255) NOT NULL "
569c2c66affSColin Finck             "PRIMARY KEY `Condition`)" );
570f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
571f860a780SAmine Khaldi     return r;
572c2c66affSColin Finck }
573c2c66affSColin Finck 
574c2c66affSColin Finck static UINT create_property_table( MSIHANDLE hdb )
575c2c66affSColin Finck {
576f860a780SAmine Khaldi     UINT r = run_query( hdb,
577c2c66affSColin Finck             "CREATE TABLE `Property` ("
578c2c66affSColin Finck             "`Property` CHAR(72) NOT NULL, "
579c2c66affSColin Finck             "`Value` CHAR(0) "
580c2c66affSColin Finck             "PRIMARY KEY `Property`)" );
581f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
582f860a780SAmine Khaldi     return r;
583c2c66affSColin Finck }
584c2c66affSColin Finck 
585c2c66affSColin Finck static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
586c2c66affSColin Finck {
587f860a780SAmine Khaldi     UINT r = run_query( hdb,
588c2c66affSColin Finck             "CREATE TABLE `InstallExecuteSequence` ("
589c2c66affSColin Finck             "`Action` CHAR(72) NOT NULL, "
590c2c66affSColin Finck             "`Condition` CHAR(255), "
591c2c66affSColin Finck             "`Sequence` SHORT "
592c2c66affSColin Finck             "PRIMARY KEY `Action`)" );
593f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
594f860a780SAmine Khaldi     return r;
595f860a780SAmine Khaldi }
596f860a780SAmine Khaldi 
597f860a780SAmine Khaldi static UINT create_install_ui_sequence_table( MSIHANDLE hdb )
598f860a780SAmine Khaldi {
599f860a780SAmine Khaldi     UINT r = run_query( hdb,
600f860a780SAmine Khaldi             "CREATE TABLE `InstallUISequence` ("
601f860a780SAmine Khaldi             "`Action` CHAR(72) NOT NULL, "
602f860a780SAmine Khaldi             "`Condition` CHAR(255), "
603f860a780SAmine Khaldi             "`Sequence` SHORT "
604f860a780SAmine Khaldi             "PRIMARY KEY `Action`)" );
605f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
606f860a780SAmine Khaldi     return r;
607c2c66affSColin Finck }
608c2c66affSColin Finck 
609c2c66affSColin Finck static UINT create_media_table( MSIHANDLE hdb )
610c2c66affSColin Finck {
611f860a780SAmine Khaldi     UINT r = run_query( hdb,
612c2c66affSColin Finck             "CREATE TABLE `Media` ("
613c2c66affSColin Finck             "`DiskId` SHORT NOT NULL, "
614c2c66affSColin Finck             "`LastSequence` SHORT NOT NULL, "
615c2c66affSColin Finck             "`DiskPrompt` CHAR(64), "
616c2c66affSColin Finck             "`Cabinet` CHAR(255), "
617c2c66affSColin Finck             "`VolumeLabel` CHAR(32), "
618c2c66affSColin Finck             "`Source` CHAR(72) "
619c2c66affSColin Finck             "PRIMARY KEY `DiskId`)" );
620f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
621f860a780SAmine Khaldi     return r;
622c2c66affSColin Finck }
623c2c66affSColin Finck 
624c2c66affSColin Finck static UINT create_ccpsearch_table( MSIHANDLE hdb )
625c2c66affSColin Finck {
626f860a780SAmine Khaldi     UINT r = run_query( hdb,
627c2c66affSColin Finck             "CREATE TABLE `CCPSearch` ("
628c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL "
629c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
630f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
631f860a780SAmine Khaldi     return r;
632c2c66affSColin Finck }
633c2c66affSColin Finck 
634c2c66affSColin Finck static UINT create_drlocator_table( MSIHANDLE hdb )
635c2c66affSColin Finck {
636f860a780SAmine Khaldi     UINT r = run_query( hdb,
637c2c66affSColin Finck             "CREATE TABLE `DrLocator` ("
638c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
639c2c66affSColin Finck             "`Parent` CHAR(72), "
640c2c66affSColin Finck             "`Path` CHAR(255), "
641c2c66affSColin Finck             "`Depth` SHORT "
642c2c66affSColin Finck             "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
643f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
644f860a780SAmine Khaldi     return r;
645c2c66affSColin Finck }
646c2c66affSColin Finck 
647c2c66affSColin Finck static UINT create_complocator_table( MSIHANDLE hdb )
648c2c66affSColin Finck {
649f860a780SAmine Khaldi     UINT r = run_query( hdb,
650c2c66affSColin Finck             "CREATE TABLE `CompLocator` ("
651c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
652c2c66affSColin Finck             "`ComponentId` CHAR(38) NOT NULL, "
653c2c66affSColin Finck             "`Type` SHORT "
654c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
655f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
656f860a780SAmine Khaldi     return r;
657c2c66affSColin Finck }
658c2c66affSColin Finck 
659c2c66affSColin Finck static UINT create_inilocator_table( MSIHANDLE hdb )
660c2c66affSColin Finck {
661f860a780SAmine Khaldi     UINT r = run_query( hdb,
662c2c66affSColin Finck             "CREATE TABLE `IniLocator` ("
663c2c66affSColin Finck             "`Signature_` CHAR(72) NOT NULL, "
664c2c66affSColin Finck             "`FileName` CHAR(255) NOT NULL, "
665c2c66affSColin Finck             "`Section` CHAR(96)NOT NULL, "
666c2c66affSColin Finck             "`Key` CHAR(128)NOT NULL, "
667c2c66affSColin Finck             "`Field` SHORT, "
668c2c66affSColin Finck             "`Type` SHORT "
669c2c66affSColin Finck             "PRIMARY KEY `Signature_`)" );
670f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
671f860a780SAmine Khaldi     return r;
672c2c66affSColin Finck }
673c2c66affSColin Finck 
674c2c66affSColin Finck static UINT create_custom_action_table( MSIHANDLE hdb )
675c2c66affSColin Finck {
676f860a780SAmine Khaldi     UINT r = run_query( hdb,
677c2c66affSColin Finck             "CREATE TABLE `CustomAction` ("
678c2c66affSColin Finck             "`Action` CHAR(72) NOT NULL, "
679c2c66affSColin Finck             "`Type` SHORT NOT NULL, "
680c2c66affSColin Finck             "`Source` CHAR(75), "
681c2c66affSColin Finck             "`Target` CHAR(255) "
682c2c66affSColin Finck             "PRIMARY KEY `Action`)" );
683f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
684f860a780SAmine Khaldi     return r;
685c2c66affSColin Finck }
686c2c66affSColin Finck 
6872f8e6f71SAmine Khaldi static UINT create_dialog_table( MSIHANDLE hdb )
6882f8e6f71SAmine Khaldi {
689f860a780SAmine Khaldi     UINT r = run_query(hdb,
6902f8e6f71SAmine Khaldi             "CREATE TABLE `Dialog` ("
6912f8e6f71SAmine Khaldi             "`Dialog` CHAR(72) NOT NULL, "
6922f8e6f71SAmine Khaldi             "`HCentering` SHORT NOT NULL, "
6932f8e6f71SAmine Khaldi             "`VCentering` SHORT NOT NULL, "
6942f8e6f71SAmine Khaldi             "`Width` SHORT NOT NULL, "
6952f8e6f71SAmine Khaldi             "`Height` SHORT NOT NULL, "
6962f8e6f71SAmine Khaldi             "`Attributes` LONG, "
6972f8e6f71SAmine Khaldi             "`Title` CHAR(128) LOCALIZABLE, "
6982f8e6f71SAmine Khaldi             "`Control_First` CHAR(50) NOT NULL, "
6992f8e6f71SAmine Khaldi             "`Control_Default` CHAR(50), "
7002f8e6f71SAmine Khaldi             "`Control_Cancel` CHAR(50) "
7012f8e6f71SAmine Khaldi             "PRIMARY KEY `Dialog`)");
702f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
703f860a780SAmine Khaldi     return r;
7042f8e6f71SAmine Khaldi }
7052f8e6f71SAmine Khaldi 
7062f8e6f71SAmine Khaldi static UINT create_control_table( MSIHANDLE hdb )
7072f8e6f71SAmine Khaldi {
708f860a780SAmine Khaldi     UINT r = run_query(hdb,
7092f8e6f71SAmine Khaldi             "CREATE TABLE `Control` ("
7102f8e6f71SAmine Khaldi             "`Dialog_` CHAR(72) NOT NULL, "
7112f8e6f71SAmine Khaldi             "`Control` CHAR(50) NOT NULL, "
7122f8e6f71SAmine Khaldi             "`Type` CHAR(20) NOT NULL, "
7132f8e6f71SAmine Khaldi             "`X` SHORT NOT NULL, "
7142f8e6f71SAmine Khaldi             "`Y` SHORT NOT NULL, "
7152f8e6f71SAmine Khaldi             "`Width` SHORT NOT NULL, "
7162f8e6f71SAmine Khaldi             "`Height` SHORT NOT NULL, "
7172f8e6f71SAmine Khaldi             "`Attributes` LONG, "
7182f8e6f71SAmine Khaldi             "`Property` CHAR(50), "
7192f8e6f71SAmine Khaldi             "`Text` CHAR(0) LOCALIZABLE, "
7202f8e6f71SAmine Khaldi             "`Control_Next` CHAR(50), "
7212f8e6f71SAmine Khaldi             "`Help` CHAR(255) LOCALIZABLE "
7222f8e6f71SAmine Khaldi             "PRIMARY KEY `Dialog_`, `Control`)");
723f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
724f860a780SAmine Khaldi     return r;
7252f8e6f71SAmine Khaldi }
7262f8e6f71SAmine Khaldi 
7272f8e6f71SAmine Khaldi static UINT create_controlevent_table( MSIHANDLE hdb )
7282f8e6f71SAmine Khaldi {
729f860a780SAmine Khaldi     UINT r = run_query(hdb,
7302f8e6f71SAmine Khaldi             "CREATE TABLE `ControlEvent` ("
7312f8e6f71SAmine Khaldi             "`Dialog_` CHAR(72) NOT NULL, "
7322f8e6f71SAmine Khaldi             "`Control_` CHAR(50) NOT NULL, "
7332f8e6f71SAmine Khaldi             "`Event` CHAR(50) NOT NULL, "
7342f8e6f71SAmine Khaldi             "`Argument` CHAR(255) NOT NULL, "
7352f8e6f71SAmine Khaldi             "`Condition` CHAR(255), "
7362f8e6f71SAmine Khaldi             "`Ordering` SHORT "
7372f8e6f71SAmine Khaldi             "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
738f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
739f860a780SAmine Khaldi     return r;
7402f8e6f71SAmine Khaldi }
7412f8e6f71SAmine Khaldi 
7422f8e6f71SAmine Khaldi static UINT create_actiontext_table( MSIHANDLE hdb )
7432f8e6f71SAmine Khaldi {
744f860a780SAmine Khaldi     UINT r = run_query(hdb,
7452f8e6f71SAmine Khaldi             "CREATE TABLE `ActionText` ("
7462f8e6f71SAmine Khaldi             "`Action` CHAR(72) NOT NULL, "
7472f8e6f71SAmine Khaldi             "`Description` CHAR(64) LOCALIZABLE, "
7482f8e6f71SAmine Khaldi             "`Template` CHAR(128) LOCALIZABLE "
7492f8e6f71SAmine Khaldi             "PRIMARY KEY `Action`)");
750f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
751f860a780SAmine Khaldi     return r;
7522f8e6f71SAmine Khaldi }
7532f8e6f71SAmine Khaldi 
754f860a780SAmine Khaldi static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
755f860a780SAmine Khaldi {
756f860a780SAmine Khaldi     char *query;
757f860a780SAmine Khaldi     UINT sz, r;
758f860a780SAmine Khaldi 
759f860a780SAmine Khaldi     sz = strlen(values) + strlen(insert) + 1;
760f860a780SAmine Khaldi     query = HeapAlloc(GetProcessHeap(), 0, sz);
761f860a780SAmine Khaldi     sprintf(query, insert, values);
762f860a780SAmine Khaldi     r = run_query(hdb, query);
763f860a780SAmine Khaldi     HeapFree(GetProcessHeap(), 0, query);
764f860a780SAmine Khaldi     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
765f860a780SAmine Khaldi     return r;
766c2c66affSColin Finck }
767c2c66affSColin Finck 
768f860a780SAmine Khaldi #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
769f860a780SAmine Khaldi                "INSERT INTO `Component`  " \
770f860a780SAmine Khaldi                "(`Component`, `ComponentId`, `Directory_`, " \
771c2c66affSColin Finck                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
772c2c66affSColin Finck 
773f860a780SAmine Khaldi #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
774f860a780SAmine Khaldi                "INSERT INTO `Directory` " \
775c2c66affSColin Finck                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
776c2c66affSColin Finck 
777f860a780SAmine Khaldi #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
778f860a780SAmine Khaldi                "INSERT INTO `Feature` " \
779f860a780SAmine Khaldi                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
780c2c66affSColin Finck                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
781c2c66affSColin Finck 
782f860a780SAmine Khaldi #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
783f860a780SAmine Khaldi                "INSERT INTO `FeatureComponents` " \
784c2c66affSColin Finck                "(`Feature_`, `Component_`) VALUES( %s )")
785c2c66affSColin Finck 
786f860a780SAmine Khaldi #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
787f860a780SAmine Khaldi                "INSERT INTO `File` " \
788f860a780SAmine Khaldi                "(`File`, `Component_`, `FileName`, `FileSize`, " \
789c2c66affSColin Finck                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
790c2c66affSColin Finck 
791f860a780SAmine Khaldi #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
792f860a780SAmine Khaldi                "INSERT INTO `AppSearch` " \
793c2c66affSColin Finck                "(`Property`, `Signature_`) VALUES( %s )")
794c2c66affSColin Finck 
795f860a780SAmine Khaldi #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
796f860a780SAmine Khaldi                "INSERT INTO `Signature` " \
797f860a780SAmine Khaldi                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
798f860a780SAmine Khaldi                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
799c2c66affSColin Finck                "VALUES( %s )")
800c2c66affSColin Finck 
801f860a780SAmine Khaldi #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
802f860a780SAmine Khaldi                "INSERT INTO `LaunchCondition` " \
803c2c66affSColin Finck                "(`Condition`, `Description`) VALUES( %s )")
804c2c66affSColin Finck 
805f860a780SAmine Khaldi #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
806c2c66affSColin Finck                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
807c2c66affSColin Finck 
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 
857c2c66affSColin Finck static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
858c2c66affSColin Finck                                   const char *name, UINT type )
859c2c66affSColin Finck {
860c2c66affSColin Finck     const char insert[] =
861c2c66affSColin Finck         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
862c2c66affSColin Finck         "VALUES( '%s', %u, '%s', '%s', %u )";
863c2c66affSColin Finck     char *query;
864c2c66affSColin Finck     UINT sz, r;
865c2c66affSColin Finck 
866c2c66affSColin Finck     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
867c2c66affSColin Finck     query = HeapAlloc( GetProcessHeap(), 0, sz );
868c2c66affSColin Finck     sprintf( query, insert, sig, root, path, name, type );
869c2c66affSColin Finck     r = run_query( hdb, query );
870c2c66affSColin Finck     HeapFree( GetProcessHeap(), 0, query );
871f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
872c2c66affSColin Finck     return r;
873c2c66affSColin Finck }
874c2c66affSColin Finck 
875c2c66affSColin Finck static UINT set_summary_info(MSIHANDLE hdb)
876c2c66affSColin Finck {
877c2c66affSColin Finck     UINT res;
878c2c66affSColin Finck     MSIHANDLE suminfo;
879c2c66affSColin Finck 
880c2c66affSColin Finck     /* build summary info */
881c2c66affSColin Finck     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
882c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
883c2c66affSColin Finck 
884c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
885c2c66affSColin Finck                         "Installation Database");
886c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
887c2c66affSColin Finck 
888c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,3, 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,4, VT_LPSTR, 0,NULL,
893c2c66affSColin Finck                         "Wine Hackers");
894c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
895c2c66affSColin Finck 
896c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
897c2c66affSColin Finck                     ";1033");
898c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
899c2c66affSColin Finck 
900c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
901c2c66affSColin Finck                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
902c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
903c2c66affSColin Finck 
904c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
905c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
906c2c66affSColin Finck 
907c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
908c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
909c2c66affSColin Finck 
910c2c66affSColin Finck     res = MsiSummaryInfoPersist(suminfo);
911c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
912c2c66affSColin Finck 
913c2c66affSColin Finck     res = MsiCloseHandle( suminfo);
914c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
915c2c66affSColin Finck 
916c2c66affSColin Finck     return res;
917c2c66affSColin Finck }
918c2c66affSColin Finck 
919c2c66affSColin Finck 
920c2c66affSColin Finck static MSIHANDLE create_package_db(void)
921c2c66affSColin Finck {
922c2c66affSColin Finck     MSIHANDLE hdb = 0;
923c2c66affSColin Finck     UINT res;
924c2c66affSColin Finck 
925c2c66affSColin Finck     DeleteFileA(msifile);
926c2c66affSColin Finck 
927c2c66affSColin Finck     /* create an empty database */
928c2c66affSColin Finck     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
929c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
930c2c66affSColin Finck     if( res != ERROR_SUCCESS )
931c2c66affSColin Finck         return hdb;
932c2c66affSColin Finck 
933c2c66affSColin Finck     res = MsiDatabaseCommit( hdb );
934c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
935c2c66affSColin Finck 
936c2c66affSColin Finck     res = set_summary_info(hdb);
937c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
938c2c66affSColin Finck 
939c2c66affSColin Finck     res = run_query( hdb,
940c2c66affSColin Finck             "CREATE TABLE `Directory` ( "
941c2c66affSColin Finck             "`Directory` CHAR(255) NOT NULL, "
942c2c66affSColin Finck             "`Directory_Parent` CHAR(255), "
943c2c66affSColin Finck             "`DefaultDir` CHAR(255) NOT NULL "
944c2c66affSColin Finck             "PRIMARY KEY `Directory`)" );
945c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
946c2c66affSColin Finck 
947c2c66affSColin Finck     return hdb;
948c2c66affSColin Finck }
949c2c66affSColin Finck 
950c2c66affSColin Finck static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
951c2c66affSColin Finck {
952c2c66affSColin Finck     UINT res;
953c2c66affSColin Finck     CHAR szPackage[12];
954c2c66affSColin Finck     MSIHANDLE hPackage;
955c2c66affSColin Finck 
956c2c66affSColin Finck     sprintf(szPackage, "#%u", hdb);
957c2c66affSColin Finck     res = MsiOpenPackageA(szPackage, &hPackage);
958c2c66affSColin Finck     if (res != ERROR_SUCCESS)
959c2c66affSColin Finck     {
960c2c66affSColin Finck         MsiCloseHandle(hdb);
961c2c66affSColin Finck         return res;
962c2c66affSColin Finck     }
963c2c66affSColin Finck 
964c2c66affSColin Finck     res = MsiCloseHandle(hdb);
965c2c66affSColin Finck     if (res != ERROR_SUCCESS)
966c2c66affSColin Finck     {
967c2c66affSColin Finck         MsiCloseHandle(hPackage);
968c2c66affSColin Finck         return res;
969c2c66affSColin Finck     }
970c2c66affSColin Finck 
971c2c66affSColin Finck     *handle = hPackage;
972c2c66affSColin Finck     return ERROR_SUCCESS;
973c2c66affSColin Finck }
974c2c66affSColin Finck 
9752f8e6f71SAmine Khaldi static void create_file_data(LPCSTR name, LPCSTR data)
976c2c66affSColin Finck {
977c2c66affSColin Finck     HANDLE file;
978c2c66affSColin Finck     DWORD written;
979c2c66affSColin Finck 
980c2c66affSColin Finck     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
981c2c66affSColin Finck     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
9822f8e6f71SAmine Khaldi     if (file == INVALID_HANDLE_VALUE)
9832f8e6f71SAmine Khaldi         return;
9842f8e6f71SAmine Khaldi 
9852f8e6f71SAmine Khaldi     WriteFile(file, data, strlen(data), &written, NULL);
986c2c66affSColin Finck     WriteFile(file, "\n", strlen("\n"), &written, NULL);
9872f8e6f71SAmine Khaldi 
988c2c66affSColin Finck     CloseHandle(file);
989c2c66affSColin Finck }
990c2c66affSColin Finck 
9912f8e6f71SAmine Khaldi static void create_test_file(const CHAR *name)
9922f8e6f71SAmine Khaldi {
9932f8e6f71SAmine Khaldi     create_file_data(name, name);
9942f8e6f71SAmine Khaldi }
9952f8e6f71SAmine Khaldi 
996c2c66affSColin Finck typedef struct _tagVS_VERSIONINFO
997c2c66affSColin Finck {
998c2c66affSColin Finck     WORD wLength;
999c2c66affSColin Finck     WORD wValueLength;
1000c2c66affSColin Finck     WORD wType;
1001c2c66affSColin Finck     WCHAR szKey[1];
1002c2c66affSColin Finck     WORD wPadding1[1];
1003c2c66affSColin Finck     VS_FIXEDFILEINFO Value;
1004c2c66affSColin Finck     WORD wPadding2[1];
1005c2c66affSColin Finck     WORD wChildren[1];
1006c2c66affSColin Finck } VS_VERSIONINFO;
1007c2c66affSColin Finck 
1008c2c66affSColin Finck #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1009c2c66affSColin Finck #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1010c2c66affSColin Finck 
1011c2c66affSColin Finck static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
1012c2c66affSColin Finck {
1013c2c66affSColin Finck     VS_VERSIONINFO *pVerInfo;
1014c2c66affSColin Finck     VS_FIXEDFILEINFO *pFixedInfo;
1015c2c66affSColin Finck     LPBYTE buffer, ofs;
1016c2c66affSColin Finck     CHAR path[MAX_PATH];
1017c2c66affSColin Finck     DWORD handle, size;
1018c2c66affSColin Finck     HANDLE resource;
1019c2c66affSColin Finck     BOOL ret = FALSE;
1020c2c66affSColin Finck 
1021c2c66affSColin Finck     GetSystemDirectoryA(path, MAX_PATH);
1022c2c66affSColin Finck     /* Some dlls can't be updated on Vista/W2K8 */
1023c2c66affSColin Finck     lstrcatA(path, "\\version.dll");
1024c2c66affSColin Finck 
1025c2c66affSColin Finck     CopyFileA(path, name, FALSE);
1026c2c66affSColin Finck 
1027c2c66affSColin Finck     size = GetFileVersionInfoSizeA(path, &handle);
1028c2c66affSColin Finck     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1029c2c66affSColin Finck 
1030c2c66affSColin Finck     GetFileVersionInfoA(path, 0, size, buffer);
1031c2c66affSColin Finck 
1032c2c66affSColin Finck     pVerInfo = (VS_VERSIONINFO *)buffer;
1033c2c66affSColin Finck     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1034c2c66affSColin Finck     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1035c2c66affSColin Finck 
1036c2c66affSColin Finck     pFixedInfo->dwFileVersionMS = ms;
1037c2c66affSColin Finck     pFixedInfo->dwFileVersionLS = ls;
1038c2c66affSColin Finck     pFixedInfo->dwProductVersionMS = ms;
1039c2c66affSColin Finck     pFixedInfo->dwProductVersionLS = ls;
1040c2c66affSColin Finck 
1041c2c66affSColin Finck     resource = BeginUpdateResourceA(name, FALSE);
1042c2c66affSColin Finck     if (!resource)
1043c2c66affSColin Finck         goto done;
1044c2c66affSColin Finck 
1045c2c66affSColin Finck     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
1046c2c66affSColin Finck                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1047c2c66affSColin Finck         goto done;
1048c2c66affSColin Finck 
1049c2c66affSColin Finck     if (!EndUpdateResourceA(resource, FALSE))
1050c2c66affSColin Finck         goto done;
1051c2c66affSColin Finck 
1052c2c66affSColin Finck     ret = TRUE;
1053c2c66affSColin Finck 
1054c2c66affSColin Finck done:
1055c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, buffer);
1056c2c66affSColin Finck     return ret;
1057c2c66affSColin Finck }
1058c2c66affSColin Finck 
1059c2c66affSColin Finck static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1060c2c66affSColin Finck {
1061c2c66affSColin Finck     RESTOREPOINTINFOA spec;
1062c2c66affSColin Finck 
1063c2c66affSColin Finck     spec.dwEventType = event_type;
1064c2c66affSColin Finck     spec.dwRestorePtType = APPLICATION_INSTALL;
1065c2c66affSColin Finck     spec.llSequenceNumber = status->llSequenceNumber;
1066c2c66affSColin Finck     lstrcpyA(spec.szDescription, "msitest restore point");
1067c2c66affSColin Finck 
1068c2c66affSColin Finck     return pSRSetRestorePointA(&spec, status);
1069c2c66affSColin Finck }
1070c2c66affSColin Finck 
1071c2c66affSColin Finck static void remove_restore_point(DWORD seq_number)
1072c2c66affSColin Finck {
1073c2c66affSColin Finck     DWORD res;
1074c2c66affSColin Finck 
1075c2c66affSColin Finck     res = pSRRemoveRestorePoint(seq_number);
1076c2c66affSColin Finck     if (res != ERROR_SUCCESS)
1077c2c66affSColin Finck         trace("Failed to remove the restore point : %08x\n", res);
1078c2c66affSColin Finck }
1079c2c66affSColin Finck 
1080c2c66affSColin Finck static BOOL is_root(const char *path)
1081c2c66affSColin Finck {
1082c2c66affSColin Finck     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1083c2c66affSColin Finck }
1084c2c66affSColin Finck 
1085c2c66affSColin Finck static void test_createpackage(void)
1086c2c66affSColin Finck {
1087c2c66affSColin Finck     MSIHANDLE hPackage = 0;
1088c2c66affSColin Finck     UINT res;
1089c2c66affSColin Finck 
1090c2c66affSColin Finck     res = package_from_db(create_package_db(), &hPackage);
1091c2c66affSColin Finck     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1092c2c66affSColin Finck     {
1093c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1094c2c66affSColin Finck         DeleteFileA(msifile);
1095c2c66affSColin Finck         return;
1096c2c66affSColin Finck     }
1097c2c66affSColin Finck     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1098c2c66affSColin Finck 
1099c2c66affSColin Finck     res = MsiCloseHandle( hPackage);
1100c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1101c2c66affSColin Finck     DeleteFileA(msifile);
1102c2c66affSColin Finck }
1103c2c66affSColin Finck 
1104c2c66affSColin Finck static void test_doaction( void )
1105c2c66affSColin Finck {
1106c2c66affSColin Finck     MSIHANDLE hpkg;
1107c2c66affSColin Finck     UINT r;
1108c2c66affSColin Finck 
1109c2c66affSColin Finck     r = MsiDoActionA( -1, NULL );
1110c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1111c2c66affSColin Finck 
1112c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1113c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1114c2c66affSColin Finck     {
1115c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1116c2c66affSColin Finck         DeleteFileA(msifile);
1117c2c66affSColin Finck         return;
1118c2c66affSColin Finck     }
1119c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1120c2c66affSColin Finck 
1121c2c66affSColin Finck     r = MsiDoActionA(hpkg, NULL);
1122c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1123c2c66affSColin Finck 
1124c2c66affSColin Finck     r = MsiDoActionA(0, "boo");
1125c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1126c2c66affSColin Finck 
1127c2c66affSColin Finck     r = MsiDoActionA(hpkg, "boo");
1128c2c66affSColin Finck     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1129c2c66affSColin Finck 
1130c2c66affSColin Finck     MsiCloseHandle( hpkg );
1131c2c66affSColin Finck     DeleteFileA(msifile);
1132c2c66affSColin Finck }
1133c2c66affSColin Finck 
1134c2c66affSColin Finck static void test_gettargetpath_bad(void)
1135c2c66affSColin Finck {
1136c2c66affSColin Finck     static const WCHAR boo[] = {'b','o','o',0};
1137c2c66affSColin Finck     static const WCHAR empty[] = {0};
1138c2c66affSColin Finck     char buffer[0x80];
1139c2c66affSColin Finck     WCHAR bufferW[0x80];
1140c2c66affSColin Finck     MSIHANDLE hpkg;
1141c2c66affSColin Finck     DWORD sz;
1142c2c66affSColin Finck     UINT r;
1143c2c66affSColin Finck 
1144c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1145c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1146c2c66affSColin Finck     {
1147c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1148c2c66affSColin Finck         DeleteFileA(msifile);
1149c2c66affSColin Finck         return;
1150c2c66affSColin Finck     }
1151c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1152c2c66affSColin Finck 
1153c2c66affSColin Finck     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1154c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1155c2c66affSColin Finck 
1156c2c66affSColin Finck     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1157c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1158c2c66affSColin Finck 
1159c2c66affSColin Finck     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1160c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1161c2c66affSColin Finck 
1162c2c66affSColin Finck     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1163c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1164c2c66affSColin Finck 
1165c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1166c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1167c2c66affSColin Finck 
1168c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1169c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1170c2c66affSColin Finck 
1171c2c66affSColin Finck     sz = 0;
1172c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1173c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1174c2c66affSColin Finck 
1175c2c66affSColin Finck     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1176c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1177c2c66affSColin Finck 
1178c2c66affSColin Finck     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1179c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1180c2c66affSColin Finck 
1181c2c66affSColin Finck     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1182c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1183c2c66affSColin Finck 
1184c2c66affSColin Finck     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1185c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1186c2c66affSColin Finck 
1187c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1188c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1189c2c66affSColin Finck 
1190c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1191c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1192c2c66affSColin Finck 
1193c2c66affSColin Finck     sz = 0;
1194c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1195c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1196c2c66affSColin Finck 
1197c2c66affSColin Finck     MsiCloseHandle( hpkg );
1198c2c66affSColin Finck     DeleteFileA(msifile);
1199c2c66affSColin Finck }
1200c2c66affSColin Finck 
1201c2c66affSColin Finck static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1202c2c66affSColin Finck {
1203c2c66affSColin Finck     UINT r;
1204c2c66affSColin Finck     DWORD size;
1205c2c66affSColin Finck     MSIHANDLE rec;
1206c2c66affSColin Finck 
1207c2c66affSColin Finck     rec = MsiCreateRecord( 1 );
1208c2c66affSColin Finck     ok(rec, "MsiCreate record failed\n");
1209c2c66affSColin Finck 
1210c2c66affSColin Finck     r = MsiRecordSetStringA( rec, 0, file );
1211c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     size = MAX_PATH;
1214c2c66affSColin Finck     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1215c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1216c2c66affSColin Finck 
1217c2c66affSColin Finck     MsiCloseHandle( rec );
1218c2c66affSColin Finck }
1219c2c66affSColin Finck 
1220c2c66affSColin Finck static void test_settargetpath(void)
1221c2c66affSColin Finck {
1222c2c66affSColin Finck     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1223c2c66affSColin Finck     DWORD sz;
1224c2c66affSColin Finck     MSIHANDLE hpkg;
1225c2c66affSColin Finck     UINT r;
1226c2c66affSColin Finck     MSIHANDLE hdb;
1227c2c66affSColin Finck 
1228c2c66affSColin Finck     hdb = create_package_db();
1229c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
1230c2c66affSColin Finck 
1231f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1232c2c66affSColin Finck 
1233f860a780SAmine Khaldi     create_component_table( hdb );
1234f860a780SAmine Khaldi     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1235f860a780SAmine Khaldi     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1236c2c66affSColin Finck 
1237f860a780SAmine Khaldi     create_feature_table( hdb );
1238f860a780SAmine Khaldi     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1239c2c66affSColin Finck 
1240f860a780SAmine Khaldi     create_feature_components_table( hdb );
1241f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1242f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1243c2c66affSColin Finck 
1244c2c66affSColin Finck     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1245c2c66affSColin Finck     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1246c2c66affSColin Finck 
1247f860a780SAmine Khaldi     create_file_table( hdb );
1248f860a780SAmine Khaldi     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1249f860a780SAmine Khaldi     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1250c2c66affSColin Finck 
1251c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
1252c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1253c2c66affSColin Finck     {
1254c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1255c2c66affSColin Finck         DeleteFileA(msifile);
1256c2c66affSColin Finck         return;
1257c2c66affSColin Finck     }
1258c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1259c2c66affSColin Finck 
1260c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1261c2c66affSColin Finck 
1262c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
1263c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
1264c2c66affSColin Finck 
1265c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
1266c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
1267c2c66affSColin Finck 
1268c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
1269c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1270c2c66affSColin Finck 
1271c2c66affSColin Finck     buffer[0] = 0;
1272c2c66affSColin Finck     sz = sizeof(buffer);
1273c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1274c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1275c2c66affSColin Finck     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1276c2c66affSColin Finck 
1277c2c66affSColin Finck     r = MsiSetTargetPathA( 0, NULL, NULL );
1278c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1279c2c66affSColin Finck 
1280c2c66affSColin Finck     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1281c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1282c2c66affSColin Finck 
1283c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1284c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1285c2c66affSColin Finck 
1286c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1287c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1288c2c66affSColin Finck 
1289c2c66affSColin Finck     sz = sizeof tempdir - 1;
1290c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1291c2c66affSColin Finck     sprintf( file, "%srootfile.txt", tempdir );
1292c2c66affSColin Finck     buffer[0] = 0;
1293c2c66affSColin Finck     query_file_path( hpkg, "[#RootFile]", buffer );
1294c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1295c2c66affSColin Finck     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1296c2c66affSColin Finck 
1297c2c66affSColin Finck     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1298c2c66affSColin Finck     sprintf( tempdir, "%s\\subdir", buffer );
1299c2c66affSColin Finck 
1300c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1301c2c66affSColin Finck     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1302c2c66affSColin Finck         "MsiSetTargetPath on file returned %d\n", r );
1303c2c66affSColin Finck 
1304c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1305c2c66affSColin Finck     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1306c2c66affSColin Finck         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1307c2c66affSColin Finck 
1308c2c66affSColin Finck     DeleteFileA( buffer );
1309c2c66affSColin Finck 
1310c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1311c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1312c2c66affSColin Finck 
1313c2c66affSColin Finck     r = GetFileAttributesA( buffer );
1314c2c66affSColin Finck     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1315c2c66affSColin Finck 
1316c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1317c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1318c2c66affSColin Finck 
1319c2c66affSColin Finck     buffer[0] = 0;
1320c2c66affSColin Finck     sz = sizeof buffer - 1;
1321c2c66affSColin Finck     lstrcatA( tempdir, "\\" );
1322c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1323c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1324c2c66affSColin Finck     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1325c2c66affSColin Finck 
1326c2c66affSColin Finck     sprintf( file, "%srootfile.txt", tempdir );
1327c2c66affSColin Finck     query_file_path( hpkg, "[#RootFile]", buffer );
1328c2c66affSColin Finck     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     buffer[0] = 0;
1331c2c66affSColin Finck     sz = sizeof(buffer);
1332c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1333c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1334c2c66affSColin Finck     lstrcatA( tempdir, "TestParent\\" );
1335c2c66affSColin Finck     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1336c2c66affSColin Finck 
1337c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1338c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1339c2c66affSColin Finck 
1340c2c66affSColin Finck     buffer[0] = 0;
1341c2c66affSColin Finck     sz = sizeof(buffer);
1342c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1343c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1344c2c66affSColin Finck     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1345c2c66affSColin Finck         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1346c2c66affSColin Finck 
1347c2c66affSColin Finck     buffer[0] = 0;
1348c2c66affSColin Finck     query_file_path( hpkg, "[#TestFile]", buffer );
1349c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1350c2c66affSColin Finck         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1351c2c66affSColin Finck 
1352c2c66affSColin Finck     buffer[0] = 0;
1353c2c66affSColin Finck     sz = sizeof buffer - 1;
1354c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1355c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1356c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1357c2c66affSColin Finck 
1358c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1359c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1360c2c66affSColin Finck 
1361c2c66affSColin Finck     buffer[0] = 0;
1362c2c66affSColin Finck     sz = sizeof buffer - 1;
1363c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1364c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1365c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1366c2c66affSColin Finck 
1367c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1368c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1369c2c66affSColin Finck 
1370c2c66affSColin Finck     buffer[0] = 0;
1371c2c66affSColin Finck     sz = sizeof buffer - 1;
1372c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1373c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1374c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1375c2c66affSColin Finck 
1376c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1377c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1378c2c66affSColin Finck 
1379c2c66affSColin Finck     buffer[0] = 0;
1380c2c66affSColin Finck     sz = sizeof buffer - 1;
1381c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1382c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1383c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1384c2c66affSColin Finck 
1385c2c66affSColin Finck     MsiCloseHandle( hpkg );
1386c2c66affSColin Finck }
1387c2c66affSColin Finck 
1388c2c66affSColin Finck static void test_condition(void)
1389c2c66affSColin Finck {
1390c2c66affSColin Finck     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1391c2c66affSColin Finck     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1392c2c66affSColin Finck     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1393c2c66affSColin Finck     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1394c2c66affSColin Finck     MSICONDITION r;
1395c2c66affSColin Finck     MSIHANDLE hpkg;
1396c2c66affSColin Finck 
1397c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1398c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1399c2c66affSColin Finck     {
1400c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1401c2c66affSColin Finck         DeleteFileA(msifile);
1402c2c66affSColin Finck         return;
1403c2c66affSColin Finck     }
1404c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1405c2c66affSColin Finck 
1406c2c66affSColin Finck     r = MsiEvaluateConditionA(0, NULL);
1407c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1408c2c66affSColin Finck 
1409c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, NULL);
1410c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1411c2c66affSColin Finck 
1412c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "");
1413c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1414c2c66affSColin Finck 
1415c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1");
1416c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1417c2c66affSColin Finck 
1418c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0");
1419c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1420c2c66affSColin Finck 
1421c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "-1");
1422c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1423c2c66affSColin Finck 
1424c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1425c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1426c2c66affSColin Finck 
1427c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1428c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1429c2c66affSColin Finck 
1430c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1431c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1432c2c66affSColin Finck 
1433c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1434c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1435c2c66affSColin Finck 
1436c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1437c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1438c2c66affSColin Finck 
1439c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1440c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1441c2c66affSColin Finck 
1442c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1443c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1444c2c66affSColin Finck 
1445c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1446c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1447c2c66affSColin Finck 
1448c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1449c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1450c2c66affSColin Finck 
1451c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1452c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1453c2c66affSColin Finck 
1454c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1455c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1456c2c66affSColin Finck 
1457c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1458c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1459c2c66affSColin Finck 
1460c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1461c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1462c2c66affSColin Finck 
1463c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1464c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1465c2c66affSColin Finck 
1466c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1467c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1468c2c66affSColin Finck 
1469c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1470c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1471c2c66affSColin Finck 
1472c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1473c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1474c2c66affSColin Finck 
1475c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1476c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1477c2c66affSColin Finck 
1478c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1479c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1480c2c66affSColin Finck 
1481c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 >=");
1482c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1483c2c66affSColin Finck 
1484c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " ");
1485c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1486c2c66affSColin Finck 
1487c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1488c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1489c2c66affSColin Finck 
1490c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1491c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1492c2c66affSColin Finck 
1493c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1494c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1495c2c66affSColin Finck 
1496c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0");
1497c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1498c2c66affSColin Finck 
1499c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not LicView");
1500c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1501c2c66affSColin Finck 
1502c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1503c2c66affSColin Finck     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1504c2c66affSColin Finck 
1505c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1506c2c66affSColin Finck     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1507c2c66affSColin Finck 
1508c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1509c2c66affSColin Finck     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1510c2c66affSColin Finck 
1511c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1512c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1513c2c66affSColin Finck 
1514c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1515c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1516c2c66affSColin Finck 
1517c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1518c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1519c2c66affSColin Finck 
1520c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1521c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1522c2c66affSColin Finck 
1523c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1524c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1525c2c66affSColin Finck 
1526c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1527c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1528c2c66affSColin Finck 
1529c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1530c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1531c2c66affSColin Finck 
1532c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(0)");
1533c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1534c2c66affSColin Finck 
1535c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1536c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1537c2c66affSColin Finck 
1538c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1539c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1540c2c66affSColin Finck 
1541c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1542c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1543c2c66affSColin Finck 
1544c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1545c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1546c2c66affSColin Finck 
1547c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1548c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1549c2c66affSColin Finck 
1550c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1551c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1552c2c66affSColin Finck 
1553c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1554c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1555c2c66affSColin Finck 
1556c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1557c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1558c2c66affSColin Finck 
1559c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1560c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1561c2c66affSColin Finck 
1562c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1563c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1564c2c66affSColin Finck 
1565c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1566c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1567c2c66affSColin Finck 
1568c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1569c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1570c2c66affSColin Finck 
1571c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1572c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1573c2c66affSColin Finck 
1574c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1575c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1576c2c66affSColin Finck 
1577c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1578c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1579c2c66affSColin Finck 
1580c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1581c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1582c2c66affSColin Finck 
1583c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1584c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1585c2c66affSColin Finck 
1586c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1587c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1588c2c66affSColin Finck 
1589c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1590c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1591c2c66affSColin Finck 
1592c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1593c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1594c2c66affSColin Finck 
1595c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1596c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1597c2c66affSColin Finck 
1598c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1599c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1600c2c66affSColin Finck 
1601c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1602c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1603c2c66affSColin Finck 
1604c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1605c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1606c2c66affSColin Finck 
1607c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1608c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1609c2c66affSColin Finck 
1610c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1611c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1612c2c66affSColin Finck 
1613c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1614c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1615c2c66affSColin Finck 
1616c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1617c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1618c2c66affSColin Finck 
1619c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1620c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1621c2c66affSColin Finck 
1622c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1623c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1624c2c66affSColin Finck 
1625c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1626c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1627c2c66affSColin Finck 
1628c2c66affSColin Finck     MsiSetPropertyA(hpkg, "mm", "5" );
1629c2c66affSColin Finck 
1630c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1631c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1632c2c66affSColin Finck 
1633c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1634c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1635c2c66affSColin Finck 
1636c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1637c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1638c2c66affSColin Finck 
1639c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1640c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1641c2c66affSColin Finck 
1642c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1643c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1644c2c66affSColin Finck 
1645c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1646c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1647c2c66affSColin Finck 
1648c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1649c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1650c2c66affSColin Finck 
1651c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1652c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1653c2c66affSColin Finck 
1654c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1655c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1656c2c66affSColin Finck 
1657c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1658c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1659c2c66affSColin Finck 
1660c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1661c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1662c2c66affSColin Finck 
1663c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1664c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1665c2c66affSColin Finck 
1666c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1667c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1668c2c66affSColin Finck 
1669c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1670c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1671c2c66affSColin Finck 
1672c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1673c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1674c2c66affSColin Finck 
1675c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1676c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1677c2c66affSColin Finck 
1678c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1679c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1680c2c66affSColin Finck 
1681c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1682c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1683c2c66affSColin Finck 
1684c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1685c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1686c2c66affSColin Finck 
1687c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1688c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1689c2c66affSColin Finck 
1690c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1691c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1692c2c66affSColin Finck 
1693c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1694c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1695c2c66affSColin Finck 
1696c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1697c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1698c2c66affSColin Finck 
1699c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1700c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1701c2c66affSColin Finck 
1702c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1703c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1704c2c66affSColin Finck 
1705c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1706c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1707c2c66affSColin Finck 
1708c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1709c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1710c2c66affSColin Finck 
1711c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1712c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1713c2c66affSColin Finck 
1714c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1715c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1716c2c66affSColin Finck 
1717c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1718c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1719c2c66affSColin Finck 
1720c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1721c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1722c2c66affSColin Finck 
1723c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1724c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1725c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1726c2c66affSColin Finck 
1727c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "" );
1728c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1730c2c66affSColin Finck 
1731c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1732c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1733c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1734c2c66affSColin Finck 
1735c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1736c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1737c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1738c2c66affSColin Finck 
1739c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
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_TRUE, "wrong return val\n");
1746c2c66affSColin Finck 
1747c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1748c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1749c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1750c2c66affSColin Finck 
1751c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1752c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1753c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1754c2c66affSColin Finck 
1755c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1756c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1757c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1758c2c66affSColin Finck 
1759c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1760c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1761c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1762c2c66affSColin Finck 
1763c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
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.0" );
1768c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1769c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1770c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1771c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1772c2c66affSColin Finck 
1773c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1774c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1775c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1776c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1777c2c66affSColin Finck 
1778c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1779c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1780c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1781c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1782c2c66affSColin Finck 
1783c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hello");
1784c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1785c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1786c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1787c2c66affSColin Finck 
1788c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hellohithere");
1789c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1790c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1791c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1792c2c66affSColin Finck 
1793c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1794c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1795c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1796c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1797c2c66affSColin Finck 
1798c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1799c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1800c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1801c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1802c2c66affSColin Finck 
1803c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1804c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1805c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1806c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1807c2c66affSColin Finck 
1808c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1809c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1810c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1811c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1812c2c66affSColin Finck 
1813c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "one 1234");
1814c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1815c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1816c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1817c2c66affSColin Finck 
1818c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1819c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1820c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1821c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1822c2c66affSColin Finck 
1823c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1824c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1825c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1826c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1827c2c66affSColin Finck 
1828c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1829c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1830c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1831c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1832c2c66affSColin Finck 
1833c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1834c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1835c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1836c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1837c2c66affSColin Finck 
1838c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1839c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1840c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1841c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1842c2c66affSColin Finck 
1843c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1844c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1845c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1846c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1847c2c66affSColin Finck 
1848c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1849c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1850c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1851c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1852c2c66affSColin Finck 
1853c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1854c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1855c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1856c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1857c2c66affSColin Finck 
1858c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234 one");
1859c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1860c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1861c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1862c2c66affSColin Finck 
1863c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1864c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1865c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1866c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1867c2c66affSColin Finck 
1868c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1869c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1870c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1871c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1872c2c66affSColin Finck 
1873c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1874c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1875c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1876c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1877c2c66affSColin Finck 
1878c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1879c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1880c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1881c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1882c2c66affSColin Finck 
1883c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1884c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1885c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1886c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1887c2c66affSColin Finck 
1888c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1889c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1890c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1891c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1892c2c66affSColin Finck 
1893c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1894c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1895c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1896c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1897c2c66affSColin Finck 
1898c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1899c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1900c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1901c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1902c2c66affSColin Finck 
1903c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1904c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "4");
1905c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1906c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1907c2c66affSColin Finck 
1908c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "one 1234");
1909c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "4");
1910c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1911c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1912c2c66affSColin Finck 
1913c2c66affSColin Finck     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1914c2c66affSColin Finck 
1915c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1916c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1917c2c66affSColin Finck 
1918c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1919c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1920c2c66affSColin Finck 
1921c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1922c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1923c2c66affSColin Finck 
1924c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1925c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1926c2c66affSColin Finck 
1927c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1928c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1929c2c66affSColin Finck 
1930c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1931c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1932c2c66affSColin Finck 
1933c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1934c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1935c2c66affSColin Finck 
1936c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1937c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1938c2c66affSColin Finck 
1939c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1940c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1941c2c66affSColin Finck 
1942c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1943c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1944c2c66affSColin Finck 
1945c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1946c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1947c2c66affSColin Finck 
1948c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1949c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1950c2c66affSColin Finck 
1951c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1952c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1953c2c66affSColin Finck 
1954c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1955c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1956c2c66affSColin Finck 
1957c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1958c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1959c2c66affSColin Finck 
1960c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1961c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1962c2c66affSColin Finck 
1963c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1964c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1965c2c66affSColin Finck 
1966c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1967c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1968c2c66affSColin Finck 
1969c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1970c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1971c2c66affSColin Finck 
1972c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1973c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1974c2c66affSColin Finck 
1975c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1976c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1977c2c66affSColin Finck 
1978c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1979c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1980c2c66affSColin Finck 
1981c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1982c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1983c2c66affSColin Finck 
1984c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1985c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1986c2c66affSColin Finck 
1987c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1988c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1989c2c66affSColin Finck 
1990c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1991c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1992c2c66affSColin Finck 
1993c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1994c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1995c2c66affSColin Finck 
1996c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1997c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1998c2c66affSColin Finck 
1999c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
2000c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2001c2c66affSColin Finck 
2002c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
2003c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2004c2c66affSColin Finck 
2005c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
2006c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2007c2c66affSColin Finck 
2008c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
2009c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2010c2c66affSColin Finck 
2011c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
2012c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2013c2c66affSColin Finck 
2014c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
2015c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2016c2c66affSColin Finck 
2017c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
2018c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2019c2c66affSColin Finck 
2020c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
2021c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2022c2c66affSColin Finck 
2023c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
2024c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2025c2c66affSColin Finck 
2026c2c66affSColin Finck     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2027c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2028c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2029c2c66affSColin Finck 
2030c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2031c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2032c2c66affSColin Finck 
2033c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2034c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2035c2c66affSColin Finck 
2036c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2037c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2038c2c66affSColin Finck 
2039c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2040c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2041c2c66affSColin Finck 
2042c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1");
2043c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2044c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2045c2c66affSColin Finck 
2046c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "5.0");
2047c2c66affSColin Finck 
2048c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2049c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2050c2c66affSColin Finck 
2051c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2052c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2053c2c66affSColin Finck 
2054c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2055c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2056c2c66affSColin Finck 
2057c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2058c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2059c2c66affSColin Finck 
2060c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2061c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2062c2c66affSColin Finck 
2063c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2064c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2065c2c66affSColin Finck 
2066c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2067c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2068c2c66affSColin Finck 
2069c2c66affSColin Finck     /* feature doesn't exist */
2070c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2071c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2072f860a780SAmine Khaldi     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2073f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2074f860a780SAmine Khaldi     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2075f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2076f860a780SAmine Khaldi     MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2077f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2078f860a780SAmine Khaldi     MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2079f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2080c2c66affSColin Finck 
2081c2c66affSColin Finck     MsiSetPropertyA(hpkg, "A", "2");
2082c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50");
2083c2c66affSColin Finck 
2084c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2085c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2086c2c66affSColin Finck 
2087c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2088c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2089c2c66affSColin Finck 
2090c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2091c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2092c2c66affSColin Finck 
2093c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50val");
2094c2c66affSColin Finck 
2095c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2096c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2097c2c66affSColin Finck 
2098c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2099c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2100c2c66affSColin Finck 
2101c2c66affSColin Finck     MsiSetPropertyA(hpkg, "A", "7");
2102c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50");
2103c2c66affSColin Finck 
2104c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2105c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2106c2c66affSColin Finck 
2107c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2108c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2109c2c66affSColin Finck 
2110c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2111c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2112c2c66affSColin Finck 
2113c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50val");
2114c2c66affSColin Finck 
2115c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2116c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2117c2c66affSColin Finck 
2118c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2119c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2120c2c66affSColin Finck 
2121c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond1);
2122c2c66affSColin Finck     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2123c2c66affSColin Finck         "wrong return val (%d)\n", r);
2124c2c66affSColin Finck 
2125c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond2);
2126c2c66affSColin Finck     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2127c2c66affSColin Finck         "wrong return val (%d)\n", r);
2128c2c66affSColin Finck 
2129c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond3);
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, cond4);
2134c2c66affSColin Finck     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2135c2c66affSColin Finck         "wrong return val (%d)\n", r);
2136c2c66affSColin Finck 
2137c2c66affSColin Finck     MsiCloseHandle( hpkg );
2138c2c66affSColin Finck     DeleteFileA(msifile);
2139c2c66affSColin Finck }
2140c2c66affSColin Finck 
2141c2000429Swinesync static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect)
2142c2c66affSColin Finck {
2143c2000429Swinesync     char buffer[20] = "x";
2144c2000429Swinesync     DWORD sz = sizeof(buffer);
2145c2000429Swinesync     UINT r = MsiGetPropertyA(hpkg, prop, buffer, &sz);
2146c2000429Swinesync     ok(!r, "'%s': got %u\n", prop, r);
2147c2000429Swinesync     ok(sz == lstrlenA(buffer), "'%s': expected %u, got %u\n", prop, lstrlenA(buffer), sz);
2148c2000429Swinesync     ok(!strcmp(buffer, expect), "expected '%s', got '%s'\n", expect, buffer);
2149c2c66affSColin Finck }
2150c2c66affSColin Finck 
2151c2c66affSColin Finck static void test_props(void)
2152c2c66affSColin Finck {
215366669aedSwinesync     static const WCHAR booW[] = {'b','o','o',0};
215466669aedSwinesync     static const WCHAR xyzW[] = {'x','y','z',0};
215566669aedSwinesync     static const WCHAR xyW[] = {'x','y',0};
2156c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
2157c2c66affSColin Finck     UINT r;
2158c2c66affSColin Finck     DWORD sz;
2159c2c66affSColin Finck     char buffer[0x100];
216066669aedSwinesync     WCHAR bufferW[10];
2161c2c66affSColin Finck 
2162c2c66affSColin Finck     hdb = create_package_db();
2163c2c66affSColin Finck 
2164f860a780SAmine Khaldi     create_property_table(hdb);
2165f860a780SAmine Khaldi     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2166c2c66affSColin Finck 
2167c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
2168c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2169c2c66affSColin Finck     {
2170c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2171c2c66affSColin Finck         DeleteFileA(msifile);
2172c2c66affSColin Finck         return;
2173c2c66affSColin Finck     }
2174c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2175c2c66affSColin Finck 
2176c2c66affSColin Finck     /* test invalid values */
2177c2c66affSColin Finck     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2178c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2179c2c66affSColin Finck 
2180c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2181c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2182c2c66affSColin Finck 
2183c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2184c2000429Swinesync     ok(!r, "got %u\n", r);
2185c2c66affSColin Finck 
2186c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2187c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2188c2c66affSColin Finck 
2189c2c66affSColin Finck     /* test retrieving an empty/nonexistent property */
2190c2c66affSColin Finck     sz = sizeof buffer;
2191c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2192c2000429Swinesync     ok(!r, "got %u\n", r);
2193c2000429Swinesync     ok(sz == 0, "got size %d\n", sz);
2194c2c66affSColin Finck 
2195c2c66affSColin Finck     sz = 0;
2196c2c66affSColin Finck     strcpy(buffer,"x");
2197c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2198c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2199c2000429Swinesync     ok(!strcmp(buffer,"x"), "got \"%s\"\n", buffer);
2200c2000429Swinesync     ok(sz == 0, "got size %u\n", sz);
2201c2c66affSColin Finck 
2202c2c66affSColin Finck     sz = 1;
2203c2c66affSColin Finck     strcpy(buffer,"x");
2204c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2205c2000429Swinesync     ok(!r, "got %u\n", r);
2206c2000429Swinesync     ok(!buffer[0], "got \"%s\"\n", buffer);
2207c2000429Swinesync     ok(sz == 0, "got size %u\n", sz);
2208c2c66affSColin Finck 
2209c2c66affSColin Finck     /* set the property to something */
2210c2c66affSColin Finck     r = MsiSetPropertyA( 0, NULL, NULL );
2211c2000429Swinesync     ok(r == ERROR_INVALID_HANDLE, "got %u\n", r);
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, NULL, NULL );
2214c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2215c2c66affSColin Finck 
2216c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "", NULL );
2217c2000429Swinesync     ok(!r, "got %u\n", r);
2218c2c66affSColin Finck 
2219c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "", "asdf" );
2220c2000429Swinesync     ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
2221c2c66affSColin Finck 
2222c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2223c2000429Swinesync     ok(!r, "got %u\n", r);
2224c2000429Swinesync     check_prop(hpkg, "=", "asdf");
2225c2c66affSColin Finck 
2226c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2227c2000429Swinesync     ok(!r, "got %u\n", r);
2228c2000429Swinesync     check_prop(hpkg, " ", "asdf");
2229c2c66affSColin Finck 
2230c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2231c2000429Swinesync     ok(!r, "got %u\n", r);
2232c2000429Swinesync     check_prop(hpkg, "'", "asdf");
2233c2c66affSColin Finck 
2234c2c66affSColin Finck     /* set empty values */
2235c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", NULL );
2236c2000429Swinesync     ok(!r, "got %u\n", r);
2237c2000429Swinesync     check_prop(hpkg, "boo", "");
2238c2c66affSColin Finck 
2239c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", "" );
2240c2000429Swinesync     ok(!r, "got %u\n", r);
2241c2000429Swinesync     check_prop(hpkg, "boo", "");
2242c2c66affSColin Finck 
2243c2c66affSColin Finck     /* set a non-empty value */
2244c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2245c2000429Swinesync     ok(!r, "got %u\n", r);
2246c2000429Swinesync     check_prop(hpkg, "boo", "xyz");
2247c2000429Swinesync 
2248c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", NULL, NULL);
2249c2000429Swinesync     ok(!r, "got %u\n", r);
2250c2000429Swinesync 
2251c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", buffer, NULL);
2252c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2253c2000429Swinesync 
2254c2000429Swinesync     sz = 0;
2255c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", NULL, &sz);
2256c2000429Swinesync     ok(!r, "got %u\n", r);
2257c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2258c2000429Swinesync 
2259c2000429Swinesync     sz = 0;
2260c2000429Swinesync     strcpy(buffer, "q");
2261c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", buffer, &sz);
2262c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2263c2000429Swinesync     ok(!strcmp(buffer, "q"), "got \"%s\"", buffer);
2264c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2265c2c66affSColin Finck 
2266c2c66affSColin Finck     sz = 1;
2267c2c66affSColin Finck     strcpy(buffer,"x");
2268c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2269c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2270c2000429Swinesync     ok(!buffer[0], "got \"%s\"\n", buffer);
2271c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2272c2c66affSColin Finck 
2273c2c66affSColin Finck     sz = 3;
2274c2c66affSColin Finck     strcpy(buffer,"x");
2275c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2276c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2277c2000429Swinesync     ok(!strcmp(buffer,"xy"), "got \"%s\"\n", buffer);
2278c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2279c2c66affSColin Finck 
2280c2c66affSColin Finck     sz = 4;
2281c2000429Swinesync     strcpy(buffer,"x");
2282c2000429Swinesync     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2283c2000429Swinesync     ok(!r, "got %u\n", r);
2284c2000429Swinesync     ok(!strcmp(buffer,"xyz"), "got \"%s\"\n", buffer);
2285c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2286c2c66affSColin Finck 
228766669aedSwinesync     sz = 0;
228866669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, NULL, &sz);
228966669aedSwinesync     ok(!r, "got %u\n", r);
229066669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
229166669aedSwinesync 
229266669aedSwinesync     sz = 0;
229366669aedSwinesync     lstrcpyW(bufferW, booW);
229466669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz);
229566669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
229666669aedSwinesync     ok(!lstrcmpW(bufferW, booW), "got %s\n", wine_dbgstr_w(bufferW));
229766669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
229866669aedSwinesync 
229966669aedSwinesync     sz = 1;
230066669aedSwinesync     lstrcpyW(bufferW, booW);
230166669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
230266669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
230366669aedSwinesync     ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
230466669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
230566669aedSwinesync 
230666669aedSwinesync     sz = 3;
230766669aedSwinesync     lstrcpyW(bufferW, booW);
230866669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
230966669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
231066669aedSwinesync     ok(!lstrcmpW(bufferW, xyW), "got %s\n", wine_dbgstr_w(bufferW));
231166669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
231266669aedSwinesync 
231366669aedSwinesync     sz = 4;
231466669aedSwinesync     lstrcpyW(bufferW, booW);
231566669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
231666669aedSwinesync     ok(!r, "got %u\n", r);
231766669aedSwinesync     ok(!lstrcmpW(bufferW, xyzW), "got %s\n", wine_dbgstr_w(bufferW));
231866669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
231966669aedSwinesync 
2320c2000429Swinesync     /* properties are case-sensitive */
2321c2000429Swinesync     check_prop(hpkg, "BOO", "");
2322c2c66affSColin Finck 
2323c2000429Swinesync     /* properties set in Property table should work */
2324c2000429Swinesync     check_prop(hpkg, "MetadataCompName", "Photoshop.dll");
2325c2c66affSColin Finck 
2326c2c66affSColin Finck     MsiCloseHandle( hpkg );
2327c2c66affSColin Finck     DeleteFileA(msifile);
2328c2c66affSColin Finck }
2329c2c66affSColin Finck 
2330c2c66affSColin Finck static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2331c2c66affSColin Finck {
2332c2c66affSColin Finck     MSIHANDLE hview, hrec;
2333c2c66affSColin Finck     BOOL found = FALSE;
2334c2c66affSColin Finck     CHAR buffer[MAX_PATH];
2335c2c66affSColin Finck     DWORD sz;
2336c2c66affSColin Finck     UINT r;
2337c2c66affSColin Finck 
2338c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2339c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2340c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
2341c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2342c2c66affSColin Finck 
2343c2c66affSColin Finck     if (len < 0) len = lstrlenA(val);
2344c2c66affSColin Finck 
2345c2c66affSColin Finck     while (r == ERROR_SUCCESS && !found)
2346c2c66affSColin Finck     {
2347c2c66affSColin Finck         r = MsiViewFetch(hview, &hrec);
2348c2c66affSColin Finck         if (r != ERROR_SUCCESS) break;
2349c2c66affSColin Finck 
2350c2c66affSColin Finck         sz = MAX_PATH;
2351c2c66affSColin Finck         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2352c2c66affSColin Finck         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2353c2c66affSColin Finck         {
2354c2c66affSColin Finck             sz = MAX_PATH;
2355c2c66affSColin Finck             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2356c2c66affSColin Finck             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2357c2c66affSColin Finck             {
2358c2c66affSColin Finck                 ok(sz == len, "wrong size %u\n", sz);
2359c2c66affSColin Finck                 found = TRUE;
2360c2c66affSColin Finck             }
2361c2c66affSColin Finck         }
2362c2c66affSColin Finck 
2363c2c66affSColin Finck         MsiCloseHandle(hrec);
2364c2c66affSColin Finck     }
2365c2c66affSColin Finck     MsiViewClose(hview);
2366c2c66affSColin Finck     MsiCloseHandle(hview);
2367c2c66affSColin Finck     return found;
2368c2c66affSColin Finck }
2369c2c66affSColin Finck 
2370c2c66affSColin Finck static void test_property_table(void)
2371c2c66affSColin Finck {
2372c2c66affSColin Finck     const char *query;
2373c2c66affSColin Finck     UINT r;
2374c2c66affSColin Finck     MSIHANDLE hpkg, hdb, hrec;
2375c2c66affSColin Finck     char buffer[MAX_PATH], package[10];
2376c2c66affSColin Finck     DWORD sz;
2377c2c66affSColin Finck     BOOL found;
2378c2c66affSColin Finck 
2379c2c66affSColin Finck     hdb = create_package_db();
2380c2c66affSColin Finck     ok( hdb, "failed to create package\n");
2381c2c66affSColin Finck 
2382c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
2383c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2384c2c66affSColin Finck     {
2385c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2386c2c66affSColin Finck         DeleteFileA(msifile);
2387c2c66affSColin Finck         return;
2388c2c66affSColin Finck     }
2389c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2390c2c66affSColin Finck 
2391c2c66affSColin Finck     MsiCloseHandle(hdb);
2392c2c66affSColin Finck 
2393c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
2394c2c66affSColin Finck 
2395c2c66affSColin Finck     query = "CREATE TABLE `_Property` ( "
2396c2c66affSColin Finck         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2397c2c66affSColin Finck     r = run_query(hdb, query);
2398c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2399c2c66affSColin Finck 
2400c2c66affSColin Finck     MsiCloseHandle(hdb);
2401c2c66affSColin Finck     MsiCloseHandle(hpkg);
2402c2c66affSColin Finck     DeleteFileA(msifile);
2403c2c66affSColin Finck 
2404c2c66affSColin Finck     hdb = create_package_db();
2405c2c66affSColin Finck     ok( hdb, "failed to create package\n");
2406c2c66affSColin Finck 
2407c2c66affSColin Finck     query = "CREATE TABLE `_Property` ( "
2408c2c66affSColin Finck         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2409c2c66affSColin Finck     r = run_query(hdb, query);
2410c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create table\n");
2411c2c66affSColin Finck 
2412c2c66affSColin Finck     query = "ALTER `_Property` ADD `foo` INTEGER";
2413c2c66affSColin Finck     r = run_query(hdb, query);
2414c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2415c2c66affSColin Finck 
2416c2c66affSColin Finck     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2417c2c66affSColin Finck     r = run_query(hdb, query);
2418c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2419c2c66affSColin Finck 
2420c2c66affSColin Finck     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2421c2c66affSColin Finck     r = run_query(hdb, query);
2422c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to add column\n");
2423c2c66affSColin Finck 
2424c2c66affSColin Finck     sprintf(package, "#%i", hdb);
2425c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
2426c2c66affSColin Finck     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2427c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2428c2c66affSColin Finck         MsiCloseHandle(hpkg);
2429c2c66affSColin Finck 
2430c2c66affSColin Finck     r = MsiCloseHandle(hdb);
2431c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2432c2c66affSColin Finck 
2433c2c66affSColin Finck     hdb = create_package_db();
2434c2c66affSColin Finck     ok (hdb, "failed to create package database\n");
2435c2c66affSColin Finck 
2436f860a780SAmine Khaldi     create_property_table(hdb);
2437f860a780SAmine Khaldi     add_property_entry(hdb, "'prop', 'val'");
2438c2c66affSColin Finck 
2439f860a780SAmine Khaldi     create_custom_action_table(hdb);
2440f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2441c2c66affSColin Finck 
2442c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
2443c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2444c2c66affSColin Finck 
2445c2c66affSColin Finck     MsiCloseHandle(hdb);
2446c2c66affSColin Finck 
2447c2c66affSColin Finck     sz = MAX_PATH;
2448c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2449c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2450c2c66affSColin Finck     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2451c2c66affSColin Finck 
2452c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
2453c2c66affSColin Finck 
2454c2c66affSColin Finck     found = find_prop_in_property(hdb, "prop", "val", -1);
2455c2c66affSColin Finck     ok(found, "prop should be in the _Property table\n");
2456c2c66affSColin Finck 
2457f860a780SAmine Khaldi     add_property_entry(hdb, "'dantes', 'mercedes'");
2458c2c66affSColin Finck 
2459c2c66affSColin Finck     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2460c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
2461c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2462c2c66affSColin Finck 
2463c2c66affSColin Finck     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2464c2c66affSColin Finck     ok(found == FALSE, "dantes should not be in the _Property table\n");
2465c2c66affSColin Finck 
2466c2c66affSColin Finck     sz = MAX_PATH;
2467c2c66affSColin Finck     lstrcpyA(buffer, "aaa");
2468c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2469c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2470c2c66affSColin Finck     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2471c2c66affSColin Finck 
2472c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2473c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2474c2c66affSColin Finck 
2475c2c66affSColin Finck     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2476c2c66affSColin Finck     ok(found == TRUE, "dantes should be in the _Property table\n");
2477c2c66affSColin Finck 
2478c2c66affSColin Finck     r = MsiDoActionA( hpkg, "EmbedNull" );
2479c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2480c2c66affSColin Finck 
2481c2c66affSColin Finck     sz = MAX_PATH;
2482c2c66affSColin Finck     memset( buffer, 'a', sizeof(buffer) );
2483c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2484c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2485c2c66affSColin Finck     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2486c2c66affSColin Finck     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2487c2c66affSColin Finck 
2488c2c66affSColin Finck     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2489c2c66affSColin Finck     ok(found == TRUE, "prop2 should be in the _Property table\n");
2490c2c66affSColin Finck 
2491c2c66affSColin Finck     MsiCloseHandle(hdb);
2492c2c66affSColin Finck     MsiCloseHandle(hpkg);
2493c2c66affSColin Finck     DeleteFileA(msifile);
2494c2c66affSColin Finck }
2495c2c66affSColin Finck 
2496c2c66affSColin Finck static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2497c2c66affSColin Finck {
2498c2c66affSColin Finck     MSIHANDLE htab = 0;
2499c2c66affSColin Finck     UINT res;
2500c2c66affSColin Finck 
2501c2c66affSColin Finck     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2502c2c66affSColin Finck     if( res == ERROR_SUCCESS )
2503c2c66affSColin Finck     {
2504c2c66affSColin Finck         UINT r;
2505c2c66affSColin Finck 
2506c2c66affSColin Finck         r = MsiViewExecute( htab, hrec );
2507c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2508c2c66affSColin Finck         {
2509c2c66affSColin Finck             res = r;
2510c2c66affSColin Finck             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2511c2c66affSColin Finck         }
2512c2c66affSColin Finck 
2513c2c66affSColin Finck         r = MsiViewClose( htab );
2514c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2515c2c66affSColin Finck             res = r;
2516c2c66affSColin Finck 
2517c2c66affSColin Finck         r = MsiCloseHandle( htab );
2518c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2519c2c66affSColin Finck             res = r;
2520c2c66affSColin Finck     }
2521c2c66affSColin Finck     return res;
2522c2c66affSColin Finck }
2523c2c66affSColin Finck 
2524c2c66affSColin Finck static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2525c2c66affSColin Finck {
2526c2c66affSColin Finck     return try_query_param( hdb, szQuery, 0 );
2527c2c66affSColin Finck }
2528c2c66affSColin Finck 
2529c2c66affSColin Finck static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2530c2c66affSColin Finck {
2531c2c66affSColin Finck     MSIHANDLE summary;
2532c2c66affSColin Finck     UINT r;
2533c2c66affSColin Finck 
2534c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2535c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2536c2c66affSColin Finck 
2537c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2538c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2539c2c66affSColin Finck 
2540c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
2541c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2542c2c66affSColin Finck 
2543c2c66affSColin Finck     MsiCloseHandle(summary);
2544c2c66affSColin Finck }
2545c2c66affSColin Finck 
2546c2c66affSColin Finck static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2547c2c66affSColin Finck {
2548c2c66affSColin Finck     MSIHANDLE summary;
2549c2c66affSColin Finck     UINT r;
2550c2c66affSColin Finck 
2551c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2552c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2553c2c66affSColin Finck 
2554c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2555c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2556c2c66affSColin Finck 
2557c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
2558c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2559c2c66affSColin Finck 
2560c2c66affSColin Finck     MsiCloseHandle(summary);
2561c2c66affSColin Finck }
2562c2c66affSColin Finck 
2563c2c66affSColin Finck static void test_msipackage(void)
2564c2c66affSColin Finck {
2565c2c66affSColin Finck     MSIHANDLE hdb = 0, hpack = 100;
2566c2c66affSColin Finck     UINT r;
2567c2c66affSColin Finck     const char *query;
2568c2c66affSColin Finck     char name[10];
2569c2c66affSColin Finck 
2570c2c66affSColin Finck     /* NULL szPackagePath */
2571c2c66affSColin Finck     r = MsiOpenPackageA(NULL, &hpack);
2572c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2573c2c66affSColin Finck 
2574c2c66affSColin Finck     /* empty szPackagePath */
2575c2c66affSColin Finck     r = MsiOpenPackageA("", &hpack);
2576c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2577c2c66affSColin Finck     {
2578c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2579c2c66affSColin Finck         return;
2580c2c66affSColin Finck     }
2581c2c66affSColin Finck     todo_wine
2582c2c66affSColin Finck     {
2583c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2584c2c66affSColin Finck     }
2585c2c66affSColin Finck 
2586c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2587c2c66affSColin Finck         MsiCloseHandle(hpack);
2588c2c66affSColin Finck 
2589c2c66affSColin Finck     /* nonexistent szPackagePath */
2590c2c66affSColin Finck     r = MsiOpenPackageA("nonexistent", &hpack);
2591c2c66affSColin Finck     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2592c2c66affSColin Finck 
2593c2c66affSColin Finck     /* NULL hProduct */
2594c2c66affSColin Finck     r = MsiOpenPackageA(msifile, NULL);
2595c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2596c2c66affSColin Finck 
2597c2c66affSColin Finck     name[0]='#';
2598c2c66affSColin Finck     name[1]=0;
2599c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2600c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2601c2c66affSColin Finck 
2602c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2603c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2604c2c66affSColin Finck 
2605c2c66affSColin Finck     /* database exists, but is empty */
2606c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2607c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2608c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2609c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2610c2c66affSColin Finck 
2611c2c66affSColin Finck     query = "CREATE TABLE `Property` ( "
2612c2c66affSColin Finck             "`Property` CHAR(72), `Value` CHAR(0) "
2613c2c66affSColin Finck             "PRIMARY KEY `Property`)";
2614c2c66affSColin Finck     r = try_query(hdb, query);
2615c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2616c2c66affSColin Finck 
2617c2c66affSColin Finck     query = "CREATE TABLE `InstallExecuteSequence` ("
2618c2c66affSColin Finck             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2619c2c66affSColin Finck             "PRIMARY KEY `Action`)";
2620c2c66affSColin Finck     r = try_query(hdb, query);
2621c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2622c2c66affSColin Finck 
2623c2c66affSColin Finck     /* a few key tables exist */
2624c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2625c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2626c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2627c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2628c2c66affSColin Finck 
2629c2c66affSColin Finck     MsiCloseHandle(hdb);
2630c2c66affSColin Finck     DeleteFileA(msifile);
2631c2c66affSColin Finck 
2632c2c66affSColin Finck     /* start with a clean database to show what constitutes a valid package */
2633c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2634c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2635c2c66affSColin Finck 
2636c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2637c2c66affSColin Finck 
2638c2c66affSColin Finck     /* The following summary information props must exist:
2639c2c66affSColin Finck      *  - PID_REVNUMBER
2640c2c66affSColin Finck      *  - PID_PAGECOUNT
2641c2c66affSColin Finck      */
2642c2c66affSColin Finck 
2643c2c66affSColin Finck     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2644c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2645c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2646c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2647c2c66affSColin Finck 
2648c2c66affSColin Finck     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2649c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2650c2c66affSColin Finck     ok(r == ERROR_SUCCESS,
2651c2c66affSColin Finck        "Expected ERROR_SUCCESS, got %d\n", r);
2652c2c66affSColin Finck 
2653c2c66affSColin Finck     MsiCloseHandle(hpack);
2654c2c66affSColin Finck     MsiCloseHandle(hdb);
2655c2c66affSColin Finck     DeleteFileA(msifile);
2656c2c66affSColin Finck }
2657c2c66affSColin Finck 
2658c2c66affSColin Finck static void test_formatrecord2(void)
2659c2c66affSColin Finck {
2660c2c66affSColin Finck     MSIHANDLE hpkg, hrec ;
2661c2c66affSColin Finck     char buffer[0x100];
2662c2c66affSColin Finck     DWORD sz;
2663c2c66affSColin Finck     UINT r;
2664c2c66affSColin Finck 
2665c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
2666c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2667c2c66affSColin Finck     {
2668c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2669c2c66affSColin Finck         DeleteFileA(msifile);
2670c2c66affSColin Finck         return;
2671c2c66affSColin Finck     }
2672c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2673c2c66affSColin Finck 
2674c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2675c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "set property failed\n");
2676c2c66affSColin Finck 
2677c2c66affSColin Finck     hrec = MsiCreateRecord(2);
2678c2c66affSColin Finck     ok(hrec, "create record failed\n");
2679c2c66affSColin Finck 
2680c2c66affSColin Finck     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2681c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format record failed\n");
2682c2c66affSColin Finck 
2683c2c66affSColin Finck     buffer[0] = 0;
2684c2c66affSColin Finck     sz = sizeof buffer;
2685c2c66affSColin Finck     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2686c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2687c2c66affSColin Finck 
2688c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2689c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2690c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "hoo");
2691c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2692c2c66affSColin Finck     sz = sizeof buffer;
2693c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2694c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2695c2c66affSColin Finck     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2696c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2697c2c66affSColin Finck 
2698c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2699c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2700c2c66affSColin Finck     sz = sizeof buffer;
2701c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2702c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2703c2c66affSColin Finck     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2704c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2705c2c66affSColin Finck 
2706c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2707c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2708c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "hoo");
2709c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2710c2c66affSColin Finck     sz = sizeof buffer;
2711c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2712c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2713c2c66affSColin Finck     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2714c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2715c2c66affSColin Finck 
2716c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2717c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2718c2c66affSColin Finck     sz = sizeof buffer;
2719c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2720c2c66affSColin Finck     ok( sz == 1, "size wrong\n");
2721c2c66affSColin Finck     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2722c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2723c2c66affSColin Finck 
2724c2c66affSColin Finck     SetEnvironmentVariableA("FOO", "BAR");
2725c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2726c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2727c2c66affSColin Finck     sz = sizeof buffer;
2728c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2729c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2730c2c66affSColin Finck     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2731c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2732c2c66affSColin Finck 
2733c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2734c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2735c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2736c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2737c2c66affSColin Finck     sz = sizeof buffer;
2738c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2739c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2740c2c66affSColin Finck     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2741c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2742c2c66affSColin Finck 
2743c2c66affSColin Finck     MsiCloseHandle( hrec );
2744c2c66affSColin Finck     MsiCloseHandle( hpkg );
2745c2c66affSColin Finck     DeleteFileA(msifile);
2746c2c66affSColin Finck }
2747c2c66affSColin Finck 
2748f860a780SAmine Khaldi static void test_formatrecord_tables(void)
2749f860a780SAmine Khaldi {
2750f860a780SAmine Khaldi     MSIHANDLE hdb, hrec, hpkg = 0;
2751f860a780SAmine Khaldi     CHAR buf[MAX_PATH];
2752f860a780SAmine Khaldi     CHAR curr_dir[MAX_PATH];
2753f860a780SAmine Khaldi     CHAR expected[MAX_PATH];
2754f860a780SAmine Khaldi     CHAR root[MAX_PATH];
2755f860a780SAmine Khaldi     DWORD size;
2756f860a780SAmine Khaldi     UINT r;
2757f860a780SAmine Khaldi 
2758f860a780SAmine Khaldi     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2759f860a780SAmine Khaldi 
2760f860a780SAmine Khaldi     hdb = create_package_db();
2761f860a780SAmine Khaldi     ok ( hdb, "failed to create package database\n");
2762f860a780SAmine Khaldi 
2763f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2764f860a780SAmine Khaldi     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2765f860a780SAmine Khaldi                              "'I am a really long directory'" );
2766f860a780SAmine Khaldi 
2767f860a780SAmine Khaldi     create_feature_table( hdb );
2768f860a780SAmine Khaldi     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2769f860a780SAmine Khaldi 
2770f860a780SAmine Khaldi     create_component_table( hdb );
2771f860a780SAmine Khaldi     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2772f860a780SAmine Khaldi     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2773f860a780SAmine Khaldi     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2774f860a780SAmine Khaldi 
2775f860a780SAmine Khaldi     create_feature_components_table( hdb );
2776f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2777f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2778f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2779f860a780SAmine Khaldi 
2780f860a780SAmine Khaldi     create_file_table( hdb );
2781f860a780SAmine Khaldi     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2782f860a780SAmine Khaldi     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2783f860a780SAmine Khaldi     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2784f860a780SAmine Khaldi 
2785f860a780SAmine Khaldi     create_custom_action_table( hdb );
2786f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2787f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2788f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2789f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2790f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2791f860a780SAmine Khaldi 
2792f860a780SAmine Khaldi     r = package_from_db( hdb, &hpkg );
2793f860a780SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2794f860a780SAmine Khaldi     {
2795f860a780SAmine Khaldi         skip("Not enough rights to perform tests\n");
2796f860a780SAmine Khaldi         MsiCloseHandle( hdb );
2797f860a780SAmine Khaldi         DeleteFileA( msifile );
2798f860a780SAmine Khaldi         return;
2799f860a780SAmine Khaldi     }
2800f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2801f860a780SAmine Khaldi 
2802f860a780SAmine Khaldi     MsiCloseHandle( hdb );
2803f860a780SAmine Khaldi 
2804f860a780SAmine Khaldi     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2805f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2806f860a780SAmine Khaldi 
2807f860a780SAmine Khaldi     hrec = MsiCreateRecord( 1 );
2808f860a780SAmine Khaldi 
2809f860a780SAmine Khaldi     /* property doesn't exist */
2810f860a780SAmine Khaldi     size = MAX_PATH;
2811f860a780SAmine Khaldi     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2812f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2813f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2814f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2815f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2816f860a780SAmine Khaldi 
2817f860a780SAmine Khaldi     /* property exists */
2818f860a780SAmine Khaldi     size = MAX_PATH;
2819f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2820f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2821f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2822f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2823f860a780SAmine Khaldi 
2824f860a780SAmine Khaldi     size = MAX_PATH;
2825f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2826f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2827f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2828f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2829f860a780SAmine Khaldi 
2830f860a780SAmine Khaldi     /* environment variable doesn't exist */
2831f860a780SAmine Khaldi     size = MAX_PATH;
2832f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2833f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2834f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2835f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2836f860a780SAmine Khaldi 
2837f860a780SAmine Khaldi     /* environment variable exists */
2838f860a780SAmine Khaldi     size = MAX_PATH;
2839f860a780SAmine Khaldi     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2840f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2841f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2842f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2843f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2844f860a780SAmine Khaldi 
2845f860a780SAmine Khaldi     /* file key before CostInitialize */
2846f860a780SAmine Khaldi     size = MAX_PATH;
2847f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2848f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2849f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2850f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2851f860a780SAmine Khaldi 
2852f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2853f860a780SAmine Khaldi 
2854f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "CostInitialize");
2855f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2856f860a780SAmine Khaldi 
2857f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "FileCost");
2858f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2859f860a780SAmine Khaldi 
2860f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "CostFinalize");
2861f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2862f860a780SAmine Khaldi 
2863f860a780SAmine Khaldi     size = MAX_PATH;
2864f860a780SAmine Khaldi     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2865f860a780SAmine Khaldi 
2866f860a780SAmine Khaldi     sprintf( expected, "1: %sfrontal.txt ", root);
2867f860a780SAmine Khaldi 
2868f860a780SAmine Khaldi     /* frontal full file key */
2869f860a780SAmine Khaldi     size = MAX_PATH;
2870f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2871f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2872f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2873f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2874f860a780SAmine Khaldi 
2875f860a780SAmine Khaldi     /* frontal short file key */
2876f860a780SAmine Khaldi     size = MAX_PATH;
2877f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2878f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2879f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2880f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2881f860a780SAmine Khaldi 
2882f860a780SAmine Khaldi     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2883f860a780SAmine Khaldi 
2884f860a780SAmine Khaldi     /* temporal full file key */
2885f860a780SAmine Khaldi     size = MAX_PATH;
2886f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2887f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2888f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2889f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2890f860a780SAmine Khaldi 
2891f860a780SAmine Khaldi     /* temporal short file key */
2892f860a780SAmine Khaldi     size = MAX_PATH;
2893f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2894f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2895f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2896f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2897f860a780SAmine Khaldi 
2898f860a780SAmine Khaldi     /* custom action 51, files don't exist */
2899f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "MyCustom" );
2900f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2901f860a780SAmine Khaldi 
2902f860a780SAmine Khaldi     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2903f860a780SAmine Khaldi 
2904f860a780SAmine Khaldi     size = MAX_PATH;
2905f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2906f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2907f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2908f860a780SAmine Khaldi 
2909f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory", root );
2910f860a780SAmine Khaldi     CreateDirectoryA( buf, NULL );
2911f860a780SAmine Khaldi 
2912f860a780SAmine Khaldi     lstrcatA( buf, "\\temporal.txt" );
2913f860a780SAmine Khaldi     create_test_file( buf );
2914f860a780SAmine Khaldi 
2915f860a780SAmine Khaldi     /* custom action 51, files exist */
2916f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "MyCustom" );
2917f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2918f860a780SAmine Khaldi 
2919f860a780SAmine Khaldi     size = MAX_PATH;
2920f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2921f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2922f860a780SAmine Khaldi     todo_wine
2923f860a780SAmine Khaldi     {
2924f860a780SAmine Khaldi         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2925f860a780SAmine Khaldi     }
2926f860a780SAmine Khaldi 
2927f860a780SAmine Khaldi     /* custom action 51, escaped text 1 */
2928f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt1" );
2929f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2930f860a780SAmine Khaldi 
2931f860a780SAmine Khaldi     size = MAX_PATH;
2932f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2933f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2934f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2935f860a780SAmine Khaldi 
2936f860a780SAmine Khaldi     /* custom action 51, escaped text 2 */
2937f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt2" );
2938f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2939f860a780SAmine Khaldi 
2940f860a780SAmine Khaldi     size = MAX_PATH;
2941f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2942f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2943f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2944f860a780SAmine Khaldi 
2945f860a780SAmine Khaldi     /* custom action 51, escaped text 3 */
2946f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt3" );
2947f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2948f860a780SAmine Khaldi 
2949f860a780SAmine Khaldi     size = MAX_PATH;
2950f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2951f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2952f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2953f860a780SAmine Khaldi 
2954f860a780SAmine Khaldi     /* custom action 51, embedded null */
2955f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EmbedNull" );
2956f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2957f860a780SAmine Khaldi 
2958f860a780SAmine Khaldi     size = MAX_PATH;
2959f860a780SAmine Khaldi     memset( buf, 'a', sizeof(buf) );
2960f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2961f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2962f860a780SAmine Khaldi     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2963f860a780SAmine Khaldi     ok( size == sizeof("\0np") - 1, "got %u\n", size );
2964f860a780SAmine Khaldi 
2965f860a780SAmine Khaldi     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2966f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2967f860a780SAmine Khaldi 
2968f860a780SAmine Khaldi     size = MAX_PATH;
2969f860a780SAmine Khaldi     memset( buf, 'a', sizeof(buf) );
2970f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2971f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2972f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2973f860a780SAmine Khaldi 
2974f860a780SAmine Khaldi     sprintf( expected, "1: %sI am a really long directory\\ ", root);
2975f860a780SAmine Khaldi 
2976f860a780SAmine Khaldi     /* component with INSTALLSTATE_LOCAL */
2977f860a780SAmine Khaldi     size = MAX_PATH;
2978f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2979f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2980f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2981f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2982f860a780SAmine Khaldi 
2983f860a780SAmine Khaldi     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2984f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2985f860a780SAmine Khaldi 
2986f860a780SAmine Khaldi     /* component with INSTALLSTATE_SOURCE */
2987f860a780SAmine Khaldi     lstrcpyA( expected, "1: " );
2988f860a780SAmine Khaldi     lstrcatA( expected, curr_dir );
2989f860a780SAmine Khaldi     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
2990f860a780SAmine Khaldi     lstrcatA( expected, " " );
2991f860a780SAmine Khaldi     size = MAX_PATH;
2992f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
2993f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2994f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2995f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
2996f860a780SAmine Khaldi 
2997f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
2998f860a780SAmine Khaldi     DeleteFileA( buf );
2999f860a780SAmine Khaldi 
3000f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory", root );
3001f860a780SAmine Khaldi     RemoveDirectoryA( buf );
3002f860a780SAmine Khaldi 
3003f860a780SAmine Khaldi     MsiCloseHandle( hrec );
3004f860a780SAmine Khaldi     MsiCloseHandle( hpkg );
3005f860a780SAmine Khaldi     DeleteFileA( msifile );
3006f860a780SAmine Khaldi }
3007f860a780SAmine Khaldi 
3008c2c66affSColin Finck static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
3009c2c66affSColin Finck                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3010c2c66affSColin Finck {
3011c2c66affSColin Finck     UINT r;
3012c2c66affSColin Finck     INSTALLSTATE state = 0xdeadbee;
3013c2c66affSColin Finck     INSTALLSTATE action = 0xdeadbee;
3014c2c66affSColin Finck 
3015c2c66affSColin Finck     r = MsiGetFeatureStateA( package, feature, &state, &action );
3016c2c66affSColin Finck     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3017c2c66affSColin Finck     if (r == ERROR_SUCCESS)
3018c2c66affSColin Finck     {
3019c2c66affSColin Finck         ok( state == expected_state, "%u: expected state %d got %d\n",
3020c2c66affSColin Finck             line, expected_state, state );
3021c2c66affSColin Finck         todo_wine_if (todo)
3022c2c66affSColin Finck             ok( action == expected_action, "%u: expected action %d got %d\n",
3023c2c66affSColin Finck                 line, expected_action, action );
3024c2c66affSColin Finck     }
3025c2c66affSColin Finck     else
3026c2c66affSColin Finck     {
3027c2c66affSColin Finck         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3028c2c66affSColin Finck         todo_wine_if (todo)
3029c2c66affSColin Finck             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3030c2c66affSColin Finck 
3031c2c66affSColin Finck     }
3032c2c66affSColin Finck }
3033c2c66affSColin Finck 
3034c2c66affSColin Finck static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3035c2c66affSColin Finck                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3036c2c66affSColin Finck {
3037c2c66affSColin Finck     UINT r;
3038c2c66affSColin Finck     INSTALLSTATE state = 0xdeadbee;
3039c2c66affSColin Finck     INSTALLSTATE action = 0xdeadbee;
3040c2c66affSColin Finck 
3041c2c66affSColin Finck     r = MsiGetComponentStateA( package, component, &state, &action );
3042c2c66affSColin Finck     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3043c2c66affSColin Finck     if (r == ERROR_SUCCESS)
3044c2c66affSColin Finck     {
3045c2c66affSColin Finck         ok( state == expected_state, "%u: expected state %d got %d\n",
3046c2c66affSColin Finck             line, expected_state, state );
3047c2c66affSColin Finck         todo_wine_if (todo)
3048c2c66affSColin Finck             ok( action == expected_action, "%u: expected action %d got %d\n",
3049c2c66affSColin Finck                 line, expected_action, action );
3050c2c66affSColin Finck     }
3051c2c66affSColin Finck     else
3052c2c66affSColin Finck     {
3053c2c66affSColin Finck         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3054c2c66affSColin Finck             line, state );
3055c2c66affSColin Finck         todo_wine_if (todo)
3056c2c66affSColin Finck             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3057c2c66affSColin Finck                 line, action );
3058c2c66affSColin Finck     }
3059c2c66affSColin Finck }
3060c2c66affSColin Finck 
3061c2c66affSColin Finck static void test_states(void)
3062c2c66affSColin Finck {
3063c2c66affSColin Finck     static const char msifile2[] = "winetest2-package.msi";
3064c2c66affSColin Finck     static const char msifile3[] = "winetest3-package.msi";
3065c2c66affSColin Finck     static const char msifile4[] = "winetest4-package.msi";
3066c2c66affSColin Finck     static const WCHAR msifile2W[] =
3067c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
3068c2c66affSColin Finck     static const WCHAR msifile3W[] =
3069c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
3070c2c66affSColin Finck     static const WCHAR msifile4W[] =
3071c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
3072f860a780SAmine Khaldi     char msi_cache_file[MAX_PATH];
3073f860a780SAmine Khaldi     DWORD cache_file_name_len;
3074c2c66affSColin Finck     INSTALLSTATE state;
3075c2c66affSColin Finck     MSIHANDLE hpkg;
3076c2c66affSColin Finck     UINT r;
3077c2c66affSColin Finck     MSIHANDLE hdb;
3078f860a780SAmine Khaldi     BOOL is_broken;
3079c2c66affSColin Finck 
3080c2c66affSColin Finck     if (is_process_limited())
3081c2c66affSColin Finck     {
3082c2c66affSColin Finck         skip("process is limited\n");
3083c2c66affSColin Finck         return;
3084c2c66affSColin Finck     }
3085c2c66affSColin Finck 
3086c2c66affSColin Finck     hdb = create_package_db();
3087c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3088c2c66affSColin Finck 
3089f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3090c2c66affSColin Finck 
3091f860a780SAmine Khaldi     create_property_table( hdb );
3092f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3093f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductLanguage', '1033'" );
3094f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3095f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3096f860a780SAmine Khaldi     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
3097c2c66affSColin Finck 
3098f860a780SAmine Khaldi     create_install_execute_sequence_table( hdb );
3099f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3100f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3101f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3102f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3103f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3104f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3105f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3106f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3107f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3108f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3109f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3110c2c66affSColin Finck 
3111f860a780SAmine Khaldi     create_media_table( hdb );
3112f860a780SAmine Khaldi     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3113c2c66affSColin Finck 
3114f860a780SAmine Khaldi     create_feature_table( hdb );
3115c2c66affSColin Finck 
3116f860a780SAmine Khaldi     create_component_table( hdb );
3117c2c66affSColin Finck 
3118c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3119f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3120c2c66affSColin Finck 
3121c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3122f860a780SAmine Khaldi     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3123c2c66affSColin Finck 
3124c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3125f860a780SAmine Khaldi     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3126c2c66affSColin Finck 
3127c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3128f860a780SAmine Khaldi     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3129c2c66affSColin Finck 
3130c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3131f860a780SAmine Khaldi     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3132c2c66affSColin Finck 
3133c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3134f860a780SAmine Khaldi     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3135c2c66affSColin Finck 
3136c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3137f860a780SAmine Khaldi     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3138c2c66affSColin Finck 
3139c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3140f860a780SAmine Khaldi     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3141c2c66affSColin Finck 
3142c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3143f860a780SAmine Khaldi     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3144c2c66affSColin Finck 
3145c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3146f860a780SAmine Khaldi     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3147c2c66affSColin Finck 
3148c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3149f860a780SAmine Khaldi     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3150c2c66affSColin Finck 
3151c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3152f860a780SAmine Khaldi     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3153c2c66affSColin Finck 
3154c2c66affSColin Finck     /* disabled */
3155f860a780SAmine Khaldi     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3156c2c66affSColin Finck 
3157c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3158f860a780SAmine Khaldi     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3159c2c66affSColin Finck 
3160c2c66affSColin Finck     /* no feature parent:msidbComponentAttributesLocalOnly */
3161f860a780SAmine Khaldi     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3162c2c66affSColin Finck 
3163c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed */
3164f860a780SAmine Khaldi     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3165c2c66affSColin Finck 
3166c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3167f860a780SAmine Khaldi     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3168c2c66affSColin Finck 
3169c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3170f860a780SAmine Khaldi     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3171c2c66affSColin Finck 
3172c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3173f860a780SAmine Khaldi     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3174c2c66affSColin Finck 
3175c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3176f860a780SAmine Khaldi     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3177c2c66affSColin Finck 
3178c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed */
3179f860a780SAmine Khaldi     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3180c2c66affSColin Finck 
3181c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3182f860a780SAmine Khaldi     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3183c2c66affSColin Finck 
3184c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3185f860a780SAmine Khaldi     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3186c2c66affSColin Finck 
3187c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3188f860a780SAmine Khaldi     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3189c2c66affSColin Finck 
3190c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3191f860a780SAmine Khaldi     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3192c2c66affSColin Finck 
3193c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3194f860a780SAmine Khaldi     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3195c2c66affSColin Finck 
3196f860a780SAmine Khaldi     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3197c2c66affSColin Finck 
3198c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3199f860a780SAmine Khaldi     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3200c2c66affSColin Finck 
3201f860a780SAmine Khaldi     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3202c2c66affSColin Finck 
3203c2c66affSColin Finck     /* msidbFeatureAttributesFavorAdvertise */
3204f860a780SAmine Khaldi     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3205c2c66affSColin Finck 
3206f860a780SAmine Khaldi     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3207c2c66affSColin Finck 
3208c2c66affSColin Finck     /* msidbFeatureAttributesUIDisallowAbsent */
3209f860a780SAmine Khaldi     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3210c2c66affSColin Finck 
3211f860a780SAmine Khaldi     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3212c2c66affSColin Finck 
3213c2c66affSColin Finck     /* high install level */
3214f860a780SAmine Khaldi     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3215c2c66affSColin Finck 
3216f860a780SAmine Khaldi     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3217c2c66affSColin Finck 
3218c2c66affSColin Finck     /* msidbFeatureAttributesFollowParent */
3219f860a780SAmine Khaldi     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3220c2c66affSColin Finck 
3221f860a780SAmine Khaldi     create_feature_components_table( hdb );
3222f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'alpha'" );
3223f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'beta'" );
3224f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'gamma'" );
3225f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'theta'" );
3226f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'delta'" );
3227f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3228f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'zeta'" );
3229f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'iota'" );
3230f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'three', 'eta'" );
3231f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'four', 'eta'" );
3232f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'five', 'eta'" );
3233f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'lambda'" );
3234f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'mu'" );
3235f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'nu'" );
3236f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'xi'" );
3237f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3238f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'pi'" );
3239f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'rho'" );
3240f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3241f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'eight', 'tau'" );
3242f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'nine', 'phi'" );
3243f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'ten', 'chi'" );
3244f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3245f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3246f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3247c2c66affSColin Finck 
3248f860a780SAmine Khaldi     create_file_table( hdb );
3249f860a780SAmine Khaldi     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3250f860a780SAmine Khaldi     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3251f860a780SAmine Khaldi     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3252f860a780SAmine Khaldi     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3253f860a780SAmine Khaldi     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3254f860a780SAmine Khaldi     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3255f860a780SAmine Khaldi     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3256f860a780SAmine Khaldi     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3257c2c66affSColin Finck 
3258c2c66affSColin Finck     /* compressed file */
3259f860a780SAmine Khaldi     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3260c2c66affSColin Finck 
3261f860a780SAmine Khaldi     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3262f860a780SAmine Khaldi     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3263f860a780SAmine Khaldi     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3264f860a780SAmine Khaldi     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3265f860a780SAmine Khaldi     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3266f860a780SAmine Khaldi     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3267f860a780SAmine Khaldi     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3268f860a780SAmine Khaldi     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3269f860a780SAmine Khaldi     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3270f860a780SAmine Khaldi     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3271f860a780SAmine Khaldi     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3272f860a780SAmine Khaldi     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3273f860a780SAmine Khaldi     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3274f860a780SAmine Khaldi     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3275c2c66affSColin Finck 
3276f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
3277f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3278c2c66affSColin Finck 
3279c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3280f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3281f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3282f860a780SAmine Khaldi     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3283f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3284f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3285c2c66affSColin Finck 
3286c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3287c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3288c2c66affSColin Finck     {
3289c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3290c2c66affSColin Finck         DeleteFileA(msifile);
3291c2c66affSColin Finck         return;
3292c2c66affSColin Finck     }
3293c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3294c2c66affSColin Finck 
3295c2c66affSColin Finck     MsiCloseHandle(hdb);
3296c2c66affSColin Finck 
3297c2c66affSColin Finck     CopyFileA(msifile, msifile2, FALSE);
3298c2c66affSColin Finck     CopyFileA(msifile, msifile3, FALSE);
3299c2c66affSColin Finck     CopyFileA(msifile, msifile4, FALSE);
3300c2c66affSColin Finck 
3301c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3302c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3303c2c66affSColin Finck 
3304c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3305c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3306c2c66affSColin Finck 
3307c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3308c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3309c2c66affSColin Finck 
3310c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3311c2c66affSColin Finck 
3312c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3313c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3314c2c66affSColin Finck 
3315c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3316c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3317c2c66affSColin Finck 
3318c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3319c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3320c2c66affSColin Finck 
3321c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3322c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3323c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3324c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3325c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3326c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3327c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3328c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3329c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3330c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3331c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3332c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3333c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3334c2c66affSColin Finck 
3335c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3336c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3337c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3338c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3339c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3340c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3341c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3342c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3343c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3344c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3345c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3346c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3347c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3348c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3349c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3350c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3351c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3352c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3353c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3354c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3355c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3356c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3357c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3358c2c66affSColin Finck 
3359c2c66affSColin Finck     MsiCloseHandle( hpkg );
3360c2c66affSColin Finck 
3361c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3362c2c66affSColin Finck 
3363c2c66affSColin Finck     /* publish the features and components */
3364c2c66affSColin Finck     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3365c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3366c2c66affSColin Finck 
3367c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3368c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3369c2c66affSColin Finck 
3370c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3371f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3372f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3373f860a780SAmine Khaldi     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3374f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3375c2c66affSColin Finck 
3376c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3377c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3378c2c66affSColin Finck 
3379c2c66affSColin Finck     MsiCloseHandle(hdb);
3380c2c66affSColin Finck 
3381c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3382c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3383c2c66affSColin Finck 
3384c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3385c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3386c2c66affSColin Finck 
3387c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3388c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3389c2c66affSColin Finck 
3390c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3391c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3392c2c66affSColin Finck 
3393c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3394c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3395c2c66affSColin Finck 
3396c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3397c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3398c2c66affSColin Finck 
3399c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3400c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3401c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3402c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3403c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3404c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3405c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3406c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3407c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3408c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3409c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3410c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3411c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3412c2c66affSColin Finck 
3413c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3414c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3415c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3416c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3417c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3418c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3419c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3420c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3421c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3422c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3423c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3424c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3425c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3426c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3427c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3428c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3429c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3430c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3431c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3432c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3433c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3434c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3435c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3436c2c66affSColin Finck 
3437c2c66affSColin Finck     MsiCloseHandle(hpkg);
3438c2c66affSColin Finck 
3439c2c66affSColin Finck     /* uninstall the product */
3440c2c66affSColin Finck     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3441c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3442c2c66affSColin Finck 
3443c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3444c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3445c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3446c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3447c2c66affSColin Finck 
3448c2c66affSColin Finck     /* all features installed locally */
3449c2c66affSColin Finck     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3450c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3451c2c66affSColin Finck 
3452c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3453c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3454c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3455c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3456c2c66affSColin Finck 
3457c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3458c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3459c2c66affSColin Finck 
3460c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3461f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3462c2c66affSColin Finck 
3463c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3464c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3465c2c66affSColin Finck 
3466c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3467c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3468c2c66affSColin Finck 
3469c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3470c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3471c2c66affSColin Finck 
3472c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3473c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3474c2c66affSColin Finck 
3475c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3476c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3477c2c66affSColin Finck 
3478c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3479c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3480c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3481c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3482c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3483c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3484c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3485c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3486c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3487c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3488c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3489c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3490c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3491c2c66affSColin Finck 
3492c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3493c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3494c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3495c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3496c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3497c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3498c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3499c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3500c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3501c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3502c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3503c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3504c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3505c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3506c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3507c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3508c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3509c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3510c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3511c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3512c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3513c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3514c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3515c2c66affSColin Finck 
3516c2c66affSColin Finck     MsiCloseHandle(hpkg);
3517c2c66affSColin Finck 
3518c2c66affSColin Finck     /* uninstall the product */
3519c2c66affSColin Finck     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3520c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3521c2c66affSColin Finck 
3522c2c66affSColin Finck     /* all features installed from source */
3523c2c66affSColin Finck     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3524c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3525c2c66affSColin Finck 
3526c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3527c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3528c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3529c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3530c2c66affSColin Finck 
3531c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3532c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3533c2c66affSColin Finck 
3534c2c66affSColin Finck     /* this property must not be in the saved msi file */
3535f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3536c2c66affSColin Finck 
3537c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3538c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3539c2c66affSColin Finck 
3540c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3541c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3542c2c66affSColin Finck 
3543c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3544c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3545c2c66affSColin Finck 
3546c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3547c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3548c2c66affSColin Finck 
3549c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3550c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3551c2c66affSColin Finck 
3552c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3553c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3554c2c66affSColin Finck 
3555c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3556c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3557c2c66affSColin Finck 
3558c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3559c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3560c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3561c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3562c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3563c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3564c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3565c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3566c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3567c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3568c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3569c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3570c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3571c2c66affSColin Finck 
3572c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3573c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3574c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3575c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3576c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3577c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3578c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3579c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3580c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3581c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3582c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3583c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3584c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3585c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3586c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3587c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3588c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3589c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3590c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3591c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3592c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3593c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3594f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3595c2c66affSColin Finck 
3596c2c66affSColin Finck     MsiCloseHandle(hpkg);
3597c2c66affSColin Finck 
3598c2c66affSColin Finck     /* reinstall the product */
3599c2c66affSColin Finck     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3600f860a780SAmine Khaldi     is_broken = (r == ERROR_INSTALL_FAILURE);
3601f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3602c2c66affSColin Finck 
3603c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3604c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3605c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3606c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3607c2c66affSColin Finck 
3608c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3609c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3610c2c66affSColin Finck 
3611c2c66affSColin Finck     /* this property must not be in the saved msi file */
3612f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3613c2c66affSColin Finck 
3614c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3615c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3616c2c66affSColin Finck 
3617c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3618c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3619c2c66affSColin Finck 
3620c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3621c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3622c2c66affSColin Finck 
3623c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3624c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3625c2c66affSColin Finck 
3626c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3627c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3628c2c66affSColin Finck 
3629c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3630c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3631c2c66affSColin Finck 
3632c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3633c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3634c2c66affSColin Finck 
3635c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3636c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3637c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3638c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3639c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3640c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3641c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3642c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3643c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3644c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3645c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3646c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3647c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3648c2c66affSColin Finck 
3649c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3650c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3651c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3652c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3653c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3654c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3655c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3656c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3657c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3658c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3659c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3660c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3661c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3662c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3663c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3664c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3665c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3666c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3667c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3668c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3669c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3670c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3671f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3672c2c66affSColin Finck 
3673c2c66affSColin Finck     MsiCloseHandle(hpkg);
3674c2c66affSColin Finck 
3675f860a780SAmine Khaldi     /* test source only install */
3676f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3677f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3678f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3679f860a780SAmine Khaldi     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3680f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3681f860a780SAmine Khaldi     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3682f860a780SAmine Khaldi 
3683f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3684f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3685f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3686f860a780SAmine Khaldi     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3687f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3688f860a780SAmine Khaldi     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3689f860a780SAmine Khaldi 
3690f860a780SAmine Khaldi     /* no arguments test */
3691f860a780SAmine Khaldi     cache_file_name_len = sizeof(msi_cache_file);
3692f860a780SAmine Khaldi     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3693f860a780SAmine Khaldi             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3694f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3695f860a780SAmine Khaldi     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3696f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3697f860a780SAmine Khaldi 
3698f860a780SAmine Khaldi     create_custom_action_table( hdb );
3699f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3700f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3701f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3702f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3703f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3704f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3705f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3706f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
37072dce4ee7Swinesync     add_custom_action_entry( hdb,
370818123440Swinesync             "'VBFeatureRequest', 38, NULL, 'Session.FeatureRequestState(\"three\") = 3'" );
3709f860a780SAmine Khaldi 
3710f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3711f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
37122dce4ee7Swinesync     add_install_execute_sequence_entry( hdb, "'VBFeatureRequest', 'NOT REMOVE', '1001'" );
3713f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3714f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3715f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3716f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3717f860a780SAmine Khaldi     /* Add "one" feature action tests */
3718f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3719f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3720f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
3721f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3722f860a780SAmine Khaldi     r = package_from_db( hdb, &hpkg );
3723f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3724f860a780SAmine Khaldi     MsiCloseHandle(hdb);
3725f860a780SAmine Khaldi 
3726f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3727f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3728f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "CostInitialize");
3729f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3730f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3731f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3732f860a780SAmine Khaldi 
3733f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "FileCost");
3734f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3735f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3736f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3737f860a780SAmine Khaldi 
3738f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "CostFinalize");
3739f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3740f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3741f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3742f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3743f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3744f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3745f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3746f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3747f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3748f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3749f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3750f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3751f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3752f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3753f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3754f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3755f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3756f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3757f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3758f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3759f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3760f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3761f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3762f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3763f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3764f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3765f860a780SAmine Khaldi 
3766f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "InstallValidate");
3767f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3768f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3769f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3770f860a780SAmine Khaldi     MsiCloseHandle( hpkg );
3771f860a780SAmine Khaldi 
3772f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "");
3773f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS || (is_broken && r == ERROR_INSTALL_FAILURE) /* win2k3 */,
3774f860a780SAmine Khaldi             "Expected ERROR_SUCCESS, got %d\n", r);
3775f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3776f860a780SAmine Khaldi     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3777f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3778f860a780SAmine Khaldi     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
37792dce4ee7Swinesync     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "three");
37802dce4ee7Swinesync     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3781f860a780SAmine Khaldi 
3782c2c66affSColin Finck     /* uninstall the product */
3783c2c66affSColin Finck     r = MsiInstallProductA(msifile4, "REMOVE=ALL");
3784c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3785c2c66affSColin Finck 
3786c2c66affSColin Finck     DeleteFileA(msifile);
3787c2c66affSColin Finck     DeleteFileA(msifile2);
3788c2c66affSColin Finck     DeleteFileA(msifile3);
3789c2c66affSColin Finck     DeleteFileA(msifile4);
3790c2c66affSColin Finck }
3791c2c66affSColin Finck 
3792c2c66affSColin Finck static void test_removefiles(void)
3793c2c66affSColin Finck {
3794c2c66affSColin Finck     MSIHANDLE hpkg;
3795c2c66affSColin Finck     UINT r;
3796c2c66affSColin Finck     MSIHANDLE hdb;
3797c2c66affSColin Finck     INSTALLSTATE installed, action;
3798c2c66affSColin Finck 
3799c2c66affSColin Finck     hdb = create_package_db();
3800c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3801c2c66affSColin Finck 
3802f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3803c2c66affSColin Finck 
3804f860a780SAmine Khaldi     create_feature_table( hdb );
3805f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3806c2c66affSColin Finck 
3807f860a780SAmine Khaldi     create_component_table( hdb );
3808f860a780SAmine Khaldi     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3809f860a780SAmine Khaldi     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3810f860a780SAmine Khaldi     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3811f860a780SAmine Khaldi     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3812f860a780SAmine Khaldi     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3813f860a780SAmine Khaldi     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3814f860a780SAmine Khaldi     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3815c2c66affSColin Finck 
3816f860a780SAmine Khaldi     create_feature_components_table( hdb );
3817f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3818f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'helium'" );
3819f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'lithium'" );
3820f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3821f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'boron'" );
3822f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'carbon'" );
3823f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3824c2c66affSColin Finck 
3825f860a780SAmine Khaldi     create_file_table( hdb );
3826f860a780SAmine Khaldi     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3827f860a780SAmine Khaldi     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3828f860a780SAmine Khaldi     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3829f860a780SAmine Khaldi     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3830f860a780SAmine Khaldi     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3831f860a780SAmine Khaldi     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3832f860a780SAmine Khaldi     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3833c2c66affSColin Finck 
3834f860a780SAmine Khaldi     create_remove_file_table( hdb );
3835c2c66affSColin Finck 
3836c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3837c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3838c2c66affSColin Finck     {
3839c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3840c2c66affSColin Finck         DeleteFileA(msifile);
3841c2c66affSColin Finck         return;
3842c2c66affSColin Finck     }
3843c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3844c2c66affSColin Finck 
3845c2c66affSColin Finck     MsiCloseHandle( hdb );
3846c2c66affSColin Finck 
3847c2c66affSColin Finck     create_test_file( "hydrogen.txt" );
3848c2c66affSColin Finck     create_test_file( "helium.txt" );
3849c2c66affSColin Finck     create_test_file( "lithium.txt" );
3850c2c66affSColin Finck     create_test_file( "beryllium.txt" );
3851c2c66affSColin Finck     create_test_file( "boron.txt" );
3852c2c66affSColin Finck     create_test_file( "carbon.txt" );
3853c2c66affSColin Finck     create_test_file( "oxygen.txt" );
3854c2c66affSColin Finck 
3855c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3856c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "set property failed\n");
3857c2c66affSColin Finck 
3858c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3859c2c66affSColin Finck 
3860c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3861c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3862c2c66affSColin Finck 
3863c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3864c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3865c2c66affSColin Finck 
3866c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3867c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3868c2c66affSColin Finck 
3869c2c66affSColin Finck     installed = action = 0xdeadbeef;
3870c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3871c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3872c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3873c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3874c2c66affSColin Finck 
3875c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3876c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3877c2c66affSColin Finck 
3878c2c66affSColin Finck     r = MsiDoActionA( hpkg, "InstallValidate");
3879c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "install validate failed\n");
3880c2c66affSColin Finck 
3881c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3882c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3883c2c66affSColin Finck 
3884c2c66affSColin Finck     installed = action = 0xdeadbeef;
3885c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3886c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3887c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3888c2c66affSColin Finck     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3889c2c66affSColin Finck 
3890c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3891c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3892c2c66affSColin Finck 
3893c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3894c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3895c2c66affSColin Finck 
3896c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
3897c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3898c2c66affSColin Finck 
3899c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
3900c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3901c2c66affSColin Finck 
3902c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
3903c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3904c2c66affSColin Finck 
3905c2c66affSColin Finck     installed = action = 0xdeadbeef;
3906c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3907c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3908c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3909c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3910c2c66affSColin Finck 
3911c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
3912c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3913c2c66affSColin Finck 
3914c2c66affSColin Finck     installed = action = 0xdeadbeef;
3915c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3916c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3917c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3918c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3919c2c66affSColin Finck 
3920c2c66affSColin Finck     r = MsiDoActionA( hpkg, "RemoveFiles");
3921c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "remove files failed\n");
3922c2c66affSColin Finck 
3923c2c66affSColin Finck     installed = action = 0xdeadbeef;
3924c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3925c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3926c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3927c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3928c2c66affSColin Finck 
3929c2c66affSColin Finck     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
3930c2c66affSColin Finck     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
3931c2c66affSColin Finck     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
3932c2c66affSColin Finck     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
3933c2c66affSColin Finck     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
3934c2c66affSColin Finck     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
3935c2c66affSColin Finck     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
3936c2c66affSColin Finck 
3937c2c66affSColin Finck     MsiCloseHandle( hpkg );
3938c2c66affSColin Finck     DeleteFileA(msifile);
3939c2c66affSColin Finck }
3940c2c66affSColin Finck 
3941c2c66affSColin Finck static void test_appsearch(void)
3942c2c66affSColin Finck {
3943c2c66affSColin Finck     MSIHANDLE hpkg;
3944c2c66affSColin Finck     UINT r;
3945c2c66affSColin Finck     MSIHANDLE hdb;
3946c2c66affSColin Finck     CHAR prop[MAX_PATH];
3947c2c66affSColin Finck     DWORD size;
3948c2c66affSColin Finck     HKEY hkey;
3949c2c66affSColin Finck     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
3950c2c66affSColin Finck 
3951c2c66affSColin Finck     hdb = create_package_db();
3952c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3953c2c66affSColin Finck 
3954f860a780SAmine Khaldi     create_appsearch_table( hdb );
3955f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
3956f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
3957f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
3958c2c66affSColin Finck 
3959f860a780SAmine Khaldi     create_reglocator_table( hdb );
3960f860a780SAmine Khaldi     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
3961c2c66affSColin Finck 
3962c2c66affSColin Finck     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
3963c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
3964c2c66affSColin Finck     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
3965c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
3966c2c66affSColin Finck     RegCloseKey(hkey);
3967f860a780SAmine Khaldi     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", 1 );
3968c2c66affSColin Finck 
3969f860a780SAmine Khaldi     create_drlocator_table( hdb );
3970f860a780SAmine Khaldi     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
3971c2c66affSColin Finck 
3972f860a780SAmine Khaldi     create_signature_table( hdb );
3973f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
3974f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3975f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
3976c2c66affSColin Finck 
3977c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3978c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3979c2c66affSColin Finck     {
3980c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3981c2c66affSColin Finck         DeleteFileA(msifile);
3982c2c66affSColin Finck         return;
3983c2c66affSColin Finck     }
3984c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3985c2c66affSColin Finck     MsiCloseHandle( hdb );
3986c2c66affSColin Finck     if (r != ERROR_SUCCESS)
3987c2c66affSColin Finck         goto done;
3988c2c66affSColin Finck 
3989c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3990c2c66affSColin Finck 
3991c2c66affSColin Finck     r = MsiDoActionA( hpkg, "AppSearch" );
3992c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
3993c2c66affSColin Finck 
3994c2c66affSColin Finck     size = sizeof(prop);
3995c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
3996c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3997c2c66affSColin Finck     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
3998c2c66affSColin Finck 
3999c2c66affSColin Finck     size = sizeof(prop);
4000c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
4001c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4002c2c66affSColin Finck 
4003c2c66affSColin Finck     size = sizeof(prop);
4004c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
4005c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4006c2c66affSColin Finck     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4007c2c66affSColin Finck 
4008c2c66affSColin Finck done:
4009c2c66affSColin Finck     MsiCloseHandle( hpkg );
4010c2c66affSColin Finck     DeleteFileA(msifile);
4011c2c66affSColin Finck     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4012c2c66affSColin Finck }
4013c2c66affSColin Finck 
4014c2c66affSColin Finck static void test_appsearch_complocator(void)
4015c2c66affSColin Finck {
4016c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4017c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4018c2c66affSColin Finck     LPSTR usersid;
4019c2c66affSColin Finck     DWORD size;
4020c2c66affSColin Finck     UINT r;
4021c2c66affSColin Finck 
4022c2c66affSColin Finck     if (!(usersid = get_user_sid()))
4023c2c66affSColin Finck         return;
4024c2c66affSColin Finck 
4025c2c66affSColin Finck     if (is_process_limited())
4026c2c66affSColin Finck     {
4027c2c66affSColin Finck         skip("process is limited\n");
4028c2c66affSColin Finck         return;
4029c2c66affSColin Finck     }
4030c2c66affSColin Finck 
4031c2c66affSColin Finck     create_test_file("FileName1");
4032c2c66affSColin Finck     create_test_file("FileName4");
4033c2c66affSColin Finck     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
4034c2c66affSColin Finck                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
4035c2c66affSColin Finck 
4036c2c66affSColin Finck     create_test_file("FileName2");
4037c2c66affSColin Finck     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4038c2c66affSColin Finck                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4039c2c66affSColin Finck 
4040c2c66affSColin Finck     create_test_file("FileName3");
4041c2c66affSColin Finck     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4042c2c66affSColin Finck                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4043c2c66affSColin Finck 
4044c2c66affSColin Finck     create_test_file("FileName5");
4045c2c66affSColin Finck     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4046c2c66affSColin Finck                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4047c2c66affSColin Finck 
4048c2c66affSColin Finck     create_test_file("FileName6");
4049c2c66affSColin Finck     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4050c2c66affSColin Finck                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4051c2c66affSColin Finck 
4052c2c66affSColin Finck     create_test_file("FileName7");
4053c2c66affSColin Finck     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4054c2c66affSColin Finck                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4055c2c66affSColin Finck 
4056c2c66affSColin Finck     /* dir is FALSE, but we're pretending it's a directory */
4057c2c66affSColin Finck     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4058c2c66affSColin Finck                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4059c2c66affSColin Finck 
4060c2c66affSColin Finck     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4061c2c66affSColin Finck     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4062c2c66affSColin Finck                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4063c2c66affSColin Finck 
4064c2c66affSColin Finck     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4065c2c66affSColin Finck     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4066c2c66affSColin Finck                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4067c2c66affSColin Finck 
4068c2c66affSColin Finck     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4069c2c66affSColin Finck     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4070c2c66affSColin Finck                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4071c2c66affSColin Finck 
4072c2c66affSColin Finck     hdb = create_package_db();
4073c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4074c2c66affSColin Finck 
4075f860a780SAmine Khaldi     create_appsearch_table(hdb);
4076f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4077f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4078f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4079f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4080f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4081f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4082f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4083f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4084f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4085f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4086f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4087f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4088c2c66affSColin Finck 
4089f860a780SAmine Khaldi     create_complocator_table(hdb);
4090c2c66affSColin Finck 
4091c2c66affSColin Finck     /* published component, machine, file, signature, misdbLocatorTypeFile */
4092f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4093c2c66affSColin Finck 
4094c2c66affSColin Finck     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4095f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4096c2c66affSColin Finck 
4097c2c66affSColin Finck     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4098f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4099c2c66affSColin Finck 
4100c2c66affSColin Finck     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4101f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4102c2c66affSColin Finck 
4103c2c66affSColin Finck     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4104f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4105c2c66affSColin Finck 
4106c2c66affSColin Finck     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4107f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4108c2c66affSColin Finck 
4109c2c66affSColin Finck     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4110f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4111c2c66affSColin Finck 
4112c2c66affSColin Finck     /* unpublished component, no signature, misdbLocatorTypeDir */
4113f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4114c2c66affSColin Finck 
4115c2c66affSColin Finck     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4116f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4117c2c66affSColin Finck 
4118c2c66affSColin Finck     /* published component, signature w/ ver, misdbLocatorTypeFile */
4119f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4120c2c66affSColin Finck 
4121c2c66affSColin Finck     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4122f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4123c2c66affSColin Finck 
4124c2c66affSColin Finck     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4125f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4126c2c66affSColin Finck 
4127f860a780SAmine Khaldi     create_signature_table(hdb);
4128f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4129f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4130f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4131f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4132f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4133f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4134f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4135f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4136c2c66affSColin Finck 
4137c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4138c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4139c2c66affSColin Finck     {
4140c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4141c2c66affSColin Finck         goto error;
4142c2c66affSColin Finck     }
4143c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4144c2c66affSColin Finck 
4145c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4146c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4147c2c66affSColin Finck 
4148c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4149c2c66affSColin Finck 
4150c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4151c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4152c2c66affSColin Finck 
4153c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4154c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4155c2c66affSColin Finck 
4156c2c66affSColin Finck     size = MAX_PATH;
4157c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4158c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4159c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4160c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4161c2c66affSColin Finck 
4162c2c66affSColin Finck     size = MAX_PATH;
4163c2c66affSColin Finck     sprintf(path, "%s\\FileName2", expected);
4164c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4165c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4166c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4167c2c66affSColin Finck 
4168c2c66affSColin Finck     size = MAX_PATH;
4169c2c66affSColin Finck     sprintf(path, "%s\\FileName3", expected);
4170c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4171c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4172c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4173c2c66affSColin Finck 
4174c2c66affSColin Finck     size = MAX_PATH;
4175c2c66affSColin Finck     sprintf(path, "%s\\FileName4", expected);
4176c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4177c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4178c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4179c2c66affSColin Finck 
4180c2c66affSColin Finck     size = MAX_PATH;
4181c2c66affSColin Finck     sprintf(path, "%s\\FileName5", expected);
4182c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4183c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4184c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4185c2c66affSColin Finck 
4186c2c66affSColin Finck     size = MAX_PATH;
4187c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4188c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4189c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4190c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4191c2c66affSColin Finck 
4192c2c66affSColin Finck     size = MAX_PATH;
4193c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4194c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4195c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4196c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4197c2c66affSColin Finck 
4198c2c66affSColin Finck     size = MAX_PATH;
4199c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4200c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4201c2c66affSColin Finck     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4202c2c66affSColin Finck 
4203c2c66affSColin Finck     size = MAX_PATH;
4204c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4205c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4206c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4207c2c66affSColin Finck 
4208c2c66affSColin Finck     size = MAX_PATH;
4209c2c66affSColin Finck     sprintf(path, "%s\\FileName8.dll", expected);
4210c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4211c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4212c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4213c2c66affSColin Finck 
4214c2c66affSColin Finck     size = MAX_PATH;
4215c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4216c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4217c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4218c2c66affSColin Finck 
4219c2c66affSColin Finck     size = MAX_PATH;
4220c2c66affSColin Finck     sprintf(path, "%s\\FileName10.dll", expected);
4221c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4222c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4223c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4224c2c66affSColin Finck 
4225c2c66affSColin Finck     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4226c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4227c2c66affSColin Finck     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4228c2c66affSColin Finck                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4229c2c66affSColin Finck     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4230c2c66affSColin Finck                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4231c2c66affSColin Finck     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4232c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4233c2c66affSColin Finck     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4234c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4235c2c66affSColin Finck     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4236c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4237c2c66affSColin Finck     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4238c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4239c2c66affSColin Finck     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4240c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4241c2c66affSColin Finck     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4242c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4243c2c66affSColin Finck     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4244c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4245c2c66affSColin Finck 
4246c2c66affSColin Finck     MsiCloseHandle(hpkg);
4247c2c66affSColin Finck 
4248c2c66affSColin Finck error:
4249c2c66affSColin Finck     DeleteFileA("FileName1");
4250c2c66affSColin Finck     DeleteFileA("FileName2");
4251c2c66affSColin Finck     DeleteFileA("FileName3");
4252c2c66affSColin Finck     DeleteFileA("FileName4");
4253c2c66affSColin Finck     DeleteFileA("FileName5");
4254c2c66affSColin Finck     DeleteFileA("FileName6");
4255c2c66affSColin Finck     DeleteFileA("FileName7");
4256c2c66affSColin Finck     DeleteFileA("FileName8.dll");
4257c2c66affSColin Finck     DeleteFileA("FileName9.dll");
4258c2c66affSColin Finck     DeleteFileA("FileName10.dll");
4259c2c66affSColin Finck     DeleteFileA(msifile);
4260c2c66affSColin Finck     LocalFree(usersid);
4261c2c66affSColin Finck }
4262c2c66affSColin Finck 
4263c2c66affSColin Finck static void test_appsearch_reglocator(void)
4264c2c66affSColin Finck {
4265c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4266c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4267c2c66affSColin Finck     DWORD binary[2], size, val;
4268c2c66affSColin Finck     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4269c2c66affSColin Finck     HKEY hklm, classes, hkcu, users;
4270c2c66affSColin Finck     LPSTR pathdata, pathvar, ptr;
4271c2c66affSColin Finck     LONG res;
4272c2c66affSColin Finck     UINT r, type = 0;
4273c2c66affSColin Finck     SYSTEM_INFO si;
4274c2c66affSColin Finck 
4275c2c66affSColin Finck     version = TRUE;
4276c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4277c2c66affSColin Finck         version = FALSE;
4278c2c66affSColin Finck 
4279c2c66affSColin Finck     DeleteFileA("test.dll");
4280c2c66affSColin Finck 
4281c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4282c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
4283c2c66affSColin Finck     {
4284c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4285c2c66affSColin Finck         return;
4286c2c66affSColin Finck     }
4287c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4288c2c66affSColin Finck 
4289c2c66affSColin Finck     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4290c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4291c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4292c2c66affSColin Finck 
4293c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4294c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4295c2c66affSColin Finck 
4296c2c66affSColin Finck     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4297c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4298c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4299c2c66affSColin Finck 
4300c2c66affSColin Finck     users = 0;
4301c2c66affSColin Finck     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4302c2c66affSColin Finck     ok(res == ERROR_SUCCESS ||
4303c2c66affSColin Finck        broken(res == ERROR_INVALID_PARAMETER),
4304c2c66affSColin Finck        "Expected ERROR_SUCCESS, got %d\n", res);
4305c2c66affSColin Finck 
4306c2c66affSColin Finck     if (res == ERROR_SUCCESS)
4307c2c66affSColin Finck     {
4308c2c66affSColin Finck         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4309c2c66affSColin Finck                              (const BYTE *)"regszdata", 10);
4310c2c66affSColin Finck         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4311c2c66affSColin Finck     }
4312c2c66affSColin Finck 
4313c2c66affSColin Finck     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4314c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4315c2c66affSColin Finck 
4316c2c66affSColin Finck     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4317c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4318c2c66affSColin Finck 
4319c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4320c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4321c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4322c2c66affSColin Finck 
4323c2c66affSColin Finck     val = 42;
4324c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4325c2c66affSColin Finck                          (const BYTE *)&val, sizeof(DWORD));
4326c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4327c2c66affSColin Finck 
4328c2c66affSColin Finck     val = -42;
4329c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4330c2c66affSColin Finck                          (const BYTE *)&val, sizeof(DWORD));
4331c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4332c2c66affSColin Finck 
4333c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4334c2c66affSColin Finck                          (const BYTE *)"%PATH%", 7);
4335c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4336c2c66affSColin Finck 
4337c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4338c2c66affSColin Finck                          (const BYTE *)"my%NOVAR%", 10);
4339c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4340c2c66affSColin Finck 
4341c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4342c2c66affSColin Finck                          (const BYTE *)"one\0two\0", 9);
4343c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4344c2c66affSColin Finck 
4345c2c66affSColin Finck     binary[0] = 0x1234abcd;
4346c2c66affSColin Finck     binary[1] = 0x567890ef;
4347c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4348c2c66affSColin Finck                          (const BYTE *)binary, sizeof(binary));
4349c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4350c2c66affSColin Finck 
4351c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4352c2c66affSColin Finck                          (const BYTE *)"#regszdata", 11);
4353c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4354c2c66affSColin Finck 
4355c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4356c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4357c2c66affSColin Finck 
4358c2c66affSColin Finck     create_test_file("FileName1");
4359c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4360c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4361c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4362c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4363c2c66affSColin Finck 
4364c2c66affSColin Finck     sprintf(path, "%s\\FileName2", expected);
4365c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4366c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4367c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4368c2c66affSColin Finck 
4369c2c66affSColin Finck     lstrcpyA(path, expected);
4370c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4371c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4372c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4373c2c66affSColin Finck 
4374c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4375c2c66affSColin Finck                          (const BYTE *)"", 1);
4376c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4377c2c66affSColin Finck 
4378c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4379c2c66affSColin Finck     sprintf(path, "%s\\FileName3.dll", expected);
4380c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4381c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4382c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4383c2c66affSColin Finck 
4384c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4385c2c66affSColin Finck     sprintf(path, "%s\\FileName4.dll", expected);
4386c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4387c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4388c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4389c2c66affSColin Finck 
4390c2c66affSColin Finck     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4391c2c66affSColin Finck     sprintf(path, "%s\\FileName5.dll", expected);
4392c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4393c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4394c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4395c2c66affSColin Finck 
4396c2c66affSColin Finck     sprintf(path, "\"%s\\FileName1\" -option", expected);
4397c2c66affSColin Finck     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4398c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4399c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4400c2c66affSColin Finck 
4401c2c66affSColin Finck     space = strchr(expected, ' ') != NULL;
4402c2c66affSColin Finck     sprintf(path, "%s\\FileName1 -option", expected);
4403c2c66affSColin Finck     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4404c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4405c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4406c2c66affSColin Finck 
4407c2c66affSColin Finck     hdb = create_package_db();
4408c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4409c2c66affSColin Finck 
4410f860a780SAmine Khaldi     create_appsearch_table(hdb);
4411f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4412f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4413f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4414f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4415f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4416f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4417f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4418f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4419f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4420f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4421f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4422f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4423f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4424f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4425f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4426f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4427f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4428f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4429f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4430f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4431f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4432f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4433f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4434f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4435f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4436f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4437f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4438f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4439f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4440f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4441c2c66affSColin Finck 
4442f860a780SAmine Khaldi     create_reglocator_table(hdb);
4443c2c66affSColin Finck 
4444c2c66affSColin Finck     type = msidbLocatorTypeRawValue;
4445c2c66affSColin Finck     if (is_64bit)
4446c2c66affSColin Finck         type |= msidbLocatorType64bit;
4447c2c66affSColin Finck 
4448c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4449f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4450c2c66affSColin Finck 
4451c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4452f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4453c2c66affSColin Finck 
4454c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4455f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4456c2c66affSColin Finck 
4457c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4458f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4459c2c66affSColin Finck 
4460c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4461f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4462c2c66affSColin Finck 
4463c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4464f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4465c2c66affSColin Finck 
4466c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4467f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4468c2c66affSColin Finck 
4469c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4470f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4471c2c66affSColin Finck 
4472c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4473c2c66affSColin Finck     if (is_64bit)
4474c2c66affSColin Finck         type |= msidbLocatorType64bit;
4475c2c66affSColin Finck 
4476c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4477f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4478c2c66affSColin Finck 
4479c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4480f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4481c2c66affSColin Finck 
4482c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature */
4483f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4484c2c66affSColin Finck 
4485c2c66affSColin Finck     type = msidbLocatorTypeDirectory;
4486c2c66affSColin Finck     if (is_64bit)
4487c2c66affSColin Finck         type |= msidbLocatorType64bit;
4488c2c66affSColin Finck 
4489c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4490f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4491c2c66affSColin Finck 
4492c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4493f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4494c2c66affSColin Finck 
4495c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4496f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4497c2c66affSColin Finck 
4498c2c66affSColin Finck     type = msidbLocatorTypeRawValue;
4499c2c66affSColin Finck     if (is_64bit)
4500c2c66affSColin Finck         type |= msidbLocatorType64bit;
4501c2c66affSColin Finck 
4502c2c66affSColin Finck     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4503f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4504c2c66affSColin Finck 
4505c2c66affSColin Finck     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4506f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4507c2c66affSColin Finck 
4508c2c66affSColin Finck     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4509f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4510c2c66affSColin Finck 
4511c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4512f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4513c2c66affSColin Finck 
4514c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4515f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4516c2c66affSColin Finck 
4517c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4518f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4519c2c66affSColin Finck 
4520c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4521c2c66affSColin Finck     if (is_64bit)
4522c2c66affSColin Finck         type |= msidbLocatorType64bit;
4523c2c66affSColin Finck 
4524c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4525f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4526c2c66affSColin Finck 
4527c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4528f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4529c2c66affSColin Finck 
4530c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4531f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4532c2c66affSColin Finck 
4533c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4534f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4535c2c66affSColin Finck 
4536c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4537f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4538c2c66affSColin Finck 
4539c2c66affSColin Finck     type = msidbLocatorTypeDirectory;
4540c2c66affSColin Finck     if (is_64bit)
4541c2c66affSColin Finck         type |= msidbLocatorType64bit;
4542c2c66affSColin Finck 
4543c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4544f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4545c2c66affSColin Finck 
4546c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4547f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4548c2c66affSColin Finck 
4549c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4550f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4551c2c66affSColin Finck 
4552c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4553c2c66affSColin Finck     if (is_64bit)
4554c2c66affSColin Finck         type |= msidbLocatorType64bit;
4555c2c66affSColin Finck 
4556c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4557f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4558c2c66affSColin Finck 
4559c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4560f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4561c2c66affSColin Finck 
4562f860a780SAmine Khaldi     create_signature_table(hdb);
4563f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4564f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4565f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4566f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4567f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4568f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4569c2c66affSColin Finck 
4570c2c66affSColin Finck     if (!is_root(CURR_DIR))
4571c2c66affSColin Finck     {
4572c2c66affSColin Finck         ptr = strrchr(expected, '\\') + 1;
4573c2c66affSColin Finck         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4574f860a780SAmine Khaldi         add_signature_entry(hdb, path);
4575c2c66affSColin Finck     }
4576f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4577f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4578f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4579c2c66affSColin Finck 
4580c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4581c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4582c2c66affSColin Finck 
4583c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4584c2c66affSColin Finck 
4585c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4586c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4587c2c66affSColin Finck 
4588c2c66affSColin Finck     size = MAX_PATH;
4589c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4590c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4591c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4592c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4593c2c66affSColin Finck 
4594c2c66affSColin Finck     size = MAX_PATH;
4595c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4596c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4597c2c66affSColin Finck     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4598c2c66affSColin Finck 
4599c2c66affSColin Finck     size = MAX_PATH;
4600c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4601c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4602c2c66affSColin Finck     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4603c2c66affSColin Finck 
4604c2c66affSColin Finck     memset(&si, 0, sizeof(si));
4605c2c66affSColin Finck     if (pGetNativeSystemInfo) pGetNativeSystemInfo(&si);
4606c2c66affSColin Finck 
4607c2c66affSColin Finck     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4608c2c66affSColin Finck     {
4609c2c66affSColin Finck         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4610c2c66affSColin Finck         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4611c2c66affSColin Finck         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4612c2c66affSColin Finck 
4613c2c66affSColin Finck         size = 0;
4614c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4615c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4616c2c66affSColin Finck 
4617c2c66affSColin Finck         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4618c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4619c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4620c2c66affSColin Finck         ok(!lstrcmpA(pathdata, pathvar),
4621c2c66affSColin Finck             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4622c2c66affSColin Finck 
4623c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pathvar);
4624c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pathdata);
4625c2c66affSColin Finck     }
4626c2c66affSColin Finck 
4627c2c66affSColin Finck     size = MAX_PATH;
4628c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4629c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4630c2c66affSColin Finck     ok(!lstrcmpA(prop,
4631c2c66affSColin Finck        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4632c2c66affSColin Finck 
4633c2c66affSColin Finck     size = MAX_PATH;
4634c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4635c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4636c2c66affSColin Finck     todo_wine
4637c2c66affSColin Finck     {
4638c2c66affSColin Finck         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4639c2c66affSColin Finck            "Expected \"\\0one\\0two\\0\\0\"\n");
4640c2c66affSColin Finck     }
4641c2c66affSColin Finck 
4642c2c66affSColin Finck     size = MAX_PATH;
4643c2c66affSColin Finck     lstrcpyA(path, "#xCDAB3412EF907856");
4644c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4645c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4646c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4647c2c66affSColin Finck 
4648c2c66affSColin Finck     size = MAX_PATH;
4649c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4650c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4651c2c66affSColin Finck     ok(!lstrcmpA(prop, "##regszdata"),
4652c2c66affSColin Finck        "Expected \"##regszdata\", got \"%s\"\n", prop);
4653c2c66affSColin Finck 
4654c2c66affSColin Finck     size = MAX_PATH;
4655c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4656c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4657c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4658c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4659c2c66affSColin Finck 
4660c2c66affSColin Finck     size = MAX_PATH;
4661c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4662c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4663c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4664c2c66affSColin Finck 
4665c2c66affSColin Finck     size = MAX_PATH;
4666c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4667c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4668c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4669c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4670c2c66affSColin Finck 
4671c2c66affSColin Finck     size = MAX_PATH;
4672c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4673c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4674c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4675c2c66affSColin Finck 
4676c2c66affSColin Finck     size = MAX_PATH;
4677c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4678c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4679c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4680c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4681c2c66affSColin Finck 
4682c2c66affSColin Finck     size = MAX_PATH;
4683c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4684c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4685c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4686c2c66affSColin Finck 
4687c2c66affSColin Finck     size = MAX_PATH;
4688c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4689c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4690c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4691c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4692c2c66affSColin Finck 
4693c2c66affSColin Finck     size = MAX_PATH;
4694c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4695c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4696c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4697c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4698c2c66affSColin Finck 
4699c2c66affSColin Finck     if (users)
4700c2c66affSColin Finck     {
4701c2c66affSColin Finck         size = MAX_PATH;
4702c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4703c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4704c2c66affSColin Finck         ok(!lstrcmpA(prop, "regszdata"),
4705c2c66affSColin Finck            "Expected \"regszdata\", got \"%s\"\n", prop);
4706c2c66affSColin Finck     }
4707c2c66affSColin Finck 
4708c2c66affSColin Finck     size = MAX_PATH;
4709c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4710c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4711c2c66affSColin Finck     ok(!lstrcmpA(prop, "defvalue"),
4712c2c66affSColin Finck        "Expected \"defvalue\", got \"%s\"\n", prop);
4713c2c66affSColin Finck 
4714c2c66affSColin Finck     size = MAX_PATH;
4715c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4716c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4717c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4718c2c66affSColin Finck 
4719c2c66affSColin Finck     size = MAX_PATH;
4720c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4721c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4722c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4723c2c66affSColin Finck 
4724c2c66affSColin Finck     if (version)
4725c2c66affSColin Finck     {
4726c2c66affSColin Finck         size = MAX_PATH;
4727c2c66affSColin Finck         sprintf(path, "%s\\FileName3.dll", expected);
4728c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4729c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4730c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4731c2c66affSColin Finck 
4732c2c66affSColin Finck         size = MAX_PATH;
4733c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4734c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4735c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4736c2c66affSColin Finck 
4737c2c66affSColin Finck         size = MAX_PATH;
4738c2c66affSColin Finck         sprintf(path, "%s\\FileName5.dll", expected);
4739c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4740c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4741c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4742c2c66affSColin Finck     }
4743c2c66affSColin Finck 
4744c2c66affSColin Finck     if (!is_root(CURR_DIR))
4745c2c66affSColin Finck     {
4746c2c66affSColin Finck         size = MAX_PATH;
4747c2c66affSColin Finck         lstrcpyA(path, expected);
4748c2c66affSColin Finck         ptr = strrchr(path, '\\') + 1;
4749c2c66affSColin Finck         *ptr = '\0';
4750c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4751c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4752c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4753c2c66affSColin Finck     }
4754c2c66affSColin Finck     size = MAX_PATH;
4755c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4756c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4757c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4758c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4759c2c66affSColin Finck 
4760c2c66affSColin Finck     size = MAX_PATH;
4761c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4762c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4763c2c66affSColin Finck     if (is_root(CURR_DIR))
4764c2c66affSColin Finck         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4765c2c66affSColin Finck     else
4766c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4767c2c66affSColin Finck 
4768c2c66affSColin Finck     size = MAX_PATH;
4769c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4770c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4771c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4772c2c66affSColin Finck 
4773c2c66affSColin Finck     size = MAX_PATH;
4774c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4775c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4776c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4777c2c66affSColin Finck 
4778c2c66affSColin Finck     size = MAX_PATH;
4779c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4780c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4781c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4782c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4783c2c66affSColin Finck 
4784c2c66affSColin Finck     size = MAX_PATH;
4785c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4786c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4787c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4788c2c66affSColin Finck     if (space)
4789c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4790c2c66affSColin Finck     else
4791c2c66affSColin Finck         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4792c2c66affSColin Finck 
4793c2c66affSColin Finck     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4794c2c66affSColin Finck     RegDeleteValueA(hklm, "Value1");
4795c2c66affSColin Finck     RegDeleteValueA(hklm, "Value2");
4796c2c66affSColin Finck     RegDeleteValueA(hklm, "Value3");
4797c2c66affSColin Finck     RegDeleteValueA(hklm, "Value4");
4798c2c66affSColin Finck     RegDeleteValueA(hklm, "Value5");
4799c2c66affSColin Finck     RegDeleteValueA(hklm, "Value6");
4800c2c66affSColin Finck     RegDeleteValueA(hklm, "Value7");
4801c2c66affSColin Finck     RegDeleteValueA(hklm, "Value8");
4802c2c66affSColin Finck     RegDeleteValueA(hklm, "Value9");
4803c2c66affSColin Finck     RegDeleteValueA(hklm, "Value10");
4804c2c66affSColin Finck     RegDeleteValueA(hklm, "Value11");
4805c2c66affSColin Finck     RegDeleteValueA(hklm, "Value12");
4806c2c66affSColin Finck     RegDeleteValueA(hklm, "Value13");
4807c2c66affSColin Finck     RegDeleteValueA(hklm, "Value14");
4808c2c66affSColin Finck     RegDeleteValueA(hklm, "Value15");
4809c2c66affSColin Finck     RegDeleteValueA(hklm, "Value16");
4810c2c66affSColin Finck     RegDeleteValueA(hklm, "Value17");
4811c2c66affSColin Finck     RegDeleteKeyA(hklm, "");
4812c2c66affSColin Finck     RegCloseKey(hklm);
4813c2c66affSColin Finck 
4814c2c66affSColin Finck     RegDeleteValueA(classes, "Value1");
4815c2c66affSColin Finck     RegDeleteKeyA(classes, "");
4816c2c66affSColin Finck     RegCloseKey(classes);
4817c2c66affSColin Finck 
4818c2c66affSColin Finck     RegDeleteValueA(hkcu, "Value1");
4819c2c66affSColin Finck     RegDeleteKeyA(hkcu, "");
4820c2c66affSColin Finck     RegCloseKey(hkcu);
4821c2c66affSColin Finck 
4822c2c66affSColin Finck     RegDeleteValueA(users, "Value1");
4823c2c66affSColin Finck     RegDeleteKeyA(users, "");
4824c2c66affSColin Finck     RegCloseKey(users);
4825c2c66affSColin Finck 
4826c2c66affSColin Finck     DeleteFileA("FileName1");
4827c2c66affSColin Finck     DeleteFileA("FileName3.dll");
4828c2c66affSColin Finck     DeleteFileA("FileName4.dll");
4829c2c66affSColin Finck     DeleteFileA("FileName5.dll");
4830c2c66affSColin Finck     MsiCloseHandle(hpkg);
4831c2c66affSColin Finck     DeleteFileA(msifile);
4832c2c66affSColin Finck }
4833c2c66affSColin Finck 
4834c2c66affSColin Finck static void delete_win_ini(LPCSTR file)
4835c2c66affSColin Finck {
4836c2c66affSColin Finck     CHAR path[MAX_PATH];
4837c2c66affSColin Finck 
4838c2c66affSColin Finck     GetWindowsDirectoryA(path, MAX_PATH);
4839c2c66affSColin Finck     lstrcatA(path, "\\");
4840c2c66affSColin Finck     lstrcatA(path, file);
4841c2c66affSColin Finck 
4842c2c66affSColin Finck     DeleteFileA(path);
4843c2c66affSColin Finck }
4844c2c66affSColin Finck 
4845c2c66affSColin Finck static void test_appsearch_inilocator(void)
4846c2c66affSColin Finck {
4847c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4848c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4849c2c66affSColin Finck     BOOL version;
4850c2c66affSColin Finck     LPSTR ptr;
4851c2c66affSColin Finck     DWORD size;
4852c2c66affSColin Finck     UINT r;
4853c2c66affSColin Finck 
4854c2c66affSColin Finck     version = TRUE;
4855c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4856c2c66affSColin Finck         version = FALSE;
4857c2c66affSColin Finck 
4858c2c66affSColin Finck     DeleteFileA("test.dll");
4859c2c66affSColin Finck 
4860c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4861c2c66affSColin Finck 
4862c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4863c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4864c2c66affSColin Finck 
4865c2c66affSColin Finck     create_test_file("FileName1");
4866c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4867c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4868c2c66affSColin Finck 
4869c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4870c2c66affSColin Finck 
4871c2c66affSColin Finck     sprintf(path, "%s\\IDontExist", expected);
4872c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4873c2c66affSColin Finck 
4874c2c66affSColin Finck     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4875c2c66affSColin Finck     sprintf(path, "%s\\FileName2.dll", expected);
4876c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4877c2c66affSColin Finck 
4878c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4879c2c66affSColin Finck     sprintf(path, "%s\\FileName3.dll", expected);
4880c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4881c2c66affSColin Finck 
4882c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4883c2c66affSColin Finck     sprintf(path, "%s\\FileName4.dll", expected);
4884c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4885c2c66affSColin Finck 
4886c2c66affSColin Finck     hdb = create_package_db();
4887c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4888c2c66affSColin Finck 
4889f860a780SAmine Khaldi     create_appsearch_table(hdb);
4890f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4891f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4892f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4893f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4894f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4895f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4896f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4897f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4898f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4899f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4900f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4901f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4902c2c66affSColin Finck 
4903f860a780SAmine Khaldi     create_inilocator_table(hdb);
4904c2c66affSColin Finck 
4905c2c66affSColin Finck     /* msidbLocatorTypeRawValue, field 1 */
4906f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
4907c2c66affSColin Finck 
4908c2c66affSColin Finck     /* msidbLocatorTypeRawValue, field 2 */
4909f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
4910c2c66affSColin Finck 
4911c2c66affSColin Finck     /* msidbLocatorTypeRawValue, entire field */
4912f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
4913c2c66affSColin Finck 
4914c2c66affSColin Finck     /* msidbLocatorTypeFile */
4915f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4916c2c66affSColin Finck 
4917c2c66affSColin Finck     /* msidbLocatorTypeDirectory, file */
4918f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
4919c2c66affSColin Finck 
4920c2c66affSColin Finck     /* msidbLocatorTypeDirectory, directory */
4921f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
4922c2c66affSColin Finck 
4923c2c66affSColin Finck     /* msidbLocatorTypeFile, file, no signature */
4924f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
4925c2c66affSColin Finck 
4926c2c66affSColin Finck     /* msidbLocatorTypeFile, dir, no signature */
4927f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
4928c2c66affSColin Finck 
4929c2c66affSColin Finck     /* msidbLocatorTypeFile, file does not exist */
4930f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
4931c2c66affSColin Finck 
4932c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version */
4933f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
4934c2c66affSColin Finck 
4935c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version, ver > max */
4936f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
4937c2c66affSColin Finck 
4938c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
4939f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
4940c2c66affSColin Finck 
4941f860a780SAmine Khaldi     create_signature_table(hdb);
4942f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
4943f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
4944f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4945f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4946f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4947c2c66affSColin Finck 
4948c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4949c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4950c2c66affSColin Finck     {
4951c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4952c2c66affSColin Finck         goto error;
4953c2c66affSColin Finck     }
4954c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4955c2c66affSColin Finck 
4956c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4957c2c66affSColin Finck 
4958c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4959c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4960c2c66affSColin Finck 
4961c2c66affSColin Finck     size = MAX_PATH;
4962c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4963c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4964c2c66affSColin Finck     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
4965c2c66affSColin Finck 
4966c2c66affSColin Finck     size = MAX_PATH;
4967c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4968c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4969c2c66affSColin Finck     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
4970c2c66affSColin Finck 
4971c2c66affSColin Finck     size = MAX_PATH;
4972c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4973c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4974c2c66affSColin Finck     ok(!lstrcmpA(prop, "keydata,field2"),
4975c2c66affSColin Finck        "Expected \"keydata,field2\", got \"%s\"\n", prop);
4976c2c66affSColin Finck 
4977c2c66affSColin Finck     size = MAX_PATH;
4978c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4979c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4980c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4981c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4982c2c66affSColin Finck 
4983c2c66affSColin Finck     size = MAX_PATH;
4984c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4985c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4986c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4987c2c66affSColin Finck 
4988c2c66affSColin Finck     size = MAX_PATH;
4989c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4990c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4991c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4992c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4993c2c66affSColin Finck 
4994c2c66affSColin Finck     size = MAX_PATH;
4995c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4996c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4997c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4998c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4999c2c66affSColin Finck 
5000c2c66affSColin Finck     if (!is_root(CURR_DIR))
5001c2c66affSColin Finck     {
5002c2c66affSColin Finck         size = MAX_PATH;
5003c2c66affSColin Finck         lstrcpyA(path, expected);
5004c2c66affSColin Finck         ptr = strrchr(path, '\\');
5005c2c66affSColin Finck         *(ptr + 1) = 0;
5006c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5007c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5008c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5009c2c66affSColin Finck     }
5010c2c66affSColin Finck     size = MAX_PATH;
5011c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5012c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5013c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5014c2c66affSColin Finck 
5015c2c66affSColin Finck     if (version)
5016c2c66affSColin Finck     {
5017c2c66affSColin Finck         size = MAX_PATH;
5018c2c66affSColin Finck         sprintf(path, "%s\\FileName2.dll", expected);
5019c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5020c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5021c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5022c2c66affSColin Finck 
5023c2c66affSColin Finck         size = MAX_PATH;
5024c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5025c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5026c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5027c2c66affSColin Finck 
5028c2c66affSColin Finck         size = MAX_PATH;
5029c2c66affSColin Finck         sprintf(path, "%s\\FileName4.dll", expected);
5030c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5031c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5032c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5033c2c66affSColin Finck     }
5034c2c66affSColin Finck 
5035c2c66affSColin Finck     MsiCloseHandle(hpkg);
5036c2c66affSColin Finck 
5037c2c66affSColin Finck error:
5038c2c66affSColin Finck     delete_win_ini("IniFile.ini");
5039c2c66affSColin Finck     DeleteFileA("FileName1");
5040c2c66affSColin Finck     DeleteFileA("FileName2.dll");
5041c2c66affSColin Finck     DeleteFileA("FileName3.dll");
5042c2c66affSColin Finck     DeleteFileA("FileName4.dll");
5043c2c66affSColin Finck     DeleteFileA(msifile);
5044c2c66affSColin Finck }
5045c2c66affSColin Finck 
5046c2c66affSColin Finck /*
5047c2c66affSColin Finck  * MSI AppSearch action on DrLocator table always returns absolute paths.
5048c2c66affSColin Finck  * If a relative path was set, it returns the first absolute path that
5049c2c66affSColin Finck  * matches or an empty string if it didn't find anything.
5050c2c66affSColin Finck  * This helper function replicates this behaviour.
5051c2c66affSColin Finck  */
5052c2c66affSColin Finck static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5053c2c66affSColin Finck {
5054c2c66affSColin Finck     int i, size;
5055c2c66affSColin Finck     DWORD attr, drives;
5056c2c66affSColin Finck 
5057c2c66affSColin Finck     size = lstrlenA(relative);
5058c2c66affSColin Finck     drives = GetLogicalDrives();
5059c2c66affSColin Finck     lstrcpyA(absolute, "A:\\");
5060c2c66affSColin Finck     for (i = 0; i < 26; absolute[0] = '\0', i++)
5061c2c66affSColin Finck     {
5062c2c66affSColin Finck         if (!(drives & (1 << i)))
5063c2c66affSColin Finck             continue;
5064c2c66affSColin Finck 
5065c2c66affSColin Finck         absolute[0] = 'A' + i;
5066c2c66affSColin Finck         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5067c2c66affSColin Finck             continue;
5068c2c66affSColin Finck 
5069c2c66affSColin Finck         lstrcpynA(absolute + 3, relative, size + 1);
5070c2c66affSColin Finck         attr = GetFileAttributesA(absolute);
5071c2c66affSColin Finck         if (attr != INVALID_FILE_ATTRIBUTES &&
5072c2c66affSColin Finck             (attr & FILE_ATTRIBUTE_DIRECTORY))
5073c2c66affSColin Finck         {
5074c2c66affSColin Finck             if (absolute[3 + size - 1] != '\\')
5075c2c66affSColin Finck                 lstrcatA(absolute, "\\");
5076c2c66affSColin Finck             break;
5077c2c66affSColin Finck         }
5078c2c66affSColin Finck         absolute[3] = '\0';
5079c2c66affSColin Finck     }
5080c2c66affSColin Finck }
5081c2c66affSColin Finck 
5082c2c66affSColin Finck static void test_appsearch_drlocator(void)
5083c2c66affSColin Finck {
5084c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
5085c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5086c2c66affSColin Finck     BOOL version;
5087c2c66affSColin Finck     DWORD size;
5088c2c66affSColin Finck     UINT r;
5089c2c66affSColin Finck 
5090c2c66affSColin Finck     version = TRUE;
5091c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5092c2c66affSColin Finck         version = FALSE;
5093c2c66affSColin Finck 
5094c2c66affSColin Finck     DeleteFileA("test.dll");
5095c2c66affSColin Finck 
5096c2c66affSColin Finck     create_test_file("FileName1");
5097c2c66affSColin Finck     CreateDirectoryA("one", NULL);
5098c2c66affSColin Finck     CreateDirectoryA("one\\two", NULL);
5099c2c66affSColin Finck     CreateDirectoryA("one\\two\\three", NULL);
5100c2c66affSColin Finck     create_test_file("one\\two\\three\\FileName2");
5101c2c66affSColin Finck     CreateDirectoryA("another", NULL);
5102c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5103c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5104c2c66affSColin Finck     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5105c2c66affSColin Finck 
5106c2c66affSColin Finck     hdb = create_package_db();
5107c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
5108c2c66affSColin Finck 
5109f860a780SAmine Khaldi     create_appsearch_table(hdb);
5110f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5111f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5112f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5113f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5114f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5115f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5116f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5117f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5118f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5119f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5120f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5121f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5122c2c66affSColin Finck 
5123f860a780SAmine Khaldi     create_drlocator_table(hdb);
5124c2c66affSColin Finck 
5125c2c66affSColin Finck     strcpy(expected, CURR_DIR);
5126c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
5127c2c66affSColin Finck 
5128c2c66affSColin Finck     /* no parent, full path, depth 0, signature */
5129c2c66affSColin Finck     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5130f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5131c2c66affSColin Finck 
5132c2c66affSColin Finck     /* no parent, full path, depth 0, no signature */
5133c2c66affSColin Finck     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5134f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5135c2c66affSColin Finck 
5136c2c66affSColin Finck     /* no parent, relative path, depth 0, no signature */
5137c2c66affSColin Finck     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5138f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5139c2c66affSColin Finck 
5140c2c66affSColin Finck     /* no parent, full path, depth 2, signature */
5141c2c66affSColin Finck     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5142f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5143c2c66affSColin Finck 
5144c2c66affSColin Finck     /* no parent, full path, depth 3, signature */
5145c2c66affSColin Finck     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5146f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5147c2c66affSColin Finck 
5148c2c66affSColin Finck     /* no parent, full path, depth 1, signature is dir */
5149c2c66affSColin Finck     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5150f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5151c2c66affSColin Finck 
5152c2c66affSColin Finck     /* parent is in DrLocator, relative path, depth 0, signature */
5153c2c66affSColin Finck     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5154f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5155c2c66affSColin Finck 
5156c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version */
5157c2c66affSColin Finck     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5158f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5159c2c66affSColin Finck 
5160c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version, ver > max */
5161c2c66affSColin Finck     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5162f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5163c2c66affSColin Finck 
5164c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5165c2c66affSColin Finck     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5166f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5167c2c66affSColin Finck 
5168c2c66affSColin Finck     /* no parent, relative empty path, depth 0, no signature */
5169c2c66affSColin Finck     sprintf(path, "'NewSignature11', '', '', 0");
5170f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5171c2c66affSColin Finck 
5172f860a780SAmine Khaldi     create_reglocator_table(hdb);
5173c2c66affSColin Finck 
5174c2c66affSColin Finck     /* parent */
5175f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5176c2c66affSColin Finck 
5177c2c66affSColin Finck     /* parent is in RegLocator, no path, depth 0, no signature */
5178c2c66affSColin Finck     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5179f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5180c2c66affSColin Finck 
5181f860a780SAmine Khaldi     create_signature_table(hdb);
5182f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5183f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5184f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5185f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5186f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5187f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5188f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5189f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5190c2c66affSColin Finck 
5191c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5192c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5193c2c66affSColin Finck     {
5194c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5195c2c66affSColin Finck         goto error;
5196c2c66affSColin Finck     }
5197c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5198c2c66affSColin Finck 
5199c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5200c2c66affSColin Finck 
5201c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
5202c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5203c2c66affSColin Finck 
5204c2c66affSColin Finck     size = MAX_PATH;
5205c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
5206c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5207c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5208c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5209c2c66affSColin Finck 
5210c2c66affSColin Finck     size = MAX_PATH;
5211c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5212c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5213c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5214c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5215c2c66affSColin Finck 
5216c2c66affSColin Finck     size = MAX_PATH;
5217c2c66affSColin Finck     search_absolute_directory(path, expected + 3);
5218c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5219c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5220c2c66affSColin Finck     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5221c2c66affSColin Finck 
5222c2c66affSColin Finck     size = MAX_PATH;
5223c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5224c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5225c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5226c2c66affSColin Finck 
5227c2c66affSColin Finck     size = MAX_PATH;
5228c2c66affSColin Finck     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5229c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5230c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5231c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5232c2c66affSColin Finck 
5233c2c66affSColin Finck     size = MAX_PATH;
5234c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5235c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5236c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5237c2c66affSColin Finck 
5238c2c66affSColin Finck     size = MAX_PATH;
5239c2c66affSColin Finck     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5240c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5241c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5242c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5243c2c66affSColin Finck 
5244c2c66affSColin Finck     if (version)
5245c2c66affSColin Finck     {
5246c2c66affSColin Finck         size = MAX_PATH;
5247c2c66affSColin Finck         sprintf(path, "%s\\FileName3.dll", expected);
5248c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5249c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5250c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5251c2c66affSColin Finck 
5252c2c66affSColin Finck         size = MAX_PATH;
5253c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5254c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5255c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5256c2c66affSColin Finck 
5257c2c66affSColin Finck         size = MAX_PATH;
5258c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5259c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5260c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5261c2c66affSColin Finck     }
5262c2c66affSColin Finck 
5263c2c66affSColin Finck     size = MAX_PATH;
5264c2c66affSColin Finck     search_absolute_directory(path, "");
5265c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5266c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5267c2c66affSColin Finck     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5268c2c66affSColin Finck 
5269c2c66affSColin Finck     size = MAX_PATH;
5270c2c66affSColin Finck     strcpy(path, "c:\\");
5271c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5272c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5273c2c66affSColin Finck     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5274c2c66affSColin Finck 
5275c2c66affSColin Finck     MsiCloseHandle(hpkg);
5276c2c66affSColin Finck 
5277c2c66affSColin Finck error:
5278c2c66affSColin Finck     DeleteFileA("FileName1");
5279c2c66affSColin Finck     DeleteFileA("FileName3.dll");
5280c2c66affSColin Finck     DeleteFileA("FileName4.dll");
5281c2c66affSColin Finck     DeleteFileA("FileName5.dll");
5282c2c66affSColin Finck     DeleteFileA("one\\two\\three\\FileName2");
5283c2c66affSColin Finck     RemoveDirectoryA("one\\two\\three");
5284c2c66affSColin Finck     RemoveDirectoryA("one\\two");
5285c2c66affSColin Finck     RemoveDirectoryA("one");
5286c2c66affSColin Finck     RemoveDirectoryA("another");
5287c2c66affSColin Finck     DeleteFileA(msifile);
5288c2c66affSColin Finck }
5289c2c66affSColin Finck 
5290c2c66affSColin Finck static void test_featureparents(void)
5291c2c66affSColin Finck {
5292c2c66affSColin Finck     MSIHANDLE hpkg;
5293c2c66affSColin Finck     UINT r;
5294c2c66affSColin Finck     MSIHANDLE hdb;
5295c2c66affSColin Finck 
5296c2c66affSColin Finck     hdb = create_package_db();
5297c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
5298c2c66affSColin Finck 
5299f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5300c2c66affSColin Finck 
5301f860a780SAmine Khaldi     create_feature_table( hdb );
5302f860a780SAmine Khaldi     create_component_table( hdb );
5303f860a780SAmine Khaldi     create_feature_components_table( hdb );
5304f860a780SAmine Khaldi     create_file_table( hdb );
5305c2c66affSColin Finck 
5306c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
5307f860a780SAmine Khaldi     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5308c2c66affSColin Finck 
5309c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
5310f860a780SAmine Khaldi     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5311c2c66affSColin Finck 
5312c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
5313f860a780SAmine Khaldi     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5314c2c66affSColin Finck 
5315c2c66affSColin Finck     /* msidbFeatureAttributesUIDisallowAbsent */
5316f860a780SAmine Khaldi     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5317c2c66affSColin Finck 
5318c2c66affSColin Finck     /* disabled because of install level */
5319f860a780SAmine Khaldi     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5320c2c66affSColin Finck 
5321c2c66affSColin Finck     /* child feature of disabled feature */
5322f860a780SAmine Khaldi     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5323c2c66affSColin Finck 
5324c2c66affSColin Finck     /* component of disabled feature (install level) */
5325f860a780SAmine Khaldi     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5326c2c66affSColin Finck 
5327c2c66affSColin Finck     /* component of disabled child feature (install level) */
5328f860a780SAmine Khaldi     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5329c2c66affSColin Finck 
5330c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5331f860a780SAmine Khaldi     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5332c2c66affSColin Finck 
5333c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5334f860a780SAmine Khaldi     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5335c2c66affSColin Finck 
5336c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5337f860a780SAmine Khaldi     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5338c2c66affSColin Finck 
5339c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5340f860a780SAmine Khaldi     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5341c2c66affSColin Finck 
5342c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5343f860a780SAmine Khaldi     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5344c2c66affSColin Finck 
5345c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5346f860a780SAmine Khaldi     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5347c2c66affSColin Finck 
5348c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5349f860a780SAmine Khaldi     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5350c2c66affSColin Finck 
5351c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5352f860a780SAmine Khaldi     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5353c2c66affSColin Finck 
5354c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5355f860a780SAmine Khaldi     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5356c2c66affSColin Finck 
5357f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5358f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5359f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5360f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5361f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5362f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5363f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'leo'" );
5364f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5365f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'libra'" );
5366f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5367f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5368f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5369f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'canis'" );
5370f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5371f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5372f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5373f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5374c2c66affSColin Finck 
5375f860a780SAmine Khaldi     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5376f860a780SAmine Khaldi     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5377f860a780SAmine Khaldi     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5378f860a780SAmine Khaldi     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5379f860a780SAmine Khaldi     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5380f860a780SAmine Khaldi     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5381f860a780SAmine Khaldi     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5382f860a780SAmine Khaldi     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5383f860a780SAmine Khaldi     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5384f860a780SAmine Khaldi     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5385f860a780SAmine Khaldi     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5386c2c66affSColin Finck 
5387c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
5388c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5389c2c66affSColin Finck     {
5390c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5391c2c66affSColin Finck         DeleteFileA(msifile);
5392c2c66affSColin Finck         return;
5393c2c66affSColin Finck     }
5394c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5395c2c66affSColin Finck 
5396c2c66affSColin Finck     MsiCloseHandle( hdb );
5397c2c66affSColin Finck 
5398c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5399c2c66affSColin Finck 
5400c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
5401c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
5402c2c66affSColin Finck 
5403c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
5404c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
5405c2c66affSColin Finck 
5406c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
5407c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5408c2c66affSColin Finck 
5409c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5410c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5411c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5412c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5413c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5414c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5415c2c66affSColin Finck 
5416c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5417c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5418c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5419c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5420c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5421c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5422c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5423c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5424c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5425c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5426c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5427c2c66affSColin Finck 
5428c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5429c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5430c2c66affSColin Finck 
5431c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5432c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5433c2c66affSColin Finck 
5434c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5435c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5436c2c66affSColin Finck 
5437c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5438c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5439c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5440c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5441c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5442c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5443c2c66affSColin Finck 
5444c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5445c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5446c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5447c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5448c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5449c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5450c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5451c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5452c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5453c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5454c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5455c2c66affSColin Finck 
5456c2c66affSColin Finck     MsiCloseHandle(hpkg);
5457c2c66affSColin Finck     DeleteFileA(msifile);
5458c2c66affSColin Finck }
5459c2c66affSColin Finck 
5460c2c66affSColin Finck static void test_installprops(void)
5461c2c66affSColin Finck {
5462c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
5463c2c66affSColin Finck     CHAR path[MAX_PATH], buf[MAX_PATH];
5464c2c66affSColin Finck     DWORD size, type;
5465c2c66affSColin Finck     LANGID langid;
5466c2c66affSColin Finck     HKEY hkey1, hkey2;
5467c2c66affSColin Finck     int res;
5468c2c66affSColin Finck     UINT r;
5469c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
5470c2c66affSColin Finck     SYSTEM_INFO si;
5471c2c66affSColin Finck     INSTALLUILEVEL uilevel;
5472c2c66affSColin Finck 
5473c2c66affSColin Finck     if (is_wow64)
5474c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
5475c2c66affSColin Finck 
5476c2c66affSColin Finck     lstrcpyA(path, CURR_DIR);
5477c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5478c2c66affSColin Finck     lstrcatA(path, msifile);
5479c2c66affSColin Finck 
5480c2c66affSColin Finck     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5481c2c66affSColin Finck 
5482c2c66affSColin Finck     hdb = create_package_db();
5483c2c66affSColin Finck     ok( hdb, "failed to create database\n");
5484c2c66affSColin Finck 
5485c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5486c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5487c2c66affSColin Finck     {
5488c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5489c2c66affSColin Finck         MsiSetInternalUI(uilevel, NULL);
5490c2c66affSColin Finck         DeleteFileA(msifile);
5491c2c66affSColin Finck         return;
5492c2c66affSColin Finck     }
5493c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5494c2c66affSColin Finck 
5495c2c66affSColin Finck     MsiCloseHandle(hdb);
5496c2c66affSColin Finck 
5497c2c66affSColin Finck     buf[0] = 0;
5498c2c66affSColin Finck     size = MAX_PATH;
5499c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5500c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5501c2c66affSColin Finck     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5502c2c66affSColin Finck 
5503c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5504c2c66affSColin Finck 
5505c2c66affSColin Finck     buf[0] = 0;
5506c2c66affSColin Finck     size = MAX_PATH;
5507c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5508c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5509c2c66affSColin Finck     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5510c2c66affSColin Finck 
5511c2c66affSColin Finck     buf[0] = 0;
5512c2c66affSColin Finck     size = MAX_PATH;
5513c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5514c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5515c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5516c2c66affSColin Finck 
5517c2c66affSColin Finck     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5518c2c66affSColin Finck     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
5519c2c66affSColin Finck 
5520c2c66affSColin Finck     size = MAX_PATH;
5521c2c66affSColin Finck     type = REG_SZ;
5522c2c66affSColin Finck     *path = '\0';
5523c2c66affSColin Finck     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5524c2c66affSColin Finck     {
5525c2c66affSColin Finck         size = MAX_PATH;
5526c2c66affSColin Finck         type = REG_SZ;
5527c2c66affSColin Finck         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5528c2c66affSColin Finck     }
5529c2c66affSColin Finck 
5530c2c66affSColin Finck     buf[0] = 0;
5531c2c66affSColin Finck     size = MAX_PATH;
5532c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5533c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5534c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5535c2c66affSColin Finck 
5536c2c66affSColin Finck     size = MAX_PATH;
5537c2c66affSColin Finck     type = REG_SZ;
5538c2c66affSColin Finck     *path = '\0';
5539c2c66affSColin Finck     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5540c2c66affSColin Finck     {
5541c2c66affSColin Finck         size = MAX_PATH;
5542c2c66affSColin Finck         type = REG_SZ;
5543c2c66affSColin Finck         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5544c2c66affSColin Finck     }
5545c2c66affSColin Finck 
5546c2c66affSColin Finck     if (*path)
5547c2c66affSColin Finck     {
5548c2c66affSColin Finck         buf[0] = 0;
5549c2c66affSColin Finck         size = MAX_PATH;
5550c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5551c2c66affSColin Finck         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5552c2c66affSColin Finck         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5553c2c66affSColin Finck     }
5554c2c66affSColin Finck 
5555c2c66affSColin Finck     buf[0] = 0;
5556c2c66affSColin Finck     size = MAX_PATH;
5557c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5558c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5559c2c66affSColin Finck     trace("VersionDatabase = %s\n", buf);
5560c2c66affSColin Finck 
5561c2c66affSColin Finck     buf[0] = 0;
5562c2c66affSColin Finck     size = MAX_PATH;
5563c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5564c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5565c2c66affSColin Finck     trace("VersionMsi = %s\n", buf);
5566c2c66affSColin Finck 
5567c2c66affSColin Finck     buf[0] = 0;
5568c2c66affSColin Finck     size = MAX_PATH;
5569c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5570c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5571c2c66affSColin Finck     trace("Date = %s\n", buf);
5572c2c66affSColin Finck 
5573c2c66affSColin Finck     buf[0] = 0;
5574c2c66affSColin Finck     size = MAX_PATH;
5575c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5576c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5577c2c66affSColin Finck     trace("Time = %s\n", buf);
5578c2c66affSColin Finck 
5579c2c66affSColin Finck     buf[0] = 0;
5580c2c66affSColin Finck     size = MAX_PATH;
5581c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5582c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5583c2c66affSColin Finck     trace("PackageCode = %s\n", buf);
5584c2c66affSColin Finck 
5585c2c66affSColin Finck     buf[0] = 0;
5586c2c66affSColin Finck     size = MAX_PATH;
5587c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5588c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5589c2c66affSColin Finck     trace("ComputerName = %s\n", buf);
5590c2c66affSColin Finck 
5591c2c66affSColin Finck     langid = GetUserDefaultLangID();
5592c2c66affSColin Finck     sprintf(path, "%d", langid);
5593c2c66affSColin Finck 
5594c2c66affSColin Finck     buf[0] = 0;
5595c2c66affSColin Finck     size = MAX_PATH;
5596c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5597c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5598c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5599c2c66affSColin Finck 
5600c2c66affSColin Finck     res = GetSystemMetrics(SM_CXSCREEN);
5601c2c66affSColin Finck     buf[0] = 0;
5602c2c66affSColin Finck     size = MAX_PATH;
5603c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5604c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5605c2c66affSColin Finck     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5606c2c66affSColin Finck 
5607c2c66affSColin Finck     res = GetSystemMetrics(SM_CYSCREEN);
5608c2c66affSColin Finck     buf[0] = 0;
5609c2c66affSColin Finck     size = MAX_PATH;
5610c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5611c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5612c2c66affSColin Finck     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5613c2c66affSColin Finck 
561431139640SAmine Khaldi     buf[0] = 0;
561531139640SAmine Khaldi     size = MAX_PATH;
561631139640SAmine Khaldi     r = MsiGetPropertyA(hpkg, "MsiNetAssemblySupport", buf, &size);
561731139640SAmine Khaldi     if (r == ERROR_SUCCESS) trace( "MsiNetAssemblySupport \"%s\"\n", buf );
561831139640SAmine Khaldi 
5619c2c66affSColin Finck     if (pGetSystemInfo && pSHGetFolderPathA)
5620c2c66affSColin Finck     {
5621c2c66affSColin Finck         pGetSystemInfo(&si);
5622c2c66affSColin Finck         if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5623c2c66affSColin Finck         {
5624c2c66affSColin Finck             buf[0] = 0;
5625c2c66affSColin Finck             size = MAX_PATH;
5626c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5627c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5628c2c66affSColin Finck             ok(buf[0], "property not set\n");
5629c2c66affSColin Finck 
5630c2c66affSColin Finck             buf[0] = 0;
5631c2c66affSColin Finck             size = MAX_PATH;
5632c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5633c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5634c2c66affSColin Finck             ok(buf[0], "property not set\n");
5635c2c66affSColin Finck 
5636c2c66affSColin Finck             buf[0] = 0;
5637c2c66affSColin Finck             size = MAX_PATH;
5638c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5639c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5640c2c66affSColin Finck             ok(buf[0], "property not set\n");
5641c2c66affSColin Finck 
5642c2c66affSColin Finck             buf[0] = 0;
5643c2c66affSColin Finck             size = MAX_PATH;
5644c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5645c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5646c2c66affSColin Finck             GetSystemDirectoryA(path, MAX_PATH);
5647c2c66affSColin Finck             if (size) buf[size - 1] = 0;
5648c2c66affSColin Finck             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5649c2c66affSColin Finck 
5650c2c66affSColin Finck             buf[0] = 0;
5651c2c66affSColin Finck             size = MAX_PATH;
5652c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5653c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5654c2c66affSColin Finck             pGetSystemWow64DirectoryA(path, MAX_PATH);
5655c2c66affSColin Finck             if (size) buf[size - 1] = 0;
5656c2c66affSColin Finck             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5657c2c66affSColin Finck 
5658c2c66affSColin Finck             buf[0] = 0;
5659c2c66affSColin Finck             size = MAX_PATH;
5660c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5661c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5662c2c66affSColin Finck             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5663c2c66affSColin Finck             if (size) buf[size - 1] = 0;
5664c2c66affSColin Finck             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5665c2c66affSColin Finck 
5666c2c66affSColin Finck             buf[0] = 0;
5667c2c66affSColin Finck             size = MAX_PATH;
5668c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5669c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5670c2c66affSColin Finck             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5671c2c66affSColin Finck             if (size) buf[size - 1] = 0;
5672c2c66affSColin Finck             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5673c2c66affSColin Finck 
5674c2c66affSColin Finck             buf[0] = 0;
5675c2c66affSColin Finck             size = MAX_PATH;
5676c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5677c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5678c2c66affSColin Finck             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5679c2c66affSColin Finck             if (size) buf[size - 1] = 0;
5680c2c66affSColin Finck             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5681c2c66affSColin Finck 
5682c2c66affSColin Finck             buf[0] = 0;
5683c2c66affSColin Finck             size = MAX_PATH;
5684c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5685c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5686c2c66affSColin Finck             pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5687c2c66affSColin Finck             if (size) buf[size - 1] = 0;
5688c2c66affSColin Finck             ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5689c2c66affSColin Finck 
5690c2c66affSColin Finck             buf[0] = 0;
5691c2c66affSColin Finck             size = MAX_PATH;
5692c2c66affSColin Finck             r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5693c2c66affSColin Finck             ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5694c2c66affSColin Finck             ok(buf[0], "property not set\n");
5695c2c66affSColin Finck         }
5696c2c66affSColin Finck         else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5697c2c66affSColin Finck         {
5698c2c66affSColin Finck             if (!is_wow64)
5699c2c66affSColin Finck             {
5700c2c66affSColin Finck                 buf[0] = 0;
5701c2c66affSColin Finck                 size = MAX_PATH;
5702c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5703c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5704c2c66affSColin Finck                 ok(buf[0], "property not set\n");
5705c2c66affSColin Finck 
5706c2c66affSColin Finck                 buf[0] = 0;
5707c2c66affSColin Finck                 size = MAX_PATH;
5708c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5709c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5710c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5711c2c66affSColin Finck 
5712c2c66affSColin Finck                 buf[0] = 0;
5713c2c66affSColin Finck                 size = MAX_PATH;
5714c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5715c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5716c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5717c2c66affSColin Finck 
5718c2c66affSColin Finck                 buf[0] = 0;
5719c2c66affSColin Finck                 size = MAX_PATH;
5720c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5721c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5722c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5723c2c66affSColin Finck 
5724c2c66affSColin Finck                 buf[0] = 0;
5725c2c66affSColin Finck                 size = MAX_PATH;
5726c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5727c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5728c2c66affSColin Finck                 GetSystemDirectoryA(path, MAX_PATH);
5729c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5730c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5731c2c66affSColin Finck 
5732c2c66affSColin Finck                 buf[0] = 0;
5733c2c66affSColin Finck                 size = MAX_PATH;
5734c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "ProgramFiles64Folder", buf, &size);
5735c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5736c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5737c2c66affSColin Finck 
5738c2c66affSColin Finck                 buf[0] = 0;
5739c2c66affSColin Finck                 size = MAX_PATH;
5740c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5741c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5742c2c66affSColin Finck                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES, NULL, 0, path);
5743c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5744c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5745c2c66affSColin Finck 
5746c2c66affSColin Finck                 buf[0] = 0;
5747c2c66affSColin Finck                 size = MAX_PATH;
5748c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "CommonFiles64Folder", buf, &size);
5749c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5750c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5751c2c66affSColin Finck 
5752c2c66affSColin Finck                 buf[0] = 0;
5753c2c66affSColin Finck                 size = MAX_PATH;
5754c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5755c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5756c2c66affSColin Finck                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMON, NULL, 0, path);
5757c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5758c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5759c2c66affSColin Finck 
5760c2c66affSColin Finck                 buf[0] = 0;
5761c2c66affSColin Finck                 size = MAX_PATH;
5762c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5763c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5764c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5765c2c66affSColin Finck             }
5766c2c66affSColin Finck             else
5767c2c66affSColin Finck             {
5768c2c66affSColin Finck                 buf[0] = 0;
5769c2c66affSColin Finck                 size = MAX_PATH;
5770c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "Intel", buf, &size);
5771c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5772c2c66affSColin Finck                 ok(buf[0], "property not set\n");
5773c2c66affSColin Finck 
5774c2c66affSColin Finck                 buf[0] = 0;
5775c2c66affSColin Finck                 size = MAX_PATH;
5776c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "MsiAMD64", buf, &size);
5777c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5778c2c66affSColin Finck                 ok(buf[0], "property not set\n");
5779c2c66affSColin Finck 
5780c2c66affSColin Finck                 buf[0] = 0;
5781c2c66affSColin Finck                 size = MAX_PATH;
5782c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "Msix64", buf, &size);
5783c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5784c2c66affSColin Finck                 ok(buf[0], "property not set\n");
5785c2c66affSColin Finck 
5786c2c66affSColin Finck                 buf[0] = 0;
5787c2c66affSColin Finck                 size = MAX_PATH;
5788c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "System64Folder", buf, &size);
5789c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5790c2c66affSColin Finck                 GetSystemDirectoryA(path, MAX_PATH);
5791c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5792c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5793c2c66affSColin Finck 
5794c2c66affSColin Finck                 buf[0] = 0;
5795c2c66affSColin Finck                 size = MAX_PATH;
5796c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "SystemFolder", buf, &size);
5797c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5798c2c66affSColin Finck                 pGetSystemWow64DirectoryA(path, MAX_PATH);
5799c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5800c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5801c2c66affSColin Finck 
5802c2c66affSColin Finck                 buf[0] = 0;
5803c2c66affSColin Finck                 size = MAX_PATH;
5804c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder64", buf, &size);
5805c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5806c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5807c2c66affSColin Finck 
5808c2c66affSColin Finck                 buf[0] = 0;
5809c2c66affSColin Finck                 size = MAX_PATH;
5810c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "ProgramFilesFolder", buf, &size);
5811c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5812c2c66affSColin Finck                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILESX86, NULL, 0, path);
5813c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5814c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5815c2c66affSColin Finck 
5816c2c66affSColin Finck                 buf[0] = 0;
5817c2c66affSColin Finck                 size = MAX_PATH;
5818c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder64", buf, &size);
5819c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5820c2c66affSColin Finck                 ok(!buf[0], "property set\n");
5821c2c66affSColin Finck 
5822c2c66affSColin Finck                 buf[0] = 0;
5823c2c66affSColin Finck                 size = MAX_PATH;
5824c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "CommonFilesFolder", buf, &size);
5825c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5826c2c66affSColin Finck                 pSHGetFolderPathA(NULL, CSIDL_PROGRAM_FILES_COMMONX86, NULL, 0, path);
5827c2c66affSColin Finck                 if (size) buf[size - 1] = 0;
5828c2c66affSColin Finck                 ok(!lstrcmpiA(path, buf), "expected \"%s\", got \"%s\"\n", path, buf);
5829c2c66affSColin Finck 
5830c2c66affSColin Finck                 buf[0] = 0;
5831c2c66affSColin Finck                 size = MAX_PATH;
5832c2c66affSColin Finck                 r = MsiGetPropertyA(hpkg, "VersionNT64", buf, &size);
5833c2c66affSColin Finck                 ok(r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5834c2c66affSColin Finck                 ok(buf[0], "property not set\n");
5835c2c66affSColin Finck             }
5836c2c66affSColin Finck         }
5837c2c66affSColin Finck     }
5838c2c66affSColin Finck 
5839c2c66affSColin Finck     CloseHandle(hkey1);
5840c2c66affSColin Finck     CloseHandle(hkey2);
5841c2c66affSColin Finck     MsiCloseHandle(hpkg);
5842c2c66affSColin Finck     DeleteFileA(msifile);
5843c2c66affSColin Finck     MsiSetInternalUI(uilevel, NULL);
5844c2c66affSColin Finck }
5845c2c66affSColin Finck 
5846c2c66affSColin Finck static void test_launchconditions(void)
5847c2c66affSColin Finck {
5848c2c66affSColin Finck     MSIHANDLE hpkg;
5849c2c66affSColin Finck     MSIHANDLE hdb;
5850c2c66affSColin Finck     UINT r;
5851c2c66affSColin Finck 
5852c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5853c2c66affSColin Finck 
5854c2c66affSColin Finck     hdb = create_package_db();
5855c2c66affSColin Finck     ok( hdb, "failed to create package database\n" );
5856c2c66affSColin Finck 
5857f860a780SAmine Khaldi     create_launchcondition_table( hdb );
5858c2c66affSColin Finck 
5859f860a780SAmine Khaldi     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5860c2c66affSColin Finck 
5861c2c66affSColin Finck     /* invalid condition */
5862f860a780SAmine Khaldi     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5863c2c66affSColin Finck 
5864c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
5865c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5866c2c66affSColin Finck     {
5867c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5868c2c66affSColin Finck         DeleteFileA(msifile);
5869c2c66affSColin Finck         return;
5870c2c66affSColin Finck     }
5871c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5872c2c66affSColin Finck 
5873c2c66affSColin Finck     MsiCloseHandle( hdb );
5874c2c66affSColin Finck 
5875c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "X", "1" );
5876c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5877c2c66affSColin Finck 
5878c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5879c2c66affSColin Finck 
5880c2c66affSColin Finck     /* invalid conditions are ignored */
5881c2c66affSColin Finck     r = MsiDoActionA( hpkg, "LaunchConditions" );
5882c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5883c2c66affSColin Finck 
5884c2c66affSColin Finck     /* verify LaunchConditions still does some verification */
5885c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "X", "2" );
5886c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5887c2c66affSColin Finck 
5888c2c66affSColin Finck     r = MsiDoActionA( hpkg, "LaunchConditions" );
5889c2c66affSColin Finck     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5890c2c66affSColin Finck 
5891c2c66affSColin Finck     MsiCloseHandle( hpkg );
5892c2c66affSColin Finck     DeleteFileA( msifile );
5893c2c66affSColin Finck }
5894c2c66affSColin Finck 
5895c2c66affSColin Finck static void test_ccpsearch(void)
5896c2c66affSColin Finck {
5897c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
5898c2c66affSColin Finck     CHAR prop[MAX_PATH];
5899c2c66affSColin Finck     DWORD size = MAX_PATH;
5900c2c66affSColin Finck     UINT r;
5901c2c66affSColin Finck 
5902c2c66affSColin Finck     hdb = create_package_db();
5903c2c66affSColin Finck     ok(hdb, "failed to create package database\n");
5904c2c66affSColin Finck 
5905f860a780SAmine Khaldi     create_ccpsearch_table(hdb);
5906f860a780SAmine Khaldi     add_ccpsearch_entry(hdb, "'CCP_random'");
5907f860a780SAmine Khaldi     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5908c2c66affSColin Finck 
5909f860a780SAmine Khaldi     create_reglocator_table(hdb);
5910f860a780SAmine Khaldi     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5911c2c66affSColin Finck 
5912f860a780SAmine Khaldi     create_drlocator_table(hdb);
5913f860a780SAmine Khaldi     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5914c2c66affSColin Finck 
5915f860a780SAmine Khaldi     create_signature_table(hdb);
5916c2c66affSColin Finck 
5917c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5918c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5919c2c66affSColin Finck     {
5920c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5921c2c66affSColin Finck         DeleteFileA(msifile);
5922c2c66affSColin Finck         return;
5923c2c66affSColin Finck     }
5924c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5925c2c66affSColin Finck 
5926c2c66affSColin Finck     MsiCloseHandle(hdb);
5927c2c66affSColin Finck 
5928c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5929c2c66affSColin Finck 
5930c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CCPSearch");
5931c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5932c2c66affSColin Finck 
5933c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5934c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5935c2c66affSColin Finck     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5936c2c66affSColin Finck 
5937c2c66affSColin Finck     MsiCloseHandle(hpkg);
5938c2c66affSColin Finck     DeleteFileA(msifile);
5939c2c66affSColin Finck }
5940c2c66affSColin Finck 
5941c2c66affSColin Finck static void test_complocator(void)
5942c2c66affSColin Finck {
5943c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
5944c2c66affSColin Finck     UINT r;
5945c2c66affSColin Finck     CHAR prop[MAX_PATH];
5946c2c66affSColin Finck     CHAR expected[MAX_PATH];
5947c2c66affSColin Finck     DWORD size = MAX_PATH;
5948c2c66affSColin Finck 
5949c2c66affSColin Finck     hdb = create_package_db();
5950c2c66affSColin Finck     ok(hdb, "failed to create package database\n");
5951c2c66affSColin Finck 
5952f860a780SAmine Khaldi     create_appsearch_table(hdb);
5953f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5954f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5955f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5956f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5957f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5958f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
5959f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
5960f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
5961f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
5962f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
5963f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
5964f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
5965f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
5966f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
5967f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
5968f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
5969c2c66affSColin Finck 
5970f860a780SAmine Khaldi     create_complocator_table(hdb);
5971f860a780SAmine Khaldi     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
5972f860a780SAmine Khaldi     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
5973f860a780SAmine Khaldi     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
5974f860a780SAmine Khaldi     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
5975f860a780SAmine Khaldi     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
5976f860a780SAmine Khaldi     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
5977f860a780SAmine Khaldi     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
5978f860a780SAmine Khaldi     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
5979f860a780SAmine Khaldi     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
5980f860a780SAmine Khaldi     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
5981f860a780SAmine Khaldi     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
5982f860a780SAmine Khaldi     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
5983f860a780SAmine Khaldi     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
5984f860a780SAmine Khaldi     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
5985f860a780SAmine Khaldi     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
5986f860a780SAmine Khaldi     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
5987c2c66affSColin Finck 
5988f860a780SAmine Khaldi     create_signature_table(hdb);
5989f860a780SAmine Khaldi     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
5990f860a780SAmine Khaldi     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
5991f860a780SAmine Khaldi     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
5992f860a780SAmine Khaldi     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
5993f860a780SAmine Khaldi     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
5994f860a780SAmine Khaldi     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
5995f860a780SAmine Khaldi     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
5996f860a780SAmine Khaldi     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
5997c2c66affSColin Finck 
5998c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5999c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6000c2c66affSColin Finck     {
6001c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
6002c2c66affSColin Finck         DeleteFileA(msifile);
6003c2c66affSColin Finck         return;
6004c2c66affSColin Finck     }
6005c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6006c2c66affSColin Finck 
6007c2c66affSColin Finck     MsiCloseHandle(hdb);
6008c2c66affSColin Finck 
6009c2c66affSColin Finck     create_test_file("abelisaurus");
6010c2c66affSColin Finck     create_test_file("bactrosaurus");
6011c2c66affSColin Finck     create_test_file("camelotia");
6012c2c66affSColin Finck     create_test_file("diclonius");
6013c2c66affSColin Finck     create_test_file("echinodon");
6014c2c66affSColin Finck     create_test_file("falcarius");
6015c2c66affSColin Finck     create_test_file("gallimimus");
6016c2c66affSColin Finck     create_test_file("hagryphus");
6017c2c66affSColin Finck     CreateDirectoryA("iguanodon", NULL);
6018c2c66affSColin Finck     CreateDirectoryA("jobaria", NULL);
6019c2c66affSColin Finck     CreateDirectoryA("kakuru", NULL);
6020c2c66affSColin Finck     CreateDirectoryA("labocania", NULL);
6021c2c66affSColin Finck     CreateDirectoryA("megaraptor", NULL);
6022c2c66affSColin Finck     CreateDirectoryA("neosodon", NULL);
6023c2c66affSColin Finck     CreateDirectoryA("olorotitan", NULL);
6024c2c66affSColin Finck     CreateDirectoryA("pantydraco", NULL);
6025c2c66affSColin Finck 
6026c2c66affSColin Finck     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
6027c2c66affSColin Finck                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
6028c2c66affSColin Finck     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
6029c2c66affSColin Finck                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
6030c2c66affSColin Finck     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
6031c2c66affSColin Finck                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
6032c2c66affSColin Finck     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
6033c2c66affSColin Finck                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
6034c2c66affSColin Finck     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
6035c2c66affSColin Finck                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
6036c2c66affSColin Finck     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
6037c2c66affSColin Finck                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
6038c2c66affSColin Finck     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
6039c2c66affSColin Finck                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
6040c2c66affSColin Finck     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
6041c2c66affSColin Finck                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
6042c2c66affSColin Finck 
6043c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6044c2c66affSColin Finck 
6045c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
6046c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6047c2c66affSColin Finck 
6048c2c66affSColin Finck     size = MAX_PATH;
6049c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6050c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6051c2c66affSColin Finck 
6052c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6053c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6054c2c66affSColin Finck     lstrcatA(expected, "abelisaurus");
6055c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6056c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6057c2c66affSColin Finck 
6058c2c66affSColin Finck     size = MAX_PATH;
6059c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6060c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6061c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6062c2c66affSColin Finck 
6063c2c66affSColin Finck     size = MAX_PATH;
6064c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6065c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6066c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6067c2c66affSColin Finck 
6068c2c66affSColin Finck     size = MAX_PATH;
6069c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6070c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6071c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6072c2c66affSColin Finck 
6073c2c66affSColin Finck     size = MAX_PATH;
6074c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6075c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6076c2c66affSColin Finck 
6077c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6078c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6079c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6080c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6081c2c66affSColin Finck 
6082c2c66affSColin Finck     size = MAX_PATH;
6083c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6084c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6085c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6086c2c66affSColin Finck 
6087c2c66affSColin Finck     size = MAX_PATH;
6088c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6089c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6090c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6091c2c66affSColin Finck 
6092c2c66affSColin Finck     size = MAX_PATH;
6093c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6094c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6095c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6096c2c66affSColin Finck 
6097c2c66affSColin Finck     size = MAX_PATH;
6098c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6099c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6100c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6101c2c66affSColin Finck 
6102c2c66affSColin Finck     size = MAX_PATH;
6103c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6104c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6105c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6106c2c66affSColin Finck 
6107c2c66affSColin Finck     size = MAX_PATH;
6108c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6109c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6110c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6111c2c66affSColin Finck 
6112c2c66affSColin Finck     size = MAX_PATH;
6113c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6114c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6115c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6116c2c66affSColin Finck 
6117c2c66affSColin Finck     size = MAX_PATH;
6118c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6119c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6120c2c66affSColin Finck 
6121c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6122c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6123c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6124c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6125c2c66affSColin Finck 
6126c2c66affSColin Finck     size = MAX_PATH;
6127c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6128c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6129c2c66affSColin Finck 
6130c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6131c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6132c2c66affSColin Finck     lstrcatA(expected, "neosodon\\");
6133c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6134c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6135c2c66affSColin Finck 
6136c2c66affSColin Finck     size = MAX_PATH;
6137c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6138c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6139c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6140c2c66affSColin Finck 
6141c2c66affSColin Finck     size = MAX_PATH;
6142c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6143c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6144c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6145c2c66affSColin Finck 
6146c2c66affSColin Finck     MsiCloseHandle(hpkg);
6147c2c66affSColin Finck     DeleteFileA("abelisaurus");
6148c2c66affSColin Finck     DeleteFileA("bactrosaurus");
6149c2c66affSColin Finck     DeleteFileA("camelotia");
6150c2c66affSColin Finck     DeleteFileA("diclonius");
6151c2c66affSColin Finck     DeleteFileA("echinodon");
6152c2c66affSColin Finck     DeleteFileA("falcarius");
6153c2c66affSColin Finck     DeleteFileA("gallimimus");
6154c2c66affSColin Finck     DeleteFileA("hagryphus");
6155c2c66affSColin Finck     RemoveDirectoryA("iguanodon");
6156c2c66affSColin Finck     RemoveDirectoryA("jobaria");
6157c2c66affSColin Finck     RemoveDirectoryA("kakuru");
6158c2c66affSColin Finck     RemoveDirectoryA("labocania");
6159c2c66affSColin Finck     RemoveDirectoryA("megaraptor");
6160c2c66affSColin Finck     RemoveDirectoryA("neosodon");
6161c2c66affSColin Finck     RemoveDirectoryA("olorotitan");
6162c2c66affSColin Finck     RemoveDirectoryA("pantydraco");
6163c2c66affSColin Finck     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6164c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6165c2c66affSColin Finck     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6166c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6167c2c66affSColin Finck     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6168c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6169c2c66affSColin Finck     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6170c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6171c2c66affSColin Finck     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6172c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6173c2c66affSColin Finck     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6174c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6175c2c66affSColin Finck     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6176c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6177c2c66affSColin Finck     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6178c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6179c2c66affSColin Finck     DeleteFileA(msifile);
6180c2c66affSColin Finck }
6181c2c66affSColin Finck 
6182c2c66affSColin Finck static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6183c2c66affSColin Finck {
6184c2c66affSColin Finck     MSIHANDLE summary;
6185c2c66affSColin Finck     UINT r;
6186c2c66affSColin Finck 
6187c2c66affSColin Finck     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6188c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6189c2c66affSColin Finck 
6190c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6191c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6192c2c66affSColin Finck 
6193c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
6194c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6195c2c66affSColin Finck 
6196c2c66affSColin Finck     MsiCloseHandle(summary);
6197c2c66affSColin Finck }
6198c2c66affSColin Finck 
6199c2c66affSColin Finck static void test_MsiGetSourcePath(void)
6200c2c66affSColin Finck {
6201c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
6202c2c66affSColin Finck     CHAR path[MAX_PATH];
6203c2c66affSColin Finck     CHAR cwd[MAX_PATH];
6204c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
6205c2c66affSColin Finck     CHAR sub2[MAX_PATH];
6206c2c66affSColin Finck     DWORD size;
6207c2c66affSColin Finck     UINT r;
6208c2c66affSColin Finck 
6209c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
6210c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6211c2c66affSColin Finck 
6212c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
6213c2c66affSColin Finck     lstrcatA(subsrc, "subsource");
6214c2c66affSColin Finck     lstrcatA(subsrc, "\\");
6215c2c66affSColin Finck 
6216c2c66affSColin Finck     lstrcpyA(sub2, subsrc);
6217c2c66affSColin Finck     lstrcatA(sub2, "sub2");
6218c2c66affSColin Finck     lstrcatA(sub2, "\\");
6219c2c66affSColin Finck 
6220c2c66affSColin Finck     /* uncompressed source */
6221c2c66affSColin Finck 
6222c2c66affSColin Finck     hdb = create_package_db();
6223c2c66affSColin Finck     ok( hdb, "failed to create database\n");
6224c2c66affSColin Finck 
6225c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6226c2c66affSColin Finck 
6227f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6228f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6229f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6230c2c66affSColin Finck 
6231c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
6232c2c66affSColin Finck     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6233c2c66affSColin Finck 
6234c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6235c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6236c2c66affSColin Finck     {
6237c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
6238c2c66affSColin Finck         DeleteFileA(msifile);
6239c2c66affSColin Finck         return;
6240c2c66affSColin Finck     }
6241c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6242c2c66affSColin Finck 
6243c2c66affSColin Finck     MsiCloseHandle(hdb);
6244c2c66affSColin Finck 
6245c2c66affSColin Finck     /* invalid database handle */
6246c2c66affSColin Finck     size = MAX_PATH;
6247c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6248c2c66affSColin Finck     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6249c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
6250c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6251c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6252c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6253c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6254c2c66affSColin Finck 
6255c2c66affSColin Finck     /* NULL szFolder */
6256c2c66affSColin Finck     size = MAX_PATH;
6257c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6258c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6259c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
6260c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6261c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6262c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6263c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6264c2c66affSColin Finck 
6265c2c66affSColin Finck     /* empty szFolder */
6266c2c66affSColin Finck     size = MAX_PATH;
6267c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6268c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "", path, &size);
6269c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6270c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6271c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6272c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6273c2c66affSColin Finck 
6274c2c66affSColin Finck     /* try TARGETDIR */
6275c2c66affSColin Finck     size = MAX_PATH;
6276c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6277c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", 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     size = MAX_PATH;
6284c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6285c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6286c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6287c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6288c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6289c2c66affSColin Finck 
6290c2c66affSColin Finck     size = MAX_PATH;
6291c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6292c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6293c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6294c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6295c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6296c2c66affSColin Finck 
6297c2c66affSColin Finck     /* try SourceDir */
6298c2c66affSColin Finck     size = MAX_PATH;
6299c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6300c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6301c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6302c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6303c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6304c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6305c2c66affSColin Finck 
6306c2c66affSColin Finck     /* try SOURCEDIR */
6307c2c66affSColin Finck     size = MAX_PATH;
6308c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6309c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6310c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6311c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6312c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6313c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6314c2c66affSColin Finck 
6315c2c66affSColin Finck     /* source path does not exist, but the property exists */
6316c2c66affSColin Finck     size = MAX_PATH;
6317c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6318c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6319c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6320c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6321c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6322c2c66affSColin Finck 
6323c2c66affSColin Finck     size = MAX_PATH;
6324c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6325c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6326c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6327c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6328c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6329c2c66affSColin Finck 
6330c2c66affSColin Finck     /* try SubDir */
6331c2c66affSColin Finck     size = MAX_PATH;
6332c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6333c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6334c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6335c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6336c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6337c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6338c2c66affSColin Finck 
6339c2c66affSColin Finck     /* try SubDir2 */
6340c2c66affSColin Finck     size = MAX_PATH;
6341c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6342c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6343c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6344c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6345c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6346c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6347c2c66affSColin Finck 
6348c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6349c2c66affSColin Finck 
6350c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6351c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "cost init failed\n");
6352c2c66affSColin Finck 
6353c2c66affSColin Finck     /* try TARGETDIR after CostInitialize */
6354c2c66affSColin Finck     size = MAX_PATH;
6355c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6356c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6357c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6358c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6359c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6360c2c66affSColin Finck 
6361c2c66affSColin Finck     /* try SourceDir after CostInitialize */
6362c2c66affSColin Finck     size = MAX_PATH;
6363c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6364c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6365c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6366c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6367c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6368c2c66affSColin Finck 
6369c2c66affSColin Finck     /* try SOURCEDIR after CostInitialize */
6370c2c66affSColin Finck     size = MAX_PATH;
6371c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6372c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6373c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6374c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6375c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6376c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6377c2c66affSColin Finck 
6378c2c66affSColin Finck     /* source path does not exist, but the property exists */
6379c2c66affSColin Finck     size = MAX_PATH;
6380c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6381c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6382c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6383c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6384c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6385c2c66affSColin Finck 
6386c2c66affSColin Finck     size = MAX_PATH;
6387c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6388c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6389c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6390c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6391c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6392c2c66affSColin Finck 
6393c2c66affSColin Finck     /* try SubDir after CostInitialize */
6394c2c66affSColin Finck     size = MAX_PATH;
6395c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6396c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6397c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6398c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6399c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6400c2c66affSColin Finck 
6401c2c66affSColin Finck     /* try SubDir2 after CostInitialize */
6402c2c66affSColin Finck     size = MAX_PATH;
6403c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6404c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6405c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6406c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6407c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6408c2c66affSColin Finck 
6409c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
6410c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6411c2c66affSColin Finck 
6412c2c66affSColin Finck     /* try TARGETDIR after ResolveSource */
6413c2c66affSColin Finck     size = MAX_PATH;
6414c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6415c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6416c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6417c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6418c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6419c2c66affSColin Finck 
6420c2c66affSColin Finck     /* try SourceDir after ResolveSource */
6421c2c66affSColin Finck     size = MAX_PATH;
6422c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6423c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6424c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6425c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6426c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6427c2c66affSColin Finck 
6428c2c66affSColin Finck     /* try SOURCEDIR after ResolveSource */
6429c2c66affSColin Finck     size = MAX_PATH;
6430c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6431c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6432c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6433c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6434c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6435c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6436c2c66affSColin Finck 
6437c2c66affSColin Finck     /* source path does not exist, but the property exists */
6438c2c66affSColin Finck     size = MAX_PATH;
6439c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6440c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6441c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6442c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6443c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6444c2c66affSColin Finck 
6445c2c66affSColin Finck     size = MAX_PATH;
6446c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6447c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6448c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6449c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6450c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6451c2c66affSColin Finck 
6452c2c66affSColin Finck     /* try SubDir after ResolveSource */
6453c2c66affSColin Finck     size = MAX_PATH;
6454c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6455c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6456c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6457c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6458c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6459c2c66affSColin Finck 
6460c2c66affSColin Finck     /* try SubDir2 after ResolveSource */
6461c2c66affSColin Finck     size = MAX_PATH;
6462c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6463c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6464c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6465c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6466c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6467c2c66affSColin Finck 
6468c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
6469c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6470c2c66affSColin Finck 
6471c2c66affSColin Finck     /* try TARGETDIR after FileCost */
6472c2c66affSColin Finck     size = MAX_PATH;
6473c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6474c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6475c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6476c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6477c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6478c2c66affSColin Finck 
6479c2c66affSColin Finck     /* try SourceDir after FileCost */
6480c2c66affSColin Finck     size = MAX_PATH;
6481c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6482c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6483c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6484c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6485c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6486c2c66affSColin Finck 
6487c2c66affSColin Finck     /* try SOURCEDIR after FileCost */
6488c2c66affSColin Finck     size = MAX_PATH;
6489c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6490c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6491c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6492c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6493c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6494c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6495c2c66affSColin Finck 
6496c2c66affSColin Finck     /* source path does not exist, but the property exists */
6497c2c66affSColin Finck     size = MAX_PATH;
6498c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6499c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6500c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6501c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6502c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6503c2c66affSColin Finck 
6504c2c66affSColin Finck     size = MAX_PATH;
6505c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6506c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6507c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6508c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6509c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6510c2c66affSColin Finck 
6511c2c66affSColin Finck     /* try SubDir after FileCost */
6512c2c66affSColin Finck     size = MAX_PATH;
6513c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6514c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6515c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6516c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6517c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6518c2c66affSColin Finck 
6519c2c66affSColin Finck     /* try SubDir2 after FileCost */
6520c2c66affSColin Finck     size = MAX_PATH;
6521c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6522c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6523c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6524c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6525c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6526c2c66affSColin Finck 
6527c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
6528c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6529c2c66affSColin Finck 
6530c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6531c2c66affSColin Finck     size = MAX_PATH;
6532c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6533c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6534c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6535c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6536c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6537c2c66affSColin Finck 
6538c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6539c2c66affSColin Finck     size = MAX_PATH;
6540c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6541c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6542c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6543c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6544c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6545c2c66affSColin Finck 
6546c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6547c2c66affSColin Finck     size = MAX_PATH;
6548c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6549c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6550c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6551c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6552c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6553c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6554c2c66affSColin Finck 
6555c2c66affSColin Finck     /* source path does not exist, but the property exists */
6556c2c66affSColin Finck     size = MAX_PATH;
6557c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6558c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6559c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6560c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6561c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6562c2c66affSColin Finck 
6563c2c66affSColin Finck     size = MAX_PATH;
6564c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6565c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6566c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6567c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6568c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6569c2c66affSColin Finck 
6570c2c66affSColin Finck     /* try SubDir after CostFinalize */
6571c2c66affSColin Finck     size = MAX_PATH;
6572c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6573c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6574c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6575c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6576c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6577c2c66affSColin Finck 
6578c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6579c2c66affSColin Finck     size = MAX_PATH;
6580c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6581c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6582c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6583c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6584c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6585c2c66affSColin Finck 
6586c2c66affSColin Finck     /* nonexistent directory */
6587c2c66affSColin Finck     size = MAX_PATH;
6588c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6589c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6590c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, 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 == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6594c2c66affSColin Finck 
6595c2c66affSColin Finck     /* NULL szPathBuf */
6596c2c66affSColin Finck     size = MAX_PATH;
6597c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6598c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6599c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6600c2c66affSColin Finck 
6601c2c66affSColin Finck     /* NULL pcchPathBuf */
6602c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6603c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6604c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
6605c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6606c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6607c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6608c2c66affSColin Finck 
6609c2c66affSColin Finck     /* pcchPathBuf is 0 */
6610c2c66affSColin Finck     size = 0;
6611c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6612c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6613c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6614c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6615c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6616c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6617c2c66affSColin Finck 
6618c2c66affSColin Finck     /* pcchPathBuf does not have room for NULL terminator */
6619c2c66affSColin Finck     size = lstrlenA(cwd);
6620c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6621c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6622c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6623c2c66affSColin Finck     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6624c2c66affSColin Finck        "Expected path with no backslash, got \"%s\"\n", path);
6625c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6626c2c66affSColin Finck 
6627c2c66affSColin Finck     /* pcchPathBuf has room for NULL terminator */
6628c2c66affSColin Finck     size = lstrlenA(cwd) + 1;
6629c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6630c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6631c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6632c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6633c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6634c2c66affSColin Finck 
6635c2c66affSColin Finck     /* remove property */
6636c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6637c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6638c2c66affSColin Finck 
6639c2c66affSColin Finck     /* try SourceDir again */
6640c2c66affSColin Finck     size = MAX_PATH;
6641c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6642c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6643c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6644c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6645c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6646c2c66affSColin Finck 
6647c2c66affSColin Finck     /* set property to a valid directory */
6648c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6649c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6650c2c66affSColin Finck 
6651c2c66affSColin Finck     /* try SOURCEDIR again */
6652c2c66affSColin Finck     size = MAX_PATH;
6653c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6654c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6655c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6656c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6657c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6658c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6659c2c66affSColin Finck 
6660c2c66affSColin Finck     MsiCloseHandle(hpkg);
6661c2c66affSColin Finck 
6662c2c66affSColin Finck     /* compressed source */
6663c2c66affSColin Finck 
6664c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6665c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6666c2c66affSColin Finck 
6667c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6668c2c66affSColin Finck 
6669c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6670c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6671c2c66affSColin Finck 
6672c2c66affSColin Finck     /* try TARGETDIR */
6673c2c66affSColin Finck     size = MAX_PATH;
6674c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6675c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6676c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6677c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6678c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6679c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6680c2c66affSColin Finck 
6681c2c66affSColin Finck     /* try SourceDir */
6682c2c66affSColin Finck     size = MAX_PATH;
6683c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6684c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6685c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6686c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6687c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6688c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6689c2c66affSColin Finck 
6690c2c66affSColin Finck     /* try SOURCEDIR */
6691c2c66affSColin Finck     size = MAX_PATH;
6692c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6693c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6694c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6695c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6696c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6697c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6698c2c66affSColin Finck 
6699c2c66affSColin Finck     /* source path nor the property exist */
6700c2c66affSColin Finck     size = MAX_PATH;
6701c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6702c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6703c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6704c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6705c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6706c2c66affSColin Finck 
6707c2c66affSColin Finck     size = MAX_PATH;
6708c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6709c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6710c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6711c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6712c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6713c2c66affSColin Finck 
6714c2c66affSColin Finck     /* try SubDir */
6715c2c66affSColin Finck     size = MAX_PATH;
6716c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6717c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6718c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6719c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6720c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6721c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6722c2c66affSColin Finck 
6723c2c66affSColin Finck     /* try SubDir2 */
6724c2c66affSColin Finck     size = MAX_PATH;
6725c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6726c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6727c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6728c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6729c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6730c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6731c2c66affSColin Finck 
6732c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6733c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6734c2c66affSColin Finck 
6735c2c66affSColin Finck     /* try TARGETDIR after CostInitialize */
6736c2c66affSColin Finck     size = MAX_PATH;
6737c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6738c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6739c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6740c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6741c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6742c2c66affSColin Finck 
6743c2c66affSColin Finck     /* try SourceDir after CostInitialize */
6744c2c66affSColin Finck     size = MAX_PATH;
6745c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6746c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6747c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6748c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6749c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6750c2c66affSColin Finck 
6751c2c66affSColin Finck     /* try SOURCEDIR after CostInitialize */
6752c2c66affSColin Finck     size = MAX_PATH;
6753c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6754c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6755c2c66affSColin Finck     todo_wine
6756c2c66affSColin Finck     {
6757c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6758c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6759c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6760c2c66affSColin Finck     }
6761c2c66affSColin Finck 
6762c2c66affSColin Finck     /* source path does not exist, but the property exists */
6763c2c66affSColin Finck     size = MAX_PATH;
6764c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6765c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", 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     size = MAX_PATH;
6771c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6772c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6773c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6774c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6775c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6776c2c66affSColin Finck 
6777c2c66affSColin Finck     /* try SubDir after CostInitialize */
6778c2c66affSColin Finck     size = MAX_PATH;
6779c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6780c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6781c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6782c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6783c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6784c2c66affSColin Finck 
6785c2c66affSColin Finck     /* try SubDir2 after CostInitialize */
6786c2c66affSColin Finck     size = MAX_PATH;
6787c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6788c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6789c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6790c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6791c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6792c2c66affSColin Finck 
6793c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
6794c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6795c2c66affSColin Finck 
6796c2c66affSColin Finck     /* try TARGETDIR after ResolveSource */
6797c2c66affSColin Finck     size = MAX_PATH;
6798c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6799c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6800c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6801c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6802c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6803c2c66affSColin Finck 
6804c2c66affSColin Finck     /* try SourceDir after ResolveSource */
6805c2c66affSColin Finck     size = MAX_PATH;
6806c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6807c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6808c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6809c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6810c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6811c2c66affSColin Finck 
6812c2c66affSColin Finck     /* try SOURCEDIR after ResolveSource */
6813c2c66affSColin Finck     size = MAX_PATH;
6814c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6815c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6816c2c66affSColin Finck     todo_wine
6817c2c66affSColin Finck     {
6818c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6819c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6820c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6821c2c66affSColin Finck     }
6822c2c66affSColin Finck 
6823c2c66affSColin Finck     /* source path and the property exist */
6824c2c66affSColin Finck     size = MAX_PATH;
6825c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6826c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", 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     size = MAX_PATH;
6832c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6833c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6834c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6835c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6836c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6837c2c66affSColin Finck 
6838c2c66affSColin Finck     /* try SubDir after ResolveSource */
6839c2c66affSColin Finck     size = MAX_PATH;
6840c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6841c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6842c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6843c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6844c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6845c2c66affSColin Finck 
6846c2c66affSColin Finck     /* try SubDir2 after ResolveSource */
6847c2c66affSColin Finck     size = MAX_PATH;
6848c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6849c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6850c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6851c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6852c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6853c2c66affSColin Finck 
6854c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
6855c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6856c2c66affSColin Finck 
6857c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6858c2c66affSColin Finck     size = MAX_PATH;
6859c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6860c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6861c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6862c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6863c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6864c2c66affSColin Finck 
6865c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6866c2c66affSColin Finck     size = MAX_PATH;
6867c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6868c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6869c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6870c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6871c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6872c2c66affSColin Finck 
6873c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6874c2c66affSColin Finck     size = MAX_PATH;
6875c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6876c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6877c2c66affSColin Finck     todo_wine
6878c2c66affSColin Finck     {
6879c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6880c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6881c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6882c2c66affSColin Finck     }
6883c2c66affSColin Finck 
6884c2c66affSColin Finck     /* source path and the property exist */
6885c2c66affSColin Finck     size = MAX_PATH;
6886c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6887c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", 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     size = MAX_PATH;
6893c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6894c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6895c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6896c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6897c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6898c2c66affSColin Finck 
6899c2c66affSColin Finck     /* try SubDir after CostFinalize */
6900c2c66affSColin Finck     size = MAX_PATH;
6901c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6902c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6903c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6904c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6905c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6906c2c66affSColin Finck 
6907c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6908c2c66affSColin Finck     size = MAX_PATH;
6909c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6910c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6911c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6912c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6913c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6914c2c66affSColin Finck 
6915c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
6916c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6917c2c66affSColin Finck 
6918c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6919c2c66affSColin Finck     size = MAX_PATH;
6920c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6921c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6922c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6923c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6924c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6925c2c66affSColin Finck 
6926c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6927c2c66affSColin Finck     size = MAX_PATH;
6928c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6929c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6930c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6931c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6932c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6933c2c66affSColin Finck 
6934c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6935c2c66affSColin Finck     size = MAX_PATH;
6936c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6937c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6938c2c66affSColin Finck     todo_wine
6939c2c66affSColin Finck     {
6940c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6941c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6942c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6943c2c66affSColin Finck     }
6944c2c66affSColin Finck 
6945c2c66affSColin Finck     /* source path and the property exist */
6946c2c66affSColin Finck     size = MAX_PATH;
6947c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6948c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", 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     size = MAX_PATH;
6954c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6955c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6956c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6957c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6958c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6959c2c66affSColin Finck 
6960c2c66affSColin Finck     /* try SubDir after CostFinalize */
6961c2c66affSColin Finck     size = MAX_PATH;
6962c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6963c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6964c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6965c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6966c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6967c2c66affSColin Finck 
6968c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6969c2c66affSColin Finck     size = MAX_PATH;
6970c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6971c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6972c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6973c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6974c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6975c2c66affSColin Finck 
6976c2c66affSColin Finck     MsiCloseHandle(hpkg);
6977c2c66affSColin Finck     DeleteFileA(msifile);
6978c2c66affSColin Finck }
6979c2c66affSColin Finck 
6980c2c66affSColin Finck static void test_shortlongsource(void)
6981c2c66affSColin Finck {
6982c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
6983c2c66affSColin Finck     CHAR path[MAX_PATH];
6984c2c66affSColin Finck     CHAR cwd[MAX_PATH];
6985c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
6986c2c66affSColin Finck     DWORD size;
6987c2c66affSColin Finck     UINT r;
6988c2c66affSColin Finck 
6989c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
6990c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6991c2c66affSColin Finck 
6992c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
6993c2c66affSColin Finck     lstrcatA(subsrc, "long");
6994c2c66affSColin Finck     lstrcatA(subsrc, "\\");
6995c2c66affSColin Finck 
6996c2c66affSColin Finck     /* long file names */
6997c2c66affSColin Finck 
6998c2c66affSColin Finck     hdb = create_package_db();
6999c2c66affSColin Finck     ok( hdb, "failed to create database\n");
7000c2c66affSColin Finck 
7001c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
7002c2c66affSColin Finck 
7003f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7004f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
7005c2c66affSColin Finck 
7006c2c66affSColin Finck     /* CostInitialize:short */
7007f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
7008c2c66affSColin Finck 
7009c2c66affSColin Finck     /* CostInitialize:long */
7010f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
7011c2c66affSColin Finck 
7012c2c66affSColin Finck     /* FileCost:short */
7013f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
7014c2c66affSColin Finck 
7015c2c66affSColin Finck     /* FileCost:long */
7016f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
7017c2c66affSColin Finck 
7018c2c66affSColin Finck     /* CostFinalize:short */
7019f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
7020c2c66affSColin Finck 
7021c2c66affSColin Finck     /* CostFinalize:long */
7022f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
7023c2c66affSColin Finck 
7024f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
7025f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
7026c2c66affSColin Finck 
7027c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
7028c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7029c2c66affSColin Finck     {
7030c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7031c2c66affSColin Finck         DeleteFileA(msifile);
7032c2c66affSColin Finck         return;
7033c2c66affSColin Finck     }
7034c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7035c2c66affSColin Finck 
7036c2c66affSColin Finck     MsiCloseHandle(hdb);
7037c2c66affSColin Finck 
7038c2c66affSColin Finck     CreateDirectoryA("one", NULL);
7039c2c66affSColin Finck     CreateDirectoryA("four", NULL);
7040c2c66affSColin Finck 
7041c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7042c2c66affSColin Finck 
7043c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7044c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7045c2c66affSColin Finck 
7046c2c66affSColin Finck     CreateDirectoryA("five", NULL);
7047c2c66affSColin Finck     CreateDirectoryA("eight", NULL);
7048c2c66affSColin Finck 
7049c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7050c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7051c2c66affSColin Finck 
7052c2c66affSColin Finck     CreateDirectoryA("nine", NULL);
7053c2c66affSColin Finck     CreateDirectoryA("twelve", NULL);
7054c2c66affSColin Finck 
7055c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7056c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7057c2c66affSColin Finck 
7058c2c66affSColin Finck     /* neither short nor long source directories exist */
7059c2c66affSColin Finck     size = MAX_PATH;
7060c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7061c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7062c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7063c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7064c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7065c2c66affSColin Finck 
7066c2c66affSColin Finck     CreateDirectoryA("short", NULL);
7067c2c66affSColin Finck 
7068c2c66affSColin Finck     /* short source directory exists */
7069c2c66affSColin Finck     size = MAX_PATH;
7070c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7071c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7072c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7073c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7074c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7075c2c66affSColin Finck 
7076c2c66affSColin Finck     CreateDirectoryA("long", NULL);
7077c2c66affSColin Finck 
7078c2c66affSColin Finck     /* both short and long source directories exist */
7079c2c66affSColin Finck     size = MAX_PATH;
7080c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7081c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7082c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7083c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7084c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7085c2c66affSColin Finck 
7086c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7087c2c66affSColin Finck     lstrcatA(subsrc, "two");
7088c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7089c2c66affSColin Finck 
7090c2c66affSColin Finck     /* short dir exists before CostInitialize */
7091c2c66affSColin Finck     size = MAX_PATH;
7092c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7093c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7094c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7095c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7096c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7097c2c66affSColin Finck 
7098c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7099c2c66affSColin Finck     lstrcatA(subsrc, "four");
7100c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7101c2c66affSColin Finck 
7102c2c66affSColin Finck     /* long dir exists before CostInitialize */
7103c2c66affSColin Finck     size = MAX_PATH;
7104c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7105c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7106c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7107c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7108c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7109c2c66affSColin Finck 
7110c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7111c2c66affSColin Finck     lstrcatA(subsrc, "six");
7112c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7113c2c66affSColin Finck 
7114c2c66affSColin Finck     /* short dir exists before FileCost */
7115c2c66affSColin Finck     size = MAX_PATH;
7116c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7117c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7118c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7119c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7120c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7121c2c66affSColin Finck 
7122c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7123c2c66affSColin Finck     lstrcatA(subsrc, "eight");
7124c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7125c2c66affSColin Finck 
7126c2c66affSColin Finck     /* long dir exists before FileCost */
7127c2c66affSColin Finck     size = MAX_PATH;
7128c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7129c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7130c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7131c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7132c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7133c2c66affSColin Finck 
7134c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7135c2c66affSColin Finck     lstrcatA(subsrc, "ten");
7136c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7137c2c66affSColin Finck 
7138c2c66affSColin Finck     /* short dir exists before CostFinalize */
7139c2c66affSColin Finck     size = MAX_PATH;
7140c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7141c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7142c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7143c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7144c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7145c2c66affSColin Finck 
7146c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7147c2c66affSColin Finck     lstrcatA(subsrc, "twelve");
7148c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7149c2c66affSColin Finck 
7150c2c66affSColin Finck     /* long dir exists before CostFinalize */
7151c2c66affSColin Finck     size = MAX_PATH;
7152c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7153c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7154c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7155c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7156c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7157c2c66affSColin Finck 
7158c2c66affSColin Finck     MsiCloseHandle(hpkg);
7159c2c66affSColin Finck     RemoveDirectoryA("short");
7160c2c66affSColin Finck     RemoveDirectoryA("long");
7161c2c66affSColin Finck     RemoveDirectoryA("one");
7162c2c66affSColin Finck     RemoveDirectoryA("four");
7163c2c66affSColin Finck     RemoveDirectoryA("five");
7164c2c66affSColin Finck     RemoveDirectoryA("eight");
7165c2c66affSColin Finck     RemoveDirectoryA("nine");
7166c2c66affSColin Finck     RemoveDirectoryA("twelve");
7167c2c66affSColin Finck 
7168c2c66affSColin Finck     /* short file names */
7169c2c66affSColin Finck 
7170c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7171c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172c2c66affSColin Finck 
7173c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7174c2c66affSColin Finck 
7175c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
7176c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7177c2c66affSColin Finck 
7178c2c66affSColin Finck     MsiCloseHandle(hdb);
7179c2c66affSColin Finck 
7180c2c66affSColin Finck     CreateDirectoryA("one", NULL);
7181c2c66affSColin Finck     CreateDirectoryA("four", NULL);
7182c2c66affSColin Finck 
7183c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7184c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7185c2c66affSColin Finck 
7186c2c66affSColin Finck     CreateDirectoryA("five", NULL);
7187c2c66affSColin Finck     CreateDirectoryA("eight", NULL);
7188c2c66affSColin Finck 
7189c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7190c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7191c2c66affSColin Finck 
7192c2c66affSColin Finck     CreateDirectoryA("nine", NULL);
7193c2c66affSColin Finck     CreateDirectoryA("twelve", NULL);
7194c2c66affSColin Finck 
7195c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7196c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7197c2c66affSColin Finck 
7198c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7199c2c66affSColin Finck     lstrcatA(subsrc, "short");
7200c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7201c2c66affSColin Finck 
7202c2c66affSColin Finck     /* neither short nor long source directories exist */
7203c2c66affSColin Finck     size = MAX_PATH;
7204c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7205c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7206c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7207c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7208c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7209c2c66affSColin Finck 
7210c2c66affSColin Finck     CreateDirectoryA("short", NULL);
7211c2c66affSColin Finck 
7212c2c66affSColin Finck     /* short source directory exists */
7213c2c66affSColin Finck     size = MAX_PATH;
7214c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7215c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7216c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7217c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7218c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7219c2c66affSColin Finck 
7220c2c66affSColin Finck     CreateDirectoryA("long", NULL);
7221c2c66affSColin Finck 
7222c2c66affSColin Finck     /* both short and long source directories exist */
7223c2c66affSColin Finck     size = MAX_PATH;
7224c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7225c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7226c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7227c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7228c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7229c2c66affSColin Finck 
7230c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7231c2c66affSColin Finck     lstrcatA(subsrc, "one");
7232c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7233c2c66affSColin Finck 
7234c2c66affSColin Finck     /* short dir exists before CostInitialize */
7235c2c66affSColin Finck     size = MAX_PATH;
7236c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7237c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7238c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7239c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7240c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7241c2c66affSColin Finck 
7242c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7243c2c66affSColin Finck     lstrcatA(subsrc, "three");
7244c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7245c2c66affSColin Finck 
7246c2c66affSColin Finck     /* long dir exists before CostInitialize */
7247c2c66affSColin Finck     size = MAX_PATH;
7248c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7249c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7250c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7251c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7252c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7253c2c66affSColin Finck 
7254c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7255c2c66affSColin Finck     lstrcatA(subsrc, "five");
7256c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7257c2c66affSColin Finck 
7258c2c66affSColin Finck     /* short dir exists before FileCost */
7259c2c66affSColin Finck     size = MAX_PATH;
7260c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7261c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7262c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7263c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7264c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7265c2c66affSColin Finck 
7266c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7267c2c66affSColin Finck     lstrcatA(subsrc, "seven");
7268c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7269c2c66affSColin Finck 
7270c2c66affSColin Finck     /* long dir exists before FileCost */
7271c2c66affSColin Finck     size = MAX_PATH;
7272c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7273c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7274c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7275c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7276c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7277c2c66affSColin Finck 
7278c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7279c2c66affSColin Finck     lstrcatA(subsrc, "nine");
7280c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7281c2c66affSColin Finck 
7282c2c66affSColin Finck     /* short dir exists before CostFinalize */
7283c2c66affSColin Finck     size = MAX_PATH;
7284c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7285c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7286c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7287c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7288c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7289c2c66affSColin Finck 
7290c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7291c2c66affSColin Finck     lstrcatA(subsrc, "eleven");
7292c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7293c2c66affSColin Finck 
7294c2c66affSColin Finck     /* long dir exists before CostFinalize */
7295c2c66affSColin Finck     size = MAX_PATH;
7296c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7297c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7298c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7299c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7300c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7301c2c66affSColin Finck 
7302c2c66affSColin Finck     MsiCloseHandle(hpkg);
7303c2c66affSColin Finck     RemoveDirectoryA("short");
7304c2c66affSColin Finck     RemoveDirectoryA("long");
7305c2c66affSColin Finck     RemoveDirectoryA("one");
7306c2c66affSColin Finck     RemoveDirectoryA("four");
7307c2c66affSColin Finck     RemoveDirectoryA("five");
7308c2c66affSColin Finck     RemoveDirectoryA("eight");
7309c2c66affSColin Finck     RemoveDirectoryA("nine");
7310c2c66affSColin Finck     RemoveDirectoryA("twelve");
7311c2c66affSColin Finck     DeleteFileA(msifile);
7312c2c66affSColin Finck }
7313c2c66affSColin Finck 
7314c2c66affSColin Finck static void test_sourcedir(void)
7315c2c66affSColin Finck {
7316c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
7317c2c66affSColin Finck     CHAR package[12];
7318c2c66affSColin Finck     CHAR path[MAX_PATH];
7319c2c66affSColin Finck     CHAR cwd[MAX_PATH];
7320c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
7321c2c66affSColin Finck     DWORD size;
7322c2c66affSColin Finck     UINT r;
7323c2c66affSColin Finck 
7324c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
7325c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7326c2c66affSColin Finck 
7327c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7328c2c66affSColin Finck     lstrcatA(subsrc, "long");
7329c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7330c2c66affSColin Finck 
7331c2c66affSColin Finck     hdb = create_package_db();
7332c2c66affSColin Finck     ok( hdb, "failed to create database\n");
7333c2c66affSColin Finck 
7334f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7335c2c66affSColin Finck 
7336c2c66affSColin Finck     sprintf(package, "#%u", hdb);
7337c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
7338c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7339c2c66affSColin Finck     {
7340c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7341c2c66affSColin Finck         goto error;
7342c2c66affSColin Finck     }
7343c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7344c2c66affSColin Finck 
7345c2c66affSColin Finck     /* properties only */
7346c2c66affSColin Finck 
7347c2c66affSColin Finck     /* SourceDir prop */
7348c2c66affSColin Finck     size = MAX_PATH;
7349c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7350c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7351c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7352c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7353c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7354c2c66affSColin Finck 
7355c2c66affSColin Finck     /* SOURCEDIR prop */
7356c2c66affSColin Finck     size = MAX_PATH;
7357c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7358c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7359c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7360c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7361c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7362c2c66affSColin Finck 
7363c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7364c2c66affSColin Finck 
7365c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7366c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7367c2c66affSColin Finck 
7368c2c66affSColin Finck     /* SourceDir after CostInitialize */
7369c2c66affSColin Finck     size = MAX_PATH;
7370c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7371c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7372c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7373c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7374c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7375c2c66affSColin Finck 
7376c2c66affSColin Finck     /* SOURCEDIR after CostInitialize */
7377c2c66affSColin Finck     size = MAX_PATH;
7378c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7379c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7380c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7381c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7382c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7383c2c66affSColin Finck 
7384c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7385c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7386c2c66affSColin Finck 
7387c2c66affSColin Finck     /* SourceDir after FileCost */
7388c2c66affSColin Finck     size = MAX_PATH;
7389c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7390c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7391c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7392c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7393c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7394c2c66affSColin Finck 
7395c2c66affSColin Finck     /* SOURCEDIR after FileCost */
7396c2c66affSColin Finck     size = MAX_PATH;
7397c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7398c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7399c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7400c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7401c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7402c2c66affSColin Finck 
7403c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7404c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7405c2c66affSColin Finck 
7406c2c66affSColin Finck     /* SourceDir after CostFinalize */
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     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7412c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7413c2c66affSColin Finck 
7414c2c66affSColin Finck     /* SOURCEDIR after CostFinalize */
7415c2c66affSColin Finck     size = MAX_PATH;
7416c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7417c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7418c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7419c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7420c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7421c2c66affSColin Finck 
7422c2c66affSColin Finck     size = MAX_PATH;
7423c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7424c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7425c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7426c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7427c2c66affSColin Finck     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7428c2c66affSColin Finck 
7429c2c66affSColin Finck     /* SOURCEDIR after calling MsiGetSourcePath */
7430c2c66affSColin Finck     size = MAX_PATH;
7431c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7432c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7433c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7434c2c66affSColin Finck     todo_wine {
7435c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7436c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7437c2c66affSColin Finck     }
7438c2c66affSColin Finck 
7439c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
7440c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7441c2c66affSColin Finck 
7442c2c66affSColin Finck     /* SourceDir after ResolveSource */
7443c2c66affSColin Finck     size = MAX_PATH;
7444c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7445c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7446c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7447c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7448c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7449c2c66affSColin Finck 
7450c2c66affSColin Finck     /* SOURCEDIR after ResolveSource */
7451c2c66affSColin Finck     size = MAX_PATH;
7452c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7453c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7454c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7455c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7456c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7457c2c66affSColin Finck 
7458c2c66affSColin Finck     /* random casing */
7459c2c66affSColin Finck     size = MAX_PATH;
7460c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7461c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7462c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7463c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7464c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7465c2c66affSColin Finck 
7466c2c66affSColin Finck     MsiCloseHandle(hpkg);
7467c2c66affSColin Finck 
7468c2c66affSColin Finck     /* reset the package state */
7469c2c66affSColin Finck     sprintf(package, "#%i", hdb);
7470c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
7471c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7472c2c66affSColin Finck 
7473c2c66affSColin Finck     /* test how MsiGetSourcePath affects the properties */
7474c2c66affSColin Finck 
7475c2c66affSColin Finck     /* SourceDir prop */
7476c2c66affSColin Finck     size = MAX_PATH;
7477c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7478c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7479c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7480c2c66affSColin Finck     todo_wine
7481c2c66affSColin Finck     {
7482c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7483c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7484c2c66affSColin Finck     }
7485c2c66affSColin Finck 
7486c2c66affSColin Finck     size = MAX_PATH;
7487c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7488c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7489c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7490c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7491c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7492c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7493c2c66affSColin Finck 
7494c2c66affSColin Finck     /* SourceDir after MsiGetSourcePath */
7495c2c66affSColin Finck     size = MAX_PATH;
7496c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7497c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7498c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7499c2c66affSColin Finck     todo_wine
7500c2c66affSColin Finck     {
7501c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7502c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7503c2c66affSColin Finck     }
7504c2c66affSColin Finck 
7505c2c66affSColin Finck     /* SOURCEDIR prop */
7506c2c66affSColin Finck     size = MAX_PATH;
7507c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7508c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7509c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7510c2c66affSColin Finck     todo_wine
7511c2c66affSColin Finck     {
7512c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7513c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7514c2c66affSColin Finck     }
7515c2c66affSColin Finck 
7516c2c66affSColin Finck     size = MAX_PATH;
7517c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7518c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7519c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7520c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7521c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7522c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7523c2c66affSColin Finck 
7524c2c66affSColin Finck     /* SOURCEDIR prop after MsiGetSourcePath */
7525c2c66affSColin Finck     size = MAX_PATH;
7526c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7527c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7528c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7529c2c66affSColin Finck     todo_wine
7530c2c66affSColin Finck     {
7531c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7532c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7533c2c66affSColin Finck     }
7534c2c66affSColin Finck 
7535c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7536c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7537c2c66affSColin Finck 
7538c2c66affSColin Finck     /* SourceDir after CostInitialize */
7539c2c66affSColin Finck     size = MAX_PATH;
7540c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7541c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7542c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7543c2c66affSColin Finck     todo_wine
7544c2c66affSColin Finck     {
7545c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7546c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7547c2c66affSColin Finck     }
7548c2c66affSColin Finck 
7549c2c66affSColin Finck     size = MAX_PATH;
7550c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7551c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7552c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7553c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7554c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7555c2c66affSColin Finck 
7556c2c66affSColin Finck     /* SourceDir after MsiGetSourcePath */
7557c2c66affSColin Finck     size = MAX_PATH;
7558c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7559c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7560c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7561c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7562c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7563c2c66affSColin Finck 
7564c2c66affSColin Finck     /* SOURCEDIR after CostInitialize */
7565c2c66affSColin Finck     size = MAX_PATH;
7566c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7567c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7568c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7569c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7570c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7571c2c66affSColin Finck 
7572c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7573c2c66affSColin Finck     size = MAX_PATH;
7574c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7575c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7576c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7577c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7578c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7579c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7580c2c66affSColin Finck 
7581c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7582c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7583c2c66affSColin Finck 
7584c2c66affSColin Finck     /* SourceDir after FileCost */
7585c2c66affSColin Finck     size = MAX_PATH;
7586c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7587c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7588c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7589c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7590c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7591c2c66affSColin Finck 
7592c2c66affSColin Finck     /* SOURCEDIR after FileCost */
7593c2c66affSColin Finck     size = MAX_PATH;
7594c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7595c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7596c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7597c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7598c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7599c2c66affSColin Finck 
7600c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7601c2c66affSColin Finck     size = MAX_PATH;
7602c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7603c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7604c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7605c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7606c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7607c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7608c2c66affSColin Finck 
7609c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7610c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7611c2c66affSColin Finck 
7612c2c66affSColin Finck     /* SourceDir after CostFinalize */
7613c2c66affSColin Finck     size = MAX_PATH;
7614c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7615c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7616c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7617c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7618c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7619c2c66affSColin Finck 
7620c2c66affSColin Finck     /* SOURCEDIR after CostFinalize */
7621c2c66affSColin Finck     size = MAX_PATH;
7622c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7623c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7624c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7625c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7626c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7627c2c66affSColin Finck 
7628c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7629c2c66affSColin Finck     size = MAX_PATH;
7630c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7631c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7632c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7633c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7634c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7635c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7636c2c66affSColin Finck 
7637c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
7638c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7639c2c66affSColin Finck 
7640c2c66affSColin Finck     /* SourceDir after ResolveSource */
7641c2c66affSColin Finck     size = MAX_PATH;
7642c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7643c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7644c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7645c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7646c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7647c2c66affSColin Finck 
7648c2c66affSColin Finck     /* SOURCEDIR after ResolveSource */
7649c2c66affSColin Finck     size = MAX_PATH;
7650c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7651c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7652c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7653c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7654c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7655c2c66affSColin Finck 
7656c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7657c2c66affSColin Finck     size = MAX_PATH;
7658c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7659c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7660c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7661c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7662c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7663c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7664c2c66affSColin Finck 
7665c2c66affSColin Finck     MsiCloseHandle(hpkg);
7666c2c66affSColin Finck 
7667c2c66affSColin Finck error:
7668c2c66affSColin Finck     MsiCloseHandle(hdb);
7669c2c66affSColin Finck     DeleteFileA(msifile);
7670c2c66affSColin Finck }
7671c2c66affSColin Finck 
7672c2c66affSColin Finck struct access_res
7673c2c66affSColin Finck {
7674c2c66affSColin Finck     BOOL gothandle;
7675c2c66affSColin Finck     DWORD lasterr;
7676c2c66affSColin Finck     BOOL ignore;
7677c2c66affSColin Finck };
7678c2c66affSColin Finck 
7679c2c66affSColin Finck static const struct access_res create[16] =
7680c2c66affSColin Finck {
7681c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7682c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7683c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7684c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7685c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7686c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7687c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7688c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7689c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7690c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7691c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7692c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7693c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7694c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7695c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7696c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE }
7697c2c66affSColin Finck };
7698c2c66affSColin Finck 
7699c2c66affSColin Finck static const struct access_res create_commit[16] =
7700c2c66affSColin Finck {
7701c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7702c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7703c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7704c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7705c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7706c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7707c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7708c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7709c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7710c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7711c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7712c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7713c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7714c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7715c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7716c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE }
7717c2c66affSColin Finck };
7718c2c66affSColin Finck 
7719c2c66affSColin Finck static const struct access_res create_close[16] =
7720c2c66affSColin Finck {
7721c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7722c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7723c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7724c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7725c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7726c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7727c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7728c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7729c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7730c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7731c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7732c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7733c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7734c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7735c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7736c2c66affSColin Finck     { TRUE, ERROR_SUCCESS }
7737c2c66affSColin Finck };
7738c2c66affSColin Finck 
7739c2c66affSColin Finck static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7740c2c66affSColin Finck {
7741c2c66affSColin Finck     DWORD access = 0, share = 0;
7742c2c66affSColin Finck     DWORD lasterr;
7743c2c66affSColin Finck     HANDLE hfile;
7744c2c66affSColin Finck     int i, j, idx = 0;
7745c2c66affSColin Finck 
7746c2c66affSColin Finck     for (i = 0; i < 4; i++)
7747c2c66affSColin Finck     {
7748c2c66affSColin Finck         if (i == 0) access = 0;
7749c2c66affSColin Finck         if (i == 1) access = GENERIC_READ;
7750c2c66affSColin Finck         if (i == 2) access = GENERIC_WRITE;
7751c2c66affSColin Finck         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7752c2c66affSColin Finck 
7753c2c66affSColin Finck         for (j = 0; j < 4; j++)
7754c2c66affSColin Finck         {
7755c2c66affSColin Finck             if (ares[idx].ignore)
7756c2c66affSColin Finck                 continue;
7757c2c66affSColin Finck 
7758c2c66affSColin Finck             if (j == 0) share = 0;
7759c2c66affSColin Finck             if (j == 1) share = FILE_SHARE_READ;
7760c2c66affSColin Finck             if (j == 2) share = FILE_SHARE_WRITE;
7761c2c66affSColin Finck             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7762c2c66affSColin Finck 
7763c2c66affSColin Finck             SetLastError(0xdeadbeef);
7764c2c66affSColin Finck             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7765c2c66affSColin Finck                                 FILE_ATTRIBUTE_NORMAL, 0);
7766c2c66affSColin Finck             lasterr = GetLastError();
7767c2c66affSColin Finck 
7768c2c66affSColin Finck             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7769c2c66affSColin Finck                "(%d, handle, %d): Expected %d, got %d\n",
7770c2c66affSColin Finck                line, idx, ares[idx].gothandle,
7771c2c66affSColin Finck                (hfile != INVALID_HANDLE_VALUE));
7772c2c66affSColin Finck 
7773c2c66affSColin Finck             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
7774c2c66affSColin Finck                line, idx, ares[idx].lasterr, lasterr);
7775c2c66affSColin Finck 
7776c2c66affSColin Finck             CloseHandle(hfile);
7777c2c66affSColin Finck             idx++;
7778c2c66affSColin Finck         }
7779c2c66affSColin Finck     }
7780c2c66affSColin Finck }
7781c2c66affSColin Finck 
7782c2c66affSColin Finck #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7783c2c66affSColin Finck 
7784c2c66affSColin Finck static void test_access(void)
7785c2c66affSColin Finck {
7786c2c66affSColin Finck     MSIHANDLE hdb;
7787c2c66affSColin Finck     UINT r;
7788c2c66affSColin Finck 
7789c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7790c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7791c2c66affSColin Finck 
7792c2c66affSColin Finck     test_file_access(msifile, create);
7793c2c66affSColin Finck 
7794c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7795c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7796c2c66affSColin Finck 
7797c2c66affSColin Finck     test_file_access(msifile, create_commit);
7798c2c66affSColin Finck     MsiCloseHandle(hdb);
7799c2c66affSColin Finck 
7800c2c66affSColin Finck     test_file_access(msifile, create_close);
7801c2c66affSColin Finck     DeleteFileA(msifile);
7802c2c66affSColin Finck 
7803c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7804c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7805c2c66affSColin Finck 
7806c2c66affSColin Finck     test_file_access(msifile, create);
7807c2c66affSColin Finck 
7808c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7809c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7810c2c66affSColin Finck 
7811c2c66affSColin Finck     test_file_access(msifile, create_commit);
7812c2c66affSColin Finck     MsiCloseHandle(hdb);
7813c2c66affSColin Finck 
7814c2c66affSColin Finck     test_file_access(msifile, create_close);
7815c2c66affSColin Finck     DeleteFileA(msifile);
7816c2c66affSColin Finck }
7817c2c66affSColin Finck 
7818c2c66affSColin Finck static void test_emptypackage(void)
7819c2c66affSColin Finck {
7820c2c66affSColin Finck     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7821c2c66affSColin Finck     MSIHANDLE hview = 0, hrec = 0;
7822c2c66affSColin Finck     MSICONDITION condition;
7823c2c66affSColin Finck     CHAR buffer[MAX_PATH];
7824c2c66affSColin Finck     DWORD size;
7825c2c66affSColin Finck     UINT r;
7826c2c66affSColin Finck 
7827c2c66affSColin Finck     r = MsiOpenPackageA("", &hpkg);
7828c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7829c2c66affSColin Finck     {
7830c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7831c2c66affSColin Finck         return;
7832c2c66affSColin Finck     }
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     hdb = MsiGetActiveDatabase(hpkg);
7839c2c66affSColin Finck     todo_wine
7840c2c66affSColin Finck     {
7841c2c66affSColin Finck         ok(hdb != 0, "Expected a valid database handle\n");
7842c2c66affSColin Finck     }
7843c2c66affSColin Finck 
7844c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7845c2c66affSColin Finck     todo_wine
7846c2c66affSColin Finck     {
7847c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7848c2c66affSColin Finck     }
7849c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7850c2c66affSColin Finck     todo_wine
7851c2c66affSColin Finck     {
7852c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7853c2c66affSColin Finck     }
7854c2c66affSColin Finck 
7855c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7856c2c66affSColin Finck     todo_wine
7857c2c66affSColin Finck     {
7858c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7859c2c66affSColin Finck     }
7860c2c66affSColin Finck 
7861c2c66affSColin Finck     buffer[0] = 0;
7862c2c66affSColin Finck     size = MAX_PATH;
7863c2c66affSColin Finck     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7864c2c66affSColin Finck     todo_wine
7865c2c66affSColin Finck     {
7866c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7867c2c66affSColin Finck         ok(!lstrcmpA(buffer, "_Property"),
7868c2c66affSColin Finck            "Expected \"_Property\", got \"%s\"\n", buffer);
7869c2c66affSColin Finck     }
7870c2c66affSColin Finck 
7871c2c66affSColin Finck     MsiCloseHandle(hrec);
7872c2c66affSColin Finck 
7873c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7874c2c66affSColin Finck     todo_wine
7875c2c66affSColin Finck     {
7876c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7877c2c66affSColin Finck     }
7878c2c66affSColin Finck 
7879c2c66affSColin Finck     size = MAX_PATH;
7880c2c66affSColin Finck     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7881c2c66affSColin Finck     todo_wine
7882c2c66affSColin Finck     {
7883c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7884c2c66affSColin Finck         ok(!lstrcmpA(buffer, "#_FolderCache"),
7885c2c66affSColin Finck            "Expected \"_Property\", got \"%s\"\n", buffer);
7886c2c66affSColin Finck     }
7887c2c66affSColin Finck 
7888c2c66affSColin Finck     MsiCloseHandle(hrec);
7889c2c66affSColin Finck     MsiViewClose(hview);
7890c2c66affSColin Finck     MsiCloseHandle(hview);
7891c2c66affSColin Finck 
7892c2c66affSColin Finck     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7893c2c66affSColin Finck     todo_wine
7894c2c66affSColin Finck     {
7895c2c66affSColin Finck         ok(condition == MSICONDITION_FALSE,
7896c2c66affSColin Finck            "Expected MSICONDITION_FALSE, got %d\n", condition);
7897c2c66affSColin Finck     }
7898c2c66affSColin Finck 
7899c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7900c2c66affSColin Finck     todo_wine
7901c2c66affSColin Finck     {
7902c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7903c2c66affSColin Finck     }
7904c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7905c2c66affSColin Finck     todo_wine
7906c2c66affSColin Finck     {
7907c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7908c2c66affSColin Finck     }
7909c2c66affSColin Finck 
7910c2c66affSColin Finck     /* _Property table is not empty */
7911c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7912c2c66affSColin Finck     todo_wine
7913c2c66affSColin Finck     {
7914c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7915c2c66affSColin Finck     }
7916c2c66affSColin Finck 
7917c2c66affSColin Finck     MsiCloseHandle(hrec);
7918c2c66affSColin Finck     MsiViewClose(hview);
7919c2c66affSColin Finck     MsiCloseHandle(hview);
7920c2c66affSColin Finck 
7921c2c66affSColin Finck     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7922c2c66affSColin Finck     todo_wine
7923c2c66affSColin Finck     {
7924c2c66affSColin Finck         ok(condition == MSICONDITION_FALSE,
7925c2c66affSColin Finck            "Expected MSICONDITION_FALSE, got %d\n", condition);
7926c2c66affSColin Finck     }
7927c2c66affSColin Finck 
7928c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7929c2c66affSColin Finck     todo_wine
7930c2c66affSColin Finck     {
7931c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7932c2c66affSColin Finck     }
7933c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7934c2c66affSColin Finck     todo_wine
7935c2c66affSColin Finck     {
7936c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7937c2c66affSColin Finck     }
7938c2c66affSColin Finck 
7939c2c66affSColin Finck     /* #_FolderCache is not empty */
7940c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7941c2c66affSColin Finck     todo_wine
7942c2c66affSColin Finck     {
7943c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7944c2c66affSColin Finck     }
7945c2c66affSColin Finck 
7946c2c66affSColin Finck     MsiCloseHandle(hrec);
7947c2c66affSColin Finck     MsiViewClose(hview);
7948c2c66affSColin Finck     MsiCloseHandle(hview);
7949c2c66affSColin Finck 
7950c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7951c2c66affSColin Finck     todo_wine
7952c2c66affSColin Finck     {
7953c2c66affSColin Finck         ok(r == ERROR_BAD_QUERY_SYNTAX,
7954c2c66affSColin Finck            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7955c2c66affSColin Finck     }
7956c2c66affSColin Finck 
7957c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7958c2c66affSColin Finck     todo_wine
7959c2c66affSColin Finck     {
7960c2c66affSColin Finck         ok(r == ERROR_BAD_QUERY_SYNTAX,
7961c2c66affSColin Finck            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7962c2c66affSColin Finck     }
7963c2c66affSColin Finck 
7964c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
7965c2c66affSColin Finck     todo_wine
7966c2c66affSColin Finck     {
7967c2c66affSColin Finck         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
7968c2c66affSColin Finck            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
7969c2c66affSColin Finck     }
7970c2c66affSColin Finck 
7971c2c66affSColin Finck     MsiCloseHandle(hsuminfo);
7972c2c66affSColin Finck 
7973c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7974c2c66affSColin Finck     todo_wine
7975c2c66affSColin Finck     {
7976c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7977c2c66affSColin Finck     }
7978c2c66affSColin Finck 
7979c2c66affSColin Finck     MsiCloseHandle(hdb);
7980c2c66affSColin Finck     MsiCloseHandle(hpkg);
7981c2c66affSColin Finck }
7982c2c66affSColin Finck 
7983c2c66affSColin Finck static void test_MsiGetProductProperty(void)
7984c2c66affSColin Finck {
7985c2c66affSColin Finck     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
7986c2c66affSColin Finck     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
7987c2c66affSColin Finck     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
7988c2c66affSColin Finck     static const WCHAR appleW[] = {'a','p','p','l','e',0};
7989c2c66affSColin Finck     static const WCHAR emptyW[] = {0};
7990c2c66affSColin Finck     WCHAR valW[MAX_PATH];
7991c2c66affSColin Finck     MSIHANDLE hprod, hdb;
7992c2c66affSColin Finck     CHAR val[MAX_PATH];
7993c2c66affSColin Finck     CHAR path[MAX_PATH];
7994c2c66affSColin Finck     CHAR query[MAX_PATH];
7995c2c66affSColin Finck     CHAR keypath[MAX_PATH*2];
7996c2c66affSColin Finck     CHAR prodcode[MAX_PATH];
7997c2c66affSColin Finck     WCHAR prodcodeW[MAX_PATH];
7998c2c66affSColin Finck     CHAR prod_squashed[MAX_PATH];
7999c2c66affSColin Finck     WCHAR prod_squashedW[MAX_PATH];
8000c2c66affSColin Finck     HKEY prodkey, userkey, props;
8001c2c66affSColin Finck     DWORD size;
8002c2c66affSColin Finck     LONG res;
8003c2c66affSColin Finck     UINT r;
8004c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
8005c2c66affSColin Finck 
8006c2c66affSColin Finck     GetCurrentDirectoryA(MAX_PATH, path);
8007c2c66affSColin Finck     lstrcatA(path, "\\");
8008c2c66affSColin Finck 
8009c2c66affSColin Finck     create_test_guid(prodcode, prod_squashed);
8010c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
8011c2c66affSColin Finck     squash_guid(prodcodeW, prod_squashedW);
8012c2c66affSColin Finck 
8013c2c66affSColin Finck     if (is_wow64)
8014c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
8015c2c66affSColin Finck 
8016c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
8017c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8018c2c66affSColin Finck 
8019c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
8020c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8021c2c66affSColin Finck 
8022c2c66affSColin Finck     r = set_summary_info(hdb);
8023c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8024c2c66affSColin Finck 
8025c2c66affSColin Finck     r = run_query(hdb,
8026c2c66affSColin Finck             "CREATE TABLE `Directory` ( "
8027c2c66affSColin Finck             "`Directory` CHAR(255) NOT NULL, "
8028c2c66affSColin Finck             "`Directory_Parent` CHAR(255), "
8029c2c66affSColin Finck             "`DefaultDir` CHAR(255) NOT NULL "
8030c2c66affSColin Finck             "PRIMARY KEY `Directory`)");
8031c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8032c2c66affSColin Finck 
8033f860a780SAmine Khaldi     create_property_table(hdb);
8034c2c66affSColin Finck 
8035f860a780SAmine Khaldi     sprintf(query, "'ProductCode', '%s'", prodcode);
8036f860a780SAmine Khaldi     r = add_property_entry(hdb, query);
8037c2c66affSColin Finck 
8038c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
8039c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8040c2c66affSColin Finck 
8041c2c66affSColin Finck     MsiCloseHandle(hdb);
8042c2c66affSColin Finck 
8043c2c66affSColin Finck     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
8044c2c66affSColin Finck     lstrcatA(keypath, prod_squashed);
8045c2c66affSColin Finck 
8046c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8047c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
8048c2c66affSColin Finck     {
8049c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8050c2c66affSColin Finck         DeleteFileA(msifile);
8051c2c66affSColin Finck         return;
8052c2c66affSColin Finck     }
8053c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8054c2c66affSColin Finck 
8055c2c66affSColin Finck     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8056c2c66affSColin Finck     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8057c2c66affSColin Finck     lstrcatA(keypath, prod_squashed);
8058c2c66affSColin Finck 
8059c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8060c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
8061c2c66affSColin Finck     {
8062c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8063c2c66affSColin Finck         RegDeleteKeyA(prodkey, "");
8064c2c66affSColin Finck         RegCloseKey(prodkey);
8065c2c66affSColin Finck         return;
8066c2c66affSColin Finck     }
8067c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8068c2c66affSColin Finck 
8069c2c66affSColin Finck     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8070c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8071c2c66affSColin Finck 
8072c2c66affSColin Finck     lstrcpyA(val, path);
8073c2c66affSColin Finck     lstrcatA(val, "\\");
8074c2c66affSColin Finck     lstrcatA(val, msifile);
8075c2c66affSColin Finck     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8076c2c66affSColin Finck                          (const BYTE *)val, lstrlenA(val) + 1);
8077c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8078c2c66affSColin Finck 
8079c2c66affSColin Finck     hprod = 0xdeadbeef;
8080c2c66affSColin Finck     r = MsiOpenProductA(prodcode, &hprod);
8081c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8082c2c66affSColin Finck     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8083c2c66affSColin Finck 
8084c2c66affSColin Finck     /* hProduct is invalid */
8085c2c66affSColin Finck     size = MAX_PATH;
8086c2c66affSColin Finck     lstrcpyA(val, "apple");
8087c2c66affSColin Finck     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8088c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8089c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8090c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8091c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8092c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8093c2c66affSColin Finck 
8094c2c66affSColin Finck     size = MAX_PATH;
8095c2c66affSColin Finck     lstrcpyW(valW, appleW);
8096c2c66affSColin Finck     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8097c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8098c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8099c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8100c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8101c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8102c2c66affSColin Finck 
8103c2c66affSColin Finck     /* szProperty is NULL */
8104c2c66affSColin Finck     size = MAX_PATH;
8105c2c66affSColin Finck     lstrcpyA(val, "apple");
8106c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8107c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8108c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8109c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8110c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8111c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8112c2c66affSColin Finck 
8113c2c66affSColin Finck     size = MAX_PATH;
8114c2c66affSColin Finck     lstrcpyW(valW, appleW);
8115c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8116c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8117c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8118c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8119c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8120c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8121c2c66affSColin Finck 
8122c2c66affSColin Finck     /* szProperty is empty */
8123c2c66affSColin Finck     size = MAX_PATH;
8124c2c66affSColin Finck     lstrcpyA(val, "apple");
8125c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "", val, &size);
8126c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8127c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8128c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8129c2c66affSColin Finck 
8130c2c66affSColin Finck     size = MAX_PATH;
8131c2c66affSColin Finck     lstrcpyW(valW, appleW);
8132c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8133c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8134c2c66affSColin Finck     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8135c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8136c2c66affSColin Finck 
8137c2c66affSColin Finck     /* get the property */
8138c2c66affSColin Finck     size = MAX_PATH;
8139c2c66affSColin Finck     lstrcpyA(val, "apple");
8140c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8141c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8142c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8143c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8144c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8145c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8146c2c66affSColin Finck 
8147c2c66affSColin Finck     size = MAX_PATH;
8148c2c66affSColin Finck     lstrcpyW(valW, appleW);
8149c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8150c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8151c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8152c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8153c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8154c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8155c2c66affSColin Finck 
8156c2c66affSColin Finck     /* lpValueBuf is NULL */
8157c2c66affSColin Finck     size = MAX_PATH;
8158c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8159c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8160c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8161c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8162c2c66affSColin Finck 
8163c2c66affSColin Finck     size = MAX_PATH;
8164c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8165c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8166c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8167c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8168c2c66affSColin Finck 
8169c2c66affSColin Finck     /* pcchValueBuf is NULL */
8170c2c66affSColin Finck     lstrcpyA(val, "apple");
8171c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8172c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8173c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8174c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8175c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8176c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8177c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8178c2c66affSColin Finck 
8179c2c66affSColin Finck     lstrcpyW(valW, appleW);
8180c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8181c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8182c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8183c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8184c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8185c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8186c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8187c2c66affSColin Finck 
8188c2c66affSColin Finck     /* pcchValueBuf is too small */
8189c2c66affSColin Finck     size = 4;
8190c2c66affSColin Finck     lstrcpyA(val, "apple");
8191c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8192c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8193c2c66affSColin Finck     ok(!strncmp(val, prodcode, 3),
8194c2c66affSColin Finck        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8195c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8196c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8197c2c66affSColin Finck 
8198c2c66affSColin Finck     size = 4;
8199c2c66affSColin Finck     lstrcpyW(valW, appleW);
8200c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8201c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8202c2c66affSColin Finck     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8203c2c66affSColin Finck        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8204c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8205c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8206c2c66affSColin Finck 
8207c2c66affSColin Finck     /* pcchValueBuf does not leave room for NULL terminator */
8208c2c66affSColin Finck     size = lstrlenA(prodcode);
8209c2c66affSColin Finck     lstrcpyA(val, "apple");
8210c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8211c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8212c2c66affSColin Finck     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8213c2c66affSColin Finck        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8214c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8215c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8216c2c66affSColin Finck 
8217c2c66affSColin Finck     size = lstrlenW(prodcodeW);
8218c2c66affSColin Finck     lstrcpyW(valW, appleW);
8219c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8220c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8221c2c66affSColin Finck     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8222c2c66affSColin Finck        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8223c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8224c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8225c2c66affSColin Finck 
8226c2c66affSColin Finck     /* pcchValueBuf has enough room for NULL terminator */
8227c2c66affSColin Finck     size = lstrlenA(prodcode) + 1;
8228c2c66affSColin Finck     lstrcpyA(val, "apple");
8229c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8230c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8231c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8232c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8233c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8234c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8235c2c66affSColin Finck 
8236c2c66affSColin Finck     size = lstrlenW(prodcodeW) + 1;
8237c2c66affSColin Finck     lstrcpyW(valW, appleW);
8238c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8239c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8240c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8241c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8242c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8243c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8244c2c66affSColin Finck 
8245c2c66affSColin Finck     /* nonexistent property */
8246c2c66affSColin Finck     size = MAX_PATH;
8247c2c66affSColin Finck     lstrcpyA(val, "apple");
8248c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8249c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8250c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8251c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8252c2c66affSColin Finck 
8253c2c66affSColin Finck     size = MAX_PATH;
8254c2c66affSColin Finck     lstrcpyW(valW, appleW);
8255c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8256c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8257c2c66affSColin Finck     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8258c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8259c2c66affSColin Finck 
8260c2c66affSColin Finck     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8261c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8262c2c66affSColin Finck 
8263c2c66affSColin Finck     /* non-product property set */
8264c2c66affSColin Finck     size = MAX_PATH;
8265c2c66affSColin Finck     lstrcpyA(val, "apple");
8266c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8267c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8268c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8269c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8270c2c66affSColin Finck 
8271c2c66affSColin Finck     size = MAX_PATH;
8272c2c66affSColin Finck     lstrcpyW(valW, appleW);
8273c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8274c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8275c2c66affSColin Finck     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8276c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8277c2c66affSColin Finck 
8278c2c66affSColin Finck     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8279c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8280c2c66affSColin Finck 
8281c2c66affSColin Finck     /* non-product property that is also a product property set */
8282c2c66affSColin Finck     size = MAX_PATH;
8283c2c66affSColin Finck     lstrcpyA(val, "apple");
8284c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8285c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8286c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8287c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8288c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8289c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8290c2c66affSColin Finck 
8291c2c66affSColin Finck     size = MAX_PATH;
8292c2c66affSColin Finck     lstrcpyW(valW, appleW);
8293c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8294c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8295c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8296c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8297c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8298c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8299c2c66affSColin Finck 
8300c2c66affSColin Finck     MsiCloseHandle(hprod);
8301c2c66affSColin Finck 
8302c2c66affSColin Finck     RegDeleteValueA(props, "LocalPackage");
8303c2c66affSColin Finck     delete_key(props, "", access);
8304c2c66affSColin Finck     RegCloseKey(props);
8305c2c66affSColin Finck     delete_key(userkey, "", access);
8306c2c66affSColin Finck     RegCloseKey(userkey);
8307c2c66affSColin Finck     delete_key(prodkey, "", access);
8308c2c66affSColin Finck     RegCloseKey(prodkey);
8309c2c66affSColin Finck     DeleteFileA(msifile);
8310c2c66affSColin Finck }
8311c2c66affSColin Finck 
8312c2c66affSColin Finck static void test_MsiSetProperty(void)
8313c2c66affSColin Finck {
8314c2c66affSColin Finck     MSIHANDLE hpkg, hdb, hrec;
8315c2c66affSColin Finck     CHAR buf[MAX_PATH];
8316c2c66affSColin Finck     LPCSTR query;
8317c2c66affSColin Finck     DWORD size;
8318c2c66affSColin Finck     UINT r;
8319c2c66affSColin Finck 
8320c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
8321c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8322c2c66affSColin Finck     {
8323c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8324c2c66affSColin Finck         DeleteFileA(msifile);
8325c2c66affSColin Finck         return;
8326c2c66affSColin Finck     }
8327c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8328c2c66affSColin Finck 
8329c2c66affSColin Finck     /* invalid hInstall */
8330c2c66affSColin Finck     r = MsiSetPropertyA(0, "Prop", "Val");
8331c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8332c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8333c2c66affSColin Finck 
8334c2c66affSColin Finck     /* invalid hInstall */
8335c2c66affSColin Finck     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8336c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8337c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8338c2c66affSColin Finck 
8339c2c66affSColin Finck     /* szName is NULL */
8340c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, NULL, "Val");
8341c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8342c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8343c2c66affSColin Finck 
8344c2c66affSColin Finck     /* both szName and szValue are NULL */
8345c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, NULL, NULL);
8346c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8347c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8348c2c66affSColin Finck 
8349c2c66affSColin Finck     /* szName is empty */
8350c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "", "Val");
8351c2c66affSColin Finck     ok(r == ERROR_FUNCTION_FAILED,
8352c2c66affSColin Finck        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8353c2c66affSColin Finck 
8354c2c66affSColin Finck     /* szName is empty and szValue is NULL */
8355c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "", NULL);
8356c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8357c2c66affSColin Finck 
8358c2c66affSColin Finck     /* set a property */
8359c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8360c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8361c2c66affSColin Finck 
8362c2c66affSColin Finck     /* get the property */
8363c2c66affSColin Finck     size = MAX_PATH;
8364c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8365c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8366c2c66affSColin Finck     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8367c2c66affSColin Finck     ok(size == 3, "Expected 3, got %d\n", size);
8368c2c66affSColin Finck 
8369c2c66affSColin Finck     /* update the property */
8370c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8371c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8372c2c66affSColin Finck 
8373c2c66affSColin Finck     /* get the property */
8374c2c66affSColin Finck     size = MAX_PATH;
8375c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8376c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8377c2c66affSColin Finck     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8378c2c66affSColin Finck     ok(size == 4, "Expected 4, got %d\n", size);
8379c2c66affSColin Finck 
8380c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
8381c2c66affSColin Finck     ok(hdb != 0, "Expected a valid database handle\n");
8382c2c66affSColin Finck 
8383c2c66affSColin Finck     /* set prop is not in the _Property table */
8384c2c66affSColin Finck     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8385c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
8386c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX,
8387c2c66affSColin Finck        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8388c2c66affSColin Finck 
8389c2c66affSColin Finck     /* set prop is not in the Property table */
8390c2c66affSColin Finck     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8391c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
8392c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX,
8393c2c66affSColin Finck        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8394c2c66affSColin Finck 
8395c2c66affSColin Finck     MsiCloseHandle(hdb);
8396c2c66affSColin Finck 
8397c2c66affSColin Finck     /* szValue is an empty string */
8398c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "");
8399c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8400c2c66affSColin Finck 
8401c2c66affSColin Finck     /* try to get the property */
8402c2c66affSColin Finck     size = MAX_PATH;
8403c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8404c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8405c2c66affSColin Finck     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8406c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8407c2c66affSColin Finck 
8408c2c66affSColin Finck     /* reset the property */
8409c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8410c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8411c2c66affSColin Finck 
8412c2c66affSColin Finck     /* delete the property */
8413c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8414c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8415c2c66affSColin Finck 
8416c2c66affSColin Finck     /* try to get the property */
8417c2c66affSColin Finck     size = MAX_PATH;
8418c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8419c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8420c2c66affSColin Finck     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8421c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8422c2c66affSColin Finck 
8423c2c66affSColin Finck     MsiCloseHandle(hpkg);
8424c2c66affSColin Finck     DeleteFileA(msifile);
8425c2c66affSColin Finck }
8426c2c66affSColin Finck 
8427c2c66affSColin Finck static void test_MsiApplyMultiplePatches(void)
8428c2c66affSColin Finck {
8429c2c66affSColin Finck     UINT r, type = GetDriveTypeW(NULL);
8430c2c66affSColin Finck 
84312f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8432c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8433c2c66affSColin Finck 
84342f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8435c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8436c2c66affSColin Finck 
84372f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8438c2c66affSColin Finck     if (type == DRIVE_FIXED)
8439c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8440c2c66affSColin Finck     else
8441c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8442c2c66affSColin Finck 
84432f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8444c2c66affSColin Finck     if (type == DRIVE_FIXED)
8445c2c66affSColin Finck         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8446c2c66affSColin Finck     else
8447c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8448c2c66affSColin Finck 
84492f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8450c2c66affSColin Finck     if (type == DRIVE_FIXED)
8451c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8452c2c66affSColin Finck     else
8453c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8454c2c66affSColin Finck 
84552f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8456c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8457c2c66affSColin Finck 
84582f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8459c2c66affSColin Finck     if (type == DRIVE_FIXED)
8460c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8461c2c66affSColin Finck     else
8462c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8463c2c66affSColin Finck 
84642f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8465c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8466c2c66affSColin Finck 
84672f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8468c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8469c2c66affSColin Finck }
8470c2c66affSColin Finck 
8471c2c66affSColin Finck static void test_MsiApplyPatch(void)
8472c2c66affSColin Finck {
8473c2c66affSColin Finck     UINT r;
8474c2c66affSColin Finck 
8475c2c66affSColin Finck     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8476c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8477c2c66affSColin Finck 
8478c2c66affSColin Finck     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8479c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8480c2c66affSColin Finck }
8481c2c66affSColin Finck 
8482*818a84ddSwinesync static void test_costs(void)
8483c2c66affSColin Finck {
8484c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
8485c2c66affSColin Finck     char package[12], drive[3];
8486c2c66affSColin Finck     DWORD len;
8487c2c66affSColin Finck     UINT r;
8488c2c66affSColin Finck     int cost, temp;
8489c2c66affSColin Finck 
8490c2c66affSColin Finck     hdb = create_package_db();
8491c2c66affSColin Finck     ok( hdb, "failed to create database\n" );
8492c2c66affSColin Finck 
8493f860a780SAmine Khaldi     create_property_table( hdb );
8494f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8495f860a780SAmine Khaldi     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8496f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8497c2c66affSColin Finck 
8498f860a780SAmine Khaldi     create_media_table( hdb );
8499f860a780SAmine Khaldi     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8500c2c66affSColin Finck 
8501f860a780SAmine Khaldi     create_file_table( hdb );
8502f860a780SAmine Khaldi     add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8503c2c66affSColin Finck 
8504f860a780SAmine Khaldi     create_component_table( hdb );
8505f860a780SAmine Khaldi     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8506f860a780SAmine Khaldi     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8507c2c66affSColin Finck 
8508f860a780SAmine Khaldi     create_feature_table( hdb );
8509f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8510f860a780SAmine Khaldi     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8511c2c66affSColin Finck 
8512f860a780SAmine Khaldi     create_feature_components_table( hdb );
8513f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'one'" );
8514f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'two'" );
8515c2c66affSColin Finck 
8516f860a780SAmine Khaldi     create_install_execute_sequence_table( hdb );
8517f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8518f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8519f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8520f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8521c2c66affSColin Finck 
8522f860a780SAmine Khaldi     r = MsiDatabaseCommit( hdb );
8523f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8524c2c66affSColin Finck 
8525c2c66affSColin Finck     sprintf( package, "#%u", hdb );
8526c2c66affSColin Finck     r = MsiOpenPackageA( package, &hpkg );
8527c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8528c2c66affSColin Finck     {
8529c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8530c2c66affSColin Finck         goto error;
8531c2c66affSColin Finck     }
8532c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8533c2c66affSColin Finck 
8534c2c66affSColin Finck     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8535c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8536c2c66affSColin Finck 
8537c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8538c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8539c2c66affSColin Finck 
8540c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8541c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8542c2c66affSColin Finck 
8543c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8544c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8545c2c66affSColin Finck 
8546c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8547c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8548c2c66affSColin Finck 
8549c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8550c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8551c2c66affSColin Finck 
8552c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8553c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8554c2c66affSColin Finck 
8555c2c66affSColin Finck     len = sizeof(drive);
8556c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8557c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8558c2c66affSColin Finck 
8559c2c66affSColin Finck     len = sizeof(drive);
8560c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8561c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8562c2c66affSColin Finck 
8563c2c66affSColin Finck     len = sizeof(drive);
8564c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8565c2c66affSColin Finck     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8566c2c66affSColin Finck 
8567c2c66affSColin Finck     len = sizeof(drive);
8568c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8569c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8570c2c66affSColin Finck 
8571c2c66affSColin Finck     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8572c2c66affSColin Finck 
8573c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize" );
8574c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8575c2c66affSColin Finck 
8576c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost" );
8577c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8578c2c66affSColin Finck 
8579c2c66affSColin Finck     len = sizeof(drive);
8580c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8581c2c66affSColin Finck     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8582c2c66affSColin Finck 
8583c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize" );
8584c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8585c2c66affSColin Finck 
8586c2c66affSColin Finck     /* contrary to what msdn says InstallValidate must be called too */
8587c2c66affSColin Finck     len = sizeof(drive);
8588c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8589c2c66affSColin Finck     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8590c2c66affSColin Finck 
8591c2c66affSColin Finck     r = MsiDoActionA( hpkg, "InstallValidate" );
8592c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8593c2c66affSColin Finck 
8594c2c66affSColin Finck     len = 0;
8595c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8596c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8597c2c66affSColin Finck 
8598c2c66affSColin Finck     len = 0;
8599c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8600c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8601c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8602c2c66affSColin Finck 
8603c2c66affSColin Finck     len = 2;
8604c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8605c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8606c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8607c2c66affSColin Finck 
8608c2c66affSColin Finck     len = 2;
8609c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8610c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8611c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8612c2c66affSColin Finck 
8613c2c66affSColin Finck     /* install state doesn't seem to matter */
8614c2c66affSColin Finck     len = sizeof(drive);
8615c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8616c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8617c2c66affSColin Finck 
8618c2c66affSColin Finck     len = sizeof(drive);
8619c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8620c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8621c2c66affSColin Finck 
8622c2c66affSColin Finck     len = sizeof(drive);
8623c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8624c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8625c2c66affSColin Finck 
8626c2c66affSColin Finck     len = sizeof(drive);
8627c2c66affSColin Finck     drive[0] = 0;
8628c2c66affSColin Finck     cost = temp = 0xdead;
8629c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8630c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8631c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8632c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8633c2c66affSColin Finck     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
8634c2c66affSColin Finck     ok( !temp, "expected temp == 0, got %d\n", temp );
8635c2c66affSColin Finck 
8636c2c66affSColin Finck     len = sizeof(drive);
8637c2c66affSColin Finck     drive[0] = 0;
8638c2c66affSColin Finck     cost = temp = 0xdead;
8639c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8640c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8641c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8642c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8643c2c66affSColin Finck     ok( !cost, "expected cost == 0, got %d\n", cost );
8644c2c66affSColin Finck     ok( !temp, "expected temp == 0, got %d\n", temp );
8645c2c66affSColin Finck 
8646c2c66affSColin Finck     len = sizeof(drive);
8647c2c66affSColin Finck     drive[0] = 0;
8648c2c66affSColin Finck     cost = temp = 0xdead;
8649c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8650c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8651c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8652c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8653c2c66affSColin Finck     ok( !cost, "expected cost == 0, got %d\n", cost );
8654c2c66affSColin Finck     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8655c2c66affSColin Finck 
8656c2c66affSColin Finck     /* increased index */
8657c2c66affSColin Finck     len = sizeof(drive);
8658c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8659c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8660c2c66affSColin Finck 
8661c2c66affSColin Finck     len = sizeof(drive);
8662c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8663c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8664c2c66affSColin Finck 
8665*818a84ddSwinesync     /* test MsiGetFeatureCost */
8666*818a84ddSwinesync     cost = 0xdead;
8667*818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, NULL, MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8668*818a84ddSwinesync     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8669*818a84ddSwinesync     ok( cost == 0xdead, "got %d\n", cost );
8670*818a84ddSwinesync 
8671*818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, NULL );
8672*818a84ddSwinesync     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8673*818a84ddSwinesync 
8674*818a84ddSwinesync     cost = 0xdead;
8675*818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8676*818a84ddSwinesync     ok( !r, "got %u\n", r);
8677*818a84ddSwinesync     ok( cost == 8, "got %d\n", cost );
8678*818a84ddSwinesync 
8679c2c66affSColin Finck     MsiCloseHandle( hpkg );
8680c2c66affSColin Finck error:
8681c2c66affSColin Finck     MsiCloseHandle( hdb );
8682c2c66affSColin Finck     DeleteFileA( msifile );
8683c2c66affSColin Finck }
8684c2c66affSColin Finck 
8685c2c66affSColin Finck static void test_MsiDatabaseCommit(void)
8686c2c66affSColin Finck {
8687c2c66affSColin Finck     UINT r;
8688c2c66affSColin Finck     MSIHANDLE hdb, hpkg = 0;
8689c2c66affSColin Finck     char buf[32], package[12];
8690c2c66affSColin Finck     DWORD sz;
8691c2c66affSColin Finck 
8692c2c66affSColin Finck     hdb = create_package_db();
8693c2c66affSColin Finck     ok( hdb, "failed to create database\n" );
8694c2c66affSColin Finck 
8695f860a780SAmine Khaldi     create_property_table( hdb );
8696c2c66affSColin Finck 
8697c2c66affSColin Finck     sprintf( package, "#%u", hdb );
8698c2c66affSColin Finck     r = MsiOpenPackageA( package, &hpkg );
8699c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8700c2c66affSColin Finck     {
8701c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8702c2c66affSColin Finck         goto error;
8703c2c66affSColin Finck     }
8704c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "got %u\n", r );
8705c2c66affSColin Finck 
8706c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8707c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "got %u\n", r );
8708c2c66affSColin Finck 
8709c2c66affSColin Finck     buf[0] = 0;
8710c2c66affSColin Finck     sz = sizeof(buf);
8711c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8712c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8713c2c66affSColin Finck     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8714c2c66affSColin Finck 
8715c2c66affSColin Finck     r = MsiDatabaseCommit( hdb );
8716c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8717c2c66affSColin Finck 
8718c2c66affSColin Finck     buf[0] = 0;
8719c2c66affSColin Finck     sz = sizeof(buf);
8720c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8721c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8722c2c66affSColin Finck     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8723c2c66affSColin Finck 
8724c2c66affSColin Finck     MsiCloseHandle( hpkg );
8725c2c66affSColin Finck error:
8726c2c66affSColin Finck     MsiCloseHandle( hdb );
8727c2c66affSColin Finck     DeleteFileA( msifile );
8728c2c66affSColin Finck }
8729c2c66affSColin Finck 
87302f8e6f71SAmine Khaldi static int externalui_ran;
87312f8e6f71SAmine Khaldi 
87322f8e6f71SAmine Khaldi static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
87332f8e6f71SAmine Khaldi {
87342f8e6f71SAmine Khaldi     externalui_ran = 1;
87352f8e6f71SAmine Khaldi     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
87362f8e6f71SAmine Khaldi     return 0;
87372f8e6f71SAmine Khaldi }
87382f8e6f71SAmine Khaldi 
87392f8e6f71SAmine Khaldi static int externalui_record_ran;
87402f8e6f71SAmine Khaldi 
87412f8e6f71SAmine Khaldi static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
87422f8e6f71SAmine Khaldi {
87432f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
87442f8e6f71SAmine Khaldi     UINT r;
87452f8e6f71SAmine Khaldi     externalui_record_ran = 1;
87462f8e6f71SAmine Khaldi     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
87472f8e6f71SAmine Khaldi     r = MsiRecordGetFieldCount(hrecord);
87482f8e6f71SAmine Khaldi     ok(r == 1, "expected 1, got %u\n", r);
87492f8e6f71SAmine Khaldi     r = MsiRecordGetInteger(hrecord, 1);
87502f8e6f71SAmine Khaldi     ok(r == 12345, "expected 12345, got %u\n", r);
87512f8e6f71SAmine Khaldi     return retval;
87522f8e6f71SAmine Khaldi }
87532f8e6f71SAmine Khaldi 
87542f8e6f71SAmine Khaldi static void test_externalui(void)
87552f8e6f71SAmine Khaldi {
87562f8e6f71SAmine Khaldi     /* test that external UI handlers work correctly */
87572f8e6f71SAmine Khaldi 
87582f8e6f71SAmine Khaldi     INSTALLUI_HANDLERA prev;
87592f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev_record;
87602f8e6f71SAmine Khaldi     MSIHANDLE hpkg, hrecord;
87612f8e6f71SAmine Khaldi     UINT r;
87622f8e6f71SAmine Khaldi     INT retval = 0;
87632f8e6f71SAmine Khaldi 
87642f8e6f71SAmine Khaldi     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
87652f8e6f71SAmine Khaldi 
87662f8e6f71SAmine Khaldi     r = package_from_db(create_package_db(), &hpkg);
87672f8e6f71SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
87682f8e6f71SAmine Khaldi     {
87692f8e6f71SAmine Khaldi         skip("Not enough rights to perform tests\n");
87702f8e6f71SAmine Khaldi         DeleteFileA(msifile);
87712f8e6f71SAmine Khaldi         return;
87722f8e6f71SAmine Khaldi     }
87732f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
87742f8e6f71SAmine Khaldi 
87752f8e6f71SAmine Khaldi     hrecord = MsiCreateRecord(1);
87762f8e6f71SAmine Khaldi     ok(hrecord, "Expected a valid record\n");
87772f8e6f71SAmine Khaldi     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
87782f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
87792f8e6f71SAmine Khaldi     r = MsiRecordSetInteger(hrecord, 1, 12345);
87802f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
87812f8e6f71SAmine Khaldi 
87822f8e6f71SAmine Khaldi     externalui_ran = 0;
87832f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87842f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87852f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87862f8e6f71SAmine Khaldi 
87872f8e6f71SAmine Khaldi     prev = MsiSetExternalUIA(prev, 0, NULL);
87882f8e6f71SAmine Khaldi     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
87892f8e6f71SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
87902f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
87912f8e6f71SAmine Khaldi 
87922f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87932f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87942f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87952f8e6f71SAmine Khaldi     ok(externalui_ran == 0, "external UI callback should not have run\n");
87962f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87972f8e6f71SAmine Khaldi 
87982f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
87992f8e6f71SAmine Khaldi 
88002f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
88012f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
88022f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
88032f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
88042f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
88052f8e6f71SAmine Khaldi 
88062f8e6f71SAmine Khaldi     retval = 1;
88072f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
88082f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
88092f8e6f71SAmine Khaldi     ok(r == 1, "expected 1, got %u\n", r);
88102f8e6f71SAmine Khaldi     ok(externalui_ran == 0, "external UI callback should not have run\n");
88112f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
88122f8e6f71SAmine Khaldi 
88132f8e6f71SAmine Khaldi     /* filter and context should be kept separately */
88142f8e6f71SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
88152f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
88162f8e6f71SAmine Khaldi 
88172f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
88182f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
88192f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
88202f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
88212f8e6f71SAmine Khaldi     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
88222f8e6f71SAmine Khaldi 
88232f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
88242f8e6f71SAmine Khaldi     DeleteFileA(msifile);
88252f8e6f71SAmine Khaldi }
88262f8e6f71SAmine Khaldi 
88272f8e6f71SAmine Khaldi struct externalui_message {
88282f8e6f71SAmine Khaldi     UINT message;
88292f8e6f71SAmine Khaldi     int field_count;
88302f8e6f71SAmine Khaldi     char field[4][100];
88312f8e6f71SAmine Khaldi     int match[4]; /* should we test for a match */
88322f8e6f71SAmine Khaldi     int optional;
88332f8e6f71SAmine Khaldi };
88342f8e6f71SAmine Khaldi 
88352f8e6f71SAmine Khaldi static struct externalui_message *sequence;
88362f8e6f71SAmine Khaldi static int sequence_count, sequence_size;
88372f8e6f71SAmine Khaldi 
88382f8e6f71SAmine Khaldi static void add_message(const struct externalui_message *msg)
88392f8e6f71SAmine Khaldi {
88402f8e6f71SAmine Khaldi     if (!sequence)
88412f8e6f71SAmine Khaldi     {
88422f8e6f71SAmine Khaldi         sequence_size = 10;
88432f8e6f71SAmine Khaldi         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
88442f8e6f71SAmine Khaldi     }
88452f8e6f71SAmine Khaldi     if (sequence_count == sequence_size)
88462f8e6f71SAmine Khaldi     {
88472f8e6f71SAmine Khaldi         sequence_size *= 2;
88482f8e6f71SAmine Khaldi         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
88492f8e6f71SAmine Khaldi     }
88502f8e6f71SAmine Khaldi 
88512f8e6f71SAmine Khaldi     assert(sequence);
88522f8e6f71SAmine Khaldi 
88532f8e6f71SAmine Khaldi     sequence[sequence_count++] = *msg;
88542f8e6f71SAmine Khaldi }
88552f8e6f71SAmine Khaldi 
88562f8e6f71SAmine Khaldi static void flush_sequence(void)
88572f8e6f71SAmine Khaldi {
88582f8e6f71SAmine Khaldi     HeapFree(GetProcessHeap(), 0, sequence);
88592f8e6f71SAmine Khaldi     sequence = NULL;
88602f8e6f71SAmine Khaldi     sequence_count = sequence_size = 0;
88612f8e6f71SAmine Khaldi }
88622f8e6f71SAmine Khaldi 
88632f8e6f71SAmine Khaldi static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
88642f8e6f71SAmine Khaldi                          const char *file, int line)
88652f8e6f71SAmine Khaldi {
88662f8e6f71SAmine Khaldi     static const struct externalui_message end_of_sequence = {0};
88672f8e6f71SAmine Khaldi     const struct externalui_message *actual;
88682f8e6f71SAmine Khaldi     int failcount = 0;
88692f8e6f71SAmine Khaldi     int i;
88702f8e6f71SAmine Khaldi 
88712f8e6f71SAmine Khaldi     add_message(&end_of_sequence);
88722f8e6f71SAmine Khaldi 
88732f8e6f71SAmine Khaldi     actual = sequence;
88742f8e6f71SAmine Khaldi 
88752f8e6f71SAmine Khaldi     while (expected->message && actual->message)
88762f8e6f71SAmine Khaldi     {
88772f8e6f71SAmine Khaldi         if (expected->message == actual->message)
88782f8e6f71SAmine Khaldi         {
8879f860a780SAmine Khaldi             if (expected->field_count < actual->field_count)
88802f8e6f71SAmine Khaldi             {
88812f8e6f71SAmine Khaldi                 todo_wine_if (todo)
88822f8e6f71SAmine Khaldi                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
88832f8e6f71SAmine Khaldi                                      context, expected->message, expected->field_count, actual->field_count);
88842f8e6f71SAmine Khaldi                 failcount++;
88852f8e6f71SAmine Khaldi             }
88862f8e6f71SAmine Khaldi 
88872f8e6f71SAmine Khaldi             for (i = 0; i <= actual->field_count; i++)
88882f8e6f71SAmine Khaldi             {
88892f8e6f71SAmine Khaldi                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
88902f8e6f71SAmine Khaldi                 {
88912f8e6f71SAmine Khaldi                     todo_wine_if (todo)
88922f8e6f71SAmine Khaldi                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
88932f8e6f71SAmine Khaldi                                          context, expected->message, i, expected->field[i], actual->field[i]);
88942f8e6f71SAmine Khaldi                     failcount++;
88952f8e6f71SAmine Khaldi                 }
88962f8e6f71SAmine Khaldi             }
88972f8e6f71SAmine Khaldi 
88982f8e6f71SAmine Khaldi             expected++;
88992f8e6f71SAmine Khaldi             actual++;
89002f8e6f71SAmine Khaldi         }
8901f860a780SAmine Khaldi         else if (expected->optional)
8902f860a780SAmine Khaldi         {
8903f860a780SAmine Khaldi             expected++;
8904f860a780SAmine Khaldi         }
89052f8e6f71SAmine Khaldi         else
89062f8e6f71SAmine Khaldi         {
89072f8e6f71SAmine Khaldi             todo_wine_if (todo)
89082f8e6f71SAmine Khaldi                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
89092f8e6f71SAmine Khaldi                                  context, expected->message, actual->message);
89102f8e6f71SAmine Khaldi             failcount++;
89112f8e6f71SAmine Khaldi             if (todo)
89122f8e6f71SAmine Khaldi                 goto done;
89132f8e6f71SAmine Khaldi             expected++;
89142f8e6f71SAmine Khaldi             actual++;
89152f8e6f71SAmine Khaldi         }
89162f8e6f71SAmine Khaldi     }
89172f8e6f71SAmine Khaldi 
89182f8e6f71SAmine Khaldi     if (expected->message || actual->message)
89192f8e6f71SAmine Khaldi     {
89202f8e6f71SAmine Khaldi         todo_wine_if (todo)
89212f8e6f71SAmine Khaldi             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
89222f8e6f71SAmine Khaldi                              context, expected->message, actual->message);
89232f8e6f71SAmine Khaldi         failcount++;
89242f8e6f71SAmine Khaldi     }
89252f8e6f71SAmine Khaldi 
89262f8e6f71SAmine Khaldi     if(todo && !failcount) /* succeeded yet marked todo */
89272f8e6f71SAmine Khaldi     {
89282f8e6f71SAmine Khaldi         todo_wine
89292f8e6f71SAmine Khaldi             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
89302f8e6f71SAmine Khaldi     }
89312f8e6f71SAmine Khaldi 
89322f8e6f71SAmine Khaldi done:
89332f8e6f71SAmine Khaldi     flush_sequence();
89342f8e6f71SAmine Khaldi }
89352f8e6f71SAmine Khaldi 
89362f8e6f71SAmine Khaldi #define ok_sequence(exp, contx, todo) \
89372f8e6f71SAmine Khaldi         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
89382f8e6f71SAmine Khaldi 
8939f860a780SAmine Khaldi /* don't use PROGRESS, which is timing-dependent,
8940f860a780SAmine Khaldi  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8941f860a780SAmine Khaldi static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8942f860a780SAmine Khaldi     INSTALLLOGMODE_FATALEXIT |
8943f860a780SAmine Khaldi     INSTALLLOGMODE_ERROR |
8944f860a780SAmine Khaldi     INSTALLLOGMODE_WARNING |
8945f860a780SAmine Khaldi     INSTALLLOGMODE_USER |
8946f860a780SAmine Khaldi     INSTALLLOGMODE_INFO |
8947f860a780SAmine Khaldi     INSTALLLOGMODE_FILESINUSE |
8948f860a780SAmine Khaldi     INSTALLLOGMODE_RESOLVESOURCE |
8949f860a780SAmine Khaldi     INSTALLLOGMODE_OUTOFDISKSPACE |
8950f860a780SAmine Khaldi     INSTALLLOGMODE_ACTIONSTART |
8951f860a780SAmine Khaldi     INSTALLLOGMODE_ACTIONDATA |
8952f860a780SAmine Khaldi     INSTALLLOGMODE_COMMONDATA |
8953f860a780SAmine Khaldi     INSTALLLOGMODE_INITIALIZE |
8954f860a780SAmine Khaldi     INSTALLLOGMODE_TERMINATE |
8955f860a780SAmine Khaldi     INSTALLLOGMODE_RMFILESINUSE |
8956f860a780SAmine Khaldi     INSTALLLOGMODE_INSTALLSTART |
8957f860a780SAmine Khaldi     INSTALLLOGMODE_INSTALLEND;
8958f860a780SAmine Khaldi 
89592f8e6f71SAmine Khaldi static const struct externalui_message empty_sequence[] = {
89602f8e6f71SAmine Khaldi     {0}
89612f8e6f71SAmine Khaldi };
89622f8e6f71SAmine Khaldi 
89632f8e6f71SAmine Khaldi static const struct externalui_message openpackage_nonexistent_sequence[] = {
89642f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
89652f8e6f71SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
89662f8e6f71SAmine Khaldi     {0}
89672f8e6f71SAmine Khaldi };
89682f8e6f71SAmine Khaldi 
89692f8e6f71SAmine Khaldi static const struct externalui_message openpackage_sequence[] = {
89702f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
89712f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
89722f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
89732f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
89742f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
89752f8e6f71SAmine Khaldi     {0}
89762f8e6f71SAmine Khaldi };
89772f8e6f71SAmine Khaldi 
89782f8e6f71SAmine Khaldi static const struct externalui_message processmessage_info_sequence[] = {
89792f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
89802f8e6f71SAmine Khaldi     {0}
89812f8e6f71SAmine Khaldi };
89822f8e6f71SAmine Khaldi 
89832f8e6f71SAmine Khaldi static const struct externalui_message processmessage_actionstart_sequence[] = {
89842f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
89852f8e6f71SAmine Khaldi     {0}
89862f8e6f71SAmine Khaldi };
89872f8e6f71SAmine Khaldi 
89882f8e6f71SAmine Khaldi static const struct externalui_message processmessage_actiondata_sequence[] = {
89892f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
89902f8e6f71SAmine Khaldi     {0}
89912f8e6f71SAmine Khaldi };
89922f8e6f71SAmine Khaldi 
89932f8e6f71SAmine Khaldi static const struct externalui_message processmessage_error_sequence[] = {
89942f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
89952f8e6f71SAmine Khaldi     {0}
89962f8e6f71SAmine Khaldi };
89972f8e6f71SAmine Khaldi 
89982f8e6f71SAmine Khaldi static const struct externalui_message processmessage_internal_error_sequence[] = {
89992f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
90002f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
90012f8e6f71SAmine Khaldi     {0}
90022f8e6f71SAmine Khaldi };
90032f8e6f71SAmine Khaldi 
90042f8e6f71SAmine Khaldi static const struct externalui_message processmessage_error_format_sequence[] = {
90052f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
90062f8e6f71SAmine Khaldi     {0}
90072f8e6f71SAmine Khaldi };
90082f8e6f71SAmine Khaldi 
90092f8e6f71SAmine Khaldi static const struct externalui_message doaction_costinitialize_sequence[] = {
90102f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
90112f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
90122f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
90132f8e6f71SAmine Khaldi     {0}
90142f8e6f71SAmine Khaldi };
90152f8e6f71SAmine Khaldi 
90162f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_sequence[] = {
90172f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
90182f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {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_custom_fullui_sequence[] = {
90242f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
90252f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
90262f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
90272f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
90282f8e6f71SAmine Khaldi     {0}
90292f8e6f71SAmine Khaldi };
90302f8e6f71SAmine Khaldi 
90312f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_cancel_sequence[] = {
90322f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
90332f8e6f71SAmine Khaldi     {0}
90342f8e6f71SAmine Khaldi };
90352f8e6f71SAmine Khaldi 
90362f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
90372f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
90382f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
90392f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
90402f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
90412f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
90422f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
90432f8e6f71SAmine Khaldi     {0}
90442f8e6f71SAmine Khaldi };
90452f8e6f71SAmine Khaldi 
90462f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_sequence[] = {
90472f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90482f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
90492f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90502f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
90512f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
90522f8e6f71SAmine Khaldi     {0}
90532f8e6f71SAmine Khaldi };
90542f8e6f71SAmine Khaldi 
90552f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_error_sequence[] = {
90562f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
90572f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
90582f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
90592f8e6f71SAmine Khaldi     {0}
90602f8e6f71SAmine Khaldi };
90612f8e6f71SAmine Khaldi 
90622f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_3_sequence[] = {
90632f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90642f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
90652f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90662f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
90672f8e6f71SAmine Khaldi     {0}
90682f8e6f71SAmine Khaldi };
90692f8e6f71SAmine Khaldi 
90702f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_12345_sequence[] = {
90712f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90722f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
90732f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90742f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
90752f8e6f71SAmine Khaldi     {0}
90762f8e6f71SAmine Khaldi };
90772f8e6f71SAmine Khaldi 
90782f8e6f71SAmine Khaldi static const struct externalui_message closehandle_sequence[] = {
90792f8e6f71SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
90802f8e6f71SAmine Khaldi     {0}
90812f8e6f71SAmine Khaldi };
90822f8e6f71SAmine Khaldi 
90832f8e6f71SAmine Khaldi static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
90842f8e6f71SAmine Khaldi {
90852f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
90862f8e6f71SAmine Khaldi     struct externalui_message msg;
90872f8e6f71SAmine Khaldi 
90882f8e6f71SAmine Khaldi     msg.message = message;
90892f8e6f71SAmine Khaldi     msg.field_count = 0;
90902f8e6f71SAmine Khaldi     strcpy(msg.field[0], string);
90912f8e6f71SAmine Khaldi     add_message(&msg);
90922f8e6f71SAmine Khaldi 
90932f8e6f71SAmine Khaldi     return retval;
90942f8e6f71SAmine Khaldi }
90952f8e6f71SAmine Khaldi 
90962f8e6f71SAmine Khaldi static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
90972f8e6f71SAmine Khaldi {
90982f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
90992f8e6f71SAmine Khaldi     struct externalui_message msg;
9100f860a780SAmine Khaldi     char buffer[256];
9101f860a780SAmine Khaldi     DWORD length;
9102f860a780SAmine Khaldi     UINT r;
91032f8e6f71SAmine Khaldi     int i;
91042f8e6f71SAmine Khaldi 
91052f8e6f71SAmine Khaldi     msg.message = message;
91062f8e6f71SAmine Khaldi     if (message == INSTALLMESSAGE_TERMINATE)
91072f8e6f71SAmine Khaldi     {
91082f8e6f71SAmine Khaldi         /* trying to access the record seems to hang on some versions of Windows */
91092f8e6f71SAmine Khaldi         msg.field_count = -1;
91102f8e6f71SAmine Khaldi         add_message(&msg);
91112f8e6f71SAmine Khaldi         return 1;
91122f8e6f71SAmine Khaldi     }
91132f8e6f71SAmine Khaldi     msg.field_count = MsiRecordGetFieldCount(hrecord);
91142f8e6f71SAmine Khaldi     for (i = 0; i <= msg.field_count; i++)
91152f8e6f71SAmine Khaldi     {
9116f860a780SAmine Khaldi         length = sizeof(buffer);
9117f860a780SAmine Khaldi         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
9118f860a780SAmine Khaldi         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
91192f8e6f71SAmine Khaldi         memcpy(msg.field[i], buffer, min(100, length+1));
91202f8e6f71SAmine Khaldi     }
91212f8e6f71SAmine Khaldi 
9122f860a780SAmine Khaldi     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
9123f860a780SAmine Khaldi     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
9124f860a780SAmine Khaldi         return retval;
9125f860a780SAmine Khaldi 
91262f8e6f71SAmine Khaldi     add_message(&msg);
91272f8e6f71SAmine Khaldi 
91282f8e6f71SAmine Khaldi     return retval;
91292f8e6f71SAmine Khaldi }
91302f8e6f71SAmine Khaldi 
91312f8e6f71SAmine Khaldi static void test_externalui_message(void)
91322f8e6f71SAmine Khaldi {
91332f8e6f71SAmine Khaldi     /* test that events trigger the correct sequence of messages */
91342f8e6f71SAmine Khaldi 
91352f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
91362f8e6f71SAmine Khaldi     MSIHANDLE hdb, hpkg, hrecord;
91372f8e6f71SAmine Khaldi     INT retval = 1;
91382f8e6f71SAmine Khaldi     UINT r;
91392f8e6f71SAmine Khaldi 
91402f8e6f71SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
91412f8e6f71SAmine Khaldi 
91422f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9143f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
91442f8e6f71SAmine Khaldi 
91452f8e6f71SAmine Khaldi     flush_sequence();
91462f8e6f71SAmine Khaldi 
91472f8e6f71SAmine Khaldi     CoInitialize(NULL);
91482f8e6f71SAmine Khaldi 
91492f8e6f71SAmine Khaldi     hdb = create_package_db();
91502f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
91512f8e6f71SAmine Khaldi 
91522f8e6f71SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
91532f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
91542f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
91552f8e6f71SAmine Khaldi 
91562f8e6f71SAmine Khaldi     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
91572f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
91582f8e6f71SAmine Khaldi     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
91592f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
91602f8e6f71SAmine Khaldi 
9161f860a780SAmine Khaldi     create_actiontext_table(hdb);
9162f860a780SAmine Khaldi     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9163f860a780SAmine Khaldi     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
91642f8e6f71SAmine Khaldi 
91652f8e6f71SAmine Khaldi     r = MsiOpenPackageA(NULL, &hpkg);
91662f8e6f71SAmine Khaldi     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
91672f8e6f71SAmine Khaldi     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
91682f8e6f71SAmine Khaldi 
91692f8e6f71SAmine Khaldi     r = MsiOpenPackageA("nonexistent", &hpkg);
91702f8e6f71SAmine Khaldi     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
91712f8e6f71SAmine Khaldi     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
91722f8e6f71SAmine Khaldi 
91732f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
91742f8e6f71SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
91752f8e6f71SAmine Khaldi     {
91762f8e6f71SAmine Khaldi         skip("Not enough rights to perform tests\n");
91772f8e6f71SAmine Khaldi         DeleteFileA(msifile);
91782f8e6f71SAmine Khaldi         return;
91792f8e6f71SAmine Khaldi     }
91802f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
91812f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
91822f8e6f71SAmine Khaldi 
91832f8e6f71SAmine Khaldi     /* Test MsiProcessMessage */
91842f8e6f71SAmine Khaldi     hrecord = MsiCreateRecord(3);
91852f8e6f71SAmine Khaldi     ok(hrecord, "failed to create record\n");
91862f8e6f71SAmine Khaldi 
91872f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "zero");
91882f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "one");
91892f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "two");
91902f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "three");
91912f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
91922f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91932f8e6f71SAmine Khaldi     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
91942f8e6f71SAmine Khaldi 
91952f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "name");
91962f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "description");
91972f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "template");
91982f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
91992f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
92002f8e6f71SAmine Khaldi     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
92012f8e6f71SAmine Khaldi 
92022f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "apple");
92032f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "cherry");
92042f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "banana");
92052f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "guava");
92062f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
92072f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
92082f8e6f71SAmine Khaldi     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
92092f8e6f71SAmine Khaldi 
92102f8e6f71SAmine Khaldi     /* non-internal error */
92112f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, NULL);
92122f8e6f71SAmine Khaldi     MsiRecordSetInteger(hrecord, 1, 1311);
92132f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
92142f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
92152f8e6f71SAmine Khaldi     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
92162f8e6f71SAmine Khaldi 
92172f8e6f71SAmine Khaldi     /* internal error */
92182f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, NULL);
92192f8e6f71SAmine Khaldi     MsiRecordSetInteger(hrecord, 1, 2726);
92202f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
92212f8e6f71SAmine Khaldi     ok(r == 0, "Expected 0, got %d\n", r);
92222f8e6f71SAmine Khaldi     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
92232f8e6f71SAmine Khaldi 
92242f8e6f71SAmine Khaldi     /* with format field */
92252f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "starfruit");
92262f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
92272f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
92282f8e6f71SAmine Khaldi     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
92292f8e6f71SAmine Khaldi 
92302f8e6f71SAmine Khaldi     /* Test a standard action */
92312f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "CostInitialize");
92322f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92332f8e6f71SAmine Khaldi     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
92342f8e6f71SAmine Khaldi 
92352f8e6f71SAmine Khaldi     /* Test a custom action */
92362f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92372f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92382f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
92392f8e6f71SAmine Khaldi 
92402f8e6f71SAmine Khaldi     /* close the package */
92412f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
92422f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
92432f8e6f71SAmine Khaldi 
92442f8e6f71SAmine Khaldi     /* Test dialogs */
92452f8e6f71SAmine Khaldi     hdb = create_package_db();
92462f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
92472f8e6f71SAmine Khaldi 
92482f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
92492f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92502f8e6f71SAmine Khaldi 
9251f860a780SAmine Khaldi     create_dialog_table(hdb);
9252f860a780SAmine Khaldi     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
92532f8e6f71SAmine Khaldi 
9254f860a780SAmine Khaldi     create_control_table(hdb);
9255f860a780SAmine Khaldi     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
92562f8e6f71SAmine Khaldi 
92572f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
92582f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
92592f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
92602f8e6f71SAmine Khaldi 
92612f8e6f71SAmine Khaldi     /* Test a custom action */
92622f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92632f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92642f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
92652f8e6f71SAmine Khaldi 
92662f8e6f71SAmine Khaldi     retval = 2;
92672f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92682f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
92692f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
92702f8e6f71SAmine Khaldi 
92712f8e6f71SAmine Khaldi     retval = 0;
92722f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92732f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92742f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
92752f8e6f71SAmine Khaldi 
92762f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92772f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92782f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
92792f8e6f71SAmine Khaldi 
92802f8e6f71SAmine Khaldi     retval = -1;
92812f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "error");
92822f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92832f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
92842f8e6f71SAmine Khaldi 
92852f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "error");
92862f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92872f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
92882f8e6f71SAmine Khaldi 
92892f8e6f71SAmine Khaldi     retval = -2;
92902f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92912f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92922f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
92932f8e6f71SAmine Khaldi 
92942f8e6f71SAmine Khaldi     retval = 3;
92952f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92962f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
92972f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
92982f8e6f71SAmine Khaldi 
92992f8e6f71SAmine Khaldi     retval = 12345;
93002f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
93012f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
93022f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
93032f8e6f71SAmine Khaldi 
93042f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
93052f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
93062f8e6f71SAmine Khaldi 
93072f8e6f71SAmine Khaldi     MsiCloseHandle(hrecord);
93082f8e6f71SAmine Khaldi     CoUninitialize();
93092f8e6f71SAmine Khaldi     DeleteFileA(msifile);
93102f8e6f71SAmine Khaldi     DeleteFileA("forcecodepage.idt");
93112f8e6f71SAmine Khaldi }
93122f8e6f71SAmine Khaldi 
93132f8e6f71SAmine Khaldi static const struct externalui_message controlevent_spawn_sequence[] = {
93142f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
93152f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
93162f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
93172f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
93182f8e6f71SAmine Khaldi 
93192f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
93202f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
93212f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
93222f8e6f71SAmine Khaldi 
93232f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
93242f8e6f71SAmine Khaldi 
93252f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
93262f8e6f71SAmine Khaldi     {0}
93272f8e6f71SAmine Khaldi };
93282f8e6f71SAmine Khaldi 
93292f8e6f71SAmine Khaldi static const struct externalui_message controlevent_spawn2_sequence[] = {
93302f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
93312f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
93322f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
93332f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
93342f8e6f71SAmine Khaldi 
93352f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
93362f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
93372f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
93382f8e6f71SAmine Khaldi 
93392f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
93402f8e6f71SAmine Khaldi 
93412f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
93422f8e6f71SAmine Khaldi     {0}
93432f8e6f71SAmine Khaldi };
93442f8e6f71SAmine Khaldi 
93452f8e6f71SAmine Khaldi static void test_controlevent(void)
93462f8e6f71SAmine Khaldi {
93472f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
93482f8e6f71SAmine Khaldi     MSIHANDLE hdb, hpkg;
93492f8e6f71SAmine Khaldi     UINT r;
93502f8e6f71SAmine Khaldi 
93512f8e6f71SAmine Khaldi     if (!winetest_interactive)
93522f8e6f71SAmine Khaldi     {
93532f8e6f71SAmine Khaldi         skip("interactive ControlEvent tests\n");
93542f8e6f71SAmine Khaldi         return;
93552f8e6f71SAmine Khaldi     }
93562f8e6f71SAmine Khaldi 
93572f8e6f71SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
93582f8e6f71SAmine Khaldi 
93592f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9360f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
93612f8e6f71SAmine Khaldi 
93622f8e6f71SAmine Khaldi     flush_sequence();
93632f8e6f71SAmine Khaldi 
93642f8e6f71SAmine Khaldi     CoInitialize(NULL);
93652f8e6f71SAmine Khaldi 
93662f8e6f71SAmine Khaldi     hdb = create_package_db();
93672f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
93682f8e6f71SAmine Khaldi 
93692f8e6f71SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
93702f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
93712f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
93722f8e6f71SAmine Khaldi 
9373f860a780SAmine Khaldi     create_dialog_table(hdb);
9374f860a780SAmine Khaldi     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9375f860a780SAmine Khaldi     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9376f860a780SAmine Khaldi     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9377f860a780SAmine Khaldi     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
93782f8e6f71SAmine Khaldi 
9379f860a780SAmine Khaldi     create_control_table(hdb);
9380f860a780SAmine Khaldi     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9381f860a780SAmine Khaldi     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9382f860a780SAmine Khaldi     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9383f860a780SAmine Khaldi     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
93842f8e6f71SAmine Khaldi 
9385f860a780SAmine Khaldi     create_controlevent_table(hdb);
9386f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9387f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
93882f8e6f71SAmine Khaldi 
9389f860a780SAmine Khaldi     create_custom_action_table(hdb);
9390f860a780SAmine Khaldi     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
93912f8e6f71SAmine Khaldi 
93922f8e6f71SAmine Khaldi     /* SpawnDialog and EndDialog should trigger after all other events */
9393f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9394f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
93952f8e6f71SAmine Khaldi 
93962f8e6f71SAmine Khaldi     /* Multiple dialog events cause only the last one to be triggered */
9397f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9398f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9399f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
94002f8e6f71SAmine Khaldi 
94012f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
94022f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
94032f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
94042f8e6f71SAmine Khaldi 
94052f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "spawn");
94062f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
94072f8e6f71SAmine Khaldi     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
94082f8e6f71SAmine Khaldi 
94092f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "spawn2");
94102f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
94112f8e6f71SAmine Khaldi     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
94122f8e6f71SAmine Khaldi 
94132f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
94142f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
94152f8e6f71SAmine Khaldi 
94162f8e6f71SAmine Khaldi     CoUninitialize();
94172f8e6f71SAmine Khaldi     DeleteFileA(msifile);
94182f8e6f71SAmine Khaldi     DeleteFileA("forcecodepage.idt");
94192f8e6f71SAmine Khaldi }
94202f8e6f71SAmine Khaldi 
9421f860a780SAmine Khaldi static const struct externalui_message toplevel_install_sequence[] = {
9422f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9423f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9424f860a780SAmine Khaldi 
9425f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9426f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9427f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9428f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9429f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9430f860a780SAmine Khaldi 
9431f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9432f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9433f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9434f860a780SAmine Khaldi 
9435f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9436f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9437f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9438f860a780SAmine Khaldi 
9439f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9440f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9441f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9442f860a780SAmine Khaldi 
9443f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9444f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9445f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9446f860a780SAmine Khaldi 
9447f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9448f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9449f860a780SAmine Khaldi 
9450f860a780SAmine Khaldi     /* property dump */
9451f860a780SAmine Khaldi 
9452f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9453f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9454f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9455f860a780SAmine Khaldi     {0}
9456f860a780SAmine Khaldi };
9457f860a780SAmine Khaldi 
9458f860a780SAmine Khaldi static const struct externalui_message toplevel_install_ui_sequence[] = {
9459f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9460f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9461f860a780SAmine Khaldi 
9462f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9463f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9464f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9465f860a780SAmine Khaldi 
9466f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9467f860a780SAmine Khaldi     {0}
9468f860a780SAmine Khaldi };
9469f860a780SAmine Khaldi 
9470f860a780SAmine Khaldi static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9471f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9472f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9473f860a780SAmine Khaldi 
9474f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9475f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9476f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9477f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9478f860a780SAmine Khaldi 
9479f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9480f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9481f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9482f860a780SAmine Khaldi 
9483f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9484f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9485f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9486f860a780SAmine Khaldi 
9487f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9488f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9489f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9490f860a780SAmine Khaldi 
9491f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9492f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9493f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9494f860a780SAmine Khaldi 
9495f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9496f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9497f860a780SAmine Khaldi 
9498f860a780SAmine Khaldi     /* property dump */
9499f860a780SAmine Khaldi 
9500f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9501f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9502f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9503f860a780SAmine Khaldi     {0}
9504f860a780SAmine Khaldi };
9505f860a780SAmine Khaldi 
9506f860a780SAmine Khaldi static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9507f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9508f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9509f860a780SAmine Khaldi 
9510f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9511f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9512f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9513f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9514f860a780SAmine Khaldi 
9515f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9516f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9517f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9518f860a780SAmine Khaldi 
9519f860a780SAmine Khaldi     /* property dump */
9520f860a780SAmine Khaldi 
9521f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9522f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9523f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9524f860a780SAmine Khaldi     {0}
9525f860a780SAmine Khaldi };
9526f860a780SAmine Khaldi 
9527f860a780SAmine Khaldi static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9528f860a780SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
9529f860a780SAmine Khaldi 
9530f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9531f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9532f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9533f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9534f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9535f860a780SAmine Khaldi 
9536f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9537f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9538f860a780SAmine Khaldi 
9539f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9540f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9541f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9542f860a780SAmine Khaldi 
9543f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9544f860a780SAmine Khaldi 
9545f860a780SAmine Khaldi     /* property dump */
9546f860a780SAmine Khaldi 
9547f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9548f860a780SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
9549f860a780SAmine Khaldi     {0}
9550f860a780SAmine Khaldi };
9551f860a780SAmine Khaldi 
9552f860a780SAmine Khaldi static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9553f860a780SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
9554f860a780SAmine Khaldi 
9555f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9556f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9557f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9558f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9559f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9560f860a780SAmine Khaldi 
9561f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9562f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9563f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9564f860a780SAmine Khaldi 
9565f860a780SAmine Khaldi     /* property dump */
9566f860a780SAmine Khaldi 
9567f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9568f860a780SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
9569f860a780SAmine Khaldi     {0}
9570f860a780SAmine Khaldi };
9571f860a780SAmine Khaldi 
9572f860a780SAmine Khaldi /* tests involving top-level actions: INSTALL, ExecuteAction */
9573f860a780SAmine Khaldi static void test_top_level_action(void)
9574f860a780SAmine Khaldi {
9575f860a780SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
9576f860a780SAmine Khaldi     MSIHANDLE hdb, hpkg;
9577f860a780SAmine Khaldi     UINT r;
9578f860a780SAmine Khaldi     char msifile_absolute[MAX_PATH];
9579f860a780SAmine Khaldi 
9580f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9581f860a780SAmine Khaldi 
9582f860a780SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9583f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9584f860a780SAmine Khaldi 
9585f860a780SAmine Khaldi     flush_sequence();
9586f860a780SAmine Khaldi 
9587f860a780SAmine Khaldi     CoInitialize(NULL);
9588f860a780SAmine Khaldi 
9589f860a780SAmine Khaldi     hdb = create_package_db();
9590f860a780SAmine Khaldi     ok(hdb, "failed to create database\n");
9591f860a780SAmine Khaldi 
9592f860a780SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9593f860a780SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9594f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9595f860a780SAmine Khaldi 
9596f860a780SAmine Khaldi     create_property_table(hdb);
9597f860a780SAmine Khaldi     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9598f860a780SAmine Khaldi 
9599f860a780SAmine Khaldi     create_install_execute_sequence_table(hdb);
9600f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9601f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9602f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9603f860a780SAmine Khaldi 
9604f860a780SAmine Khaldi     create_install_ui_sequence_table(hdb);
9605f860a780SAmine Khaldi     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9606f860a780SAmine Khaldi 
9607f860a780SAmine Khaldi     MsiDatabaseCommit(hdb);
9608f860a780SAmine Khaldi 
9609f860a780SAmine Khaldi     /* for some reason we have to open the package from file using an absolute path */
9610f860a780SAmine Khaldi     MsiCloseHandle(hdb);
9611f860a780SAmine Khaldi     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9612f860a780SAmine Khaldi     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9613f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9614f860a780SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9615f860a780SAmine Khaldi 
9616f860a780SAmine Khaldi     /* test INSTALL */
9617f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "INSTALL");
9618f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9619f860a780SAmine Khaldi     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9620f860a780SAmine Khaldi 
9621f860a780SAmine Khaldi     /* test INSTALL with reduced+ UI */
9622f860a780SAmine Khaldi     /* for some reason we need to re-open the package to change the internal UI */
9623f860a780SAmine Khaldi     MsiCloseHandle(hpkg);
9624f860a780SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9625f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9626f860a780SAmine Khaldi     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9627f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9628f860a780SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9629f860a780SAmine Khaldi 
9630f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "INSTALL");
9631f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9632f860a780SAmine Khaldi     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9633f860a780SAmine Khaldi 
9634f860a780SAmine Khaldi     /* test ExecuteAction with EXECUTEACTION property unset */
9635f860a780SAmine Khaldi     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9636f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "ExecuteAction");
9637f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9638f860a780SAmine Khaldi     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9639f860a780SAmine Khaldi 
9640f860a780SAmine Khaldi     /* test ExecuteAction with EXECUTEACTION property set */
9641f860a780SAmine Khaldi     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9642f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "ExecuteAction");
9643f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9644f860a780SAmine Khaldi     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9645f860a780SAmine Khaldi 
9646f860a780SAmine Khaldi     MsiCloseHandle(hpkg);
9647f860a780SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9648f860a780SAmine Khaldi 
9649f860a780SAmine Khaldi     /* test MsiInstallProduct() */
9650f860a780SAmine Khaldi     r = MsiInstallProductA(msifile_absolute, NULL);
9651f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9652f860a780SAmine Khaldi     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9653f860a780SAmine Khaldi 
9654f860a780SAmine Khaldi     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9655f860a780SAmine Khaldi     todo_wine
9656f860a780SAmine Khaldi     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9657f860a780SAmine Khaldi     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9658f860a780SAmine Khaldi 
9659f860a780SAmine Khaldi     CoUninitialize();
9660f860a780SAmine Khaldi     DeleteFileA(msifile);
9661f860a780SAmine Khaldi     DeleteFileA("forcecodepage.idt");
9662f860a780SAmine Khaldi }
9663f860a780SAmine Khaldi 
9664c2c66affSColin Finck START_TEST(package)
9665c2c66affSColin Finck {
9666c2c66affSColin Finck     STATEMGRSTATUS status;
9667c2c66affSColin Finck     BOOL ret = FALSE;
9668c2c66affSColin Finck 
9669c2c66affSColin Finck     init_functionpointers();
9670c2c66affSColin Finck 
9671c2c66affSColin Finck     if (pIsWow64Process)
9672c2c66affSColin Finck         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9673c2c66affSColin Finck 
9674c2c66affSColin Finck     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
9675c2c66affSColin Finck 
9676c2c66affSColin Finck     /* Create a restore point ourselves so we circumvent the multitude of restore points
9677c2c66affSColin Finck      * that would have been created by all the installation and removal tests.
9678c2c66affSColin Finck      *
9679c2c66affSColin Finck      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9680c2c66affSColin Finck      * creation of restore points.
9681c2c66affSColin Finck      */
9682c2c66affSColin Finck     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9683c2c66affSColin Finck     {
9684c2c66affSColin Finck         memset(&status, 0, sizeof(status));
9685c2c66affSColin Finck         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9686c2c66affSColin Finck     }
9687c2c66affSColin Finck 
9688c2c66affSColin Finck     test_createpackage();
9689c2c66affSColin Finck     test_doaction();
9690c2c66affSColin Finck     test_gettargetpath_bad();
9691c2c66affSColin Finck     test_settargetpath();
9692c2c66affSColin Finck     test_props();
9693c2c66affSColin Finck     test_property_table();
9694c2c66affSColin Finck     test_condition();
9695c2c66affSColin Finck     test_msipackage();
9696c2c66affSColin Finck     test_formatrecord2();
9697f860a780SAmine Khaldi     test_formatrecord_tables();
9698c2c66affSColin Finck     test_states();
9699c2c66affSColin Finck     test_removefiles();
9700c2c66affSColin Finck     test_appsearch();
9701c2c66affSColin Finck     test_appsearch_complocator();
9702c2c66affSColin Finck     test_appsearch_reglocator();
9703c2c66affSColin Finck     test_appsearch_inilocator();
9704c2c66affSColin Finck     test_appsearch_drlocator();
9705c2c66affSColin Finck     test_featureparents();
9706c2c66affSColin Finck     test_installprops();
9707c2c66affSColin Finck     test_launchconditions();
9708c2c66affSColin Finck     test_ccpsearch();
9709c2c66affSColin Finck     test_complocator();
9710c2c66affSColin Finck     test_MsiGetSourcePath();
9711c2c66affSColin Finck     test_shortlongsource();
9712c2c66affSColin Finck     test_sourcedir();
9713c2c66affSColin Finck     test_access();
9714c2c66affSColin Finck     test_emptypackage();
9715c2c66affSColin Finck     test_MsiGetProductProperty();
9716c2c66affSColin Finck     test_MsiSetProperty();
9717c2c66affSColin Finck     test_MsiApplyMultiplePatches();
9718c2c66affSColin Finck     test_MsiApplyPatch();
9719*818a84ddSwinesync     test_costs();
9720c2c66affSColin Finck     test_MsiDatabaseCommit();
97212f8e6f71SAmine Khaldi     test_externalui();
97222f8e6f71SAmine Khaldi     test_externalui_message();
97232f8e6f71SAmine Khaldi     test_controlevent();
9724f860a780SAmine Khaldi     test_top_level_action();
9725c2c66affSColin Finck 
9726c2c66affSColin Finck     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9727c2c66affSColin Finck     {
9728c2c66affSColin Finck         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9729c2c66affSColin Finck         if (ret)
9730c2c66affSColin Finck             remove_restore_point(status.llSequenceNumber);
9731c2c66affSColin Finck     }
9732c2c66affSColin Finck }
9733