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);
19086676451Swinesync     if (dwMaxLen > ARRAY_SIZE(szNameBuf))
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 
75496486643Swinesync static UINT create_upgrade_table( MSIHANDLE hdb )
75596486643Swinesync {
75696486643Swinesync     UINT r = run_query( hdb,
75796486643Swinesync             "CREATE TABLE `Upgrade` ("
75896486643Swinesync             "`UpgradeCode` CHAR(38) NOT NULL, "
75996486643Swinesync             "`VersionMin` CHAR(20), "
76096486643Swinesync             "`VersionMax` CHAR(20), "
76196486643Swinesync             "`Language` CHAR(255), "
76296486643Swinesync             "`Attributes` SHORT, "
76396486643Swinesync             "`Remove` CHAR(255), "
76496486643Swinesync             "`ActionProperty` CHAR(72) NOT NULL "
76596486643Swinesync             "PRIMARY KEY `UpgradeCode`, `VersionMin`, `VersionMax`, `Language`)" );
76696486643Swinesync     ok(r == ERROR_SUCCESS, "Failed to create Upgrade table: %u\n", r);
76796486643Swinesync     return r;
76896486643Swinesync }
76996486643Swinesync 
770f860a780SAmine Khaldi static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
771f860a780SAmine Khaldi {
772f860a780SAmine Khaldi     char *query;
773f860a780SAmine Khaldi     UINT sz, r;
774f860a780SAmine Khaldi 
775f860a780SAmine Khaldi     sz = strlen(values) + strlen(insert) + 1;
776f860a780SAmine Khaldi     query = HeapAlloc(GetProcessHeap(), 0, sz);
777f860a780SAmine Khaldi     sprintf(query, insert, values);
778f860a780SAmine Khaldi     r = run_query(hdb, query);
779f860a780SAmine Khaldi     HeapFree(GetProcessHeap(), 0, query);
780f860a780SAmine Khaldi     ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
781f860a780SAmine Khaldi     return r;
782c2c66affSColin Finck }
783c2c66affSColin Finck 
784f860a780SAmine Khaldi #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
785f860a780SAmine Khaldi                "INSERT INTO `Component`  " \
786f860a780SAmine Khaldi                "(`Component`, `ComponentId`, `Directory_`, " \
787c2c66affSColin Finck                "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
788c2c66affSColin Finck 
789f860a780SAmine Khaldi #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
790f860a780SAmine Khaldi                "INSERT INTO `Directory` " \
791c2c66affSColin Finck                "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
792c2c66affSColin Finck 
793f860a780SAmine Khaldi #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
794f860a780SAmine Khaldi                "INSERT INTO `Feature` " \
795f860a780SAmine Khaldi                "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
796c2c66affSColin Finck                "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
797c2c66affSColin Finck 
798f860a780SAmine Khaldi #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
799f860a780SAmine Khaldi                "INSERT INTO `FeatureComponents` " \
800c2c66affSColin Finck                "(`Feature_`, `Component_`) VALUES( %s )")
801c2c66affSColin Finck 
802f860a780SAmine Khaldi #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
803f860a780SAmine Khaldi                "INSERT INTO `File` " \
804f860a780SAmine Khaldi                "(`File`, `Component_`, `FileName`, `FileSize`, " \
805c2c66affSColin Finck                "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
806c2c66affSColin Finck 
807f860a780SAmine Khaldi #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
808f860a780SAmine Khaldi                "INSERT INTO `AppSearch` " \
809c2c66affSColin Finck                "(`Property`, `Signature_`) VALUES( %s )")
810c2c66affSColin Finck 
811f860a780SAmine Khaldi #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
812f860a780SAmine Khaldi                "INSERT INTO `Signature` " \
813f860a780SAmine Khaldi                "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
814f860a780SAmine Khaldi                " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
815c2c66affSColin Finck                "VALUES( %s )")
816c2c66affSColin Finck 
817f860a780SAmine Khaldi #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
818f860a780SAmine Khaldi                "INSERT INTO `LaunchCondition` " \
819c2c66affSColin Finck                "(`Condition`, `Description`) VALUES( %s )")
820c2c66affSColin Finck 
821f860a780SAmine Khaldi #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
822c2c66affSColin Finck                "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
823c2c66affSColin Finck 
82496486643Swinesync #define update_ProductVersion_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
82596486643Swinesync                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductVersion'")
82696486643Swinesync 
82796486643Swinesync #define update_ProductCode_property(hdb, value) add_entry(__FILE__, __LINE__, "Property", hdb, value, \
82896486643Swinesync                "UPDATE `Property` SET `Value` = '%s' WHERE `Property` = 'ProductCode'")
82996486643Swinesync 
830f860a780SAmine Khaldi #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
831f860a780SAmine Khaldi                "INSERT INTO `InstallExecuteSequence` " \
832c2c66affSColin Finck                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
833c2c66affSColin Finck 
834f860a780SAmine Khaldi #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
835f860a780SAmine Khaldi                "INSERT INTO `InstallUISequence` " \
836f860a780SAmine Khaldi                "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
837f860a780SAmine Khaldi 
838f860a780SAmine Khaldi #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
839f860a780SAmine Khaldi                "INSERT INTO `Media` " \
840f860a780SAmine Khaldi                "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
841c2c66affSColin Finck                "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
842c2c66affSColin Finck 
843f860a780SAmine Khaldi #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
844c2c66affSColin Finck                "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
845c2c66affSColin Finck 
846f860a780SAmine Khaldi #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
847f860a780SAmine Khaldi                "INSERT INTO `DrLocator` " \
848c2c66affSColin Finck                "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
849c2c66affSColin Finck 
850f860a780SAmine Khaldi #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
851f860a780SAmine Khaldi                "INSERT INTO `CompLocator` " \
852c2c66affSColin Finck                "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
853c2c66affSColin Finck 
854f860a780SAmine Khaldi #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
855f860a780SAmine Khaldi                "INSERT INTO `IniLocator` " \
856f860a780SAmine Khaldi                "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
857c2c66affSColin Finck                "VALUES( %s )")
858c2c66affSColin Finck 
859f860a780SAmine Khaldi #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
860f860a780SAmine Khaldi                "INSERT INTO `CustomAction`  " \
861c2c66affSColin Finck                "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
862c2c66affSColin Finck 
863f860a780SAmine Khaldi #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
864f860a780SAmine Khaldi                "INSERT INTO `Dialog` " \
8652f8e6f71SAmine Khaldi                "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
8662f8e6f71SAmine Khaldi 
867f860a780SAmine Khaldi #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
868f860a780SAmine Khaldi                "INSERT INTO `Control` " \
8692f8e6f71SAmine Khaldi                "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
8702f8e6f71SAmine Khaldi 
871f860a780SAmine Khaldi #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
872f860a780SAmine Khaldi                "INSERT INTO `ControlEvent` " \
8732f8e6f71SAmine Khaldi                "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
8742f8e6f71SAmine Khaldi 
875f860a780SAmine Khaldi #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
876f860a780SAmine Khaldi                "INSERT INTO `ActionText` " \
8772f8e6f71SAmine Khaldi                "(`Action`, `Description`, `Template`) VALUES( %s )");
8782f8e6f71SAmine Khaldi 
87996486643Swinesync #define add_upgrade_entry(hdb, values) add_entry(__FILE__, __LINE__, "Upgrade", hdb, values, \
88096486643Swinesync                "INSERT INTO `Upgrade` " \
88196486643Swinesync                "(`UpgradeCode`, `VersionMin`, `VersionMax`, `Language`, `Attributes`, `Remove`, `ActionProperty`) VALUES( %s )");
88296486643Swinesync 
883c2c66affSColin Finck static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
884c2c66affSColin Finck                                   const char *name, UINT type )
885c2c66affSColin Finck {
886c2c66affSColin Finck     const char insert[] =
887c2c66affSColin Finck         "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
888c2c66affSColin Finck         "VALUES( '%s', %u, '%s', '%s', %u )";
889c2c66affSColin Finck     char *query;
890c2c66affSColin Finck     UINT sz, r;
891c2c66affSColin Finck 
892c2c66affSColin Finck     sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
893c2c66affSColin Finck     query = HeapAlloc( GetProcessHeap(), 0, sz );
894c2c66affSColin Finck     sprintf( query, insert, sig, root, path, name, type );
895c2c66affSColin Finck     r = run_query( hdb, query );
896c2c66affSColin Finck     HeapFree( GetProcessHeap(), 0, query );
897f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
898c2c66affSColin Finck     return r;
899c2c66affSColin Finck }
900c2c66affSColin Finck 
901c2c66affSColin Finck static UINT set_summary_info(MSIHANDLE hdb)
902c2c66affSColin Finck {
903c2c66affSColin Finck     UINT res;
904c2c66affSColin Finck     MSIHANDLE suminfo;
905c2c66affSColin Finck 
906c2c66affSColin Finck     /* build summary info */
907c2c66affSColin Finck     res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
908c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
909c2c66affSColin Finck 
910c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
911c2c66affSColin Finck                         "Installation Database");
912c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
913c2c66affSColin Finck 
914c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
915c2c66affSColin Finck                         "Installation Database");
916c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
917c2c66affSColin Finck 
918c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
919c2c66affSColin Finck                         "Wine Hackers");
920c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
921c2c66affSColin Finck 
922c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
923c2c66affSColin Finck                     ";1033");
924c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
925c2c66affSColin Finck 
926c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
927c2c66affSColin Finck                     "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
928c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
929c2c66affSColin Finck 
930c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
931c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
932c2c66affSColin Finck 
933c2c66affSColin Finck     res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
934c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
935c2c66affSColin Finck 
936c2c66affSColin Finck     res = MsiSummaryInfoPersist(suminfo);
937c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
938c2c66affSColin Finck 
939c2c66affSColin Finck     res = MsiCloseHandle( suminfo);
940c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
941c2c66affSColin Finck 
942c2c66affSColin Finck     return res;
943c2c66affSColin Finck }
944c2c66affSColin Finck 
945c2c66affSColin Finck 
946c2c66affSColin Finck static MSIHANDLE create_package_db(void)
947c2c66affSColin Finck {
948c2c66affSColin Finck     MSIHANDLE hdb = 0;
949c2c66affSColin Finck     UINT res;
950c2c66affSColin Finck 
951c2c66affSColin Finck     DeleteFileA(msifile);
952c2c66affSColin Finck 
953c2c66affSColin Finck     /* create an empty database */
954c2c66affSColin Finck     res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
955c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
956c2c66affSColin Finck     if( res != ERROR_SUCCESS )
957c2c66affSColin Finck         return hdb;
958c2c66affSColin Finck 
959c2c66affSColin Finck     res = MsiDatabaseCommit( hdb );
960c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
961c2c66affSColin Finck 
962c2c66affSColin Finck     res = set_summary_info(hdb);
963c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
964c2c66affSColin Finck 
965c2c66affSColin Finck     res = run_query( hdb,
966c2c66affSColin Finck             "CREATE TABLE `Directory` ( "
967c2c66affSColin Finck             "`Directory` CHAR(255) NOT NULL, "
968c2c66affSColin Finck             "`Directory_Parent` CHAR(255), "
969c2c66affSColin Finck             "`DefaultDir` CHAR(255) NOT NULL "
970c2c66affSColin Finck             "PRIMARY KEY `Directory`)" );
971c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
972c2c66affSColin Finck 
973c2c66affSColin Finck     return hdb;
974c2c66affSColin Finck }
975c2c66affSColin Finck 
976c2c66affSColin Finck static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
977c2c66affSColin Finck {
978c2c66affSColin Finck     UINT res;
979c2c66affSColin Finck     CHAR szPackage[12];
980c2c66affSColin Finck     MSIHANDLE hPackage;
981c2c66affSColin Finck 
982c2c66affSColin Finck     sprintf(szPackage, "#%u", hdb);
983c2c66affSColin Finck     res = MsiOpenPackageA(szPackage, &hPackage);
984c2c66affSColin Finck     if (res != ERROR_SUCCESS)
985c2c66affSColin Finck     {
986c2c66affSColin Finck         MsiCloseHandle(hdb);
987c2c66affSColin Finck         return res;
988c2c66affSColin Finck     }
989c2c66affSColin Finck 
990c2c66affSColin Finck     res = MsiCloseHandle(hdb);
991c2c66affSColin Finck     if (res != ERROR_SUCCESS)
992c2c66affSColin Finck     {
993c2c66affSColin Finck         MsiCloseHandle(hPackage);
994c2c66affSColin Finck         return res;
995c2c66affSColin Finck     }
996c2c66affSColin Finck 
997c2c66affSColin Finck     *handle = hPackage;
998c2c66affSColin Finck     return ERROR_SUCCESS;
999c2c66affSColin Finck }
1000c2c66affSColin Finck 
10012f8e6f71SAmine Khaldi static void create_file_data(LPCSTR name, LPCSTR data)
1002c2c66affSColin Finck {
1003c2c66affSColin Finck     HANDLE file;
1004c2c66affSColin Finck     DWORD written;
1005c2c66affSColin Finck 
1006c2c66affSColin Finck     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1007c2c66affSColin Finck     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
10082f8e6f71SAmine Khaldi     if (file == INVALID_HANDLE_VALUE)
10092f8e6f71SAmine Khaldi         return;
10102f8e6f71SAmine Khaldi 
10112f8e6f71SAmine Khaldi     WriteFile(file, data, strlen(data), &written, NULL);
1012c2c66affSColin Finck     WriteFile(file, "\n", strlen("\n"), &written, NULL);
10132f8e6f71SAmine Khaldi 
1014c2c66affSColin Finck     CloseHandle(file);
1015c2c66affSColin Finck }
1016c2c66affSColin Finck 
10172f8e6f71SAmine Khaldi static void create_test_file(const CHAR *name)
10182f8e6f71SAmine Khaldi {
10192f8e6f71SAmine Khaldi     create_file_data(name, name);
10202f8e6f71SAmine Khaldi }
10212f8e6f71SAmine Khaldi 
1022c2c66affSColin Finck typedef struct _tagVS_VERSIONINFO
1023c2c66affSColin Finck {
1024c2c66affSColin Finck     WORD wLength;
1025c2c66affSColin Finck     WORD wValueLength;
1026c2c66affSColin Finck     WORD wType;
1027c2c66affSColin Finck     WCHAR szKey[1];
1028c2c66affSColin Finck     WORD wPadding1[1];
1029c2c66affSColin Finck     VS_FIXEDFILEINFO Value;
1030c2c66affSColin Finck     WORD wPadding2[1];
1031c2c66affSColin Finck     WORD wChildren[1];
1032c2c66affSColin Finck } VS_VERSIONINFO;
1033c2c66affSColin Finck 
1034c2c66affSColin Finck #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1035c2c66affSColin Finck #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1036c2c66affSColin Finck 
1037c2c66affSColin Finck static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
1038c2c66affSColin Finck {
1039c2c66affSColin Finck     VS_VERSIONINFO *pVerInfo;
1040c2c66affSColin Finck     VS_FIXEDFILEINFO *pFixedInfo;
1041c2c66affSColin Finck     LPBYTE buffer, ofs;
1042c2c66affSColin Finck     CHAR path[MAX_PATH];
1043c2c66affSColin Finck     DWORD handle, size;
1044c2c66affSColin Finck     HANDLE resource;
1045c2c66affSColin Finck     BOOL ret = FALSE;
1046c2c66affSColin Finck 
1047c2c66affSColin Finck     GetSystemDirectoryA(path, MAX_PATH);
1048c2c66affSColin Finck     /* Some dlls can't be updated on Vista/W2K8 */
1049c2c66affSColin Finck     lstrcatA(path, "\\version.dll");
1050c2c66affSColin Finck 
1051c2c66affSColin Finck     CopyFileA(path, name, FALSE);
1052c2c66affSColin Finck 
1053c2c66affSColin Finck     size = GetFileVersionInfoSizeA(path, &handle);
1054c2c66affSColin Finck     buffer = HeapAlloc(GetProcessHeap(), 0, size);
1055c2c66affSColin Finck 
1056c2c66affSColin Finck     GetFileVersionInfoA(path, 0, size, buffer);
1057c2c66affSColin Finck 
1058c2c66affSColin Finck     pVerInfo = (VS_VERSIONINFO *)buffer;
1059c2c66affSColin Finck     ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1060c2c66affSColin Finck     pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1061c2c66affSColin Finck 
1062c2c66affSColin Finck     pFixedInfo->dwFileVersionMS = ms;
1063c2c66affSColin Finck     pFixedInfo->dwFileVersionLS = ls;
1064c2c66affSColin Finck     pFixedInfo->dwProductVersionMS = ms;
1065c2c66affSColin Finck     pFixedInfo->dwProductVersionLS = ls;
1066c2c66affSColin Finck 
1067c2c66affSColin Finck     resource = BeginUpdateResourceA(name, FALSE);
1068c2c66affSColin Finck     if (!resource)
1069c2c66affSColin Finck         goto done;
1070c2c66affSColin Finck 
1071c2c66affSColin Finck     if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
1072c2c66affSColin Finck                          MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1073c2c66affSColin Finck         goto done;
1074c2c66affSColin Finck 
1075c2c66affSColin Finck     if (!EndUpdateResourceA(resource, FALSE))
1076c2c66affSColin Finck         goto done;
1077c2c66affSColin Finck 
1078c2c66affSColin Finck     ret = TRUE;
1079c2c66affSColin Finck 
1080c2c66affSColin Finck done:
1081c2c66affSColin Finck     HeapFree(GetProcessHeap(), 0, buffer);
1082c2c66affSColin Finck     return ret;
1083c2c66affSColin Finck }
1084c2c66affSColin Finck 
1085c2c66affSColin Finck static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1086c2c66affSColin Finck {
1087c2c66affSColin Finck     RESTOREPOINTINFOA spec;
1088c2c66affSColin Finck 
1089c2c66affSColin Finck     spec.dwEventType = event_type;
1090c2c66affSColin Finck     spec.dwRestorePtType = APPLICATION_INSTALL;
1091c2c66affSColin Finck     spec.llSequenceNumber = status->llSequenceNumber;
1092c2c66affSColin Finck     lstrcpyA(spec.szDescription, "msitest restore point");
1093c2c66affSColin Finck 
1094c2c66affSColin Finck     return pSRSetRestorePointA(&spec, status);
1095c2c66affSColin Finck }
1096c2c66affSColin Finck 
1097c2c66affSColin Finck static void remove_restore_point(DWORD seq_number)
1098c2c66affSColin Finck {
1099c2c66affSColin Finck     DWORD res;
1100c2c66affSColin Finck 
1101c2c66affSColin Finck     res = pSRRemoveRestorePoint(seq_number);
1102c2c66affSColin Finck     if (res != ERROR_SUCCESS)
1103c2c66affSColin Finck         trace("Failed to remove the restore point : %08x\n", res);
1104c2c66affSColin Finck }
1105c2c66affSColin Finck 
1106c2c66affSColin Finck static BOOL is_root(const char *path)
1107c2c66affSColin Finck {
1108c2c66affSColin Finck     return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1109c2c66affSColin Finck }
1110c2c66affSColin Finck 
1111c2c66affSColin Finck static void test_createpackage(void)
1112c2c66affSColin Finck {
1113c2c66affSColin Finck     MSIHANDLE hPackage = 0;
1114c2c66affSColin Finck     UINT res;
1115c2c66affSColin Finck 
1116c2c66affSColin Finck     res = package_from_db(create_package_db(), &hPackage);
1117c2c66affSColin Finck     if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1118c2c66affSColin Finck     {
1119c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1120c2c66affSColin Finck         DeleteFileA(msifile);
1121c2c66affSColin Finck         return;
1122c2c66affSColin Finck     }
1123c2c66affSColin Finck     ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1124c2c66affSColin Finck 
1125c2c66affSColin Finck     res = MsiCloseHandle( hPackage);
1126c2c66affSColin Finck     ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1127c2c66affSColin Finck     DeleteFileA(msifile);
1128c2c66affSColin Finck }
1129c2c66affSColin Finck 
1130c2c66affSColin Finck static void test_doaction( void )
1131c2c66affSColin Finck {
1132c2c66affSColin Finck     MSIHANDLE hpkg;
1133c2c66affSColin Finck     UINT r;
1134c2c66affSColin Finck 
1135c2c66affSColin Finck     r = MsiDoActionA( -1, NULL );
1136c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1137c2c66affSColin Finck 
1138c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1139c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1140c2c66affSColin Finck     {
1141c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1142c2c66affSColin Finck         DeleteFileA(msifile);
1143c2c66affSColin Finck         return;
1144c2c66affSColin Finck     }
1145c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1146c2c66affSColin Finck 
1147c2c66affSColin Finck     r = MsiDoActionA(hpkg, NULL);
1148c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1149c2c66affSColin Finck 
1150c2c66affSColin Finck     r = MsiDoActionA(0, "boo");
1151c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1152c2c66affSColin Finck 
1153c2c66affSColin Finck     r = MsiDoActionA(hpkg, "boo");
1154c2c66affSColin Finck     ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1155c2c66affSColin Finck 
1156c2c66affSColin Finck     MsiCloseHandle( hpkg );
1157c2c66affSColin Finck     DeleteFileA(msifile);
1158c2c66affSColin Finck }
1159c2c66affSColin Finck 
1160c2c66affSColin Finck static void test_gettargetpath_bad(void)
1161c2c66affSColin Finck {
1162c2c66affSColin Finck     static const WCHAR boo[] = {'b','o','o',0};
1163c2c66affSColin Finck     static const WCHAR empty[] = {0};
1164c2c66affSColin Finck     char buffer[0x80];
1165c2c66affSColin Finck     WCHAR bufferW[0x80];
1166c2c66affSColin Finck     MSIHANDLE hpkg;
1167c2c66affSColin Finck     DWORD sz;
1168c2c66affSColin Finck     UINT r;
1169c2c66affSColin Finck 
1170c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1171c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1172c2c66affSColin Finck     {
1173c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1174c2c66affSColin Finck         DeleteFileA(msifile);
1175c2c66affSColin Finck         return;
1176c2c66affSColin Finck     }
1177c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1178c2c66affSColin Finck 
1179c2c66affSColin Finck     r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1180c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1181c2c66affSColin Finck 
1182c2c66affSColin Finck     r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1183c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1184c2c66affSColin Finck 
1185c2c66affSColin Finck     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1186c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1187c2c66affSColin Finck 
1188c2c66affSColin Finck     r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1189c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1190c2c66affSColin Finck 
1191c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1192c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1193c2c66affSColin Finck 
1194c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1195c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1196c2c66affSColin Finck 
1197c2c66affSColin Finck     sz = 0;
1198c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1199c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1200c2c66affSColin Finck 
1201c2c66affSColin Finck     r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1202c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1203c2c66affSColin Finck 
1204c2c66affSColin Finck     r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1205c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1206c2c66affSColin Finck 
1207c2c66affSColin Finck     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1208c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1209c2c66affSColin Finck 
1210c2c66affSColin Finck     r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1211c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1212c2c66affSColin Finck 
1213c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1214c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1215c2c66affSColin Finck 
1216c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1217c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1218c2c66affSColin Finck 
1219c2c66affSColin Finck     sz = 0;
1220c2c66affSColin Finck     r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1221c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1222c2c66affSColin Finck 
1223c2c66affSColin Finck     MsiCloseHandle( hpkg );
1224c2c66affSColin Finck     DeleteFileA(msifile);
1225c2c66affSColin Finck }
1226c2c66affSColin Finck 
1227c2c66affSColin Finck static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1228c2c66affSColin Finck {
1229c2c66affSColin Finck     UINT r;
1230c2c66affSColin Finck     DWORD size;
1231c2c66affSColin Finck     MSIHANDLE rec;
1232c2c66affSColin Finck 
1233c2c66affSColin Finck     rec = MsiCreateRecord( 1 );
1234c2c66affSColin Finck     ok(rec, "MsiCreate record failed\n");
1235c2c66affSColin Finck 
1236c2c66affSColin Finck     r = MsiRecordSetStringA( rec, 0, file );
1237c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1238c2c66affSColin Finck 
1239c2c66affSColin Finck     size = MAX_PATH;
1240c2c66affSColin Finck     r = MsiFormatRecordA( hpkg, rec, buff, &size );
1241c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1242c2c66affSColin Finck 
1243c2c66affSColin Finck     MsiCloseHandle( rec );
1244c2c66affSColin Finck }
1245c2c66affSColin Finck 
1246c2c66affSColin Finck static void test_settargetpath(void)
1247c2c66affSColin Finck {
1248c2c66affSColin Finck     char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1249c2c66affSColin Finck     DWORD sz;
1250c2c66affSColin Finck     MSIHANDLE hpkg;
1251c2c66affSColin Finck     UINT r;
1252c2c66affSColin Finck     MSIHANDLE hdb;
1253c2c66affSColin Finck 
1254c2c66affSColin Finck     hdb = create_package_db();
1255c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
1256c2c66affSColin Finck 
1257f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1258c2c66affSColin Finck 
1259f860a780SAmine Khaldi     create_component_table( hdb );
1260f860a780SAmine Khaldi     add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1261f860a780SAmine Khaldi     add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1262c2c66affSColin Finck 
1263f860a780SAmine Khaldi     create_feature_table( hdb );
1264f860a780SAmine Khaldi     add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1265c2c66affSColin Finck 
1266f860a780SAmine Khaldi     create_feature_components_table( hdb );
1267f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1268f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1269c2c66affSColin Finck 
1270c2c66affSColin Finck     add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1271c2c66affSColin Finck     add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1272c2c66affSColin Finck 
1273f860a780SAmine Khaldi     create_file_table( hdb );
1274f860a780SAmine Khaldi     add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1275f860a780SAmine Khaldi     add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1276c2c66affSColin Finck 
1277c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
1278c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1279c2c66affSColin Finck     {
1280c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1281c2c66affSColin Finck         DeleteFileA(msifile);
1282c2c66affSColin Finck         return;
1283c2c66affSColin Finck     }
1284c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1285c2c66affSColin Finck 
1286c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1287c2c66affSColin Finck 
1288c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
1289c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
1290c2c66affSColin Finck 
1291c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
1292c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
1293c2c66affSColin Finck 
1294c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
1295c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1296c2c66affSColin Finck 
1297c2c66affSColin Finck     buffer[0] = 0;
1298c2c66affSColin Finck     sz = sizeof(buffer);
1299c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1300c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1301c2c66affSColin Finck     trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1302c2c66affSColin Finck 
1303c2c66affSColin Finck     r = MsiSetTargetPathA( 0, NULL, NULL );
1304c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1305c2c66affSColin Finck 
1306c2c66affSColin Finck     r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1307c2c66affSColin Finck     ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1308c2c66affSColin Finck 
1309c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "boo", NULL );
1310c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1311c2c66affSColin Finck 
1312c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1313c2c66affSColin Finck     ok( r == ERROR_DIRECTORY, "wrong return val\n");
1314c2c66affSColin Finck 
1315c2c66affSColin Finck     sz = sizeof tempdir - 1;
1316c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1317c2c66affSColin Finck     sprintf( file, "%srootfile.txt", tempdir );
1318c2c66affSColin Finck     buffer[0] = 0;
1319c2c66affSColin Finck     query_file_path( hpkg, "[#RootFile]", buffer );
1320c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1321c2c66affSColin Finck     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1322c2c66affSColin Finck 
1323c2c66affSColin Finck     GetTempFileNameA( tempdir, "_wt", 0, buffer );
1324c2c66affSColin Finck     sprintf( tempdir, "%s\\subdir", buffer );
1325c2c66affSColin Finck 
1326c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1327c2c66affSColin Finck     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1328c2c66affSColin Finck         "MsiSetTargetPath on file returned %d\n", r );
1329c2c66affSColin Finck 
1330c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1331c2c66affSColin Finck     ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1332c2c66affSColin Finck         "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1333c2c66affSColin Finck 
1334c2c66affSColin Finck     DeleteFileA( buffer );
1335c2c66affSColin Finck 
1336c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1337c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1338c2c66affSColin Finck 
1339c2c66affSColin Finck     r = GetFileAttributesA( buffer );
1340c2c66affSColin Finck     ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1341c2c66affSColin Finck 
1342c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1343c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1344c2c66affSColin Finck 
1345c2c66affSColin Finck     buffer[0] = 0;
1346c2c66affSColin Finck     sz = sizeof buffer - 1;
1347c2c66affSColin Finck     lstrcatA( tempdir, "\\" );
1348c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1349c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1350c2c66affSColin Finck     ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1351c2c66affSColin Finck 
1352c2c66affSColin Finck     sprintf( file, "%srootfile.txt", tempdir );
1353c2c66affSColin Finck     query_file_path( hpkg, "[#RootFile]", buffer );
1354c2c66affSColin Finck     ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1355c2c66affSColin Finck 
1356c2c66affSColin Finck     buffer[0] = 0;
1357c2c66affSColin Finck     sz = sizeof(buffer);
1358c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1359c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1360c2c66affSColin Finck     lstrcatA( tempdir, "TestParent\\" );
1361c2c66affSColin Finck     ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1362c2c66affSColin Finck 
1363c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1364c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1365c2c66affSColin Finck 
1366c2c66affSColin Finck     buffer[0] = 0;
1367c2c66affSColin Finck     sz = sizeof(buffer);
1368c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1369c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1370c2c66affSColin Finck     ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1371c2c66affSColin Finck         "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1372c2c66affSColin Finck 
1373c2c66affSColin Finck     buffer[0] = 0;
1374c2c66affSColin Finck     query_file_path( hpkg, "[#TestFile]", buffer );
1375c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1376c2c66affSColin Finck         "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1377c2c66affSColin Finck 
1378c2c66affSColin Finck     buffer[0] = 0;
1379c2c66affSColin Finck     sz = sizeof buffer - 1;
1380c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1381c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1382c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1383c2c66affSColin Finck 
1384c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1385c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1386c2c66affSColin Finck 
1387c2c66affSColin Finck     buffer[0] = 0;
1388c2c66affSColin Finck     sz = sizeof buffer - 1;
1389c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1390c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1391c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1392c2c66affSColin Finck 
1393c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two  " );
1394c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1395c2c66affSColin Finck 
1396c2c66affSColin Finck     buffer[0] = 0;
1397c2c66affSColin Finck     sz = sizeof buffer - 1;
1398c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1399c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1400c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1401c2c66affSColin Finck 
1402c2c66affSColin Finck     r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1403c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1404c2c66affSColin Finck 
1405c2c66affSColin Finck     buffer[0] = 0;
1406c2c66affSColin Finck     sz = sizeof buffer - 1;
1407c2c66affSColin Finck     r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1408c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1409c2c66affSColin Finck     ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1410c2c66affSColin Finck 
1411c2c66affSColin Finck     MsiCloseHandle( hpkg );
1412c2c66affSColin Finck }
1413c2c66affSColin Finck 
1414c2c66affSColin Finck static void test_condition(void)
1415c2c66affSColin Finck {
1416c2c66affSColin Finck     static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1417c2c66affSColin Finck     static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1418c2c66affSColin Finck     static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1419c2c66affSColin Finck     static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1420c2c66affSColin Finck     MSICONDITION r;
1421c2c66affSColin Finck     MSIHANDLE hpkg;
1422c2c66affSColin Finck 
1423c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
1424c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1425c2c66affSColin Finck     {
1426c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
1427c2c66affSColin Finck         DeleteFileA(msifile);
1428c2c66affSColin Finck         return;
1429c2c66affSColin Finck     }
1430c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1431c2c66affSColin Finck 
1432c2c66affSColin Finck     r = MsiEvaluateConditionA(0, NULL);
1433c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1434c2c66affSColin Finck 
1435c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, NULL);
1436c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1437c2c66affSColin Finck 
1438c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "");
1439c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1440c2c66affSColin Finck 
1441c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1");
1442c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1443c2c66affSColin Finck 
1444c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0");
1445c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1446c2c66affSColin Finck 
1447c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "-1");
1448c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1449c2c66affSColin Finck 
1450c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = 0");
1451c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1452c2c66affSColin Finck 
1453c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1454c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1455c2c66affSColin Finck 
1456c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = 1");
1457c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1458c2c66affSColin Finck 
1459c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 > 1");
1460c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1461c2c66affSColin Finck 
1462c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1463c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1464c2c66affSColin Finck 
1465c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 > 1");
1466c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1467c2c66affSColin Finck 
1468c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1469c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1470c2c66affSColin Finck 
1471c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1472c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1473c2c66affSColin Finck 
1474c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1475c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1476c2c66affSColin Finck 
1477c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1478c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1479c2c66affSColin Finck 
1480c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1481c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1482c2c66affSColin Finck 
1483c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 < 1");
1484c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1485c2c66affSColin Finck 
1486c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1487c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1488c2c66affSColin Finck 
1489c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 < 1");
1490c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1491c2c66affSColin Finck 
1492c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1493c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1494c2c66affSColin Finck 
1495c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1496c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1497c2c66affSColin Finck 
1498c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1499c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1500c2c66affSColin Finck 
1501c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1502c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1503c2c66affSColin Finck 
1504c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1505c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1506c2c66affSColin Finck 
1507c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 >=");
1508c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1509c2c66affSColin Finck 
1510c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " ");
1511c2c66affSColin Finck     ok( r == MSICONDITION_NONE, "wrong return val\n");
1512c2c66affSColin Finck 
1513c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1514c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1515c2c66affSColin Finck 
1516c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1517c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1518c2c66affSColin Finck 
1519c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1520c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1521c2c66affSColin Finck 
1522c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0");
1523c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1524c2c66affSColin Finck 
1525c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not LicView");
1526c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1527c2c66affSColin Finck 
1528c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1529c2c66affSColin Finck     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1530c2c66affSColin Finck 
1531c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1532c2c66affSColin Finck     ok (r == MSICONDITION_FALSE, "wrong return val\n");
1533c2c66affSColin Finck 
1534c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1535c2c66affSColin Finck     ok (r == MSICONDITION_TRUE, "wrong return val\n");
1536c2c66affSColin Finck 
1537c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1538c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1539c2c66affSColin Finck 
1540c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1541c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1542c2c66affSColin Finck 
1543c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"0\"");
1544c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1545c2c66affSColin Finck 
1546c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 and 2");
1547c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1548c2c66affSColin Finck 
1549c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1550c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1551c2c66affSColin Finck 
1552c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1553c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1554c2c66affSColin Finck 
1555c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1556c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1557c2c66affSColin Finck 
1558c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(0)");
1559c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1560c2c66affSColin Finck 
1561c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1562c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1563c2c66affSColin Finck 
1564c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1565c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1566c2c66affSColin Finck 
1567c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1568c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1569c2c66affSColin Finck 
1570c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1571c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1572c2c66affSColin Finck 
1573c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1574c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1575c2c66affSColin Finck 
1576c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1577c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1578c2c66affSColin Finck 
1579c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1580c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1581c2c66affSColin Finck 
1582c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1583c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1584c2c66affSColin Finck 
1585c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1586c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1587c2c66affSColin Finck 
1588c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1589c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1590c2c66affSColin Finck 
1591c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1592c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1593c2c66affSColin Finck 
1594c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1595c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1596c2c66affSColin Finck 
1597c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1598c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1599c2c66affSColin Finck 
1600c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1601c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1602c2c66affSColin Finck 
1603c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1604c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1605c2c66affSColin Finck 
1606c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1607c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1608c2c66affSColin Finck 
1609c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1610c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1611c2c66affSColin Finck 
1612c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1613c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1614c2c66affSColin Finck 
1615c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1616c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1617c2c66affSColin Finck 
1618c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1619c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1620c2c66affSColin Finck 
1621c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1622c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1623c2c66affSColin Finck 
1624c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1625c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1626c2c66affSColin Finck 
1627c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1628c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1629c2c66affSColin Finck 
1630c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1631c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1632c2c66affSColin Finck 
1633c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1634c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1635c2c66affSColin Finck 
1636c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1637c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1638c2c66affSColin Finck 
1639c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1640c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1641c2c66affSColin Finck 
1642c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1643c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1644c2c66affSColin Finck 
1645c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1646c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1647c2c66affSColin Finck 
1648c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1649c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1650c2c66affSColin Finck 
1651c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1652c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1653c2c66affSColin Finck 
1654c2c66affSColin Finck     MsiSetPropertyA(hpkg, "mm", "5" );
1655c2c66affSColin Finck 
1656c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm = 5");
1657c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1658c2c66affSColin Finck 
1659c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm < 6");
1660c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1661c2c66affSColin Finck 
1662c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1663c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1664c2c66affSColin Finck 
1665c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm > 4");
1666c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1667c2c66affSColin Finck 
1668c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm < 12");
1669c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1670c2c66affSColin Finck 
1671c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1672c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1673c2c66affSColin Finck 
1674c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1675c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1676c2c66affSColin Finck 
1677c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1678c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1679c2c66affSColin Finck 
1680c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1681c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1682c2c66affSColin Finck 
1683c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1684c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1685c2c66affSColin Finck 
1686c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1687c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1688c2c66affSColin Finck 
1689c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1690c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1691c2c66affSColin Finck 
1692c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1693c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1694c2c66affSColin Finck 
1695c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1696c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1697c2c66affSColin Finck 
1698c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1699c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1700c2c66affSColin Finck 
1701c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1702c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1703c2c66affSColin Finck 
1704c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1705c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1706c2c66affSColin Finck 
1707c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1708c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1709c2c66affSColin Finck 
1710c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1711c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1712c2c66affSColin Finck 
1713c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1714c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val\n");
1715c2c66affSColin Finck 
1716c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1717c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1718c2c66affSColin Finck 
1719c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1720c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1721c2c66affSColin Finck 
1722c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1723c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1724c2c66affSColin Finck 
1725c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1726c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1727c2c66affSColin Finck 
1728c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1730c2c66affSColin Finck 
1731c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1732c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1733c2c66affSColin Finck 
1734c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1735c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1736c2c66affSColin Finck 
1737c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1738c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1739c2c66affSColin Finck 
1740c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1741c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1742c2c66affSColin Finck 
1743c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1744c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1745c2c66affSColin Finck 
1746c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1747c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1748c2c66affSColin Finck 
1749c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0" );
1750c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1751c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1752c2c66affSColin Finck 
1753c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "" );
1754c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1755c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1756c2c66affSColin Finck 
1757c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1758c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1759c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1760c2c66affSColin Finck 
1761c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1762c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1763c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1764c2c66affSColin Finck 
1765c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1766c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1767c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1768c2c66affSColin Finck 
1769c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1770c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1771c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1772c2c66affSColin Finck 
1773c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1774c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1775c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1776c2c66affSColin Finck 
1777c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1778c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1779c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1780c2c66affSColin Finck 
1781c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1782c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1783c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1784c2c66affSColin Finck 
1785c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "-" );
1786c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1787c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1788c2c66affSColin Finck 
1789c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1790c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1791c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1792c2c66affSColin Finck 
1793c2c66affSColin Finck     MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1794c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1795c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1796c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1797c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1798c2c66affSColin Finck 
1799c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1800c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1801c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1802c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1803c2c66affSColin Finck 
1804c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1805c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1806c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1807c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1808c2c66affSColin Finck 
1809c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hello");
1810c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1811c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1812c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1813c2c66affSColin Finck 
1814c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hellohithere");
1815c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1816c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1817c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1818c2c66affSColin Finck 
1819c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1820c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1821c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1822c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1823c2c66affSColin Finck 
1824c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1825c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1826c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1827c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1828c2c66affSColin Finck 
1829c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1830c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1831c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1832c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1833c2c66affSColin Finck 
1834c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1835c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1836c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1837c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1838c2c66affSColin Finck 
1839c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "one 1234");
1840c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1841c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >< two");
1842c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1843c2c66affSColin Finck 
1844c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1845c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1846c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1847c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1848c2c66affSColin Finck 
1849c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1850c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1851c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1852c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1853c2c66affSColin Finck 
1854c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hi");
1855c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1856c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1857c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1858c2c66affSColin Finck 
1859c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1860c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1861c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1862c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1863c2c66affSColin Finck 
1864c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1865c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1866c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1867c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1868c2c66affSColin Finck 
1869c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1870c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1871c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1872c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1873c2c66affSColin Finck 
1874c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1875c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1876c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1877c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1878c2c66affSColin Finck 
1879c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1880c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1881c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1882c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1883c2c66affSColin Finck 
1884c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234 one");
1885c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "1");
1886c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one << two");
1887c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1888c2c66affSColin Finck 
1889c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1890c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1891c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1892c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1893c2c66affSColin Finck 
1894c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "hithere");
1895c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1896c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1897c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1898c2c66affSColin Finck 
1899c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1900c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hithere");
1901c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1902c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1903c2c66affSColin Finck 
1904c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1905c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1906c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1907c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1908c2c66affSColin Finck 
1909c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "abcdhithere");
1910c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "hi");
1911c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1912c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1913c2c66affSColin Finck 
1914c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1915c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "there");
1916c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1917c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1918c2c66affSColin Finck 
1919c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "there");
1920c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1921c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1922c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1923c2c66affSColin Finck 
1924c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "");
1925c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "");
1926c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1927c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1928c2c66affSColin Finck 
1929c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1234");
1930c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "4");
1931c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1932c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
1933c2c66affSColin Finck 
1934c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "one 1234");
1935c2c66affSColin Finck     MsiSetPropertyA(hpkg, "two", "4");
1936c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one >> two");
1937c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val\n");
1938c2c66affSColin Finck 
1939c2c66affSColin Finck     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL);  /* make sure it's empty */
1940c2c66affSColin Finck 
1941c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1942c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1943c2c66affSColin Finck 
1944c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1945c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1946c2c66affSColin Finck 
1947c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1948c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1949c2c66affSColin Finck 
1950c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1951c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1952c2c66affSColin Finck 
1953c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1954c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1955c2c66affSColin Finck 
1956c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1957c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1958c2c66affSColin Finck 
1959c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1960c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1961c2c66affSColin Finck 
1962c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1963c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1964c2c66affSColin Finck 
1965c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1966c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1967c2c66affSColin Finck 
1968c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1969c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1970c2c66affSColin Finck 
1971c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1972c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1973c2c66affSColin Finck 
1974c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1975c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1976c2c66affSColin Finck 
1977c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1978c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1979c2c66affSColin Finck 
1980c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1981c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1982c2c66affSColin Finck 
1983c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1984c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1985c2c66affSColin Finck 
1986c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1987c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1988c2c66affSColin Finck 
1989c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1990c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1991c2c66affSColin Finck 
1992c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1993c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1994c2c66affSColin Finck 
1995c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1996c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1997c2c66affSColin Finck 
1998c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1999c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2000c2c66affSColin Finck 
2001c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
2002c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2003c2c66affSColin Finck 
2004c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
2005c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2006c2c66affSColin Finck 
2007c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
2008c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2009c2c66affSColin Finck 
2010c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
2011c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2012c2c66affSColin Finck 
2013c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
2014c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2015c2c66affSColin Finck 
2016c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
2017c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2018c2c66affSColin Finck 
2019c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
2020c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2021c2c66affSColin Finck 
2022c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
2023c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2024c2c66affSColin Finck 
2025c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
2026c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2027c2c66affSColin Finck 
2028c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
2029c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2030c2c66affSColin Finck 
2031c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
2032c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2033c2c66affSColin Finck 
2034c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
2035c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2036c2c66affSColin Finck 
2037c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
2038c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2039c2c66affSColin Finck 
2040c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
2041c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2042c2c66affSColin Finck 
2043c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
2044c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2045c2c66affSColin Finck 
2046c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
2047c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2048c2c66affSColin Finck 
2049c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
2050c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2051c2c66affSColin Finck 
2052c2c66affSColin Finck     MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2053c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2054c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2055c2c66affSColin Finck 
2056c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2057c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2058c2c66affSColin Finck 
2059c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2060c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2061c2c66affSColin Finck 
2062c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2063c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2064c2c66affSColin Finck 
2065c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2066c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2067c2c66affSColin Finck 
2068c2c66affSColin Finck     MsiSetPropertyA(hpkg, "one", "1");
2069c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2070c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val\n");
2071c2c66affSColin Finck 
2072c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "5.0");
2073c2c66affSColin Finck 
2074c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2075c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2076c2c66affSColin Finck 
2077c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2078c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2079c2c66affSColin Finck 
2080c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2081c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2082c2c66affSColin Finck 
2083c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2084c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2085c2c66affSColin Finck 
2086c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2087c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2088c2c66affSColin Finck 
2089c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2090c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2091c2c66affSColin Finck 
2092c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2093c2c66affSColin Finck     ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2094c2c66affSColin Finck 
2095c2c66affSColin Finck     /* feature doesn't exist */
2096c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "&nofeature");
2097c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2098f860a780SAmine Khaldi     r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2099f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2100*331be612Swinesync     r = MsiEvaluateConditionA(hpkg, "&nofeature<>3");
2101*331be612Swinesync     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2102*331be612Swinesync     r = MsiEvaluateConditionA(hpkg, "\"\"<>3");
2103*331be612Swinesync     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2104f860a780SAmine Khaldi     r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2105f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2106f860a780SAmine Khaldi     MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2107f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2108f860a780SAmine Khaldi     MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2109f860a780SAmine Khaldi     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2110c2c66affSColin Finck 
2111c2c66affSColin Finck     MsiSetPropertyA(hpkg, "A", "2");
2112c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50");
2113c2c66affSColin Finck 
2114c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2115c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2116c2c66affSColin Finck 
2117c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2118c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2119c2c66affSColin Finck 
2120c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2121c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2122c2c66affSColin Finck 
2123c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50val");
2124c2c66affSColin Finck 
2125c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2126c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2127c2c66affSColin Finck 
2128c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2129c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2130c2c66affSColin Finck 
2131c2c66affSColin Finck     MsiSetPropertyA(hpkg, "A", "7");
2132c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50");
2133c2c66affSColin Finck 
2134c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "7 <= X");
2135c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2136c2c66affSColin Finck 
2137c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2138c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2139c2c66affSColin Finck 
2140c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= 50");
2141c2c66affSColin Finck     ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2142c2c66affSColin Finck 
2143c2c66affSColin Finck     MsiSetPropertyA(hpkg, "X", "50val");
2144c2c66affSColin Finck 
2145c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "2 <= X");
2146c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2147c2c66affSColin Finck 
2148c2c66affSColin Finck     r = MsiEvaluateConditionA(hpkg, "A <= X");
2149c2c66affSColin Finck     ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2150c2c66affSColin Finck 
2151c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond1);
2152c2c66affSColin Finck     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2153c2c66affSColin Finck         "wrong return val (%d)\n", r);
2154c2c66affSColin Finck 
2155c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond2);
2156c2c66affSColin Finck     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2157c2c66affSColin Finck         "wrong return val (%d)\n", r);
2158c2c66affSColin Finck 
2159c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond3);
2160c2c66affSColin Finck     ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2161c2c66affSColin Finck         "wrong return val (%d)\n", r);
2162c2c66affSColin Finck 
2163c2c66affSColin Finck     r = MsiEvaluateConditionW(hpkg, cond4);
2164c2c66affSColin Finck     ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2165c2c66affSColin Finck         "wrong return val (%d)\n", r);
2166c2c66affSColin Finck 
2167c2c66affSColin Finck     MsiCloseHandle( hpkg );
2168c2c66affSColin Finck     DeleteFileA(msifile);
2169c2c66affSColin Finck }
2170c2c66affSColin Finck 
2171c2000429Swinesync static void check_prop(MSIHANDLE hpkg, const char *prop, const char *expect)
2172c2c66affSColin Finck {
21733ec0ea99Swinesync     char buffer[MAX_PATH] = "x";
2174c2000429Swinesync     DWORD sz = sizeof(buffer);
2175c2000429Swinesync     UINT r = MsiGetPropertyA(hpkg, prop, buffer, &sz);
2176c2000429Swinesync     ok(!r, "'%s': got %u\n", prop, r);
2177c2000429Swinesync     ok(sz == lstrlenA(buffer), "'%s': expected %u, got %u\n", prop, lstrlenA(buffer), sz);
21783ec0ea99Swinesync     ok(!strcmp(buffer, expect), "'%s': expected '%s', got '%s'\n", prop, expect, buffer);
2179c2c66affSColin Finck }
2180c2c66affSColin Finck 
2181c2c66affSColin Finck static void test_props(void)
2182c2c66affSColin Finck {
218366669aedSwinesync     static const WCHAR booW[] = {'b','o','o',0};
218466669aedSwinesync     static const WCHAR xyzW[] = {'x','y','z',0};
218566669aedSwinesync     static const WCHAR xyW[] = {'x','y',0};
2186c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
2187c2c66affSColin Finck     UINT r;
2188c2c66affSColin Finck     DWORD sz;
2189c2c66affSColin Finck     char buffer[0x100];
219066669aedSwinesync     WCHAR bufferW[10];
2191c2c66affSColin Finck 
2192c2c66affSColin Finck     hdb = create_package_db();
2193c2c66affSColin Finck 
2194f860a780SAmine Khaldi     create_property_table(hdb);
2195f860a780SAmine Khaldi     add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2196c2c66affSColin Finck 
2197c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
2198c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2199c2c66affSColin Finck     {
2200c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2201c2c66affSColin Finck         DeleteFileA(msifile);
2202c2c66affSColin Finck         return;
2203c2c66affSColin Finck     }
2204c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2205c2c66affSColin Finck 
2206c2c66affSColin Finck     /* test invalid values */
2207c2c66affSColin Finck     r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2208c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2209c2c66affSColin Finck 
2210c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2211c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2212c2c66affSColin Finck 
2213c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2214c2000429Swinesync     ok(!r, "got %u\n", r);
2215c2c66affSColin Finck 
2216c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2217c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2218c2c66affSColin Finck 
2219c2c66affSColin Finck     /* test retrieving an empty/nonexistent property */
2220c2c66affSColin Finck     sz = sizeof buffer;
2221c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2222c2000429Swinesync     ok(!r, "got %u\n", r);
2223c2000429Swinesync     ok(sz == 0, "got size %d\n", sz);
2224c2c66affSColin Finck 
2225c2c66affSColin Finck     sz = 0;
2226c2c66affSColin Finck     strcpy(buffer,"x");
2227c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2228c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2229c2000429Swinesync     ok(!strcmp(buffer,"x"), "got \"%s\"\n", buffer);
2230c2000429Swinesync     ok(sz == 0, "got size %u\n", sz);
2231c2c66affSColin Finck 
2232c2c66affSColin Finck     sz = 1;
2233c2c66affSColin Finck     strcpy(buffer,"x");
2234c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2235c2000429Swinesync     ok(!r, "got %u\n", r);
2236c2000429Swinesync     ok(!buffer[0], "got \"%s\"\n", buffer);
2237c2000429Swinesync     ok(sz == 0, "got size %u\n", sz);
2238c2c66affSColin Finck 
2239c2c66affSColin Finck     /* set the property to something */
2240c2c66affSColin Finck     r = MsiSetPropertyA( 0, NULL, NULL );
2241c2000429Swinesync     ok(r == ERROR_INVALID_HANDLE, "got %u\n", r);
2242c2c66affSColin Finck 
2243c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, NULL, NULL );
2244c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2245c2c66affSColin Finck 
2246c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "", NULL );
2247c2000429Swinesync     ok(!r, "got %u\n", r);
2248c2c66affSColin Finck 
2249c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "", "asdf" );
2250c2000429Swinesync     ok(r == ERROR_FUNCTION_FAILED, "got %u\n", r);
2251c2c66affSColin Finck 
2252c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "=", "asdf" );
2253c2000429Swinesync     ok(!r, "got %u\n", r);
2254c2000429Swinesync     check_prop(hpkg, "=", "asdf");
2255c2c66affSColin Finck 
2256c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, " ", "asdf" );
2257c2000429Swinesync     ok(!r, "got %u\n", r);
2258c2000429Swinesync     check_prop(hpkg, " ", "asdf");
2259c2c66affSColin Finck 
2260c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "'", "asdf" );
2261c2000429Swinesync     ok(!r, "got %u\n", r);
2262c2000429Swinesync     check_prop(hpkg, "'", "asdf");
2263c2c66affSColin Finck 
2264c2c66affSColin Finck     /* set empty values */
2265c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", NULL );
2266c2000429Swinesync     ok(!r, "got %u\n", r);
2267c2000429Swinesync     check_prop(hpkg, "boo", "");
2268c2c66affSColin Finck 
2269c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", "" );
2270c2000429Swinesync     ok(!r, "got %u\n", r);
2271c2000429Swinesync     check_prop(hpkg, "boo", "");
2272c2c66affSColin Finck 
2273c2c66affSColin Finck     /* set a non-empty value */
2274c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2275c2000429Swinesync     ok(!r, "got %u\n", r);
2276c2000429Swinesync     check_prop(hpkg, "boo", "xyz");
2277c2000429Swinesync 
2278c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", NULL, NULL);
2279c2000429Swinesync     ok(!r, "got %u\n", r);
2280c2000429Swinesync 
2281c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", buffer, NULL);
2282c2000429Swinesync     ok(r == ERROR_INVALID_PARAMETER, "got %u\n", r);
2283c2000429Swinesync 
2284c2000429Swinesync     sz = 0;
2285c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", NULL, &sz);
2286c2000429Swinesync     ok(!r, "got %u\n", r);
2287c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2288c2000429Swinesync 
2289c2000429Swinesync     sz = 0;
2290c2000429Swinesync     strcpy(buffer, "q");
2291c2000429Swinesync     r = MsiGetPropertyA(hpkg, "boo", buffer, &sz);
2292c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2293c2000429Swinesync     ok(!strcmp(buffer, "q"), "got \"%s\"", buffer);
2294c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2295c2c66affSColin Finck 
2296c2c66affSColin Finck     sz = 1;
2297c2c66affSColin Finck     strcpy(buffer,"x");
2298c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2299c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2300c2000429Swinesync     ok(!buffer[0], "got \"%s\"\n", buffer);
2301c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2302c2c66affSColin Finck 
2303c2c66affSColin Finck     sz = 3;
2304c2c66affSColin Finck     strcpy(buffer,"x");
2305c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2306c2000429Swinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
2307c2000429Swinesync     ok(!strcmp(buffer,"xy"), "got \"%s\"\n", buffer);
2308c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2309c2c66affSColin Finck 
2310c2c66affSColin Finck     sz = 4;
2311c2000429Swinesync     strcpy(buffer,"x");
2312c2000429Swinesync     r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2313c2000429Swinesync     ok(!r, "got %u\n", r);
2314c2000429Swinesync     ok(!strcmp(buffer,"xyz"), "got \"%s\"\n", buffer);
2315c2000429Swinesync     ok(sz == 3, "got size %u\n", sz);
2316c2c66affSColin Finck 
231766669aedSwinesync     sz = 0;
231866669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, NULL, &sz);
231966669aedSwinesync     ok(!r, "got %u\n", r);
232066669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
232166669aedSwinesync 
232266669aedSwinesync     sz = 0;
232366669aedSwinesync     lstrcpyW(bufferW, booW);
232466669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz);
232566669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
232666669aedSwinesync     ok(!lstrcmpW(bufferW, booW), "got %s\n", wine_dbgstr_w(bufferW));
232766669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
232866669aedSwinesync 
232966669aedSwinesync     sz = 1;
233066669aedSwinesync     lstrcpyW(bufferW, booW);
233166669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
233266669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
233366669aedSwinesync     ok(!bufferW[0], "got %s\n", wine_dbgstr_w(bufferW));
233466669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
233566669aedSwinesync 
233666669aedSwinesync     sz = 3;
233766669aedSwinesync     lstrcpyW(bufferW, booW);
233866669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
233966669aedSwinesync     ok(r == ERROR_MORE_DATA, "got %u\n", r);
234066669aedSwinesync     ok(!lstrcmpW(bufferW, xyW), "got %s\n", wine_dbgstr_w(bufferW));
234166669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
234266669aedSwinesync 
234366669aedSwinesync     sz = 4;
234466669aedSwinesync     lstrcpyW(bufferW, booW);
234566669aedSwinesync     r = MsiGetPropertyW(hpkg, booW, bufferW, &sz );
234666669aedSwinesync     ok(!r, "got %u\n", r);
234766669aedSwinesync     ok(!lstrcmpW(bufferW, xyzW), "got %s\n", wine_dbgstr_w(bufferW));
234866669aedSwinesync     ok(sz == 3, "got size %u\n", sz);
234966669aedSwinesync 
2350c2000429Swinesync     /* properties are case-sensitive */
2351c2000429Swinesync     check_prop(hpkg, "BOO", "");
2352c2c66affSColin Finck 
2353c2000429Swinesync     /* properties set in Property table should work */
2354c2000429Swinesync     check_prop(hpkg, "MetadataCompName", "Photoshop.dll");
2355c2c66affSColin Finck 
2356c2c66affSColin Finck     MsiCloseHandle( hpkg );
2357c2c66affSColin Finck     DeleteFileA(msifile);
2358c2c66affSColin Finck }
2359c2c66affSColin Finck 
2360c2c66affSColin Finck static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2361c2c66affSColin Finck {
2362c2c66affSColin Finck     MSIHANDLE hview, hrec;
2363c2c66affSColin Finck     BOOL found = FALSE;
2364c2c66affSColin Finck     CHAR buffer[MAX_PATH];
2365c2c66affSColin Finck     DWORD sz;
2366c2c66affSColin Finck     UINT r;
2367c2c66affSColin Finck 
2368c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2369c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2370c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
2371c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2372c2c66affSColin Finck 
2373c2c66affSColin Finck     if (len < 0) len = lstrlenA(val);
2374c2c66affSColin Finck 
2375c2c66affSColin Finck     while (r == ERROR_SUCCESS && !found)
2376c2c66affSColin Finck     {
2377c2c66affSColin Finck         r = MsiViewFetch(hview, &hrec);
2378c2c66affSColin Finck         if (r != ERROR_SUCCESS) break;
2379c2c66affSColin Finck 
2380c2c66affSColin Finck         sz = MAX_PATH;
2381c2c66affSColin Finck         r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2382c2c66affSColin Finck         if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2383c2c66affSColin Finck         {
2384c2c66affSColin Finck             sz = MAX_PATH;
2385c2c66affSColin Finck             r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2386c2c66affSColin Finck             if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2387c2c66affSColin Finck             {
2388c2c66affSColin Finck                 ok(sz == len, "wrong size %u\n", sz);
2389c2c66affSColin Finck                 found = TRUE;
2390c2c66affSColin Finck             }
2391c2c66affSColin Finck         }
2392c2c66affSColin Finck 
2393c2c66affSColin Finck         MsiCloseHandle(hrec);
2394c2c66affSColin Finck     }
2395c2c66affSColin Finck     MsiViewClose(hview);
2396c2c66affSColin Finck     MsiCloseHandle(hview);
2397c2c66affSColin Finck     return found;
2398c2c66affSColin Finck }
2399c2c66affSColin Finck 
2400c2c66affSColin Finck static void test_property_table(void)
2401c2c66affSColin Finck {
2402c2c66affSColin Finck     const char *query;
2403c2c66affSColin Finck     UINT r;
2404c2c66affSColin Finck     MSIHANDLE hpkg, hdb, hrec;
2405c2c66affSColin Finck     char buffer[MAX_PATH], package[10];
2406c2c66affSColin Finck     DWORD sz;
2407c2c66affSColin Finck     BOOL found;
2408c2c66affSColin Finck 
2409c2c66affSColin Finck     hdb = create_package_db();
2410c2c66affSColin Finck     ok( hdb, "failed to create package\n");
2411c2c66affSColin Finck 
2412c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
2413c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2414c2c66affSColin Finck     {
2415c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2416c2c66affSColin Finck         DeleteFileA(msifile);
2417c2c66affSColin Finck         return;
2418c2c66affSColin Finck     }
2419c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2420c2c66affSColin Finck 
2421c2c66affSColin Finck     MsiCloseHandle(hdb);
2422c2c66affSColin Finck 
2423c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
2424c2c66affSColin Finck 
2425c2c66affSColin Finck     query = "CREATE TABLE `_Property` ( "
2426c2c66affSColin Finck         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2427c2c66affSColin Finck     r = run_query(hdb, query);
2428c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2429c2c66affSColin Finck 
2430c2c66affSColin Finck     MsiCloseHandle(hdb);
2431c2c66affSColin Finck     MsiCloseHandle(hpkg);
2432c2c66affSColin Finck     DeleteFileA(msifile);
2433c2c66affSColin Finck 
2434c2c66affSColin Finck     hdb = create_package_db();
2435c2c66affSColin Finck     ok( hdb, "failed to create package\n");
2436c2c66affSColin Finck 
2437c2c66affSColin Finck     query = "CREATE TABLE `_Property` ( "
2438c2c66affSColin Finck         "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2439c2c66affSColin Finck     r = run_query(hdb, query);
2440c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create table\n");
2441c2c66affSColin Finck 
2442c2c66affSColin Finck     query = "ALTER `_Property` ADD `foo` INTEGER";
2443c2c66affSColin Finck     r = run_query(hdb, query);
2444c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2445c2c66affSColin Finck 
2446c2c66affSColin Finck     query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2447c2c66affSColin Finck     r = run_query(hdb, query);
2448c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2449c2c66affSColin Finck 
2450c2c66affSColin Finck     query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2451c2c66affSColin Finck     r = run_query(hdb, query);
2452c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to add column\n");
2453c2c66affSColin Finck 
2454c2c66affSColin Finck     sprintf(package, "#%i", hdb);
2455c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
2456c2c66affSColin Finck     ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2457c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2458c2c66affSColin Finck         MsiCloseHandle(hpkg);
2459c2c66affSColin Finck 
2460c2c66affSColin Finck     r = MsiCloseHandle(hdb);
2461c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2462c2c66affSColin Finck 
2463c2c66affSColin Finck     hdb = create_package_db();
2464c2c66affSColin Finck     ok (hdb, "failed to create package database\n");
2465c2c66affSColin Finck 
2466f860a780SAmine Khaldi     create_property_table(hdb);
2467f860a780SAmine Khaldi     add_property_entry(hdb, "'prop', 'val'");
2468c2c66affSColin Finck 
2469f860a780SAmine Khaldi     create_custom_action_table(hdb);
2470f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2471c2c66affSColin Finck 
2472c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
2473c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2474c2c66affSColin Finck 
2475c2c66affSColin Finck     MsiCloseHandle(hdb);
2476c2c66affSColin Finck 
2477c2c66affSColin Finck     sz = MAX_PATH;
2478c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2479c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2480c2c66affSColin Finck     ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2481c2c66affSColin Finck 
2482c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
2483c2c66affSColin Finck 
2484c2c66affSColin Finck     found = find_prop_in_property(hdb, "prop", "val", -1);
2485c2c66affSColin Finck     ok(found, "prop should be in the _Property table\n");
2486c2c66affSColin Finck 
2487f860a780SAmine Khaldi     add_property_entry(hdb, "'dantes', 'mercedes'");
2488c2c66affSColin Finck 
2489c2c66affSColin Finck     query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2490c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
2491c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2492c2c66affSColin Finck 
2493c2c66affSColin Finck     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2494c2c66affSColin Finck     ok(found == FALSE, "dantes should not be in the _Property table\n");
2495c2c66affSColin Finck 
2496c2c66affSColin Finck     sz = MAX_PATH;
2497c2c66affSColin Finck     lstrcpyA(buffer, "aaa");
2498c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2499c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2500c2c66affSColin Finck     ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2501c2c66affSColin Finck 
2502c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2503c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2504c2c66affSColin Finck 
2505c2c66affSColin Finck     found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2506c2c66affSColin Finck     ok(found == TRUE, "dantes should be in the _Property table\n");
2507c2c66affSColin Finck 
2508c2c66affSColin Finck     r = MsiDoActionA( hpkg, "EmbedNull" );
2509c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2510c2c66affSColin Finck 
2511c2c66affSColin Finck     sz = MAX_PATH;
2512c2c66affSColin Finck     memset( buffer, 'a', sizeof(buffer) );
2513c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2514c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2515c2c66affSColin Finck     ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2516c2c66affSColin Finck     ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2517c2c66affSColin Finck 
2518c2c66affSColin Finck     found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2519c2c66affSColin Finck     ok(found == TRUE, "prop2 should be in the _Property table\n");
2520c2c66affSColin Finck 
2521c2c66affSColin Finck     MsiCloseHandle(hdb);
2522c2c66affSColin Finck     MsiCloseHandle(hpkg);
2523c2c66affSColin Finck     DeleteFileA(msifile);
2524c2c66affSColin Finck }
2525c2c66affSColin Finck 
2526c2c66affSColin Finck static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2527c2c66affSColin Finck {
2528c2c66affSColin Finck     MSIHANDLE htab = 0;
2529c2c66affSColin Finck     UINT res;
2530c2c66affSColin Finck 
2531c2c66affSColin Finck     res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2532c2c66affSColin Finck     if( res == ERROR_SUCCESS )
2533c2c66affSColin Finck     {
2534c2c66affSColin Finck         UINT r;
2535c2c66affSColin Finck 
2536c2c66affSColin Finck         r = MsiViewExecute( htab, hrec );
2537c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2538c2c66affSColin Finck         {
2539c2c66affSColin Finck             res = r;
2540c2c66affSColin Finck             fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2541c2c66affSColin Finck         }
2542c2c66affSColin Finck 
2543c2c66affSColin Finck         r = MsiViewClose( htab );
2544c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2545c2c66affSColin Finck             res = r;
2546c2c66affSColin Finck 
2547c2c66affSColin Finck         r = MsiCloseHandle( htab );
2548c2c66affSColin Finck         if( r != ERROR_SUCCESS )
2549c2c66affSColin Finck             res = r;
2550c2c66affSColin Finck     }
2551c2c66affSColin Finck     return res;
2552c2c66affSColin Finck }
2553c2c66affSColin Finck 
2554c2c66affSColin Finck static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2555c2c66affSColin Finck {
2556c2c66affSColin Finck     return try_query_param( hdb, szQuery, 0 );
2557c2c66affSColin Finck }
2558c2c66affSColin Finck 
2559c2c66affSColin Finck static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2560c2c66affSColin Finck {
2561c2c66affSColin Finck     MSIHANDLE summary;
2562c2c66affSColin Finck     UINT r;
2563c2c66affSColin Finck 
2564c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2565c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2566c2c66affSColin Finck 
2567c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2568c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2569c2c66affSColin Finck 
2570c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
2571c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2572c2c66affSColin Finck 
2573c2c66affSColin Finck     MsiCloseHandle(summary);
2574c2c66affSColin Finck }
2575c2c66affSColin Finck 
2576c2c66affSColin Finck static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2577c2c66affSColin Finck {
2578c2c66affSColin Finck     MSIHANDLE summary;
2579c2c66affSColin Finck     UINT r;
2580c2c66affSColin Finck 
2581c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2582c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2583c2c66affSColin Finck 
2584c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2585c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2586c2c66affSColin Finck 
2587c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
2588c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2589c2c66affSColin Finck 
2590c2c66affSColin Finck     MsiCloseHandle(summary);
2591c2c66affSColin Finck }
2592c2c66affSColin Finck 
2593c2c66affSColin Finck static void test_msipackage(void)
2594c2c66affSColin Finck {
2595c2c66affSColin Finck     MSIHANDLE hdb = 0, hpack = 100;
2596c2c66affSColin Finck     UINT r;
2597c2c66affSColin Finck     const char *query;
2598c2c66affSColin Finck     char name[10];
2599c2c66affSColin Finck 
2600c2c66affSColin Finck     /* NULL szPackagePath */
2601c2c66affSColin Finck     r = MsiOpenPackageA(NULL, &hpack);
2602c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2603c2c66affSColin Finck 
2604c2c66affSColin Finck     /* empty szPackagePath */
2605c2c66affSColin Finck     r = MsiOpenPackageA("", &hpack);
2606c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2607c2c66affSColin Finck     {
2608c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2609c2c66affSColin Finck         return;
2610c2c66affSColin Finck     }
2611c2c66affSColin Finck     todo_wine
2612c2c66affSColin Finck     {
2613c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2614c2c66affSColin Finck     }
2615c2c66affSColin Finck 
2616c2c66affSColin Finck     if (r == ERROR_SUCCESS)
2617c2c66affSColin Finck         MsiCloseHandle(hpack);
2618c2c66affSColin Finck 
2619c2c66affSColin Finck     /* nonexistent szPackagePath */
2620c2c66affSColin Finck     r = MsiOpenPackageA("nonexistent", &hpack);
2621c2c66affSColin Finck     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2622c2c66affSColin Finck 
2623c2c66affSColin Finck     /* NULL hProduct */
2624c2c66affSColin Finck     r = MsiOpenPackageA(msifile, NULL);
2625c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2626c2c66affSColin Finck 
2627c2c66affSColin Finck     name[0]='#';
2628c2c66affSColin Finck     name[1]=0;
2629c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2630c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2631c2c66affSColin Finck 
2632c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2633c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2634c2c66affSColin Finck 
2635c2c66affSColin Finck     /* database exists, but is empty */
2636c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2637c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2638c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2639c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2640c2c66affSColin Finck 
2641c2c66affSColin Finck     query = "CREATE TABLE `Property` ( "
2642c2c66affSColin Finck             "`Property` CHAR(72), `Value` CHAR(0) "
2643c2c66affSColin Finck             "PRIMARY KEY `Property`)";
2644c2c66affSColin Finck     r = try_query(hdb, query);
2645c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2646c2c66affSColin Finck 
2647c2c66affSColin Finck     query = "CREATE TABLE `InstallExecuteSequence` ("
2648c2c66affSColin Finck             "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2649c2c66affSColin Finck             "PRIMARY KEY `Action`)";
2650c2c66affSColin Finck     r = try_query(hdb, query);
2651c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2652c2c66affSColin Finck 
2653c2c66affSColin Finck     /* a few key tables exist */
2654c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2655c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2656c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2657c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2658c2c66affSColin Finck 
2659c2c66affSColin Finck     MsiCloseHandle(hdb);
2660c2c66affSColin Finck     DeleteFileA(msifile);
2661c2c66affSColin Finck 
2662c2c66affSColin Finck     /* start with a clean database to show what constitutes a valid package */
2663c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2664c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2665c2c66affSColin Finck 
2666c2c66affSColin Finck     sprintf(name, "#%d", hdb);
2667c2c66affSColin Finck 
2668c2c66affSColin Finck     /* The following summary information props must exist:
2669c2c66affSColin Finck      *  - PID_REVNUMBER
2670c2c66affSColin Finck      *  - PID_PAGECOUNT
2671c2c66affSColin Finck      */
2672c2c66affSColin Finck 
2673c2c66affSColin Finck     set_summary_dword(hdb, PID_PAGECOUNT, 100);
2674c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2675c2c66affSColin Finck     ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2676c2c66affSColin Finck        "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2677c2c66affSColin Finck 
2678c2c66affSColin Finck     set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2679c2c66affSColin Finck     r = MsiOpenPackageA(name, &hpack);
2680c2c66affSColin Finck     ok(r == ERROR_SUCCESS,
2681c2c66affSColin Finck        "Expected ERROR_SUCCESS, got %d\n", r);
2682c2c66affSColin Finck 
2683c2c66affSColin Finck     MsiCloseHandle(hpack);
2684c2c66affSColin Finck     MsiCloseHandle(hdb);
2685c2c66affSColin Finck     DeleteFileA(msifile);
2686c2c66affSColin Finck }
2687c2c66affSColin Finck 
2688c2c66affSColin Finck static void test_formatrecord2(void)
2689c2c66affSColin Finck {
2690c2c66affSColin Finck     MSIHANDLE hpkg, hrec ;
2691c2c66affSColin Finck     char buffer[0x100];
2692c2c66affSColin Finck     DWORD sz;
2693c2c66affSColin Finck     UINT r;
2694c2c66affSColin Finck 
2695c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
2696c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2697c2c66affSColin Finck     {
2698c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
2699c2c66affSColin Finck         DeleteFileA(msifile);
2700c2c66affSColin Finck         return;
2701c2c66affSColin Finck     }
2702c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2703c2c66affSColin Finck 
2704c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2705c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "set property failed\n");
2706c2c66affSColin Finck 
2707c2c66affSColin Finck     hrec = MsiCreateRecord(2);
2708c2c66affSColin Finck     ok(hrec, "create record failed\n");
2709c2c66affSColin Finck 
2710c2c66affSColin Finck     r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2711c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format record failed\n");
2712c2c66affSColin Finck 
2713c2c66affSColin Finck     buffer[0] = 0;
2714c2c66affSColin Finck     sz = sizeof buffer;
2715c2c66affSColin Finck     r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2716c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2717c2c66affSColin Finck 
2718c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2719c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2720c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "hoo");
2721c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2722c2c66affSColin Finck     sz = sizeof buffer;
2723c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2724c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2725c2c66affSColin Finck     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2726c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2727c2c66affSColin Finck 
2728c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2729c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2730c2c66affSColin Finck     sz = sizeof buffer;
2731c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2732c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2733c2c66affSColin Finck     ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2734c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2735c2c66affSColin Finck 
2736c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2737c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2738c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "hoo");
2739c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2740c2c66affSColin Finck     sz = sizeof buffer;
2741c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2742c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2743c2c66affSColin Finck     ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2744c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2745c2c66affSColin Finck 
2746c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2747c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2748c2c66affSColin Finck     sz = sizeof buffer;
2749c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2750c2c66affSColin Finck     ok( sz == 1, "size wrong\n");
2751c2c66affSColin Finck     ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2752c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2753c2c66affSColin Finck 
2754c2c66affSColin Finck     SetEnvironmentVariableA("FOO", "BAR");
2755c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2756c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2757c2c66affSColin Finck     sz = sizeof buffer;
2758c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2759c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2760c2c66affSColin Finck     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2761c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2762c2c66affSColin Finck 
2763c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2764c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2765c2c66affSColin Finck     r = MsiRecordSetStringA(hrec, 1, "%FOO");
2766c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2767c2c66affSColin Finck     sz = sizeof buffer;
2768c2c66affSColin Finck     r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2769c2c66affSColin Finck     ok( sz == 3, "size wrong\n");
2770c2c66affSColin Finck     ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2771c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "format failed\n");
2772c2c66affSColin Finck 
2773c2c66affSColin Finck     MsiCloseHandle( hrec );
2774c2c66affSColin Finck     MsiCloseHandle( hpkg );
2775c2c66affSColin Finck     DeleteFileA(msifile);
2776c2c66affSColin Finck }
2777c2c66affSColin Finck 
2778f860a780SAmine Khaldi static void test_formatrecord_tables(void)
2779f860a780SAmine Khaldi {
2780f860a780SAmine Khaldi     MSIHANDLE hdb, hrec, hpkg = 0;
2781f860a780SAmine Khaldi     CHAR buf[MAX_PATH];
2782f860a780SAmine Khaldi     CHAR curr_dir[MAX_PATH];
2783f860a780SAmine Khaldi     CHAR expected[MAX_PATH];
2784f860a780SAmine Khaldi     CHAR root[MAX_PATH];
2785f860a780SAmine Khaldi     DWORD size;
2786f860a780SAmine Khaldi     UINT r;
2787f860a780SAmine Khaldi 
2788f860a780SAmine Khaldi     GetCurrentDirectoryA( MAX_PATH, curr_dir );
2789f860a780SAmine Khaldi 
2790f860a780SAmine Khaldi     hdb = create_package_db();
2791f860a780SAmine Khaldi     ok ( hdb, "failed to create package database\n");
2792f860a780SAmine Khaldi 
2793f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2794f860a780SAmine Khaldi     add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2795f860a780SAmine Khaldi                              "'I am a really long directory'" );
2796f860a780SAmine Khaldi 
2797f860a780SAmine Khaldi     create_feature_table( hdb );
2798f860a780SAmine Khaldi     add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2799f860a780SAmine Khaldi 
2800f860a780SAmine Khaldi     create_component_table( hdb );
2801f860a780SAmine Khaldi     add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2802f860a780SAmine Khaldi     add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2803f860a780SAmine Khaldi     add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2804f860a780SAmine Khaldi 
2805f860a780SAmine Khaldi     create_feature_components_table( hdb );
2806f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2807f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2808f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2809f860a780SAmine Khaldi 
2810f860a780SAmine Khaldi     create_file_table( hdb );
2811f860a780SAmine Khaldi     add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2812f860a780SAmine Khaldi     add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2813f860a780SAmine Khaldi     add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2814f860a780SAmine Khaldi 
2815f860a780SAmine Khaldi     create_custom_action_table( hdb );
2816f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2817f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2818f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2819f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2820f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2821f860a780SAmine Khaldi 
2822f860a780SAmine Khaldi     r = package_from_db( hdb, &hpkg );
2823f860a780SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2824f860a780SAmine Khaldi     {
2825f860a780SAmine Khaldi         skip("Not enough rights to perform tests\n");
2826f860a780SAmine Khaldi         MsiCloseHandle( hdb );
2827f860a780SAmine Khaldi         DeleteFileA( msifile );
2828f860a780SAmine Khaldi         return;
2829f860a780SAmine Khaldi     }
2830f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2831f860a780SAmine Khaldi 
2832f860a780SAmine Khaldi     MsiCloseHandle( hdb );
2833f860a780SAmine Khaldi 
2834f860a780SAmine Khaldi     r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2835f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2836f860a780SAmine Khaldi 
2837f860a780SAmine Khaldi     hrec = MsiCreateRecord( 1 );
2838f860a780SAmine Khaldi 
2839f860a780SAmine Khaldi     /* property doesn't exist */
2840f860a780SAmine Khaldi     size = MAX_PATH;
2841f860a780SAmine Khaldi     /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2842f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2843f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2844f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2845f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2846f860a780SAmine Khaldi 
2847f860a780SAmine Khaldi     /* property exists */
2848f860a780SAmine Khaldi     size = MAX_PATH;
2849f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2850f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2851f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2852f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2853f860a780SAmine Khaldi 
2854f860a780SAmine Khaldi     size = MAX_PATH;
2855f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 0, "1: [1] " );
2856f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2857f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2858f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2859f860a780SAmine Khaldi 
2860f860a780SAmine Khaldi     /* environment variable doesn't exist */
2861f860a780SAmine Khaldi     size = MAX_PATH;
2862f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2863f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2864f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2865f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "1:  " ), "Expected '1:  ', got %s\n", buf );
2866f860a780SAmine Khaldi 
2867f860a780SAmine Khaldi     /* environment variable exists */
2868f860a780SAmine Khaldi     size = MAX_PATH;
2869f860a780SAmine Khaldi     SetEnvironmentVariableA( "crazyvar", "crazyval" );
2870f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
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, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2874f860a780SAmine Khaldi 
2875f860a780SAmine Khaldi     /* file key before CostInitialize */
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, "1:  " ), "Expected '1:  ', got %s\n", buf );
2881f860a780SAmine Khaldi 
2882f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2883f860a780SAmine Khaldi 
2884f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "CostInitialize");
2885f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2886f860a780SAmine Khaldi 
2887f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "FileCost");
2888f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2889f860a780SAmine Khaldi 
2890f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "CostFinalize");
2891f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2892f860a780SAmine Khaldi 
2893f860a780SAmine Khaldi     size = MAX_PATH;
2894f860a780SAmine Khaldi     MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2895f860a780SAmine Khaldi 
2896f860a780SAmine Khaldi     sprintf( expected, "1: %sfrontal.txt ", root);
2897f860a780SAmine Khaldi 
2898f860a780SAmine Khaldi     /* frontal full file key */
2899f860a780SAmine Khaldi     size = MAX_PATH;
2900f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2901f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2902f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2903f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2904f860a780SAmine Khaldi 
2905f860a780SAmine Khaldi     /* frontal short file key */
2906f860a780SAmine Khaldi     size = MAX_PATH;
2907f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2908f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2909f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2910f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2911f860a780SAmine Khaldi 
2912f860a780SAmine Khaldi     sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2913f860a780SAmine Khaldi 
2914f860a780SAmine Khaldi     /* temporal full file key */
2915f860a780SAmine Khaldi     size = MAX_PATH;
2916f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2917f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2918f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2919f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2920f860a780SAmine Khaldi 
2921f860a780SAmine Khaldi     /* temporal short file key */
2922f860a780SAmine Khaldi     size = MAX_PATH;
2923f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2924f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2925f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2926f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2927f860a780SAmine Khaldi 
2928f860a780SAmine Khaldi     /* custom action 51, files don't exist */
2929f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "MyCustom" );
2930f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2931f860a780SAmine Khaldi 
2932f860a780SAmine Khaldi     sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2933f860a780SAmine Khaldi 
2934f860a780SAmine Khaldi     size = MAX_PATH;
2935f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2936f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2937f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2938f860a780SAmine Khaldi 
2939f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory", root );
2940f860a780SAmine Khaldi     CreateDirectoryA( buf, NULL );
2941f860a780SAmine Khaldi 
2942f860a780SAmine Khaldi     lstrcatA( buf, "\\temporal.txt" );
2943f860a780SAmine Khaldi     create_test_file( buf );
2944f860a780SAmine Khaldi 
2945f860a780SAmine Khaldi     /* custom action 51, files exist */
2946f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "MyCustom" );
2947f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "MyCustom 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     todo_wine
2953f860a780SAmine Khaldi     {
2954f860a780SAmine Khaldi         ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2955f860a780SAmine Khaldi     }
2956f860a780SAmine Khaldi 
2957f860a780SAmine Khaldi     /* custom action 51, escaped text 1 */
2958f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt1" );
2959f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2960f860a780SAmine Khaldi 
2961f860a780SAmine Khaldi     size = MAX_PATH;
2962f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2963f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2964f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2965f860a780SAmine Khaldi 
2966f860a780SAmine Khaldi     /* custom action 51, escaped text 2 */
2967f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt2" );
2968f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2969f860a780SAmine Khaldi 
2970f860a780SAmine Khaldi     size = MAX_PATH;
2971f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2972f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2973f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2974f860a780SAmine Khaldi 
2975f860a780SAmine Khaldi     /* custom action 51, escaped text 3 */
2976f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EscapeIt3" );
2977f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2978f860a780SAmine Khaldi 
2979f860a780SAmine Khaldi     size = MAX_PATH;
2980f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2981f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2982f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2983f860a780SAmine Khaldi 
2984f860a780SAmine Khaldi     /* custom action 51, embedded null */
2985f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "EmbedNull" );
2986f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2987f860a780SAmine Khaldi 
2988f860a780SAmine Khaldi     size = MAX_PATH;
2989f860a780SAmine Khaldi     memset( buf, 'a', sizeof(buf) );
2990f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2991f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2992f860a780SAmine Khaldi     ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2993f860a780SAmine Khaldi     ok( size == sizeof("\0np") - 1, "got %u\n", size );
2994f860a780SAmine Khaldi 
2995f860a780SAmine Khaldi     r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2996f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2997f860a780SAmine Khaldi 
2998f860a780SAmine Khaldi     size = MAX_PATH;
2999f860a780SAmine Khaldi     memset( buf, 'a', sizeof(buf) );
3000f860a780SAmine Khaldi     r = MsiGetPropertyA( hpkg, "prop", buf, &size );
3001f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3002f860a780SAmine Khaldi     ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
3003f860a780SAmine Khaldi 
3004f860a780SAmine Khaldi     sprintf( expected, "1: %sI am a really long directory\\ ", root);
3005f860a780SAmine Khaldi 
3006f860a780SAmine Khaldi     /* component with INSTALLSTATE_LOCAL */
3007f860a780SAmine Khaldi     size = MAX_PATH;
3008f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[$temporal]" );
3009f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
3010f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
3011f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
3012f860a780SAmine Khaldi 
3013f860a780SAmine Khaldi     r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
3014f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
3015f860a780SAmine Khaldi 
3016f860a780SAmine Khaldi     /* component with INSTALLSTATE_SOURCE */
3017f860a780SAmine Khaldi     lstrcpyA( expected, "1: " );
3018f860a780SAmine Khaldi     lstrcatA( expected, curr_dir );
3019f860a780SAmine Khaldi     if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
3020f860a780SAmine Khaldi     lstrcatA( expected, " " );
3021f860a780SAmine Khaldi     size = MAX_PATH;
3022f860a780SAmine Khaldi     MsiRecordSetStringA( hrec, 1, "[$parietal]" );
3023f860a780SAmine Khaldi     r = MsiFormatRecordA( hpkg, hrec, buf, &size );
3024f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
3025f860a780SAmine Khaldi     ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
3026f860a780SAmine Khaldi 
3027f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
3028f860a780SAmine Khaldi     DeleteFileA( buf );
3029f860a780SAmine Khaldi 
3030f860a780SAmine Khaldi     sprintf( buf, "%sI am a really long directory", root );
3031f860a780SAmine Khaldi     RemoveDirectoryA( buf );
3032f860a780SAmine Khaldi 
3033f860a780SAmine Khaldi     MsiCloseHandle( hrec );
3034f860a780SAmine Khaldi     MsiCloseHandle( hpkg );
3035f860a780SAmine Khaldi     DeleteFileA( msifile );
3036f860a780SAmine Khaldi }
3037f860a780SAmine Khaldi 
3038c2c66affSColin Finck static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
3039c2c66affSColin Finck                                  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3040c2c66affSColin Finck {
3041c2c66affSColin Finck     UINT r;
3042c2c66affSColin Finck     INSTALLSTATE state = 0xdeadbee;
3043c2c66affSColin Finck     INSTALLSTATE action = 0xdeadbee;
3044c2c66affSColin Finck 
3045c2c66affSColin Finck     r = MsiGetFeatureStateA( package, feature, &state, &action );
3046c2c66affSColin Finck     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3047c2c66affSColin Finck     if (r == ERROR_SUCCESS)
3048c2c66affSColin Finck     {
3049c2c66affSColin Finck         ok( state == expected_state, "%u: expected state %d got %d\n",
3050c2c66affSColin Finck             line, expected_state, state );
3051c2c66affSColin Finck         todo_wine_if (todo)
3052c2c66affSColin Finck             ok( action == expected_action, "%u: expected action %d got %d\n",
3053c2c66affSColin Finck                 line, expected_action, action );
3054c2c66affSColin Finck     }
3055c2c66affSColin Finck     else
3056c2c66affSColin Finck     {
3057c2c66affSColin Finck         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3058c2c66affSColin Finck         todo_wine_if (todo)
3059c2c66affSColin Finck             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3060c2c66affSColin Finck 
3061c2c66affSColin Finck     }
3062c2c66affSColin Finck }
3063c2c66affSColin Finck 
3064c2c66affSColin Finck static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3065c2c66affSColin Finck                                    INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3066c2c66affSColin Finck {
3067c2c66affSColin Finck     UINT r;
3068c2c66affSColin Finck     INSTALLSTATE state = 0xdeadbee;
3069c2c66affSColin Finck     INSTALLSTATE action = 0xdeadbee;
3070c2c66affSColin Finck 
3071c2c66affSColin Finck     r = MsiGetComponentStateA( package, component, &state, &action );
3072c2c66affSColin Finck     ok( r == error, "%u: expected %d got %d\n", line, error, r );
3073c2c66affSColin Finck     if (r == ERROR_SUCCESS)
3074c2c66affSColin Finck     {
3075c2c66affSColin Finck         ok( state == expected_state, "%u: expected state %d got %d\n",
3076c2c66affSColin Finck             line, expected_state, state );
3077c2c66affSColin Finck         todo_wine_if (todo)
3078c2c66affSColin Finck             ok( action == expected_action, "%u: expected action %d got %d\n",
3079c2c66affSColin Finck                 line, expected_action, action );
3080c2c66affSColin Finck     }
3081c2c66affSColin Finck     else
3082c2c66affSColin Finck     {
3083c2c66affSColin Finck         ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3084c2c66affSColin Finck             line, state );
3085c2c66affSColin Finck         todo_wine_if (todo)
3086c2c66affSColin Finck             ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3087c2c66affSColin Finck                 line, action );
3088c2c66affSColin Finck     }
3089c2c66affSColin Finck }
3090c2c66affSColin Finck 
3091c2c66affSColin Finck static void test_states(void)
3092c2c66affSColin Finck {
3093c2c66affSColin Finck     static const char msifile2[] = "winetest2-package.msi";
3094c2c66affSColin Finck     static const char msifile3[] = "winetest3-package.msi";
3095c2c66affSColin Finck     static const char msifile4[] = "winetest4-package.msi";
3096c2c66affSColin Finck     static const WCHAR msifile2W[] =
3097c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
3098c2c66affSColin Finck     static const WCHAR msifile3W[] =
3099c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
3100c2c66affSColin Finck     static const WCHAR msifile4W[] =
3101c2c66affSColin Finck         {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
3102f860a780SAmine Khaldi     char msi_cache_file[MAX_PATH];
3103f860a780SAmine Khaldi     DWORD cache_file_name_len;
3104c2c66affSColin Finck     INSTALLSTATE state;
310596486643Swinesync     MSIHANDLE hpkg, hprod;
3106c2c66affSColin Finck     UINT r;
3107c2c66affSColin Finck     MSIHANDLE hdb;
3108f860a780SAmine Khaldi     BOOL is_broken;
310996486643Swinesync     char value[MAX_PATH];
311096486643Swinesync     DWORD size;
3111c2c66affSColin Finck 
3112c2c66affSColin Finck     if (is_process_limited())
3113c2c66affSColin Finck     {
3114c2c66affSColin Finck         skip("process is limited\n");
3115c2c66affSColin Finck         return;
3116c2c66affSColin Finck     }
3117c2c66affSColin Finck 
3118c2c66affSColin Finck     hdb = create_package_db();
3119c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3120c2c66affSColin Finck 
3121f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3122c2c66affSColin Finck 
3123f860a780SAmine Khaldi     create_property_table( hdb );
3124f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3125f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductLanguage', '1033'" );
3126f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3127f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3128f860a780SAmine Khaldi     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
312996486643Swinesync     add_property_entry( hdb, "'UpgradeCode', '{3494EEEA-4221-4A66-802E-DED8916BC5C5}'" );
3130c2c66affSColin Finck 
3131f860a780SAmine Khaldi     create_install_execute_sequence_table( hdb );
3132f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3133f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3134f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3135f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3136f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3137f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3138f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3139f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3140f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3141f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3142f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3143c2c66affSColin Finck 
3144f860a780SAmine Khaldi     create_media_table( hdb );
3145f860a780SAmine Khaldi     add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3146c2c66affSColin Finck 
3147f860a780SAmine Khaldi     create_feature_table( hdb );
3148c2c66affSColin Finck 
3149f860a780SAmine Khaldi     create_component_table( hdb );
3150c2c66affSColin Finck 
3151c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3152f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3153c2c66affSColin Finck 
3154c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3155f860a780SAmine Khaldi     add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3156c2c66affSColin Finck 
3157c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3158f860a780SAmine Khaldi     add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3159c2c66affSColin Finck 
3160c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3161f860a780SAmine Khaldi     add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3162c2c66affSColin Finck 
3163c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3164f860a780SAmine Khaldi     add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3165c2c66affSColin Finck 
3166c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3167f860a780SAmine Khaldi     add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3168c2c66affSColin Finck 
3169c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3170f860a780SAmine Khaldi     add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3171c2c66affSColin Finck 
3172c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3173f860a780SAmine Khaldi     add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3174c2c66affSColin Finck 
3175c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3176f860a780SAmine Khaldi     add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3177c2c66affSColin Finck 
3178c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3179f860a780SAmine Khaldi     add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3180c2c66affSColin Finck 
3181c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3182f860a780SAmine Khaldi     add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3183c2c66affSColin Finck 
3184c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3185f860a780SAmine Khaldi     add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3186c2c66affSColin Finck 
3187c2c66affSColin Finck     /* disabled */
3188f860a780SAmine Khaldi     add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3189c2c66affSColin Finck 
3190c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3191f860a780SAmine Khaldi     add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3192c2c66affSColin Finck 
3193c2c66affSColin Finck     /* no feature parent:msidbComponentAttributesLocalOnly */
3194f860a780SAmine Khaldi     add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3195c2c66affSColin Finck 
3196c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed */
3197f860a780SAmine Khaldi     add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3198c2c66affSColin Finck 
3199c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3200f860a780SAmine Khaldi     add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3201c2c66affSColin Finck 
3202c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3203f860a780SAmine Khaldi     add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3204c2c66affSColin Finck 
3205c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3206f860a780SAmine Khaldi     add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3207c2c66affSColin Finck 
3208c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3209f860a780SAmine Khaldi     add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3210c2c66affSColin Finck 
3211c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed */
3212f860a780SAmine Khaldi     add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3213c2c66affSColin Finck 
3214c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3215f860a780SAmine Khaldi     add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3216c2c66affSColin Finck 
3217c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3218f860a780SAmine Khaldi     add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3219c2c66affSColin Finck 
3220c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3221f860a780SAmine Khaldi     add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3222c2c66affSColin Finck 
3223c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3224f860a780SAmine Khaldi     add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3225c2c66affSColin Finck 
3226c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
3227f860a780SAmine Khaldi     add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3228c2c66affSColin Finck 
3229f860a780SAmine Khaldi     add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3230c2c66affSColin Finck 
3231c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
3232f860a780SAmine Khaldi     add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3233c2c66affSColin Finck 
3234f860a780SAmine Khaldi     add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3235c2c66affSColin Finck 
3236c2c66affSColin Finck     /* msidbFeatureAttributesFavorAdvertise */
3237f860a780SAmine Khaldi     add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3238c2c66affSColin Finck 
3239f860a780SAmine Khaldi     add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3240c2c66affSColin Finck 
3241c2c66affSColin Finck     /* msidbFeatureAttributesUIDisallowAbsent */
3242f860a780SAmine Khaldi     add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3243c2c66affSColin Finck 
3244f860a780SAmine Khaldi     add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3245c2c66affSColin Finck 
3246c2c66affSColin Finck     /* high install level */
3247f860a780SAmine Khaldi     add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3248c2c66affSColin Finck 
3249f860a780SAmine Khaldi     add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3250c2c66affSColin Finck 
3251c2c66affSColin Finck     /* msidbFeatureAttributesFollowParent */
3252f860a780SAmine Khaldi     add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3253c2c66affSColin Finck 
3254f860a780SAmine Khaldi     create_feature_components_table( hdb );
3255f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'alpha'" );
3256f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'beta'" );
3257f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'gamma'" );
3258f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'theta'" );
3259f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'delta'" );
3260f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'epsilon'" );
3261f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'zeta'" );
3262f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'iota'" );
3263f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'three', 'eta'" );
3264f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'four', 'eta'" );
3265f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'five', 'eta'" );
3266f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'lambda'" );
3267f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'mu'" );
3268f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'nu'" );
3269f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'six', 'xi'" );
3270f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'omicron'" );
3271f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'pi'" );
3272f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'rho'" );
3273f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'seven', 'sigma'" );
3274f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'eight', 'tau'" );
3275f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'nine', 'phi'" );
3276f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'ten', 'chi'" );
3277f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'eleven', 'psi'" );
3278f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3279f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3280c2c66affSColin Finck 
3281f860a780SAmine Khaldi     create_file_table( hdb );
3282f860a780SAmine Khaldi     add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3283f860a780SAmine Khaldi     add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3284f860a780SAmine Khaldi     add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3285f860a780SAmine Khaldi     add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3286f860a780SAmine Khaldi     add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3287f860a780SAmine Khaldi     add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3288f860a780SAmine Khaldi     add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3289f860a780SAmine Khaldi     add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3290c2c66affSColin Finck 
3291c2c66affSColin Finck     /* compressed file */
3292f860a780SAmine Khaldi     add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3293c2c66affSColin Finck 
3294f860a780SAmine Khaldi     add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3295f860a780SAmine Khaldi     add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3296f860a780SAmine Khaldi     add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3297f860a780SAmine Khaldi     add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3298f860a780SAmine Khaldi     add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3299f860a780SAmine Khaldi     add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3300f860a780SAmine Khaldi     add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3301f860a780SAmine Khaldi     add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3302f860a780SAmine Khaldi     add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3303f860a780SAmine Khaldi     add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3304f860a780SAmine Khaldi     add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3305f860a780SAmine Khaldi     add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3306f860a780SAmine Khaldi     add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3307f860a780SAmine Khaldi     add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3308c2c66affSColin Finck 
3309f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
3310f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3311c2c66affSColin Finck 
3312c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3313f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3314f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3315f860a780SAmine Khaldi     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3316f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3317f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3318c2c66affSColin Finck 
3319c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3320c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3321c2c66affSColin Finck     {
3322c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3323c2c66affSColin Finck         DeleteFileA(msifile);
3324c2c66affSColin Finck         return;
3325c2c66affSColin Finck     }
3326c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3327c2c66affSColin Finck 
3328c2c66affSColin Finck     MsiCloseHandle(hdb);
3329c2c66affSColin Finck 
3330c2c66affSColin Finck     CopyFileA(msifile, msifile2, FALSE);
3331c2c66affSColin Finck     CopyFileA(msifile, msifile3, FALSE);
3332c2c66affSColin Finck     CopyFileA(msifile, msifile4, FALSE);
3333c2c66affSColin Finck 
3334fbdb719bSwinesync     size = sizeof(value);
3335fbdb719bSwinesync     memset(value, 0, sizeof(value));
3336fbdb719bSwinesync     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3337fbdb719bSwinesync     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3338fbdb719bSwinesync     ok(!value[0], "ProductToBeRegistered = %s\n", value);
3339fbdb719bSwinesync 
3340c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3341c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3342c2c66affSColin Finck 
3343c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3344c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3345c2c66affSColin Finck 
3346c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3347c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3348c2c66affSColin Finck 
3349c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3350c2c66affSColin Finck 
3351c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3352c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3353c2c66affSColin Finck 
3354c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3355c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3356c2c66affSColin Finck 
3357c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3358c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3359c2c66affSColin Finck 
3360c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3361c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3362c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3363c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3364c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3365c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3366c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3367c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3368c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3369c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3370c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3371c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3372c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3373c2c66affSColin Finck 
3374c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3375c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3376c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3377c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3378c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3379c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3380c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
3381c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3382c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
3383c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3384c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3385c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3386c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3387c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3388c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3389c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3390c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3391c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3392c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3393c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3394c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3395c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3396c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3397c2c66affSColin Finck 
3398c2c66affSColin Finck     MsiCloseHandle( hpkg );
3399c2c66affSColin Finck 
3400c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3401c2c66affSColin Finck 
3402c2c66affSColin Finck     /* publish the features and components */
3403c2c66affSColin Finck     r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3404c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3405c2c66affSColin Finck 
3406c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
3407c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3408c2c66affSColin Finck 
3409c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3410f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3411f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3412f860a780SAmine Khaldi     add_property_entry( hdb, "'REMOVE', 'six,seven'");
3413f860a780SAmine Khaldi     add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3414c2c66affSColin Finck 
3415c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3416c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3417c2c66affSColin Finck 
3418c2c66affSColin Finck     MsiCloseHandle(hdb);
3419c2c66affSColin Finck 
3420fbdb719bSwinesync     size = sizeof(value);
3421fbdb719bSwinesync     memset(value, 0, sizeof(value));
3422fbdb719bSwinesync     r = MsiGetPropertyA(hpkg, "ProductToBeRegistered", value, &size);
3423fbdb719bSwinesync     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
3424fbdb719bSwinesync     ok(value[0]=='1' && !value[1], "ProductToBeRegistered = %s\n", value);
3425fbdb719bSwinesync 
3426c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3427c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3428c2c66affSColin Finck 
3429c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3430c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3431c2c66affSColin Finck 
3432c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3433c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3434c2c66affSColin Finck 
3435c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3436c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3437c2c66affSColin Finck 
3438c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3439c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3440c2c66affSColin Finck 
3441c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3442c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3443c2c66affSColin Finck 
3444c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3445c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3446c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3447c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3448c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3449c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3450c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3451c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3452c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3453c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3454c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3455c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3456c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3457c2c66affSColin Finck 
3458c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3459c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3460c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3461c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3462c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3463c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3464c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3465c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3466c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3467c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3468c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3469c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3470c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3471c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3472c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3473c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3474c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3475c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3476c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3477c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3478c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3479c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3480c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3481c2c66affSColin Finck 
3482c2c66affSColin Finck     MsiCloseHandle(hpkg);
3483c2c66affSColin Finck 
3484c2c66affSColin Finck     /* uninstall the product */
3485c2c66affSColin Finck     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3486c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3487c2c66affSColin Finck 
3488c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3489c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3490c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3491c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3492c2c66affSColin Finck 
3493c2c66affSColin Finck     /* all features installed locally */
3494c2c66affSColin Finck     r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3495c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3496c2c66affSColin Finck 
3497c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3498c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3499c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3500c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3501c2c66affSColin Finck 
3502c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3503c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3504c2c66affSColin Finck 
3505c2c66affSColin Finck     /* these properties must not be in the saved msi file */
3506f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3507c2c66affSColin Finck 
3508c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3509c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3510c2c66affSColin Finck 
3511c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3512c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3513c2c66affSColin Finck 
3514c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3515c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3516c2c66affSColin Finck 
3517c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3518c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3519c2c66affSColin Finck 
3520c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3521c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3522c2c66affSColin Finck 
3523c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3524c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3525c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3526c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3527c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3528c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3529c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_LOCAL, FALSE );
3530c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3531c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3532c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, TRUE );
3533c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3534c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3535c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3536c2c66affSColin Finck 
3537c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3538c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3539c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3540c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3541c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3542c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3543c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3544c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3545c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3546c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3547c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3548c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3549c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3550c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3551c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3552c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3553c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3554c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3555c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3556c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3557c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3558c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3559c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3560c2c66affSColin Finck 
3561c2c66affSColin Finck     MsiCloseHandle(hpkg);
3562c2c66affSColin Finck 
3563c2c66affSColin Finck     /* uninstall the product */
3564c2c66affSColin Finck     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3565c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3566c2c66affSColin Finck 
3567c2c66affSColin Finck     /* all features installed from source */
3568c2c66affSColin Finck     r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3569c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3570c2c66affSColin Finck 
3571c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3572c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3573c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3574c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3575c2c66affSColin Finck 
3576c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3577c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3578c2c66affSColin Finck 
3579c2c66affSColin Finck     /* this property must not be in the saved msi file */
3580f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3581c2c66affSColin Finck 
3582c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3583c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3584c2c66affSColin Finck 
3585c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3586c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3587c2c66affSColin Finck 
3588c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3589c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3590c2c66affSColin Finck 
3591c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3592c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3593c2c66affSColin Finck 
3594c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3595c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3596c2c66affSColin Finck 
3597c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3598c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3599c2c66affSColin Finck 
3600c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3601c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3602c2c66affSColin Finck 
3603c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3604c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3605c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3606c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3607c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3608c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3609c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3610c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3611c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3612c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3613c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3614c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3615c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3616c2c66affSColin Finck 
3617c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3618c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3619c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3620c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3621c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3622c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3623c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3624c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3625c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3626c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3627c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3628c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3629c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3630c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3631c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3632c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3633c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3634c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3635c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3636c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3637c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3638c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3639f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3640c2c66affSColin Finck 
3641c2c66affSColin Finck     MsiCloseHandle(hpkg);
3642c2c66affSColin Finck 
3643c2c66affSColin Finck     /* reinstall the product */
3644c2c66affSColin Finck     r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3645f860a780SAmine Khaldi     is_broken = (r == ERROR_INSTALL_FAILURE);
3646f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3647c2c66affSColin Finck 
3648c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3649c2c66affSColin Finck     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3650c2c66affSColin Finck     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3651c2c66affSColin Finck     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3652c2c66affSColin Finck 
3653c2c66affSColin Finck     r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3654c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3655c2c66affSColin Finck 
3656c2c66affSColin Finck     /* this property must not be in the saved msi file */
3657f860a780SAmine Khaldi     add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3658c2c66affSColin Finck 
3659c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3660c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3661c2c66affSColin Finck 
3662c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3663c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3664c2c66affSColin Finck 
3665c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3666c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3667c2c66affSColin Finck 
3668c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3669c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3670c2c66affSColin Finck 
3671c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3672c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3673c2c66affSColin Finck 
3674c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3675c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3676c2c66affSColin Finck 
3677c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3678c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3679c2c66affSColin Finck 
3680c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3681c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3682c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "three", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3683c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "four", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3684c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "five", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3685c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "six", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3686c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "seven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3687c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eight", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3688c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "nine", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3689c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "ten", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_SOURCE, FALSE );
3690c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "eleven", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, TRUE );
3691c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "twelve", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3692c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "thirteen", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_UNKNOWN, FALSE );
3693c2c66affSColin Finck 
3694c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3695c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3696c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3697c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3698c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3699c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3700c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3701c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3702c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3703c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3704c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3705c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3706c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3707c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3708c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3709c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3710c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3711c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3712c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3713c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3714c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3715c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3716f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3717c2c66affSColin Finck 
3718c2c66affSColin Finck     MsiCloseHandle(hpkg);
3719c2c66affSColin Finck 
3720f860a780SAmine Khaldi     /* test source only install */
3721f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3722f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3723f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3724f860a780SAmine Khaldi     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3725f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3726f860a780SAmine Khaldi     ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3727f860a780SAmine Khaldi 
3728f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3729f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3730f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3731f860a780SAmine Khaldi     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3732f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3733f860a780SAmine Khaldi     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3734f860a780SAmine Khaldi 
3735f860a780SAmine Khaldi     /* no arguments test */
3736f860a780SAmine Khaldi     cache_file_name_len = sizeof(msi_cache_file);
3737f860a780SAmine Khaldi     r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3738f860a780SAmine Khaldi             INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3739f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3740f860a780SAmine Khaldi     r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3741f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3742f860a780SAmine Khaldi 
3743f860a780SAmine Khaldi     create_custom_action_table( hdb );
3744f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3745f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3746f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3747f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3748f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3749f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3750f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3751f860a780SAmine Khaldi     add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
37522dce4ee7Swinesync     add_custom_action_entry( hdb,
375318123440Swinesync             "'VBFeatureRequest', 38, NULL, 'Session.FeatureRequestState(\"three\") = 3'" );
3754f860a780SAmine Khaldi 
3755f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3756f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
37572dce4ee7Swinesync     add_install_execute_sequence_entry( hdb, "'VBFeatureRequest', 'NOT REMOVE', '1001'" );
3758f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3759f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3760f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3761f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3762f860a780SAmine Khaldi     /* Add "one" feature action tests */
3763f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3764f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3765f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
3766f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3767f860a780SAmine Khaldi     r = package_from_db( hdb, &hpkg );
3768f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3769f860a780SAmine Khaldi     MsiCloseHandle(hdb);
3770f860a780SAmine Khaldi 
3771f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3772f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3773f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "CostInitialize");
3774f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3775f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3776f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3777f860a780SAmine Khaldi 
3778f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "FileCost");
3779f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "FileCost failed\n");
3780f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3781f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
3782f860a780SAmine Khaldi 
3783f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "CostFinalize");
3784f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "CostFinalize failed\n");
3785f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3786f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3787f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "alpha", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3788f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "beta", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3789f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "gamma", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3790f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "theta", ERROR_SUCCESS, INSTALLSTATE_LOCAL, INSTALLSTATE_LOCAL, FALSE );
3791f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "delta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3792f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "epsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3793f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "zeta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3794f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "iota", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3795f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "eta", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3796f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "kappa", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3797f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "lambda", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3798f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "mu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3799f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "nu", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3800f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "xi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3801f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "omicron", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3802f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "pi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3803f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "rho", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3804f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "sigma", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3805f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "tau", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3806f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "phi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3807f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "chi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3808f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "psi", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3809f860a780SAmine Khaldi     test_component_states( __LINE__, hpkg, "upsilon", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3810f860a780SAmine Khaldi 
3811f860a780SAmine Khaldi     r = MsiDoActionA( hpkg, "InstallValidate");
3812f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "InstallValidate failed %d\n", r);
3813f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "one", ERROR_SUCCESS, INSTALLSTATE_SOURCE, INSTALLSTATE_UNKNOWN, FALSE );
3814f860a780SAmine Khaldi     test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
3815f860a780SAmine Khaldi     MsiCloseHandle( hpkg );
3816f860a780SAmine Khaldi 
3817f860a780SAmine Khaldi     r = MsiInstallProductA(msifile, "");
3818f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS || (is_broken && r == ERROR_INSTALL_FAILURE) /* win2k3 */,
3819f860a780SAmine Khaldi             "Expected ERROR_SUCCESS, got %d\n", r);
3820f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3821f860a780SAmine Khaldi     ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3822f860a780SAmine Khaldi     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3823f860a780SAmine Khaldi     ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
38242dce4ee7Swinesync     state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "three");
38252dce4ee7Swinesync     ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3826f860a780SAmine Khaldi 
382796486643Swinesync     /* minor upgrade test with no REINSTALL argument */
382896486643Swinesync     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
382996486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
383096486643Swinesync     size = MAX_PATH;
383196486643Swinesync     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
383296486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
383396486643Swinesync     ok(!strcmp(value, "1.1.1"), "ProductVersion = %s\n", value);
383496486643Swinesync     MsiCloseHandle(hprod);
383596486643Swinesync 
383696486643Swinesync     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
383796486643Swinesync     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
383896486643Swinesync     update_ProductVersion_property( hdb, "1.1.2" );
383996486643Swinesync     set_summary_str(hdb, PID_REVNUMBER, "{A219A62A-D931-4F1B-89DB-FF1C300A8D43}");
384096486643Swinesync     r = MsiDatabaseCommit(hdb);
384196486643Swinesync     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
384296486643Swinesync     MsiCloseHandle(hdb);
384396486643Swinesync 
384496486643Swinesync     r = MsiInstallProductA(msifile2, "");
3845b7b9c0c4Swinesync     ok(r == ERROR_PRODUCT_VERSION, "Expected ERROR_PRODUCT_VERSION, got %d\n", r);
384696486643Swinesync 
3847a2371385Swinesync     r = MsiInstallProductA(msifile2, "REINSTALLMODe=V");
3848a2371385Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3849366dd26eSwinesync 
3850366dd26eSwinesync     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
3851366dd26eSwinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3852366dd26eSwinesync     size = MAX_PATH;
3853366dd26eSwinesync     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
3854366dd26eSwinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3855a2371385Swinesync     ok(!strcmp(value, "1.1.2"), "ProductVersion = %s\n", value);
3856366dd26eSwinesync     MsiCloseHandle(hprod);
3857366dd26eSwinesync 
385896486643Swinesync     /* major upgrade test */
385996486643Swinesync     r = MsiOpenDatabaseA(msifile2, (const char*)MSIDBOPEN_DIRECT, &hdb);
386096486643Swinesync     ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3861366dd26eSwinesync     add_install_execute_sequence_entry( hdb, "'FindRelatedProducts', '', '100'" );
3862366dd26eSwinesync     add_install_execute_sequence_entry( hdb, "'RemoveExistingProducts', '', '1401'" );
3863366dd26eSwinesync     create_upgrade_table( hdb );
3864366dd26eSwinesync     add_upgrade_entry( hdb, "'{3494EEEA-4221-4A66-802E-DED8916BC5C5}', NULL, '1.1.3', NULL, 0, NULL, 'OLDERVERSIONBEINGUPGRADED'");
386596486643Swinesync     update_ProductCode_property( hdb, "{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}" );
3866366dd26eSwinesync     update_ProductVersion_property( hdb, "1.1.3" );
3867366dd26eSwinesync     set_summary_str(hdb, PID_REVNUMBER, "{5F99011C-02E6-48BD-8B8D-DE7CFABC7A09}");
386896486643Swinesync     r = MsiDatabaseCommit(hdb);
386996486643Swinesync     ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
387096486643Swinesync     MsiCloseHandle(hdb);
387196486643Swinesync 
387296486643Swinesync     r = MsiInstallProductA(msifile2, "");
3873366dd26eSwinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
387496486643Swinesync 
387596486643Swinesync     r = MsiOpenProductA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", &hprod);
387696486643Swinesync     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
387796486643Swinesync     r = MsiOpenProductA("{333DB27A-C25E-4EBC-9BEC-0F49546C19A6}", &hprod);
387896486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
387996486643Swinesync     size = MAX_PATH;
388096486643Swinesync     r = MsiGetProductPropertyA(hprod, "ProductVersion", value, &size);
388196486643Swinesync     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3882366dd26eSwinesync     ok(!strcmp(value, "1.1.3"), "ProductVersion = %s\n", value);
388396486643Swinesync     MsiCloseHandle(hprod);
388496486643Swinesync 
3885c2c66affSColin Finck     /* uninstall the product */
388696486643Swinesync     r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3887c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3888c2c66affSColin Finck 
3889c2c66affSColin Finck     DeleteFileA(msifile);
3890c2c66affSColin Finck     DeleteFileA(msifile2);
3891c2c66affSColin Finck     DeleteFileA(msifile3);
3892c2c66affSColin Finck     DeleteFileA(msifile4);
3893c2c66affSColin Finck }
3894c2c66affSColin Finck 
3895c2c66affSColin Finck static void test_removefiles(void)
3896c2c66affSColin Finck {
3897c2c66affSColin Finck     MSIHANDLE hpkg;
3898c2c66affSColin Finck     UINT r;
3899c2c66affSColin Finck     MSIHANDLE hdb;
3900c2c66affSColin Finck     INSTALLSTATE installed, action;
3901c2c66affSColin Finck 
3902c2c66affSColin Finck     hdb = create_package_db();
3903c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
3904c2c66affSColin Finck 
3905f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3906c2c66affSColin Finck 
3907f860a780SAmine Khaldi     create_feature_table( hdb );
3908f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3909c2c66affSColin Finck 
3910f860a780SAmine Khaldi     create_component_table( hdb );
3911f860a780SAmine Khaldi     add_component_entry( hdb, "'hydrogen', '', 'TARGETDIR', 0, '', 'hydrogen_file'" );
3912f860a780SAmine Khaldi     add_component_entry( hdb, "'helium', '', 'TARGETDIR', 0, '', 'helium_file'" );
3913f860a780SAmine Khaldi     add_component_entry( hdb, "'lithium', '', 'TARGETDIR', 0, '', 'lithium_file'" );
3914f860a780SAmine Khaldi     add_component_entry( hdb, "'beryllium', '', 'TARGETDIR', 0, '', 'beryllium_file'" );
3915f860a780SAmine Khaldi     add_component_entry( hdb, "'boron', '', 'TARGETDIR', 0, '', 'boron_file'" );
3916f860a780SAmine Khaldi     add_component_entry( hdb, "'carbon', '', 'TARGETDIR', 0, '', 'carbon_file'" );
3917f860a780SAmine Khaldi     add_component_entry( hdb, "'oxygen', '', 'TARGETDIR', 0, '0', 'oxygen_file'" );
3918c2c66affSColin Finck 
3919f860a780SAmine Khaldi     create_feature_components_table( hdb );
3920f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'hydrogen'" );
3921f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'helium'" );
3922f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'lithium'" );
3923f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'beryllium'" );
3924f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'boron'" );
3925f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'carbon'" );
3926f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'oxygen'" );
3927c2c66affSColin Finck 
3928f860a780SAmine Khaldi     create_file_table( hdb );
3929f860a780SAmine Khaldi     add_file_entry( hdb, "'hydrogen_file', 'hydrogen', 'hydrogen.txt', 0, '', '1033', 8192, 1" );
3930f860a780SAmine Khaldi     add_file_entry( hdb, "'helium_file', 'helium', 'helium.txt', 0, '', '1033', 8192, 1" );
3931f860a780SAmine Khaldi     add_file_entry( hdb, "'lithium_file', 'lithium', 'lithium.txt', 0, '', '1033', 8192, 1" );
3932f860a780SAmine Khaldi     add_file_entry( hdb, "'beryllium_file', 'beryllium', 'beryllium.txt', 0, '', '1033', 16384, 1" );
3933f860a780SAmine Khaldi     add_file_entry( hdb, "'boron_file', 'boron', 'boron.txt', 0, '', '1033', 16384, 1" );
3934f860a780SAmine Khaldi     add_file_entry( hdb, "'carbon_file', 'carbon', 'carbon.txt', 0, '', '1033', 16384, 1" );
3935f860a780SAmine Khaldi     add_file_entry( hdb, "'oxygen_file', 'oxygen', 'oxygen.txt', 0, '', '1033', 16384, 1" );
3936c2c66affSColin Finck 
3937f860a780SAmine Khaldi     create_remove_file_table( hdb );
3938c2c66affSColin Finck 
3939c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
3940c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
3941c2c66affSColin Finck     {
3942c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
3943c2c66affSColin Finck         DeleteFileA(msifile);
3944c2c66affSColin Finck         return;
3945c2c66affSColin Finck     }
3946c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3947c2c66affSColin Finck 
3948c2c66affSColin Finck     MsiCloseHandle( hdb );
3949c2c66affSColin Finck 
3950c2c66affSColin Finck     create_test_file( "hydrogen.txt" );
3951c2c66affSColin Finck     create_test_file( "helium.txt" );
3952c2c66affSColin Finck     create_test_file( "lithium.txt" );
3953c2c66affSColin Finck     create_test_file( "beryllium.txt" );
3954c2c66affSColin Finck     create_test_file( "boron.txt" );
3955c2c66affSColin Finck     create_test_file( "carbon.txt" );
3956c2c66affSColin Finck     create_test_file( "oxygen.txt" );
3957c2c66affSColin Finck 
3958c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "TARGETDIR", CURR_DIR );
3959c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "set property failed\n");
3960c2c66affSColin Finck 
3961c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3962c2c66affSColin Finck 
3963c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3964c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_COMPONENT, "expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
3965c2c66affSColin Finck 
3966c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
3967c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
3968c2c66affSColin Finck 
3969c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
3970c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
3971c2c66affSColin Finck 
3972c2c66affSColin Finck     installed = action = 0xdeadbeef;
3973c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
3974c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3975c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3976c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3977c2c66affSColin Finck 
3978c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
3979c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
3980c2c66affSColin Finck 
3981c2c66affSColin Finck     r = MsiDoActionA( hpkg, "InstallValidate");
3982c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "install validate failed\n");
3983c2c66affSColin Finck 
3984c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "hydrogen", INSTALLSTATE_ABSENT );
3985c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3986c2c66affSColin Finck 
3987c2c66affSColin Finck     installed = action = 0xdeadbeef;
3988c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "hydrogen", &installed, &action );
3989c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
3990c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
3991c2c66affSColin Finck     todo_wine ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
3992c2c66affSColin Finck 
3993c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "helium", INSTALLSTATE_LOCAL );
3994c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3995c2c66affSColin Finck 
3996c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "lithium", INSTALLSTATE_SOURCE );
3997c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
3998c2c66affSColin Finck 
3999c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "beryllium", INSTALLSTATE_ABSENT );
4000c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
4001c2c66affSColin Finck 
4002c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "boron", INSTALLSTATE_LOCAL );
4003c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
4004c2c66affSColin Finck 
4005c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "carbon", INSTALLSTATE_SOURCE );
4006c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
4007c2c66affSColin Finck 
4008c2c66affSColin Finck     installed = action = 0xdeadbeef;
4009c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
4010c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
4011c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
4012c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
4013c2c66affSColin Finck 
4014c2c66affSColin Finck     r = MsiSetComponentStateA( hpkg, "oxygen", INSTALLSTATE_ABSENT );
4015c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set component state: %d\n", r);
4016c2c66affSColin Finck 
4017c2c66affSColin Finck     installed = action = 0xdeadbeef;
4018c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
4019c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
4020c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
4021c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
4022c2c66affSColin Finck 
4023c2c66affSColin Finck     r = MsiDoActionA( hpkg, "RemoveFiles");
4024c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "remove files failed\n");
4025c2c66affSColin Finck 
4026c2c66affSColin Finck     installed = action = 0xdeadbeef;
4027c2c66affSColin Finck     r = MsiGetComponentStateA( hpkg, "oxygen", &installed, &action );
4028c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get component state %u\n", r );
4029c2c66affSColin Finck     ok( installed == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", installed );
4030c2c66affSColin Finck     ok( action == INSTALLSTATE_UNKNOWN, "expected INSTALLSTATE_UNKNOWN, got %d\n", action );
4031c2c66affSColin Finck 
4032c2c66affSColin Finck     ok(DeleteFileA("hydrogen.txt"), "Expected hydrogen.txt to exist\n");
4033c2c66affSColin Finck     ok(DeleteFileA("lithium.txt"), "Expected lithium.txt to exist\n");
4034c2c66affSColin Finck     ok(DeleteFileA("beryllium.txt"), "Expected beryllium.txt to exist\n");
4035c2c66affSColin Finck     ok(DeleteFileA("carbon.txt"), "Expected carbon.txt to exist\n");
4036c2c66affSColin Finck     ok(DeleteFileA("helium.txt"), "Expected helium.txt to exist\n");
4037c2c66affSColin Finck     ok(DeleteFileA("boron.txt"), "Expected boron.txt to exist\n");
4038c2c66affSColin Finck     ok(DeleteFileA("oxygen.txt"), "Expected oxygen.txt to exist\n");
4039c2c66affSColin Finck 
4040c2c66affSColin Finck     MsiCloseHandle( hpkg );
4041c2c66affSColin Finck     DeleteFileA(msifile);
4042c2c66affSColin Finck }
4043c2c66affSColin Finck 
4044c2c66affSColin Finck static void test_appsearch(void)
4045c2c66affSColin Finck {
4046c2c66affSColin Finck     MSIHANDLE hpkg;
4047c2c66affSColin Finck     UINT r;
4048c2c66affSColin Finck     MSIHANDLE hdb;
4049c2c66affSColin Finck     CHAR prop[MAX_PATH];
4050c2c66affSColin Finck     DWORD size;
4051c2c66affSColin Finck     HKEY hkey;
4052c2c66affSColin Finck     const char reg_expand_value[] = "%systemroot%\\system32\\notepad.exe";
4053c2c66affSColin Finck 
4054c2c66affSColin Finck     hdb = create_package_db();
4055c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
4056c2c66affSColin Finck 
4057f860a780SAmine Khaldi     create_appsearch_table( hdb );
4058f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'WEBBROWSERPROG', 'NewSignature1'" );
4059f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'NOTEPAD', 'NewSignature2'" );
4060f860a780SAmine Khaldi     add_appsearch_entry( hdb, "'REGEXPANDVAL', 'NewSignature3'" );
4061c2c66affSColin Finck 
4062f860a780SAmine Khaldi     create_reglocator_table( hdb );
4063f860a780SAmine Khaldi     add_reglocator_entry( hdb, "NewSignature1", 0, "htmlfile\\shell\\open\\command", "", 1 );
4064c2c66affSColin Finck 
4065c2c66affSColin Finck     r = RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Winetest_msi", 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL);
4066c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Could not create key: %d.\n", r );
4067c2c66affSColin Finck     r = RegSetValueExA(hkey, NULL, 0, REG_EXPAND_SZ, (const BYTE*)reg_expand_value, strlen(reg_expand_value) + 1);
4068c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Could not set key value: %d.\n", r);
4069c2c66affSColin Finck     RegCloseKey(hkey);
4070f860a780SAmine Khaldi     add_reglocator_entry( hdb, "NewSignature3", 1, "Software\\Winetest_msi", "", 1 );
4071c2c66affSColin Finck 
4072f860a780SAmine Khaldi     create_drlocator_table( hdb );
4073f860a780SAmine Khaldi     add_drlocator_entry( hdb, "'NewSignature2', 0, 'c:\\windows\\system32', 0" );
4074c2c66affSColin Finck 
4075f860a780SAmine Khaldi     create_signature_table( hdb );
4076f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature1', 'FileName', '', '', '', '', '', '', ''" );
4077f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature2', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4078f860a780SAmine Khaldi     add_signature_entry( hdb, "'NewSignature3', 'NOTEPAD.EXE|notepad.exe', '', '', '', '', '', '', ''" );
4079c2c66affSColin Finck 
4080c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
4081c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4082c2c66affSColin Finck     {
4083c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4084c2c66affSColin Finck         DeleteFileA(msifile);
4085c2c66affSColin Finck         return;
4086c2c66affSColin Finck     }
4087c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
4088c2c66affSColin Finck     MsiCloseHandle( hdb );
4089c2c66affSColin Finck     if (r != ERROR_SUCCESS)
4090c2c66affSColin Finck         goto done;
4091c2c66affSColin Finck 
4092c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4093c2c66affSColin Finck 
4094c2c66affSColin Finck     r = MsiDoActionA( hpkg, "AppSearch" );
4095c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "AppSearch failed: %d\n", r);
4096c2c66affSColin Finck 
4097c2c66affSColin Finck     size = sizeof(prop);
4098c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "WEBBROWSERPROG", prop, &size );
4099c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4100c2c66affSColin Finck     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4101c2c66affSColin Finck 
4102c2c66affSColin Finck     size = sizeof(prop);
4103c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "NOTEPAD", prop, &size );
4104c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4105c2c66affSColin Finck 
4106c2c66affSColin Finck     size = sizeof(prop);
4107c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "REGEXPANDVAL", prop, &size );
4108c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
4109c2c66affSColin Finck     ok( lstrlenA(prop) != 0, "Expected non-zero length\n");
4110c2c66affSColin Finck 
4111c2c66affSColin Finck done:
4112c2c66affSColin Finck     MsiCloseHandle( hpkg );
4113c2c66affSColin Finck     DeleteFileA(msifile);
4114c2c66affSColin Finck     RegDeleteKeyA(HKEY_CURRENT_USER, "Software\\Winetest_msi");
4115c2c66affSColin Finck }
4116c2c66affSColin Finck 
4117c2c66affSColin Finck static void test_appsearch_complocator(void)
4118c2c66affSColin Finck {
4119c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4120c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4121c2c66affSColin Finck     LPSTR usersid;
4122c2c66affSColin Finck     DWORD size;
4123c2c66affSColin Finck     UINT r;
4124c2c66affSColin Finck 
4125c2c66affSColin Finck     if (!(usersid = get_user_sid()))
4126c2c66affSColin Finck         return;
4127c2c66affSColin Finck 
4128c2c66affSColin Finck     if (is_process_limited())
4129c2c66affSColin Finck     {
4130c2c66affSColin Finck         skip("process is limited\n");
4131c2c66affSColin Finck         return;
4132c2c66affSColin Finck     }
4133c2c66affSColin Finck 
4134c2c66affSColin Finck     create_test_file("FileName1");
4135c2c66affSColin Finck     create_test_file("FileName4");
4136c2c66affSColin Finck     set_component_path("FileName1", MSIINSTALLCONTEXT_MACHINE,
4137c2c66affSColin Finck                        "{A8AE6692-96BA-4198-8399-145D7D1D0D0E}", NULL, FALSE);
4138c2c66affSColin Finck 
4139c2c66affSColin Finck     create_test_file("FileName2");
4140c2c66affSColin Finck     set_component_path("FileName2", MSIINSTALLCONTEXT_USERUNMANAGED,
4141c2c66affSColin Finck                        "{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}", usersid, FALSE);
4142c2c66affSColin Finck 
4143c2c66affSColin Finck     create_test_file("FileName3");
4144c2c66affSColin Finck     set_component_path("FileName3", MSIINSTALLCONTEXT_USERMANAGED,
4145c2c66affSColin Finck                        "{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}", usersid, FALSE);
4146c2c66affSColin Finck 
4147c2c66affSColin Finck     create_test_file("FileName5");
4148c2c66affSColin Finck     set_component_path("FileName5", MSIINSTALLCONTEXT_MACHINE,
4149c2c66affSColin Finck                        "{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}", NULL, TRUE);
4150c2c66affSColin Finck 
4151c2c66affSColin Finck     create_test_file("FileName6");
4152c2c66affSColin Finck     set_component_path("FileName6", MSIINSTALLCONTEXT_MACHINE,
4153c2c66affSColin Finck                        "{C0ECD96F-7898-4410-9667-194BD8C1B648}", NULL, TRUE);
4154c2c66affSColin Finck 
4155c2c66affSColin Finck     create_test_file("FileName7");
4156c2c66affSColin Finck     set_component_path("FileName7", MSIINSTALLCONTEXT_MACHINE,
4157c2c66affSColin Finck                        "{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}", NULL, FALSE);
4158c2c66affSColin Finck 
4159c2c66affSColin Finck     /* dir is FALSE, but we're pretending it's a directory */
4160c2c66affSColin Finck     set_component_path("IDontExist\\", MSIINSTALLCONTEXT_MACHINE,
4161c2c66affSColin Finck                        "{91B7359B-07F2-4221-AA8D-DE102BB87A5F}", NULL, FALSE);
4162c2c66affSColin Finck 
4163c2c66affSColin Finck     create_file_with_version("FileName8.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4164c2c66affSColin Finck     set_component_path("FileName8.dll", MSIINSTALLCONTEXT_MACHINE,
4165c2c66affSColin Finck                        "{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}", NULL, FALSE);
4166c2c66affSColin Finck 
4167c2c66affSColin Finck     create_file_with_version("FileName9.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4168c2c66affSColin Finck     set_component_path("FileName9.dll", MSIINSTALLCONTEXT_MACHINE,
4169c2c66affSColin Finck                        "{A204DF48-7346-4635-BA2E-66247DBAC9DF}", NULL, FALSE);
4170c2c66affSColin Finck 
4171c2c66affSColin Finck     create_file_with_version("FileName10.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4172c2c66affSColin Finck     set_component_path("FileName10.dll", MSIINSTALLCONTEXT_MACHINE,
4173c2c66affSColin Finck                        "{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}", NULL, FALSE);
4174c2c66affSColin Finck 
4175c2c66affSColin Finck     hdb = create_package_db();
4176c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4177c2c66affSColin Finck 
4178f860a780SAmine Khaldi     create_appsearch_table(hdb);
4179f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4180f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4181f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4182f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4183f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4184f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4185f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4186f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4187f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4188f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4189f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4190f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4191c2c66affSColin Finck 
4192f860a780SAmine Khaldi     create_complocator_table(hdb);
4193c2c66affSColin Finck 
4194c2c66affSColin Finck     /* published component, machine, file, signature, misdbLocatorTypeFile */
4195f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature1', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 1");
4196c2c66affSColin Finck 
4197c2c66affSColin Finck     /* published component, user-unmanaged, file, signature, misdbLocatorTypeFile */
4198f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature2', '{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}', 1");
4199c2c66affSColin Finck 
4200c2c66affSColin Finck     /* published component, user-managed, file, signature, misdbLocatorTypeFile */
4201f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature3', '{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}', 1");
4202c2c66affSColin Finck 
4203c2c66affSColin Finck     /* published component, machine, file, signature, misdbLocatorTypeDirectory */
4204f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature4', '{A8AE6692-96BA-4198-8399-145D7D1D0D0E}', 0");
4205c2c66affSColin Finck 
4206c2c66affSColin Finck     /* published component, machine, dir, signature, misdbLocatorTypeDirectory */
4207f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature5', '{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}', 0");
4208c2c66affSColin Finck 
4209c2c66affSColin Finck     /* published component, machine, dir, no signature, misdbLocatorTypeDirectory */
4210f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature6', '{C0ECD96F-7898-4410-9667-194BD8C1B648}', 0");
4211c2c66affSColin Finck 
4212c2c66affSColin Finck     /* published component, machine, file, no signature, misdbLocatorTypeFile */
4213f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature7', '{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}', 1");
4214c2c66affSColin Finck 
4215c2c66affSColin Finck     /* unpublished component, no signature, misdbLocatorTypeDir */
4216f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature8', '{FB671D5B-5083-4048-90E0-481C48D8F3A5}', 0");
4217c2c66affSColin Finck 
4218c2c66affSColin Finck     /* published component, no signature, dir does not exist misdbLocatorTypeDir */
4219f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature9', '{91B7359B-07F2-4221-AA8D-DE102BB87A5F}', 0");
4220c2c66affSColin Finck 
4221c2c66affSColin Finck     /* published component, signature w/ ver, misdbLocatorTypeFile */
4222f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature10', '{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}', 1");
4223c2c66affSColin Finck 
4224c2c66affSColin Finck     /* published component, signature w/ ver, ver > max, misdbLocatorTypeFile */
4225f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature11', '{A204DF48-7346-4635-BA2E-66247DBAC9DF}', 1");
4226c2c66affSColin Finck 
4227c2c66affSColin Finck     /* published component, signature w/ ver, sig->name ignored, misdbLocatorTypeFile */
4228f860a780SAmine Khaldi     add_complocator_entry(hdb, "'NewSignature12', '{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}', 1");
4229c2c66affSColin Finck 
4230f860a780SAmine Khaldi     create_signature_table(hdb);
4231f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
4232f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature2', 'FileName2', '', '', '', '', '', '', ''");
4233f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature3', 'FileName3', '', '', '', '', '', '', ''");
4234f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName4', '', '', '', '', '', '', ''");
4235f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature5', 'FileName5', '', '', '', '', '', '', ''");
4236f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName8.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4237f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature11', 'FileName9.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4238f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4239c2c66affSColin Finck 
4240c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4241c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
4242c2c66affSColin Finck     {
4243c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4244c2c66affSColin Finck         goto error;
4245c2c66affSColin Finck     }
4246c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4247c2c66affSColin Finck 
4248c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SIGPROP8", "october");
4249c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4250c2c66affSColin Finck 
4251c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4252c2c66affSColin Finck 
4253c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4254c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4255c2c66affSColin Finck 
4256c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4257c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4258c2c66affSColin Finck 
4259c2c66affSColin Finck     size = MAX_PATH;
4260c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4261c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4262c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4263c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4264c2c66affSColin Finck 
4265c2c66affSColin Finck     size = MAX_PATH;
4266c2c66affSColin Finck     sprintf(path, "%s\\FileName2", expected);
4267c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4268c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4269c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4270c2c66affSColin Finck 
4271c2c66affSColin Finck     size = MAX_PATH;
4272c2c66affSColin Finck     sprintf(path, "%s\\FileName3", expected);
4273c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4274c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4275c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4276c2c66affSColin Finck 
4277c2c66affSColin Finck     size = MAX_PATH;
4278c2c66affSColin Finck     sprintf(path, "%s\\FileName4", expected);
4279c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
4280c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4281c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4282c2c66affSColin Finck 
4283c2c66affSColin Finck     size = MAX_PATH;
4284c2c66affSColin Finck     sprintf(path, "%s\\FileName5", expected);
4285c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4286c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4287c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4288c2c66affSColin Finck 
4289c2c66affSColin Finck     size = MAX_PATH;
4290c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4291c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4292c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4293c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4294c2c66affSColin Finck 
4295c2c66affSColin Finck     size = MAX_PATH;
4296c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4297c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4298c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4299c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4300c2c66affSColin Finck 
4301c2c66affSColin Finck     size = MAX_PATH;
4302c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4303c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4304c2c66affSColin Finck     ok(!lstrcmpA(prop, "october"), "Expected \"october\", got \"%s\"\n", prop);
4305c2c66affSColin Finck 
4306c2c66affSColin Finck     size = MAX_PATH;
4307c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4308c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4309c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4310c2c66affSColin Finck 
4311c2c66affSColin Finck     size = MAX_PATH;
4312c2c66affSColin Finck     sprintf(path, "%s\\FileName8.dll", expected);
4313c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4314c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4315c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4316c2c66affSColin Finck 
4317c2c66affSColin Finck     size = MAX_PATH;
4318c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4319c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4320c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4321c2c66affSColin Finck 
4322c2c66affSColin Finck     size = MAX_PATH;
4323c2c66affSColin Finck     sprintf(path, "%s\\FileName10.dll", expected);
4324c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4325c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4326c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4327c2c66affSColin Finck 
4328c2c66affSColin Finck     delete_component_path("{A8AE6692-96BA-4198-8399-145D7D1D0D0E}",
4329c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4330c2c66affSColin Finck     delete_component_path("{1D2CE6F3-E81C-4949-AB81-78D7DAD2AF2E}",
4331c2c66affSColin Finck                           MSIINSTALLCONTEXT_USERUNMANAGED, usersid);
4332c2c66affSColin Finck     delete_component_path("{19E0B999-85F5-4973-A61B-DBE4D66ECB1D}",
4333c2c66affSColin Finck                           MSIINSTALLCONTEXT_USERMANAGED, usersid);
4334c2c66affSColin Finck     delete_component_path("{F0CCA976-27A3-4808-9DDD-1A6FD50A0D5A}",
4335c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4336c2c66affSColin Finck     delete_component_path("{C0ECD96F-7898-4410-9667-194BD8C1B648}",
4337c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4338c2c66affSColin Finck     delete_component_path("{DB20F535-9C26-4127-9C2B-CC45A8B51DA1}",
4339c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4340c2c66affSColin Finck     delete_component_path("{91B7359B-07F2-4221-AA8D-DE102BB87A5F}",
4341c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4342c2c66affSColin Finck     delete_component_path("{4A2E1B5B-4034-4177-833B-8CC35F1B3EF1}",
4343c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4344c2c66affSColin Finck     delete_component_path("{A204DF48-7346-4635-BA2E-66247DBAC9DF}",
4345c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4346c2c66affSColin Finck     delete_component_path("{EC30CE73-4CF9-4908-BABD-1ED82E1515FD}",
4347c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
4348c2c66affSColin Finck 
4349c2c66affSColin Finck     MsiCloseHandle(hpkg);
4350c2c66affSColin Finck 
4351c2c66affSColin Finck error:
4352c2c66affSColin Finck     DeleteFileA("FileName1");
4353c2c66affSColin Finck     DeleteFileA("FileName2");
4354c2c66affSColin Finck     DeleteFileA("FileName3");
4355c2c66affSColin Finck     DeleteFileA("FileName4");
4356c2c66affSColin Finck     DeleteFileA("FileName5");
4357c2c66affSColin Finck     DeleteFileA("FileName6");
4358c2c66affSColin Finck     DeleteFileA("FileName7");
4359c2c66affSColin Finck     DeleteFileA("FileName8.dll");
4360c2c66affSColin Finck     DeleteFileA("FileName9.dll");
4361c2c66affSColin Finck     DeleteFileA("FileName10.dll");
4362c2c66affSColin Finck     DeleteFileA(msifile);
4363c2c66affSColin Finck     LocalFree(usersid);
4364c2c66affSColin Finck }
4365c2c66affSColin Finck 
4366c2c66affSColin Finck static void test_appsearch_reglocator(void)
4367c2c66affSColin Finck {
4368c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4369c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4370c2c66affSColin Finck     DWORD binary[2], size, val;
4371c2c66affSColin Finck     BOOL space, version, is_64bit = sizeof(void *) > sizeof(int);
4372c2c66affSColin Finck     HKEY hklm, classes, hkcu, users;
4373c2c66affSColin Finck     LPSTR pathdata, pathvar, ptr;
4374c2c66affSColin Finck     LONG res;
4375c2c66affSColin Finck     UINT r, type = 0;
4376c2c66affSColin Finck     SYSTEM_INFO si;
4377c2c66affSColin Finck 
4378c2c66affSColin Finck     version = TRUE;
4379c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4380c2c66affSColin Finck         version = FALSE;
4381c2c66affSColin Finck 
4382c2c66affSColin Finck     DeleteFileA("test.dll");
4383c2c66affSColin Finck 
4384c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CLASSES_ROOT, "Software\\Wine", &classes);
4385c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
4386c2c66affSColin Finck     {
4387c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
4388c2c66affSColin Finck         return;
4389c2c66affSColin Finck     }
4390c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4391c2c66affSColin Finck 
4392c2c66affSColin Finck     res = RegSetValueExA(classes, "Value1", 0, REG_SZ,
4393c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4394c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4395c2c66affSColin Finck 
4396c2c66affSColin Finck     res = RegCreateKeyA(HKEY_CURRENT_USER, "Software\\Wine", &hkcu);
4397c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4398c2c66affSColin Finck 
4399c2c66affSColin Finck     res = RegSetValueExA(hkcu, "Value1", 0, REG_SZ,
4400c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4401c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4402c2c66affSColin Finck 
4403c2c66affSColin Finck     users = 0;
4404c2c66affSColin Finck     res = RegCreateKeyA(HKEY_USERS, "S-1-5-18\\Software\\Wine", &users);
4405c2c66affSColin Finck     ok(res == ERROR_SUCCESS ||
4406c2c66affSColin Finck        broken(res == ERROR_INVALID_PARAMETER),
4407c2c66affSColin Finck        "Expected ERROR_SUCCESS, got %d\n", res);
4408c2c66affSColin Finck 
4409c2c66affSColin Finck     if (res == ERROR_SUCCESS)
4410c2c66affSColin Finck     {
4411c2c66affSColin Finck         res = RegSetValueExA(users, "Value1", 0, REG_SZ,
4412c2c66affSColin Finck                              (const BYTE *)"regszdata", 10);
4413c2c66affSColin Finck         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4414c2c66affSColin Finck     }
4415c2c66affSColin Finck 
4416c2c66affSColin Finck     res = RegCreateKeyA(HKEY_LOCAL_MACHINE, "Software\\Wine", &hklm);
4417c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4418c2c66affSColin Finck 
4419c2c66affSColin Finck     res = RegSetValueA(hklm, NULL, REG_SZ, "defvalue", 8);
4420c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4421c2c66affSColin Finck 
4422c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value1", 0, REG_SZ,
4423c2c66affSColin Finck                          (const BYTE *)"regszdata", 10);
4424c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4425c2c66affSColin Finck 
4426c2c66affSColin Finck     val = 42;
4427c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value2", 0, REG_DWORD,
4428c2c66affSColin Finck                          (const BYTE *)&val, sizeof(DWORD));
4429c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4430c2c66affSColin Finck 
4431c2c66affSColin Finck     val = -42;
4432c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value3", 0, REG_DWORD,
4433c2c66affSColin Finck                          (const BYTE *)&val, sizeof(DWORD));
4434c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4435c2c66affSColin Finck 
4436c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value4", 0, REG_EXPAND_SZ,
4437c2c66affSColin Finck                          (const BYTE *)"%PATH%", 7);
4438c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4439c2c66affSColin Finck 
4440c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value5", 0, REG_EXPAND_SZ,
4441c2c66affSColin Finck                          (const BYTE *)"my%NOVAR%", 10);
4442c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4443c2c66affSColin Finck 
4444c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value6", 0, REG_MULTI_SZ,
4445c2c66affSColin Finck                          (const BYTE *)"one\0two\0", 9);
4446c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4447c2c66affSColin Finck 
4448c2c66affSColin Finck     binary[0] = 0x1234abcd;
4449c2c66affSColin Finck     binary[1] = 0x567890ef;
4450c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value7", 0, REG_BINARY,
4451c2c66affSColin Finck                          (const BYTE *)binary, sizeof(binary));
4452c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4453c2c66affSColin Finck 
4454c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value8", 0, REG_SZ,
4455c2c66affSColin Finck                          (const BYTE *)"#regszdata", 11);
4456c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4457c2c66affSColin Finck 
4458c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4459c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4460c2c66affSColin Finck 
4461c2c66affSColin Finck     create_test_file("FileName1");
4462c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4463c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value9", 0, REG_SZ,
4464c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4465c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4466c2c66affSColin Finck 
4467c2c66affSColin Finck     sprintf(path, "%s\\FileName2", expected);
4468c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value10", 0, REG_SZ,
4469c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4470c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4471c2c66affSColin Finck 
4472c2c66affSColin Finck     lstrcpyA(path, expected);
4473c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value11", 0, REG_SZ,
4474c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4475c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4476c2c66affSColin Finck 
4477c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value12", 0, REG_SZ,
4478c2c66affSColin Finck                          (const BYTE *)"", 1);
4479c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4480c2c66affSColin Finck 
4481c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4482c2c66affSColin Finck     sprintf(path, "%s\\FileName3.dll", expected);
4483c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value13", 0, REG_SZ,
4484c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4485c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4486c2c66affSColin Finck 
4487c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4488c2c66affSColin Finck     sprintf(path, "%s\\FileName4.dll", expected);
4489c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value14", 0, REG_SZ,
4490c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4491c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4492c2c66affSColin Finck 
4493c2c66affSColin Finck     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4494c2c66affSColin Finck     sprintf(path, "%s\\FileName5.dll", expected);
4495c2c66affSColin Finck     res = RegSetValueExA(hklm, "Value15", 0, REG_SZ,
4496c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4497c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4498c2c66affSColin Finck 
4499c2c66affSColin Finck     sprintf(path, "\"%s\\FileName1\" -option", expected);
4500c2c66affSColin Finck     res = RegSetValueExA(hklm, "value16", 0, REG_SZ,
4501c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4502c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4503c2c66affSColin Finck 
4504c2c66affSColin Finck     space = strchr(expected, ' ') != NULL;
4505c2c66affSColin Finck     sprintf(path, "%s\\FileName1 -option", expected);
4506c2c66affSColin Finck     res = RegSetValueExA(hklm, "value17", 0, REG_SZ,
4507c2c66affSColin Finck                          (const BYTE *)path, lstrlenA(path) + 1);
4508c2c66affSColin Finck     ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
4509c2c66affSColin Finck 
4510c2c66affSColin Finck     hdb = create_package_db();
4511c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4512c2c66affSColin Finck 
4513f860a780SAmine Khaldi     create_appsearch_table(hdb);
4514f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4515f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4516f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4517f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4518f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4519f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4520f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
4521f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
4522f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
4523f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
4524f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
4525f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
4526f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
4527f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP14', 'NewSignature14'");
4528f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP15', 'NewSignature15'");
4529f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP16', 'NewSignature16'");
4530f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP17', 'NewSignature17'");
4531f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP18', 'NewSignature18'");
4532f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP19', 'NewSignature19'");
4533f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP20', 'NewSignature20'");
4534f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP21', 'NewSignature21'");
4535f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP22', 'NewSignature22'");
4536f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP23', 'NewSignature23'");
4537f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP24', 'NewSignature24'");
4538f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP25', 'NewSignature25'");
4539f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP26', 'NewSignature26'");
4540f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP27', 'NewSignature27'");
4541f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP28', 'NewSignature28'");
4542f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP29', 'NewSignature29'");
4543f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP30', 'NewSignature30'");
4544c2c66affSColin Finck 
4545f860a780SAmine Khaldi     create_reglocator_table(hdb);
4546c2c66affSColin Finck 
4547c2c66affSColin Finck     type = msidbLocatorTypeRawValue;
4548c2c66affSColin Finck     if (is_64bit)
4549c2c66affSColin Finck         type |= msidbLocatorType64bit;
4550c2c66affSColin Finck 
4551c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ */
4552f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature1", 2, "Software\\Wine", "Value1", type);
4553c2c66affSColin Finck 
4554c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, positive DWORD */
4555f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature2", 2, "Software\\Wine", "Value2", type);
4556c2c66affSColin Finck 
4557c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, negative DWORD */
4558f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature3", 2, "Software\\Wine", "Value3", type);
4559c2c66affSColin Finck 
4560c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4561f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature4", 2, "Software\\Wine", "Value4", type);
4562c2c66affSColin Finck 
4563c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_EXPAND_SZ */
4564f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature5", 2, "Software\\Wine", "Value5", type);
4565c2c66affSColin Finck 
4566c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_MULTI_SZ */
4567f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature6", 2, "Software\\Wine", "Value6", type);
4568c2c66affSColin Finck 
4569c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_BINARY */
4570f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature7", 2, "Software\\Wine", "Value7", type);
4571c2c66affSColin Finck 
4572c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ first char is # */
4573f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature8", 2, "Software\\Wine", "Value8", type);
4574c2c66affSColin Finck 
4575c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4576c2c66affSColin Finck     if (is_64bit)
4577c2c66affSColin Finck         type |= msidbLocatorType64bit;
4578c2c66affSColin Finck 
4579c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file exists */
4580f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature9", 2, "Software\\Wine", "Value9", type);
4581c2c66affSColin Finck 
4582c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file does not exist */
4583f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature10", 2, "Software\\Wine", "Value10", type);
4584c2c66affSColin Finck 
4585c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature */
4586f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature11", 2, "Software\\Wine", "Value9", type);
4587c2c66affSColin Finck 
4588c2c66affSColin Finck     type = msidbLocatorTypeDirectory;
4589c2c66affSColin Finck     if (is_64bit)
4590c2c66affSColin Finck         type |= msidbLocatorType64bit;
4591c2c66affSColin Finck 
4592c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, file exists */
4593f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature12", 2, "Software\\Wine", "Value9", type);
4594c2c66affSColin Finck 
4595c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, directory exists */
4596f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature13", 2, "Software\\Wine", "Value11", type);
4597c2c66affSColin Finck 
4598c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, file exists */
4599f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature14", 2, "Software\\Wine", "Value9", type);
4600c2c66affSColin Finck 
4601c2c66affSColin Finck     type = msidbLocatorTypeRawValue;
4602c2c66affSColin Finck     if (is_64bit)
4603c2c66affSColin Finck         type |= msidbLocatorType64bit;
4604c2c66affSColin Finck 
4605c2c66affSColin Finck     /* HKCR, msidbLocatorTypeRawValue, REG_SZ */
4606f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature15", 0, "Software\\Wine", "Value1", type);
4607c2c66affSColin Finck 
4608c2c66affSColin Finck     /* HKCU, msidbLocatorTypeRawValue, REG_SZ */
4609f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature16", 1, "Software\\Wine", "Value1", type);
4610c2c66affSColin Finck 
4611c2c66affSColin Finck     /* HKU, msidbLocatorTypeRawValue, REG_SZ */
4612f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature17", 3, "S-1-5-18\\Software\\Wine", "Value1", type);
4613c2c66affSColin Finck 
4614c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, NULL Name */
4615f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature18", 2, "Software\\Wine", "", type);
4616c2c66affSColin Finck 
4617c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, key does not exist */
4618f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature19", 2, "Software\\IDontExist", "", type);
4619c2c66affSColin Finck 
4620c2c66affSColin Finck     /* HKLM, msidbLocatorTypeRawValue, REG_SZ, value is empty */
4621f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature20", 2, "Software\\Wine", "Value12", type);
4622c2c66affSColin Finck 
4623c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4624c2c66affSColin Finck     if (is_64bit)
4625c2c66affSColin Finck         type |= msidbLocatorType64bit;
4626c2c66affSColin Finck 
4627c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, signature, file exists w/ version */
4628f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature21", 2, "Software\\Wine", "Value13", type);
4629c2c66affSColin Finck 
4630c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, version > max */
4631f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature22", 2, "Software\\Wine", "Value14", type);
4632c2c66affSColin Finck 
4633c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, file exists w/ version, sig->name ignored */
4634f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature23", 2, "Software\\Wine", "Value15", type);
4635c2c66affSColin Finck 
4636c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature, directory exists */
4637f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature24", 2, "Software\\Wine", "Value11", type);
4638c2c66affSColin Finck 
4639c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFileName, no signature, file does not exist */
4640f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature25", 2, "Software\\Wine", "Value10", type);
4641c2c66affSColin Finck 
4642c2c66affSColin Finck     type = msidbLocatorTypeDirectory;
4643c2c66affSColin Finck     if (is_64bit)
4644c2c66affSColin Finck         type |= msidbLocatorType64bit;
4645c2c66affSColin Finck 
4646c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, directory exists */
4647f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature26", 2, "Software\\Wine", "Value11", type);
4648c2c66affSColin Finck 
4649c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, signature, file does not exist */
4650f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature27", 2, "Software\\Wine", "Value10", type);
4651c2c66affSColin Finck 
4652c2c66affSColin Finck     /* HKLM, msidbLocatorTypeDirectory, no signature, file does not exist */
4653f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature28", 2, "Software\\Wine", "Value10", type);
4654c2c66affSColin Finck 
4655c2c66affSColin Finck     type = msidbLocatorTypeFileName;
4656c2c66affSColin Finck     if (is_64bit)
4657c2c66affSColin Finck         type |= msidbLocatorType64bit;
4658c2c66affSColin Finck 
4659c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFile, file exists, in quotes */
4660f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature29", 2, "Software\\Wine", "Value16", type);
4661c2c66affSColin Finck 
4662c2c66affSColin Finck     /* HKLM, msidbLocatorTypeFile, file exists, no quotes */
4663f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature30", 2, "Software\\Wine", "Value17", type);
4664c2c66affSColin Finck 
4665f860a780SAmine Khaldi     create_signature_table(hdb);
4666f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'FileName1', '', '', '', '', '', '', ''");
4667f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName2', '', '', '', '', '', '', ''");
4668f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature14', 'FileName1', '', '', '', '', '', '', ''");
4669f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature21', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4670f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature22', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4671f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature23', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
4672c2c66affSColin Finck 
4673c2c66affSColin Finck     if (!is_root(CURR_DIR))
4674c2c66affSColin Finck     {
4675c2c66affSColin Finck         ptr = strrchr(expected, '\\') + 1;
4676c2c66affSColin Finck         sprintf(path, "'NewSignature26', '%s', '', '', '', '', '', '', ''", ptr);
4677f860a780SAmine Khaldi         add_signature_entry(hdb, path);
4678c2c66affSColin Finck     }
4679f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature27', 'FileName2', '', '', '', '', '', '', ''");
4680f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature29', 'FileName1', '', '', '', '', '', '', ''");
4681f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature30', 'FileName1', '', '', '', '', '', '', ''");
4682c2c66affSColin Finck 
4683c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
4684c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
4685c2c66affSColin Finck 
4686c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4687c2c66affSColin Finck 
4688c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
4689c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4690c2c66affSColin Finck 
4691c2c66affSColin Finck     size = MAX_PATH;
4692c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
4693c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4694c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4695c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4696c2c66affSColin Finck 
4697c2c66affSColin Finck     size = MAX_PATH;
4698c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
4699c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4700c2c66affSColin Finck     ok(!lstrcmpA(prop, "#42"), "Expected \"#42\", got \"%s\"\n", prop);
4701c2c66affSColin Finck 
4702c2c66affSColin Finck     size = MAX_PATH;
4703c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
4704c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4705c2c66affSColin Finck     ok(!lstrcmpA(prop, "#-42"), "Expected \"#-42\", got \"%s\"\n", prop);
4706c2c66affSColin Finck 
4707c2c66affSColin Finck     memset(&si, 0, sizeof(si));
4708c2c66affSColin Finck     if (pGetNativeSystemInfo) pGetNativeSystemInfo(&si);
4709c2c66affSColin Finck 
4710c2c66affSColin Finck     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
4711c2c66affSColin Finck     {
4712c2c66affSColin Finck         size = ExpandEnvironmentStringsA("%PATH%", NULL, 0);
4713c2c66affSColin Finck         pathvar = HeapAlloc(GetProcessHeap(), 0, size);
4714c2c66affSColin Finck         ExpandEnvironmentStringsA("%PATH%", pathvar, size);
4715c2c66affSColin Finck 
4716c2c66affSColin Finck         size = 0;
4717c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP4", NULL, &size);
4718c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4719c2c66affSColin Finck 
4720c2c66affSColin Finck         pathdata = HeapAlloc(GetProcessHeap(), 0, ++size);
4721c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP4", pathdata, &size);
4722c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4723c2c66affSColin Finck         ok(!lstrcmpA(pathdata, pathvar),
4724c2c66affSColin Finck             "Expected \"%s\", got \"%s\"\n", pathvar, pathdata);
4725c2c66affSColin Finck 
4726c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pathvar);
4727c2c66affSColin Finck         HeapFree(GetProcessHeap(), 0, pathdata);
4728c2c66affSColin Finck     }
4729c2c66affSColin Finck 
4730c2c66affSColin Finck     size = MAX_PATH;
4731c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
4732c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4733c2c66affSColin Finck     ok(!lstrcmpA(prop,
4734c2c66affSColin Finck        "my%NOVAR%"), "Expected \"my%%NOVAR%%\", got \"%s\"\n", prop);
4735c2c66affSColin Finck 
4736c2c66affSColin Finck     size = MAX_PATH;
4737c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
4738c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4739c2c66affSColin Finck     todo_wine
4740c2c66affSColin Finck     {
4741c2c66affSColin Finck         ok(!memcmp(prop, "\0one\0two\0\0", 10),
4742c2c66affSColin Finck            "Expected \"\\0one\\0two\\0\\0\"\n");
4743c2c66affSColin Finck     }
4744c2c66affSColin Finck 
4745c2c66affSColin Finck     size = MAX_PATH;
4746c2c66affSColin Finck     lstrcpyA(path, "#xCDAB3412EF907856");
4747c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
4748c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4749c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4750c2c66affSColin Finck 
4751c2c66affSColin Finck     size = MAX_PATH;
4752c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
4753c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4754c2c66affSColin Finck     ok(!lstrcmpA(prop, "##regszdata"),
4755c2c66affSColin Finck        "Expected \"##regszdata\", got \"%s\"\n", prop);
4756c2c66affSColin Finck 
4757c2c66affSColin Finck     size = MAX_PATH;
4758c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4759c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
4760c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4761c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4762c2c66affSColin Finck 
4763c2c66affSColin Finck     size = MAX_PATH;
4764c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
4765c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4766c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4767c2c66affSColin Finck 
4768c2c66affSColin Finck     size = MAX_PATH;
4769c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4770c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
4771c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4772c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4773c2c66affSColin Finck 
4774c2c66affSColin Finck     size = MAX_PATH;
4775c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
4776c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4777c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4778c2c66affSColin Finck 
4779c2c66affSColin Finck     size = MAX_PATH;
4780c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4781c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
4782c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4783c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4784c2c66affSColin Finck 
4785c2c66affSColin Finck     size = MAX_PATH;
4786c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP14", prop, &size);
4787c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4788c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4789c2c66affSColin Finck 
4790c2c66affSColin Finck     size = MAX_PATH;
4791c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP15", prop, &size);
4792c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4793c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4794c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4795c2c66affSColin Finck 
4796c2c66affSColin Finck     size = MAX_PATH;
4797c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP16", prop, &size);
4798c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4799c2c66affSColin Finck     ok(!lstrcmpA(prop, "regszdata"),
4800c2c66affSColin Finck        "Expected \"regszdata\", got \"%s\"\n", prop);
4801c2c66affSColin Finck 
4802c2c66affSColin Finck     if (users)
4803c2c66affSColin Finck     {
4804c2c66affSColin Finck         size = MAX_PATH;
4805c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP17", prop, &size);
4806c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4807c2c66affSColin Finck         ok(!lstrcmpA(prop, "regszdata"),
4808c2c66affSColin Finck            "Expected \"regszdata\", got \"%s\"\n", prop);
4809c2c66affSColin Finck     }
4810c2c66affSColin Finck 
4811c2c66affSColin Finck     size = MAX_PATH;
4812c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP18", prop, &size);
4813c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4814c2c66affSColin Finck     ok(!lstrcmpA(prop, "defvalue"),
4815c2c66affSColin Finck        "Expected \"defvalue\", got \"%s\"\n", prop);
4816c2c66affSColin Finck 
4817c2c66affSColin Finck     size = MAX_PATH;
4818c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP19", prop, &size);
4819c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4820c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4821c2c66affSColin Finck 
4822c2c66affSColin Finck     size = MAX_PATH;
4823c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP20", prop, &size);
4824c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4825c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4826c2c66affSColin Finck 
4827c2c66affSColin Finck     if (version)
4828c2c66affSColin Finck     {
4829c2c66affSColin Finck         size = MAX_PATH;
4830c2c66affSColin Finck         sprintf(path, "%s\\FileName3.dll", expected);
4831c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP21", prop, &size);
4832c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4833c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4834c2c66affSColin Finck 
4835c2c66affSColin Finck         size = MAX_PATH;
4836c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP22", prop, &size);
4837c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4838c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4839c2c66affSColin Finck 
4840c2c66affSColin Finck         size = MAX_PATH;
4841c2c66affSColin Finck         sprintf(path, "%s\\FileName5.dll", expected);
4842c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP23", prop, &size);
4843c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4844c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4845c2c66affSColin Finck     }
4846c2c66affSColin Finck 
4847c2c66affSColin Finck     if (!is_root(CURR_DIR))
4848c2c66affSColin Finck     {
4849c2c66affSColin Finck         size = MAX_PATH;
4850c2c66affSColin Finck         lstrcpyA(path, expected);
4851c2c66affSColin Finck         ptr = strrchr(path, '\\') + 1;
4852c2c66affSColin Finck         *ptr = '\0';
4853c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP24", prop, &size);
4854c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4855c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4856c2c66affSColin Finck     }
4857c2c66affSColin Finck     size = MAX_PATH;
4858c2c66affSColin Finck     sprintf(path, "%s\\", expected);
4859c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP25", prop, &size);
4860c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4861c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4862c2c66affSColin Finck 
4863c2c66affSColin Finck     size = MAX_PATH;
4864c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP26", prop, &size);
4865c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4866c2c66affSColin Finck     if (is_root(CURR_DIR))
4867c2c66affSColin Finck         ok(!lstrcmpA(prop, CURR_DIR), "Expected \"%s\", got \"%s\"\n", CURR_DIR, prop);
4868c2c66affSColin Finck     else
4869c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4870c2c66affSColin Finck 
4871c2c66affSColin Finck     size = MAX_PATH;
4872c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP27", prop, &size);
4873c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4874c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4875c2c66affSColin Finck 
4876c2c66affSColin Finck     size = MAX_PATH;
4877c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP28", prop, &size);
4878c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4879c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4880c2c66affSColin Finck 
4881c2c66affSColin Finck     size = MAX_PATH;
4882c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4883c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP29", prop, &size);
4884c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4885c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4886c2c66affSColin Finck 
4887c2c66affSColin Finck     size = MAX_PATH;
4888c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4889c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP30", prop, &size);
4890c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4891c2c66affSColin Finck     if (space)
4892c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
4893c2c66affSColin Finck     else
4894c2c66affSColin Finck         todo_wine ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
4895c2c66affSColin Finck 
4896c2c66affSColin Finck     RegSetValueA(hklm, NULL, REG_SZ, "", 0);
4897c2c66affSColin Finck     RegDeleteValueA(hklm, "Value1");
4898c2c66affSColin Finck     RegDeleteValueA(hklm, "Value2");
4899c2c66affSColin Finck     RegDeleteValueA(hklm, "Value3");
4900c2c66affSColin Finck     RegDeleteValueA(hklm, "Value4");
4901c2c66affSColin Finck     RegDeleteValueA(hklm, "Value5");
4902c2c66affSColin Finck     RegDeleteValueA(hklm, "Value6");
4903c2c66affSColin Finck     RegDeleteValueA(hklm, "Value7");
4904c2c66affSColin Finck     RegDeleteValueA(hklm, "Value8");
4905c2c66affSColin Finck     RegDeleteValueA(hklm, "Value9");
4906c2c66affSColin Finck     RegDeleteValueA(hklm, "Value10");
4907c2c66affSColin Finck     RegDeleteValueA(hklm, "Value11");
4908c2c66affSColin Finck     RegDeleteValueA(hklm, "Value12");
4909c2c66affSColin Finck     RegDeleteValueA(hklm, "Value13");
4910c2c66affSColin Finck     RegDeleteValueA(hklm, "Value14");
4911c2c66affSColin Finck     RegDeleteValueA(hklm, "Value15");
4912c2c66affSColin Finck     RegDeleteValueA(hklm, "Value16");
4913c2c66affSColin Finck     RegDeleteValueA(hklm, "Value17");
4914c2c66affSColin Finck     RegDeleteKeyA(hklm, "");
4915c2c66affSColin Finck     RegCloseKey(hklm);
4916c2c66affSColin Finck 
4917c2c66affSColin Finck     RegDeleteValueA(classes, "Value1");
4918c2c66affSColin Finck     RegDeleteKeyA(classes, "");
4919c2c66affSColin Finck     RegCloseKey(classes);
4920c2c66affSColin Finck 
4921c2c66affSColin Finck     RegDeleteValueA(hkcu, "Value1");
4922c2c66affSColin Finck     RegDeleteKeyA(hkcu, "");
4923c2c66affSColin Finck     RegCloseKey(hkcu);
4924c2c66affSColin Finck 
4925c2c66affSColin Finck     RegDeleteValueA(users, "Value1");
4926c2c66affSColin Finck     RegDeleteKeyA(users, "");
4927c2c66affSColin Finck     RegCloseKey(users);
4928c2c66affSColin Finck 
4929c2c66affSColin Finck     DeleteFileA("FileName1");
4930c2c66affSColin Finck     DeleteFileA("FileName3.dll");
4931c2c66affSColin Finck     DeleteFileA("FileName4.dll");
4932c2c66affSColin Finck     DeleteFileA("FileName5.dll");
4933c2c66affSColin Finck     MsiCloseHandle(hpkg);
4934c2c66affSColin Finck     DeleteFileA(msifile);
4935c2c66affSColin Finck }
4936c2c66affSColin Finck 
4937c2c66affSColin Finck static void delete_win_ini(LPCSTR file)
4938c2c66affSColin Finck {
4939c2c66affSColin Finck     CHAR path[MAX_PATH];
4940c2c66affSColin Finck 
4941c2c66affSColin Finck     GetWindowsDirectoryA(path, MAX_PATH);
4942c2c66affSColin Finck     lstrcatA(path, "\\");
4943c2c66affSColin Finck     lstrcatA(path, file);
4944c2c66affSColin Finck 
4945c2c66affSColin Finck     DeleteFileA(path);
4946c2c66affSColin Finck }
4947c2c66affSColin Finck 
4948c2c66affSColin Finck static void test_appsearch_inilocator(void)
4949c2c66affSColin Finck {
4950c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
4951c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
4952c2c66affSColin Finck     BOOL version;
4953c2c66affSColin Finck     LPSTR ptr;
4954c2c66affSColin Finck     DWORD size;
4955c2c66affSColin Finck     UINT r;
4956c2c66affSColin Finck 
4957c2c66affSColin Finck     version = TRUE;
4958c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
4959c2c66affSColin Finck         version = FALSE;
4960c2c66affSColin Finck 
4961c2c66affSColin Finck     DeleteFileA("test.dll");
4962c2c66affSColin Finck 
4963c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key", "keydata,field2", "IniFile.ini");
4964c2c66affSColin Finck 
4965c2c66affSColin Finck     strcpy(expected, CURR_DIR);
4966c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
4967c2c66affSColin Finck 
4968c2c66affSColin Finck     create_test_file("FileName1");
4969c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
4970c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key2", path, "IniFile.ini");
4971c2c66affSColin Finck 
4972c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key3", expected, "IniFile.ini");
4973c2c66affSColin Finck 
4974c2c66affSColin Finck     sprintf(path, "%s\\IDontExist", expected);
4975c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key4", path, "IniFile.ini");
4976c2c66affSColin Finck 
4977c2c66affSColin Finck     create_file_with_version("FileName2.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4978c2c66affSColin Finck     sprintf(path, "%s\\FileName2.dll", expected);
4979c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key5", path, "IniFile.ini");
4980c2c66affSColin Finck 
4981c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(1, 2), MAKELONG(3, 4));
4982c2c66affSColin Finck     sprintf(path, "%s\\FileName3.dll", expected);
4983c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key6", path, "IniFile.ini");
4984c2c66affSColin Finck 
4985c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(2, 1), MAKELONG(4, 3));
4986c2c66affSColin Finck     sprintf(path, "%s\\FileName4.dll", expected);
4987c2c66affSColin Finck     WritePrivateProfileStringA("Section", "Key7", path, "IniFile.ini");
4988c2c66affSColin Finck 
4989c2c66affSColin Finck     hdb = create_package_db();
4990c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
4991c2c66affSColin Finck 
4992f860a780SAmine Khaldi     create_appsearch_table(hdb);
4993f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
4994f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
4995f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
4996f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
4997f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
4998f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
4999f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5000f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5001f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5002f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5003f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5004f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP12', 'NewSignature12'");
5005c2c66affSColin Finck 
5006f860a780SAmine Khaldi     create_inilocator_table(hdb);
5007c2c66affSColin Finck 
5008c2c66affSColin Finck     /* msidbLocatorTypeRawValue, field 1 */
5009f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature1', 'IniFile.ini', 'Section', 'Key', 1, 2");
5010c2c66affSColin Finck 
5011c2c66affSColin Finck     /* msidbLocatorTypeRawValue, field 2 */
5012f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature2', 'IniFile.ini', 'Section', 'Key', 2, 2");
5013c2c66affSColin Finck 
5014c2c66affSColin Finck     /* msidbLocatorTypeRawValue, entire field */
5015f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature3', 'IniFile.ini', 'Section', 'Key', 0, 2");
5016c2c66affSColin Finck 
5017c2c66affSColin Finck     /* msidbLocatorTypeFile */
5018f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature4', 'IniFile.ini', 'Section', 'Key2', 1, 1");
5019c2c66affSColin Finck 
5020c2c66affSColin Finck     /* msidbLocatorTypeDirectory, file */
5021f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature5', 'IniFile.ini', 'Section', 'Key2', 1, 0");
5022c2c66affSColin Finck 
5023c2c66affSColin Finck     /* msidbLocatorTypeDirectory, directory */
5024f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature6', 'IniFile.ini', 'Section', 'Key3', 1, 0");
5025c2c66affSColin Finck 
5026c2c66affSColin Finck     /* msidbLocatorTypeFile, file, no signature */
5027f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature7', 'IniFile.ini', 'Section', 'Key2', 1, 1");
5028c2c66affSColin Finck 
5029c2c66affSColin Finck     /* msidbLocatorTypeFile, dir, no signature */
5030f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature8', 'IniFile.ini', 'Section', 'Key3', 1, 1");
5031c2c66affSColin Finck 
5032c2c66affSColin Finck     /* msidbLocatorTypeFile, file does not exist */
5033f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature9', 'IniFile.ini', 'Section', 'Key4', 1, 1");
5034c2c66affSColin Finck 
5035c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version */
5036f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature10', 'IniFile.ini', 'Section', 'Key5', 1, 1");
5037c2c66affSColin Finck 
5038c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version, ver > max */
5039f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature11', 'IniFile.ini', 'Section', 'Key6', 1, 1");
5040c2c66affSColin Finck 
5041c2c66affSColin Finck     /* msidbLocatorTypeFile, signature with version, sig->name ignored */
5042f860a780SAmine Khaldi     add_inilocator_entry(hdb, "'NewSignature12', 'IniFile.ini', 'Section', 'Key7', 1, 1");
5043c2c66affSColin Finck 
5044f860a780SAmine Khaldi     create_signature_table(hdb);
5045f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName1', '', '', '', '', '', '', ''");
5046f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'IDontExist', '', '', '', '', '', '', ''");
5047f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'FileName2.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5048f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature11', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5049f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature12', 'ignored', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5050c2c66affSColin Finck 
5051c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5052c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5053c2c66affSColin Finck     {
5054c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5055c2c66affSColin Finck         goto error;
5056c2c66affSColin Finck     }
5057c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5058c2c66affSColin Finck 
5059c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5060c2c66affSColin Finck 
5061c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
5062c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5063c2c66affSColin Finck 
5064c2c66affSColin Finck     size = MAX_PATH;
5065c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5066c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5067c2c66affSColin Finck     ok(!lstrcmpA(prop, "keydata"), "Expected \"keydata\", got \"%s\"\n", prop);
5068c2c66affSColin Finck 
5069c2c66affSColin Finck     size = MAX_PATH;
5070c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5071c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5072c2c66affSColin Finck     ok(!lstrcmpA(prop, "field2"), "Expected \"field2\", got \"%s\"\n", prop);
5073c2c66affSColin Finck 
5074c2c66affSColin Finck     size = MAX_PATH;
5075c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5076c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5077c2c66affSColin Finck     ok(!lstrcmpA(prop, "keydata,field2"),
5078c2c66affSColin Finck        "Expected \"keydata,field2\", got \"%s\"\n", prop);
5079c2c66affSColin Finck 
5080c2c66affSColin Finck     size = MAX_PATH;
5081c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
5082c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5083c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5084c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5085c2c66affSColin Finck 
5086c2c66affSColin Finck     size = MAX_PATH;
5087c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5088c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5089c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5090c2c66affSColin Finck 
5091c2c66affSColin Finck     size = MAX_PATH;
5092c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5093c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5094c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5095c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5096c2c66affSColin Finck 
5097c2c66affSColin Finck     size = MAX_PATH;
5098c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5099c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5100c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5101c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5102c2c66affSColin Finck 
5103c2c66affSColin Finck     if (!is_root(CURR_DIR))
5104c2c66affSColin Finck     {
5105c2c66affSColin Finck         size = MAX_PATH;
5106c2c66affSColin Finck         lstrcpyA(path, expected);
5107c2c66affSColin Finck         ptr = strrchr(path, '\\');
5108c2c66affSColin Finck         *(ptr + 1) = 0;
5109c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5110c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5111c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5112c2c66affSColin Finck     }
5113c2c66affSColin Finck     size = MAX_PATH;
5114c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5115c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5116c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5117c2c66affSColin Finck 
5118c2c66affSColin Finck     if (version)
5119c2c66affSColin Finck     {
5120c2c66affSColin Finck         size = MAX_PATH;
5121c2c66affSColin Finck         sprintf(path, "%s\\FileName2.dll", expected);
5122c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5123c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5124c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5125c2c66affSColin Finck 
5126c2c66affSColin Finck         size = MAX_PATH;
5127c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5128c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5129c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5130c2c66affSColin Finck 
5131c2c66affSColin Finck         size = MAX_PATH;
5132c2c66affSColin Finck         sprintf(path, "%s\\FileName4.dll", expected);
5133c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP12", prop, &size);
5134c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5135c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5136c2c66affSColin Finck     }
5137c2c66affSColin Finck 
5138c2c66affSColin Finck     MsiCloseHandle(hpkg);
5139c2c66affSColin Finck 
5140c2c66affSColin Finck error:
5141c2c66affSColin Finck     delete_win_ini("IniFile.ini");
5142c2c66affSColin Finck     DeleteFileA("FileName1");
5143c2c66affSColin Finck     DeleteFileA("FileName2.dll");
5144c2c66affSColin Finck     DeleteFileA("FileName3.dll");
5145c2c66affSColin Finck     DeleteFileA("FileName4.dll");
5146c2c66affSColin Finck     DeleteFileA(msifile);
5147c2c66affSColin Finck }
5148c2c66affSColin Finck 
5149c2c66affSColin Finck /*
5150c2c66affSColin Finck  * MSI AppSearch action on DrLocator table always returns absolute paths.
5151c2c66affSColin Finck  * If a relative path was set, it returns the first absolute path that
5152c2c66affSColin Finck  * matches or an empty string if it didn't find anything.
5153c2c66affSColin Finck  * This helper function replicates this behaviour.
5154c2c66affSColin Finck  */
5155c2c66affSColin Finck static void search_absolute_directory(LPSTR absolute, LPCSTR relative)
5156c2c66affSColin Finck {
5157c2c66affSColin Finck     int i, size;
5158c2c66affSColin Finck     DWORD attr, drives;
5159c2c66affSColin Finck 
5160c2c66affSColin Finck     size = lstrlenA(relative);
5161c2c66affSColin Finck     drives = GetLogicalDrives();
5162c2c66affSColin Finck     lstrcpyA(absolute, "A:\\");
5163c2c66affSColin Finck     for (i = 0; i < 26; absolute[0] = '\0', i++)
5164c2c66affSColin Finck     {
5165c2c66affSColin Finck         if (!(drives & (1 << i)))
5166c2c66affSColin Finck             continue;
5167c2c66affSColin Finck 
5168c2c66affSColin Finck         absolute[0] = 'A' + i;
5169c2c66affSColin Finck         if (GetDriveTypeA(absolute) != DRIVE_FIXED)
5170c2c66affSColin Finck             continue;
5171c2c66affSColin Finck 
5172c2c66affSColin Finck         lstrcpynA(absolute + 3, relative, size + 1);
5173c2c66affSColin Finck         attr = GetFileAttributesA(absolute);
5174c2c66affSColin Finck         if (attr != INVALID_FILE_ATTRIBUTES &&
5175c2c66affSColin Finck             (attr & FILE_ATTRIBUTE_DIRECTORY))
5176c2c66affSColin Finck         {
5177c2c66affSColin Finck             if (absolute[3 + size - 1] != '\\')
5178c2c66affSColin Finck                 lstrcatA(absolute, "\\");
5179c2c66affSColin Finck             break;
5180c2c66affSColin Finck         }
5181c2c66affSColin Finck         absolute[3] = '\0';
5182c2c66affSColin Finck     }
5183c2c66affSColin Finck }
5184c2c66affSColin Finck 
5185c2c66affSColin Finck static void test_appsearch_drlocator(void)
5186c2c66affSColin Finck {
5187c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
5188c2c66affSColin Finck     char path[MAX_PATH], expected[MAX_PATH], prop[MAX_PATH];
5189c2c66affSColin Finck     BOOL version;
5190c2c66affSColin Finck     DWORD size;
5191c2c66affSColin Finck     UINT r;
5192c2c66affSColin Finck 
5193c2c66affSColin Finck     version = TRUE;
5194c2c66affSColin Finck     if (!create_file_with_version("test.dll", MAKELONG(2, 1), MAKELONG(4, 3)))
5195c2c66affSColin Finck         version = FALSE;
5196c2c66affSColin Finck 
5197c2c66affSColin Finck     DeleteFileA("test.dll");
5198c2c66affSColin Finck 
5199c2c66affSColin Finck     create_test_file("FileName1");
5200c2c66affSColin Finck     CreateDirectoryA("one", NULL);
5201c2c66affSColin Finck     CreateDirectoryA("one\\two", NULL);
5202c2c66affSColin Finck     CreateDirectoryA("one\\two\\three", NULL);
5203c2c66affSColin Finck     create_test_file("one\\two\\three\\FileName2");
5204c2c66affSColin Finck     CreateDirectoryA("another", NULL);
5205c2c66affSColin Finck     create_file_with_version("FileName3.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5206c2c66affSColin Finck     create_file_with_version("FileName4.dll", MAKELONG(1, 2), MAKELONG(3, 4));
5207c2c66affSColin Finck     create_file_with_version("FileName5.dll", MAKELONG(2, 1), MAKELONG(4, 3));
5208c2c66affSColin Finck 
5209c2c66affSColin Finck     hdb = create_package_db();
5210c2c66affSColin Finck     ok(hdb, "Expected a valid database handle\n");
5211c2c66affSColin Finck 
5212f860a780SAmine Khaldi     create_appsearch_table(hdb);
5213f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP1', 'NewSignature1'");
5214f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP2', 'NewSignature2'");
5215f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP3', 'NewSignature3'");
5216f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP4', 'NewSignature4'");
5217f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP5', 'NewSignature5'");
5218f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP6', 'NewSignature6'");
5219f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP7', 'NewSignature7'");
5220f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP8', 'NewSignature8'");
5221f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP9', 'NewSignature9'");
5222f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP10', 'NewSignature10'");
5223f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP11', 'NewSignature11'");
5224f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'SIGPROP13', 'NewSignature13'");
5225c2c66affSColin Finck 
5226f860a780SAmine Khaldi     create_drlocator_table(hdb);
5227c2c66affSColin Finck 
5228c2c66affSColin Finck     strcpy(expected, CURR_DIR);
5229c2c66affSColin Finck     if (is_root(CURR_DIR)) expected[2] = 0;
5230c2c66affSColin Finck 
5231c2c66affSColin Finck     /* no parent, full path, depth 0, signature */
5232c2c66affSColin Finck     sprintf(path, "'NewSignature1', '', '%s', 0", expected);
5233f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5234c2c66affSColin Finck 
5235c2c66affSColin Finck     /* no parent, full path, depth 0, no signature */
5236c2c66affSColin Finck     sprintf(path, "'NewSignature2', '', '%s', 0", expected);
5237f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5238c2c66affSColin Finck 
5239c2c66affSColin Finck     /* no parent, relative path, depth 0, no signature */
5240c2c66affSColin Finck     sprintf(path, "'NewSignature3', '', '%s', 0", expected + 3);
5241f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5242c2c66affSColin Finck 
5243c2c66affSColin Finck     /* no parent, full path, depth 2, signature */
5244c2c66affSColin Finck     sprintf(path, "'NewSignature4', '', '%s', 2", expected);
5245f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5246c2c66affSColin Finck 
5247c2c66affSColin Finck     /* no parent, full path, depth 3, signature */
5248c2c66affSColin Finck     sprintf(path, "'NewSignature5', '', '%s', 3", expected);
5249f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5250c2c66affSColin Finck 
5251c2c66affSColin Finck     /* no parent, full path, depth 1, signature is dir */
5252c2c66affSColin Finck     sprintf(path, "'NewSignature6', '', '%s', 1", expected);
5253f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5254c2c66affSColin Finck 
5255c2c66affSColin Finck     /* parent is in DrLocator, relative path, depth 0, signature */
5256c2c66affSColin Finck     sprintf(path, "'NewSignature7', 'NewSignature1', 'one\\two\\three', 1");
5257f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5258c2c66affSColin Finck 
5259c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version */
5260c2c66affSColin Finck     sprintf(path, "'NewSignature8', '', '%s', 0", expected);
5261f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5262c2c66affSColin Finck 
5263c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version, ver > max */
5264c2c66affSColin Finck     sprintf(path, "'NewSignature9', '', '%s', 0", expected);
5265f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5266c2c66affSColin Finck 
5267c2c66affSColin Finck     /* no parent, full path, depth 0, signature w/ version, sig->name not ignored */
5268c2c66affSColin Finck     sprintf(path, "'NewSignature10', '', '%s', 0", expected);
5269f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5270c2c66affSColin Finck 
5271c2c66affSColin Finck     /* no parent, relative empty path, depth 0, no signature */
5272c2c66affSColin Finck     sprintf(path, "'NewSignature11', '', '', 0");
5273f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5274c2c66affSColin Finck 
5275f860a780SAmine Khaldi     create_reglocator_table(hdb);
5276c2c66affSColin Finck 
5277c2c66affSColin Finck     /* parent */
5278f860a780SAmine Khaldi     add_reglocator_entry(hdb, "NewSignature12", 2, "htmlfile\\shell\\open\\nonexistent", "", 1);
5279c2c66affSColin Finck 
5280c2c66affSColin Finck     /* parent is in RegLocator, no path, depth 0, no signature */
5281c2c66affSColin Finck     sprintf(path, "'NewSignature13', 'NewSignature12', '', 0");
5282f860a780SAmine Khaldi     add_drlocator_entry(hdb, path);
5283c2c66affSColin Finck 
5284f860a780SAmine Khaldi     create_signature_table(hdb);
5285f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature1', 'FileName1', '', '', '', '', '', '', ''");
5286f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature4', 'FileName2', '', '', '', '', '', '', ''");
5287f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature5', 'FileName2', '', '', '', '', '', '', ''");
5288f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature6', 'another', '', '', '', '', '', '', ''");
5289f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature7', 'FileName2', '', '', '', '', '', '', ''");
5290f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature8', 'FileName3.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5291f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature9', 'FileName4.dll', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5292f860a780SAmine Khaldi     add_signature_entry(hdb, "'NewSignature10', 'necessary', '1.1.1.1', '2.1.1.1', '', '', '', '', ''");
5293c2c66affSColin Finck 
5294c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5295c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5296c2c66affSColin Finck     {
5297c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5298c2c66affSColin Finck         goto error;
5299c2c66affSColin Finck     }
5300c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package handle %u\n", r);
5301c2c66affSColin Finck 
5302c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5303c2c66affSColin Finck 
5304c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
5305c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5306c2c66affSColin Finck 
5307c2c66affSColin Finck     size = MAX_PATH;
5308c2c66affSColin Finck     sprintf(path, "%s\\FileName1", expected);
5309c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP1", prop, &size);
5310c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5311c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5312c2c66affSColin Finck 
5313c2c66affSColin Finck     size = MAX_PATH;
5314c2c66affSColin Finck     sprintf(path, "%s\\", expected);
5315c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP2", prop, &size);
5316c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5317c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5318c2c66affSColin Finck 
5319c2c66affSColin Finck     size = MAX_PATH;
5320c2c66affSColin Finck     search_absolute_directory(path, expected + 3);
5321c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP3", prop, &size);
5322c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5323c2c66affSColin Finck     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5324c2c66affSColin Finck 
5325c2c66affSColin Finck     size = MAX_PATH;
5326c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP4", prop, &size);
5327c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5328c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5329c2c66affSColin Finck 
5330c2c66affSColin Finck     size = MAX_PATH;
5331c2c66affSColin Finck     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5332c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP5", prop, &size);
5333c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5334c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5335c2c66affSColin Finck 
5336c2c66affSColin Finck     size = MAX_PATH;
5337c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP6", prop, &size);
5338c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5339c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5340c2c66affSColin Finck 
5341c2c66affSColin Finck     size = MAX_PATH;
5342c2c66affSColin Finck     sprintf(path, "%s\\one\\two\\three\\FileName2", expected);
5343c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP7", prop, &size);
5344c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5345c2c66affSColin Finck     ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5346c2c66affSColin Finck 
5347c2c66affSColin Finck     if (version)
5348c2c66affSColin Finck     {
5349c2c66affSColin Finck         size = MAX_PATH;
5350c2c66affSColin Finck         sprintf(path, "%s\\FileName3.dll", expected);
5351c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP8", prop, &size);
5352c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5353c2c66affSColin Finck         ok(!lstrcmpA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5354c2c66affSColin Finck 
5355c2c66affSColin Finck         size = MAX_PATH;
5356c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP9", prop, &size);
5357c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5358c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5359c2c66affSColin Finck 
5360c2c66affSColin Finck         size = MAX_PATH;
5361c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "SIGPROP10", prop, &size);
5362c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5363c2c66affSColin Finck         ok(!lstrcmpA(prop, ""), "Expected \"\", got \"%s\"\n", prop);
5364c2c66affSColin Finck     }
5365c2c66affSColin Finck 
5366c2c66affSColin Finck     size = MAX_PATH;
5367c2c66affSColin Finck     search_absolute_directory(path, "");
5368c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP11", prop, &size);
5369c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5370c2c66affSColin Finck     ok(!lstrcmpiA(prop, path), "Expected \"%s\", got \"%s\"\n", path, prop);
5371c2c66affSColin Finck 
5372c2c66affSColin Finck     size = MAX_PATH;
5373c2c66affSColin Finck     strcpy(path, "c:\\");
5374c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SIGPROP13", prop, &size);
5375c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5376c2c66affSColin Finck     ok(!prop[0], "Expected \"\", got \"%s\"\n", prop);
5377c2c66affSColin Finck 
5378c2c66affSColin Finck     MsiCloseHandle(hpkg);
5379c2c66affSColin Finck 
5380c2c66affSColin Finck error:
5381c2c66affSColin Finck     DeleteFileA("FileName1");
5382c2c66affSColin Finck     DeleteFileA("FileName3.dll");
5383c2c66affSColin Finck     DeleteFileA("FileName4.dll");
5384c2c66affSColin Finck     DeleteFileA("FileName5.dll");
5385c2c66affSColin Finck     DeleteFileA("one\\two\\three\\FileName2");
5386c2c66affSColin Finck     RemoveDirectoryA("one\\two\\three");
5387c2c66affSColin Finck     RemoveDirectoryA("one\\two");
5388c2c66affSColin Finck     RemoveDirectoryA("one");
5389c2c66affSColin Finck     RemoveDirectoryA("another");
5390c2c66affSColin Finck     DeleteFileA(msifile);
5391c2c66affSColin Finck }
5392c2c66affSColin Finck 
5393c2c66affSColin Finck static void test_featureparents(void)
5394c2c66affSColin Finck {
5395c2c66affSColin Finck     MSIHANDLE hpkg;
5396c2c66affSColin Finck     UINT r;
5397c2c66affSColin Finck     MSIHANDLE hdb;
5398c2c66affSColin Finck 
5399c2c66affSColin Finck     hdb = create_package_db();
5400c2c66affSColin Finck     ok ( hdb, "failed to create package database\n" );
5401c2c66affSColin Finck 
5402f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
5403c2c66affSColin Finck 
5404f860a780SAmine Khaldi     create_feature_table( hdb );
5405f860a780SAmine Khaldi     create_component_table( hdb );
5406f860a780SAmine Khaldi     create_feature_components_table( hdb );
5407f860a780SAmine Khaldi     create_file_table( hdb );
5408c2c66affSColin Finck 
5409c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
5410f860a780SAmine Khaldi     add_feature_entry( hdb, "'zodiac', '', '', '', 2, 1, '', 0" );
5411c2c66affSColin Finck 
5412c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource */
5413f860a780SAmine Khaldi     add_feature_entry( hdb, "'perseus', '', '', '', 2, 1, '', 1" );
5414c2c66affSColin Finck 
5415c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal */
5416f860a780SAmine Khaldi     add_feature_entry( hdb, "'orion', '', '', '', 2, 1, '', 0" );
5417c2c66affSColin Finck 
5418c2c66affSColin Finck     /* msidbFeatureAttributesUIDisallowAbsent */
5419f860a780SAmine Khaldi     add_feature_entry( hdb, "'lyra', '', '', '', 2, 1, '', 16" );
5420c2c66affSColin Finck 
5421c2c66affSColin Finck     /* disabled because of install level */
5422f860a780SAmine Khaldi     add_feature_entry( hdb, "'waters', '', '', '', 15, 101, '', 9" );
5423c2c66affSColin Finck 
5424c2c66affSColin Finck     /* child feature of disabled feature */
5425f860a780SAmine Khaldi     add_feature_entry( hdb, "'bayer', 'waters', '', '', 14, 1, '', 9" );
5426c2c66affSColin Finck 
5427c2c66affSColin Finck     /* component of disabled feature (install level) */
5428f860a780SAmine Khaldi     add_component_entry( hdb, "'delphinus', '', 'TARGETDIR', 0, '', 'delphinus_file'" );
5429c2c66affSColin Finck 
5430c2c66affSColin Finck     /* component of disabled child feature (install level) */
5431f860a780SAmine Khaldi     add_component_entry( hdb, "'hydrus', '', 'TARGETDIR', 0, '', 'hydrus_file'" );
5432c2c66affSColin Finck 
5433c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5434f860a780SAmine Khaldi     add_component_entry( hdb, "'leo', '', 'TARGETDIR', 0, '', 'leo_file'" );
5435c2c66affSColin Finck 
5436c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5437f860a780SAmine Khaldi     add_component_entry( hdb, "'virgo', '', 'TARGETDIR', 1, '', 'virgo_file'" );
5438c2c66affSColin Finck 
5439c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5440f860a780SAmine Khaldi     add_component_entry( hdb, "'libra', '', 'TARGETDIR', 2, '', 'libra_file'" );
5441c2c66affSColin Finck 
5442c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
5443f860a780SAmine Khaldi     add_component_entry( hdb, "'cassiopeia', '', 'TARGETDIR', 0, '', 'cassiopeia_file'" );
5444c2c66affSColin Finck 
5445c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
5446f860a780SAmine Khaldi     add_component_entry( hdb, "'cepheus', '', 'TARGETDIR', 1, '', 'cepheus_file'" );
5447c2c66affSColin Finck 
5448c2c66affSColin Finck     /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
5449f860a780SAmine Khaldi     add_component_entry( hdb, "'andromeda', '', 'TARGETDIR', 2, '', 'andromeda_file'" );
5450c2c66affSColin Finck 
5451c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
5452f860a780SAmine Khaldi     add_component_entry( hdb, "'canis', '', 'TARGETDIR', 0, '', 'canis_file'" );
5453c2c66affSColin Finck 
5454c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
5455f860a780SAmine Khaldi     add_component_entry( hdb, "'monoceros', '', 'TARGETDIR', 1, '', 'monoceros_file'" );
5456c2c66affSColin Finck 
5457c2c66affSColin Finck     /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
5458f860a780SAmine Khaldi     add_component_entry( hdb, "'lepus', '', 'TARGETDIR', 2, '', 'lepus_file'" );
5459c2c66affSColin Finck 
5460f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'leo'" );
5461f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'virgo'" );
5462f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'zodiac', 'libra'" );
5463f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'cassiopeia'" );
5464f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'cepheus'" );
5465f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'perseus', 'andromeda'" );
5466f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'leo'" );
5467f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'virgo'" );
5468f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'libra'" );
5469f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'cassiopeia'" );
5470f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'cepheus'" );
5471f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'andromeda'" );
5472f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'canis'" );
5473f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'monoceros'" );
5474f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'orion', 'lepus'" );
5475f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'waters', 'delphinus'" );
5476f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'bayer', 'hydrus'" );
5477c2c66affSColin Finck 
5478f860a780SAmine Khaldi     add_file_entry( hdb, "'leo_file', 'leo', 'leo.txt', 100, '', '1033', 8192, 1" );
5479f860a780SAmine Khaldi     add_file_entry( hdb, "'virgo_file', 'virgo', 'virgo.txt', 0, '', '1033', 8192, 1" );
5480f860a780SAmine Khaldi     add_file_entry( hdb, "'libra_file', 'libra', 'libra.txt', 0, '', '1033', 8192, 1" );
5481f860a780SAmine Khaldi     add_file_entry( hdb, "'cassiopeia_file', 'cassiopeia', 'cassiopeia.txt', 0, '', '1033', 8192, 1" );
5482f860a780SAmine Khaldi     add_file_entry( hdb, "'cepheus_file', 'cepheus', 'cepheus.txt', 0, '', '1033', 8192, 1" );
5483f860a780SAmine Khaldi     add_file_entry( hdb, "'andromeda_file', 'andromeda', 'andromeda.txt', 0, '', '1033', 8192, 1" );
5484f860a780SAmine Khaldi     add_file_entry( hdb, "'canis_file', 'canis', 'canis.txt', 0, '', '1033', 8192, 1" );
5485f860a780SAmine Khaldi     add_file_entry( hdb, "'monoceros_file', 'monoceros', 'monoceros.txt', 0, '', '1033', 8192, 1" );
5486f860a780SAmine Khaldi     add_file_entry( hdb, "'lepus_file', 'lepus', 'lepus.txt', 0, '', '1033', 8192, 1" );
5487f860a780SAmine Khaldi     add_file_entry( hdb, "'delphinus_file', 'delphinus', 'delphinus.txt', 0, '', '1033', 8192, 1" );
5488f860a780SAmine Khaldi     add_file_entry( hdb, "'hydrus_file', 'hydrus', 'hydrus.txt', 0, '', '1033', 8192, 1" );
5489c2c66affSColin Finck 
5490c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
5491c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5492c2c66affSColin Finck     {
5493c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5494c2c66affSColin Finck         DeleteFileA(msifile);
5495c2c66affSColin Finck         return;
5496c2c66affSColin Finck     }
5497c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5498c2c66affSColin Finck 
5499c2c66affSColin Finck     MsiCloseHandle( hdb );
5500c2c66affSColin Finck 
5501c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5502c2c66affSColin Finck 
5503c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize");
5504c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n");
5505c2c66affSColin Finck 
5506c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost");
5507c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "file cost failed\n");
5508c2c66affSColin Finck 
5509c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize");
5510c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost finalize failed\n");
5511c2c66affSColin Finck 
5512c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5513c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5514c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5515c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5516c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5517c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5518c2c66affSColin Finck 
5519c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5520c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5521c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5522c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5523c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5524c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5525c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5526c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5527c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5528c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5529c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5530c2c66affSColin Finck 
5531c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "orion", INSTALLSTATE_ABSENT);
5532c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5533c2c66affSColin Finck 
5534c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "lyra", INSTALLSTATE_ABSENT);
5535c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set feature state: %d\n", r);
5536c2c66affSColin Finck 
5537c2c66affSColin Finck     r = MsiSetFeatureStateA(hpkg, "nosuchfeature", INSTALLSTATE_ABSENT);
5538c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_FEATURE, "Expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
5539c2c66affSColin Finck 
5540c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "zodiac", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_LOCAL, FALSE );
5541c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "perseus", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_SOURCE, FALSE );
5542c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "orion", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5543c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "lyra", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_ABSENT, FALSE );
5544c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "waters", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5545c2c66affSColin Finck     test_feature_states( __LINE__, hpkg, "bayer", ERROR_SUCCESS, INSTALLSTATE_ABSENT, INSTALLSTATE_UNKNOWN, FALSE );
5546c2c66affSColin Finck 
5547c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "leo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5548c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "virgo", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5549c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "libra", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5550c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cassiopeia", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_LOCAL, FALSE );
5551c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "cepheus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5552c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "andromeda", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_SOURCE, FALSE );
5553c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "canis", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5554c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "monoceros", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5555c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "lepus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5556c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "delphinus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5557c2c66affSColin Finck     test_component_states( __LINE__, hpkg, "hydrus", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN, INSTALLSTATE_UNKNOWN, FALSE );
5558c2c66affSColin Finck 
5559c2c66affSColin Finck     MsiCloseHandle(hpkg);
5560c2c66affSColin Finck     DeleteFileA(msifile);
5561c2c66affSColin Finck }
5562c2c66affSColin Finck 
5563c2c66affSColin Finck static void test_installprops(void)
5564c2c66affSColin Finck {
5565c2c66affSColin Finck     MSIHANDLE hpkg, hdb;
5566c2c66affSColin Finck     CHAR path[MAX_PATH], buf[MAX_PATH];
5567c2c66affSColin Finck     DWORD size, type;
5568c2c66affSColin Finck     LANGID langid;
55693ec0ea99Swinesync     HKEY hkey1, hkey2, pathkey;
5570c2c66affSColin Finck     int res;
5571c2c66affSColin Finck     UINT r;
5572c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
5573c2c66affSColin Finck     SYSTEM_INFO si;
5574c2c66affSColin Finck     INSTALLUILEVEL uilevel;
5575c2c66affSColin Finck 
5576c2c66affSColin Finck     if (is_wow64)
5577c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
5578c2c66affSColin Finck 
5579c2c66affSColin Finck     lstrcpyA(path, CURR_DIR);
5580c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(path, "\\");
5581c2c66affSColin Finck     lstrcatA(path, msifile);
5582c2c66affSColin Finck 
5583c2c66affSColin Finck     uilevel = MsiSetInternalUI(INSTALLUILEVEL_BASIC|INSTALLUILEVEL_SOURCERESONLY, NULL);
5584c2c66affSColin Finck 
5585c2c66affSColin Finck     hdb = create_package_db();
5586c2c66affSColin Finck     ok( hdb, "failed to create database\n");
5587c2c66affSColin Finck 
5588c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5589c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5590c2c66affSColin Finck     {
5591c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5592c2c66affSColin Finck         MsiSetInternalUI(uilevel, NULL);
5593c2c66affSColin Finck         DeleteFileA(msifile);
5594c2c66affSColin Finck         return;
5595c2c66affSColin Finck     }
5596c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5597c2c66affSColin Finck 
5598c2c66affSColin Finck     MsiCloseHandle(hdb);
5599c2c66affSColin Finck 
5600c2c66affSColin Finck     buf[0] = 0;
5601c2c66affSColin Finck     size = MAX_PATH;
5602c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5603c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5604c2c66affSColin Finck     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5605c2c66affSColin Finck 
5606c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5607c2c66affSColin Finck 
5608c2c66affSColin Finck     buf[0] = 0;
5609c2c66affSColin Finck     size = MAX_PATH;
5610c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UILevel", buf, &size);
5611c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5612c2c66affSColin Finck     ok( !lstrcmpA(buf, "3"), "Expected \"3\", got \"%s\"\n", buf);
5613c2c66affSColin Finck 
5614c2c66affSColin Finck     buf[0] = 0;
5615c2c66affSColin Finck     size = MAX_PATH;
5616c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "DATABASE", buf, &size);
5617c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5618c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5619c2c66affSColin Finck 
5620c2c66affSColin Finck     RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\MS Setup (ACME)\\User Info", &hkey1);
5621c2c66affSColin Finck     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, access, &hkey2);
56223ec0ea99Swinesync     RegOpenKeyExA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion",
56233ec0ea99Swinesync         0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &pathkey);
5624c2c66affSColin Finck 
5625c2c66affSColin Finck     size = MAX_PATH;
5626c2c66affSColin Finck     type = REG_SZ;
5627c2c66affSColin Finck     *path = '\0';
5628c2c66affSColin Finck     if (RegQueryValueExA(hkey1, "DefName", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5629c2c66affSColin Finck     {
5630c2c66affSColin Finck         size = MAX_PATH;
5631c2c66affSColin Finck         type = REG_SZ;
5632c2c66affSColin Finck         RegQueryValueExA(hkey2, "RegisteredOwner", NULL, &type, (LPBYTE)path, &size);
5633c2c66affSColin Finck     }
5634c2c66affSColin Finck 
5635c2c66affSColin Finck     buf[0] = 0;
5636c2c66affSColin Finck     size = MAX_PATH;
5637c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "USERNAME", buf, &size);
5638c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5639c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5640c2c66affSColin Finck 
5641c2c66affSColin Finck     size = MAX_PATH;
5642c2c66affSColin Finck     type = REG_SZ;
5643c2c66affSColin Finck     *path = '\0';
5644c2c66affSColin Finck     if (RegQueryValueExA(hkey1, "DefCompany", NULL, &type, (LPBYTE)path, &size) != ERROR_SUCCESS)
5645c2c66affSColin Finck     {
5646c2c66affSColin Finck         size = MAX_PATH;
5647c2c66affSColin Finck         type = REG_SZ;
5648c2c66affSColin Finck         RegQueryValueExA(hkey2, "RegisteredOrganization", NULL, &type, (LPBYTE)path, &size);
5649c2c66affSColin Finck     }
5650c2c66affSColin Finck 
5651c2c66affSColin Finck     if (*path)
5652c2c66affSColin Finck     {
5653c2c66affSColin Finck         buf[0] = 0;
5654c2c66affSColin Finck         size = MAX_PATH;
5655c2c66affSColin Finck         r = MsiGetPropertyA(hpkg, "COMPANYNAME", buf, &size);
5656c2c66affSColin Finck         ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5657c2c66affSColin Finck         ok( !lstrcmpA(buf, path), "Expected %s, got %s\n", path, buf);
5658c2c66affSColin Finck     }
5659c2c66affSColin Finck 
5660c2c66affSColin Finck     buf[0] = 0;
5661c2c66affSColin Finck     size = MAX_PATH;
5662c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "VersionDatabase", buf, &size);
5663c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5664c2c66affSColin Finck     trace("VersionDatabase = %s\n", buf);
5665c2c66affSColin Finck 
5666c2c66affSColin Finck     buf[0] = 0;
5667c2c66affSColin Finck     size = MAX_PATH;
5668c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "VersionMsi", buf, &size);
5669c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5670c2c66affSColin Finck     trace("VersionMsi = %s\n", buf);
5671c2c66affSColin Finck 
5672c2c66affSColin Finck     buf[0] = 0;
5673c2c66affSColin Finck     size = MAX_PATH;
5674c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Date", buf, &size);
5675c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5676c2c66affSColin Finck     trace("Date = %s\n", buf);
5677c2c66affSColin Finck 
5678c2c66affSColin Finck     buf[0] = 0;
5679c2c66affSColin Finck     size = MAX_PATH;
5680c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Time", buf, &size);
5681c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5682c2c66affSColin Finck     trace("Time = %s\n", buf);
5683c2c66affSColin Finck 
5684c2c66affSColin Finck     buf[0] = 0;
5685c2c66affSColin Finck     size = MAX_PATH;
5686c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "PackageCode", buf, &size);
5687c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to get property: %d\n", r);
5688c2c66affSColin Finck     trace("PackageCode = %s\n", buf);
5689c2c66affSColin Finck 
5690c2c66affSColin Finck     buf[0] = 0;
5691c2c66affSColin Finck     size = MAX_PATH;
5692c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ComputerName", buf, &size);
5693c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5694c2c66affSColin Finck     trace("ComputerName = %s\n", buf);
5695c2c66affSColin Finck 
5696c2c66affSColin Finck     langid = GetUserDefaultLangID();
5697c2c66affSColin Finck     sprintf(path, "%d", langid);
5698c2c66affSColin Finck 
5699c2c66affSColin Finck     buf[0] = 0;
5700c2c66affSColin Finck     size = MAX_PATH;
5701c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "UserLanguageID", buf, &size);
5702c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5703c2c66affSColin Finck     ok( !lstrcmpA(buf, path), "Expected \"%s\", got \"%s\"\n", path, buf);
5704c2c66affSColin Finck 
5705c2c66affSColin Finck     res = GetSystemMetrics(SM_CXSCREEN);
5706c2c66affSColin Finck     buf[0] = 0;
5707c2c66affSColin Finck     size = MAX_PATH;
5708c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ScreenX", buf, &size);
5709c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5710c2c66affSColin Finck     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5711c2c66affSColin Finck 
5712c2c66affSColin Finck     res = GetSystemMetrics(SM_CYSCREEN);
5713c2c66affSColin Finck     buf[0] = 0;
5714c2c66affSColin Finck     size = MAX_PATH;
5715c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ScreenY", buf, &size);
5716c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
5717c2c66affSColin Finck     ok(atol(buf) == res, "Expected %d, got %ld\n", res, atol(buf));
5718c2c66affSColin Finck 
571931139640SAmine Khaldi     buf[0] = 0;
572031139640SAmine Khaldi     size = MAX_PATH;
572131139640SAmine Khaldi     r = MsiGetPropertyA(hpkg, "MsiNetAssemblySupport", buf, &size);
572231139640SAmine Khaldi     if (r == ERROR_SUCCESS) trace( "MsiNetAssemblySupport \"%s\"\n", buf );
572331139640SAmine Khaldi 
57243ec0ea99Swinesync     if (pGetNativeSystemInfo)
57253ec0ea99Swinesync         pGetNativeSystemInfo(&si);
57263ec0ea99Swinesync     else
5727c2c66affSColin Finck         pGetSystemInfo(&si);
57283ec0ea99Swinesync 
5729c2c66affSColin Finck     if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
5730c2c66affSColin Finck     {
57313ec0ea99Swinesync         sprintf(buf, "%d", si.wProcessorLevel);
57323ec0ea99Swinesync         check_prop(hpkg, "Intel", buf);
57333ec0ea99Swinesync         check_prop(hpkg, "MsiAMD64", buf);
57343ec0ea99Swinesync         check_prop(hpkg, "Msix64", buf);
57353ec0ea99Swinesync         sprintf(buf, "%d", LOBYTE(LOWORD(GetVersion())) * 100 + HIBYTE(LOWORD(GetVersion())));
57363ec0ea99Swinesync         check_prop(hpkg, "VersionNT64", buf);
5737c2c66affSColin Finck 
5738c2c66affSColin Finck         GetSystemDirectoryA(path, MAX_PATH);
57393ec0ea99Swinesync         strcat(path, "\\");
57403ec0ea99Swinesync         check_prop(hpkg, "System64Folder", path);
5741c2c66affSColin Finck 
5742c2c66affSColin Finck         pGetSystemWow64DirectoryA(path, MAX_PATH);
57433ec0ea99Swinesync         strcat(path, "\\");
57443ec0ea99Swinesync         check_prop(hpkg, "SystemFolder", path);
5745c2c66affSColin Finck 
5746c2c66affSColin Finck         size = MAX_PATH;
57473ec0ea99Swinesync         r = RegQueryValueExA(pathkey, "ProgramFilesDir (x86)", 0, &type, (BYTE *)path, &size);
57483ec0ea99Swinesync         strcat(path, "\\");
57493ec0ea99Swinesync         check_prop(hpkg, "ProgramFilesFolder", path);
5750c2c66affSColin Finck 
5751c2c66affSColin Finck         size = MAX_PATH;
57523ec0ea99Swinesync         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
57533ec0ea99Swinesync         strcat(path, "\\");
57543ec0ea99Swinesync         check_prop(hpkg, "ProgramFiles64Folder", path);
5755c2c66affSColin Finck 
5756c2c66affSColin Finck         size = MAX_PATH;
57573ec0ea99Swinesync         RegQueryValueExA(pathkey, "CommonFilesDir (x86)", 0, &type, (BYTE *)path, &size);
57583ec0ea99Swinesync         strcat(path, "\\");
57593ec0ea99Swinesync         check_prop(hpkg, "CommonFilesFolder", path);
5760c2c66affSColin Finck 
5761c2c66affSColin Finck         size = MAX_PATH;
57623ec0ea99Swinesync         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
57633ec0ea99Swinesync         strcat(path, "\\");
57643ec0ea99Swinesync         check_prop(hpkg, "CommonFiles64Folder", path);
5765c2c66affSColin Finck     }
5766c2c66affSColin Finck     else if (S(U(si)).wProcessorArchitecture == PROCESSOR_ARCHITECTURE_INTEL)
5767c2c66affSColin Finck     {
57683ec0ea99Swinesync         sprintf(buf, "%d", si.wProcessorLevel);
57693ec0ea99Swinesync         check_prop(hpkg, "Intel", buf);
5770c2c66affSColin Finck 
5771c2c66affSColin Finck         GetSystemDirectoryA(path, MAX_PATH);
57723ec0ea99Swinesync         strcat(path, "\\");
57733ec0ea99Swinesync         check_prop(hpkg, "SystemFolder", path);
5774c2c66affSColin Finck 
5775c2c66affSColin Finck         size = MAX_PATH;
57763ec0ea99Swinesync         RegQueryValueExA(pathkey, "ProgramFilesDir", 0, &type, (BYTE *)path, &size);
57773ec0ea99Swinesync         strcat(path, "\\");
57783ec0ea99Swinesync         check_prop(hpkg, "ProgramFilesFolder", path);
5779c2c66affSColin Finck 
5780c2c66affSColin Finck         size = MAX_PATH;
57813ec0ea99Swinesync         RegQueryValueExA(pathkey, "CommonFilesDir", 0, &type, (BYTE *)path, &size);
57823ec0ea99Swinesync         strcat(path, "\\");
57833ec0ea99Swinesync         check_prop(hpkg, "CommonFilesFolder", path);
5784c2c66affSColin Finck 
57853ec0ea99Swinesync         check_prop(hpkg, "MsiAMD64", "");
57863ec0ea99Swinesync         check_prop(hpkg, "Msix64", "");
57873ec0ea99Swinesync         check_prop(hpkg, "VersionNT64", "");
57883ec0ea99Swinesync         check_prop(hpkg, "System64Folder", "");
57893ec0ea99Swinesync         check_prop(hpkg, "ProgramFiles64Dir", "");
57903ec0ea99Swinesync         check_prop(hpkg, "CommonFiles64Dir", "");
5791c2c66affSColin Finck     }
5792c2c66affSColin Finck 
5793c2c66affSColin Finck     CloseHandle(hkey1);
5794c2c66affSColin Finck     CloseHandle(hkey2);
57953ec0ea99Swinesync     RegCloseKey(pathkey);
5796c2c66affSColin Finck     MsiCloseHandle(hpkg);
5797c2c66affSColin Finck     DeleteFileA(msifile);
5798c2c66affSColin Finck     MsiSetInternalUI(uilevel, NULL);
5799c2c66affSColin Finck }
5800c2c66affSColin Finck 
5801c2c66affSColin Finck static void test_launchconditions(void)
5802c2c66affSColin Finck {
5803c2c66affSColin Finck     MSIHANDLE hpkg;
5804c2c66affSColin Finck     MSIHANDLE hdb;
5805c2c66affSColin Finck     UINT r;
5806c2c66affSColin Finck 
5807c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5808c2c66affSColin Finck 
5809c2c66affSColin Finck     hdb = create_package_db();
5810c2c66affSColin Finck     ok( hdb, "failed to create package database\n" );
5811c2c66affSColin Finck 
5812f860a780SAmine Khaldi     create_launchcondition_table( hdb );
5813c2c66affSColin Finck 
5814f860a780SAmine Khaldi     add_launchcondition_entry( hdb, "'X = \"1\"', 'one'" );
5815c2c66affSColin Finck 
5816c2c66affSColin Finck     /* invalid condition */
5817f860a780SAmine Khaldi     add_launchcondition_entry( hdb, "'X != \"1\"', 'one'" );
5818c2c66affSColin Finck 
5819c2c66affSColin Finck     r = package_from_db( hdb, &hpkg );
5820c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5821c2c66affSColin Finck     {
5822c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5823c2c66affSColin Finck         DeleteFileA(msifile);
5824c2c66affSColin Finck         return;
5825c2c66affSColin Finck     }
5826c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
5827c2c66affSColin Finck 
5828c2c66affSColin Finck     MsiCloseHandle( hdb );
5829c2c66affSColin Finck 
5830c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "X", "1" );
5831c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5832c2c66affSColin Finck 
5833c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5834c2c66affSColin Finck 
5835c2c66affSColin Finck     /* invalid conditions are ignored */
5836c2c66affSColin Finck     r = MsiDoActionA( hpkg, "LaunchConditions" );
5837c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "cost init failed\n" );
5838c2c66affSColin Finck 
5839c2c66affSColin Finck     /* verify LaunchConditions still does some verification */
5840c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "X", "2" );
5841c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "failed to set property\n" );
5842c2c66affSColin Finck 
5843c2c66affSColin Finck     r = MsiDoActionA( hpkg, "LaunchConditions" );
5844c2c66affSColin Finck     ok( r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r );
5845c2c66affSColin Finck 
5846c2c66affSColin Finck     MsiCloseHandle( hpkg );
5847c2c66affSColin Finck     DeleteFileA( msifile );
5848c2c66affSColin Finck }
5849c2c66affSColin Finck 
5850c2c66affSColin Finck static void test_ccpsearch(void)
5851c2c66affSColin Finck {
5852c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
5853c2c66affSColin Finck     CHAR prop[MAX_PATH];
5854c2c66affSColin Finck     DWORD size = MAX_PATH;
5855c2c66affSColin Finck     UINT r;
5856c2c66affSColin Finck 
5857c2c66affSColin Finck     hdb = create_package_db();
5858c2c66affSColin Finck     ok(hdb, "failed to create package database\n");
5859c2c66affSColin Finck 
5860f860a780SAmine Khaldi     create_ccpsearch_table(hdb);
5861f860a780SAmine Khaldi     add_ccpsearch_entry(hdb, "'CCP_random'");
5862f860a780SAmine Khaldi     add_ccpsearch_entry(hdb, "'RMCCP_random'");
5863c2c66affSColin Finck 
5864f860a780SAmine Khaldi     create_reglocator_table(hdb);
5865f860a780SAmine Khaldi     add_reglocator_entry(hdb, "CCP_random", 0, "htmlfile\\shell\\open\\nonexistent", "", 1);
5866c2c66affSColin Finck 
5867f860a780SAmine Khaldi     create_drlocator_table(hdb);
5868f860a780SAmine Khaldi     add_drlocator_entry(hdb, "'RMCCP_random', '', 'C:\\', '0'");
5869c2c66affSColin Finck 
5870f860a780SAmine Khaldi     create_signature_table(hdb);
5871c2c66affSColin Finck 
5872c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5873c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5874c2c66affSColin Finck     {
5875c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5876c2c66affSColin Finck         DeleteFileA(msifile);
5877c2c66affSColin Finck         return;
5878c2c66affSColin Finck     }
5879c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5880c2c66affSColin Finck 
5881c2c66affSColin Finck     MsiCloseHandle(hdb);
5882c2c66affSColin Finck 
5883c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5884c2c66affSColin Finck 
5885c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CCPSearch");
5886c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5887c2c66affSColin Finck 
5888c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "CCP_Success", prop, &size);
5889c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5890c2c66affSColin Finck     ok(!lstrcmpA(prop, "1"), "Expected 1, got %s\n", prop);
5891c2c66affSColin Finck 
5892c2c66affSColin Finck     MsiCloseHandle(hpkg);
5893c2c66affSColin Finck     DeleteFileA(msifile);
5894c2c66affSColin Finck }
5895c2c66affSColin Finck 
5896c2c66affSColin Finck static void test_complocator(void)
5897c2c66affSColin Finck {
5898c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
5899c2c66affSColin Finck     UINT r;
5900c2c66affSColin Finck     CHAR prop[MAX_PATH];
5901c2c66affSColin Finck     CHAR expected[MAX_PATH];
5902c2c66affSColin Finck     DWORD size = MAX_PATH;
5903c2c66affSColin Finck 
5904c2c66affSColin Finck     hdb = create_package_db();
5905c2c66affSColin Finck     ok(hdb, "failed to create package database\n");
5906c2c66affSColin Finck 
5907f860a780SAmine Khaldi     create_appsearch_table(hdb);
5908f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'ABELISAURUS', 'abelisaurus'");
5909f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'BACTROSAURUS', 'bactrosaurus'");
5910f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'CAMELOTIA', 'camelotia'");
5911f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'DICLONIUS', 'diclonius'");
5912f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'ECHINODON', 'echinodon'");
5913f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'FALCARIUS', 'falcarius'");
5914f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'GALLIMIMUS', 'gallimimus'");
5915f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'HAGRYPHUS', 'hagryphus'");
5916f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'IGUANODON', 'iguanodon'");
5917f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'JOBARIA', 'jobaria'");
5918f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'KAKURU', 'kakuru'");
5919f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'LABOCANIA', 'labocania'");
5920f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'MEGARAPTOR', 'megaraptor'");
5921f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'NEOSODON', 'neosodon'");
5922f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'OLOROTITAN', 'olorotitan'");
5923f860a780SAmine Khaldi     add_appsearch_entry(hdb, "'PANTYDRACO', 'pantydraco'");
5924c2c66affSColin Finck 
5925f860a780SAmine Khaldi     create_complocator_table(hdb);
5926f860a780SAmine Khaldi     add_complocator_entry(hdb, "'abelisaurus', '{E3619EED-305A-418C-B9C7-F7D7377F0934}', 1");
5927f860a780SAmine Khaldi     add_complocator_entry(hdb, "'bactrosaurus', '{D56B688D-542F-42Ef-90FD-B6DA76EE8119}', 0");
5928f860a780SAmine Khaldi     add_complocator_entry(hdb, "'camelotia', '{8211BE36-2466-47E3-AFB7-6AC72E51AED2}', 1");
5929f860a780SAmine Khaldi     add_complocator_entry(hdb, "'diclonius', '{5C767B20-A33C-45A4-B80B-555E512F01AE}', 0");
5930f860a780SAmine Khaldi     add_complocator_entry(hdb, "'echinodon', '{A19E16C5-C75D-4699-8111-C4338C40C3CB}', 1");
5931f860a780SAmine Khaldi     add_complocator_entry(hdb, "'falcarius', '{17762FA1-A7AE-4CC6-8827-62873C35361D}', 0");
5932f860a780SAmine Khaldi     add_complocator_entry(hdb, "'gallimimus', '{75EBF568-C959-41E0-A99E-9050638CF5FB}', 1");
5933f860a780SAmine Khaldi     add_complocator_entry(hdb, "'hagrphus', '{D4969B72-17D9-4AB6-BE49-78F2FEE857AC}', 0");
5934f860a780SAmine Khaldi     add_complocator_entry(hdb, "'iguanodon', '{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}', 1");
5935f860a780SAmine Khaldi     add_complocator_entry(hdb, "'jobaria', '{243C22B1-8C51-4151-B9D1-1AE5265E079E}', 0");
5936f860a780SAmine Khaldi     add_complocator_entry(hdb, "'kakuru', '{5D0F03BA-50BC-44F2-ABB1-72C972F4E514}', 1");
5937f860a780SAmine Khaldi     add_complocator_entry(hdb, "'labocania', '{C7DDB60C-7828-4046-A6F8-699D5E92F1ED}', 0");
5938f860a780SAmine Khaldi     add_complocator_entry(hdb, "'megaraptor', '{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}', 1");
5939f860a780SAmine Khaldi     add_complocator_entry(hdb, "'neosodon', '{0B499649-197A-48EF-93D2-AF1C17ED6E90}', 0");
5940f860a780SAmine Khaldi     add_complocator_entry(hdb, "'olorotitan', '{54E9E91F-AED2-46D5-A25A-7E50AFA24513}', 1");
5941f860a780SAmine Khaldi     add_complocator_entry(hdb, "'pantydraco', '{2A989951-5565-4FA7-93A7-E800A3E67D71}', 0");
5942c2c66affSColin Finck 
5943f860a780SAmine Khaldi     create_signature_table(hdb);
5944f860a780SAmine Khaldi     add_signature_entry(hdb, "'abelisaurus', 'abelisaurus', '', '', '', '', '', '', ''");
5945f860a780SAmine Khaldi     add_signature_entry(hdb, "'bactrosaurus', 'bactrosaurus', '', '', '', '', '', '', ''");
5946f860a780SAmine Khaldi     add_signature_entry(hdb, "'camelotia', 'camelotia', '', '', '', '', '', '', ''");
5947f860a780SAmine Khaldi     add_signature_entry(hdb, "'diclonius', 'diclonius', '', '', '', '', '', '', ''");
5948f860a780SAmine Khaldi     add_signature_entry(hdb, "'iguanodon', 'iguanodon', '', '', '', '', '', '', ''");
5949f860a780SAmine Khaldi     add_signature_entry(hdb, "'jobaria', 'jobaria', '', '', '', '', '', '', ''");
5950f860a780SAmine Khaldi     add_signature_entry(hdb, "'kakuru', 'kakuru', '', '', '', '', '', '', ''");
5951f860a780SAmine Khaldi     add_signature_entry(hdb, "'labocania', 'labocania', '', '', '', '', '', '', ''");
5952c2c66affSColin Finck 
5953c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
5954c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
5955c2c66affSColin Finck     {
5956c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
5957c2c66affSColin Finck         DeleteFileA(msifile);
5958c2c66affSColin Finck         return;
5959c2c66affSColin Finck     }
5960c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
5961c2c66affSColin Finck 
5962c2c66affSColin Finck     MsiCloseHandle(hdb);
5963c2c66affSColin Finck 
5964c2c66affSColin Finck     create_test_file("abelisaurus");
5965c2c66affSColin Finck     create_test_file("bactrosaurus");
5966c2c66affSColin Finck     create_test_file("camelotia");
5967c2c66affSColin Finck     create_test_file("diclonius");
5968c2c66affSColin Finck     create_test_file("echinodon");
5969c2c66affSColin Finck     create_test_file("falcarius");
5970c2c66affSColin Finck     create_test_file("gallimimus");
5971c2c66affSColin Finck     create_test_file("hagryphus");
5972c2c66affSColin Finck     CreateDirectoryA("iguanodon", NULL);
5973c2c66affSColin Finck     CreateDirectoryA("jobaria", NULL);
5974c2c66affSColin Finck     CreateDirectoryA("kakuru", NULL);
5975c2c66affSColin Finck     CreateDirectoryA("labocania", NULL);
5976c2c66affSColin Finck     CreateDirectoryA("megaraptor", NULL);
5977c2c66affSColin Finck     CreateDirectoryA("neosodon", NULL);
5978c2c66affSColin Finck     CreateDirectoryA("olorotitan", NULL);
5979c2c66affSColin Finck     CreateDirectoryA("pantydraco", NULL);
5980c2c66affSColin Finck 
5981c2c66affSColin Finck     set_component_path("abelisaurus", MSIINSTALLCONTEXT_MACHINE,
5982c2c66affSColin Finck                        "{E3619EED-305A-418C-B9C7-F7D7377F0934}", NULL, FALSE);
5983c2c66affSColin Finck     set_component_path("bactrosaurus", MSIINSTALLCONTEXT_MACHINE,
5984c2c66affSColin Finck                        "{D56B688D-542F-42Ef-90FD-B6DA76EE8119}", NULL, FALSE);
5985c2c66affSColin Finck     set_component_path("echinodon", MSIINSTALLCONTEXT_MACHINE,
5986c2c66affSColin Finck                        "{A19E16C5-C75D-4699-8111-C4338C40C3CB}", NULL, FALSE);
5987c2c66affSColin Finck     set_component_path("falcarius", MSIINSTALLCONTEXT_MACHINE,
5988c2c66affSColin Finck                        "{17762FA1-A7AE-4CC6-8827-62873C35361D}", NULL, FALSE);
5989c2c66affSColin Finck     set_component_path("iguanodon", MSIINSTALLCONTEXT_MACHINE,
5990c2c66affSColin Finck                        "{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}", NULL, FALSE);
5991c2c66affSColin Finck     set_component_path("jobaria", MSIINSTALLCONTEXT_MACHINE,
5992c2c66affSColin Finck                        "{243C22B1-8C51-4151-B9D1-1AE5265E079E}", NULL, FALSE);
5993c2c66affSColin Finck     set_component_path("megaraptor", MSIINSTALLCONTEXT_MACHINE,
5994c2c66affSColin Finck                        "{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}", NULL, FALSE);
5995c2c66affSColin Finck     set_component_path("neosodon", MSIINSTALLCONTEXT_MACHINE,
5996c2c66affSColin Finck                        "{0B499649-197A-48EF-93D2-AF1C17ED6E90}", NULL, FALSE);
5997c2c66affSColin Finck 
5998c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5999c2c66affSColin Finck 
6000c2c66affSColin Finck     r = MsiDoActionA(hpkg, "AppSearch");
6001c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6002c2c66affSColin Finck 
6003c2c66affSColin Finck     size = MAX_PATH;
6004c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ABELISAURUS", prop, &size);
6005c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6006c2c66affSColin Finck 
6007c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6008c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6009c2c66affSColin Finck     lstrcatA(expected, "abelisaurus");
6010c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6011c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6012c2c66affSColin Finck 
6013c2c66affSColin Finck     size = MAX_PATH;
6014c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "BACTROSAURUS", prop, &size);
6015c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6016c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6017c2c66affSColin Finck 
6018c2c66affSColin Finck     size = MAX_PATH;
6019c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "CAMELOTIA", prop, &size);
6020c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6021c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6022c2c66affSColin Finck 
6023c2c66affSColin Finck     size = MAX_PATH;
6024c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "DICLONIUS", prop, &size);
6025c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6026c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6027c2c66affSColin Finck 
6028c2c66affSColin Finck     size = MAX_PATH;
6029c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "ECHINODON", prop, &size);
6030c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6031c2c66affSColin Finck 
6032c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6033c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6034c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6035c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6036c2c66affSColin Finck 
6037c2c66affSColin Finck     size = MAX_PATH;
6038c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "FALCARIUS", prop, &size);
6039c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6040c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6041c2c66affSColin Finck 
6042c2c66affSColin Finck     size = MAX_PATH;
6043c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "GALLIMIMUS", prop, &size);
6044c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6045c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6046c2c66affSColin Finck 
6047c2c66affSColin Finck     size = MAX_PATH;
6048c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "HAGRYPHUS", prop, &size);
6049c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6050c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6051c2c66affSColin Finck 
6052c2c66affSColin Finck     size = MAX_PATH;
6053c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "IGUANODON", prop, &size);
6054c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6055c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6056c2c66affSColin Finck 
6057c2c66affSColin Finck     size = MAX_PATH;
6058c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "JOBARIA", prop, &size);
6059c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6060c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6061c2c66affSColin Finck 
6062c2c66affSColin Finck     size = MAX_PATH;
6063c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "KAKURU", prop, &size);
6064c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6065c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6066c2c66affSColin Finck 
6067c2c66affSColin Finck     size = MAX_PATH;
6068c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "LABOCANIA", prop, &size);
6069c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6070c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6071c2c66affSColin Finck 
6072c2c66affSColin Finck     size = MAX_PATH;
6073c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "MEGARAPTOR", prop, &size);
6074c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6075c2c66affSColin Finck 
6076c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6077c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6078c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6079c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6080c2c66affSColin Finck 
6081c2c66affSColin Finck     size = MAX_PATH;
6082c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "NEOSODON", prop, &size);
6083c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6084c2c66affSColin Finck 
6085c2c66affSColin Finck     lstrcpyA(expected, CURR_DIR);
6086c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(expected, "\\");
6087c2c66affSColin Finck     lstrcatA(expected, "neosodon\\");
6088c2c66affSColin Finck     ok(!lstrcmpA(prop, expected) || !lstrcmpA(prop, ""),
6089c2c66affSColin Finck        "Expected %s or empty string, got %s\n", expected, prop);
6090c2c66affSColin Finck 
6091c2c66affSColin Finck     size = MAX_PATH;
6092c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "OLOROTITAN", prop, &size);
6093c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6094c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6095c2c66affSColin Finck 
6096c2c66affSColin Finck     size = MAX_PATH;
6097c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "PANTYDRACO", prop, &size);
6098c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6099c2c66affSColin Finck     ok(!lstrcmpA(prop, ""), "Expected , got %s\n", prop);
6100c2c66affSColin Finck 
6101c2c66affSColin Finck     MsiCloseHandle(hpkg);
6102c2c66affSColin Finck     DeleteFileA("abelisaurus");
6103c2c66affSColin Finck     DeleteFileA("bactrosaurus");
6104c2c66affSColin Finck     DeleteFileA("camelotia");
6105c2c66affSColin Finck     DeleteFileA("diclonius");
6106c2c66affSColin Finck     DeleteFileA("echinodon");
6107c2c66affSColin Finck     DeleteFileA("falcarius");
6108c2c66affSColin Finck     DeleteFileA("gallimimus");
6109c2c66affSColin Finck     DeleteFileA("hagryphus");
6110c2c66affSColin Finck     RemoveDirectoryA("iguanodon");
6111c2c66affSColin Finck     RemoveDirectoryA("jobaria");
6112c2c66affSColin Finck     RemoveDirectoryA("kakuru");
6113c2c66affSColin Finck     RemoveDirectoryA("labocania");
6114c2c66affSColin Finck     RemoveDirectoryA("megaraptor");
6115c2c66affSColin Finck     RemoveDirectoryA("neosodon");
6116c2c66affSColin Finck     RemoveDirectoryA("olorotitan");
6117c2c66affSColin Finck     RemoveDirectoryA("pantydraco");
6118c2c66affSColin Finck     delete_component_path("{E3619EED-305A-418C-B9C7-F7D7377F0934}",
6119c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6120c2c66affSColin Finck     delete_component_path("{D56B688D-542F-42Ef-90FD-B6DA76EE8119}",
6121c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6122c2c66affSColin Finck     delete_component_path("{A19E16C5-C75D-4699-8111-C4338C40C3CB}",
6123c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6124c2c66affSColin Finck     delete_component_path("{17762FA1-A7AE-4CC6-8827-62873C35361D}",
6125c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6126c2c66affSColin Finck     delete_component_path("{8E0DA02E-F6A7-4A8F-B25D-6F564C492308}",
6127c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6128c2c66affSColin Finck     delete_component_path("{243C22B1-8C51-4151-B9D1-1AE5265E079E}",
6129c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6130c2c66affSColin Finck     delete_component_path("{8B1034B7-BD5E-41ac-B52C-0105D3DFD74D}",
6131c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6132c2c66affSColin Finck     delete_component_path("{0B499649-197A-48EF-93D2-AF1C17ED6E90}",
6133c2c66affSColin Finck                           MSIINSTALLCONTEXT_MACHINE, NULL);
6134c2c66affSColin Finck     DeleteFileA(msifile);
6135c2c66affSColin Finck }
6136c2c66affSColin Finck 
6137c2c66affSColin Finck static void set_suminfo_prop(MSIHANDLE db, DWORD prop, DWORD val)
6138c2c66affSColin Finck {
6139c2c66affSColin Finck     MSIHANDLE summary;
6140c2c66affSColin Finck     UINT r;
6141c2c66affSColin Finck 
6142c2c66affSColin Finck     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
6143c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6144c2c66affSColin Finck 
6145c2c66affSColin Finck     r = MsiSummaryInfoSetPropertyA(summary, prop, VT_I4, val, NULL, NULL);
6146c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6147c2c66affSColin Finck 
6148c2c66affSColin Finck     r = MsiSummaryInfoPersist(summary);
6149c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
6150c2c66affSColin Finck 
6151c2c66affSColin Finck     MsiCloseHandle(summary);
6152c2c66affSColin Finck }
6153c2c66affSColin Finck 
6154c2c66affSColin Finck static void test_MsiGetSourcePath(void)
6155c2c66affSColin Finck {
6156c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
6157c2c66affSColin Finck     CHAR path[MAX_PATH];
6158c2c66affSColin Finck     CHAR cwd[MAX_PATH];
6159c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
6160c2c66affSColin Finck     CHAR sub2[MAX_PATH];
6161c2c66affSColin Finck     DWORD size;
6162c2c66affSColin Finck     UINT r;
6163c2c66affSColin Finck 
6164c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
6165c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6166c2c66affSColin Finck 
6167c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
6168c2c66affSColin Finck     lstrcatA(subsrc, "subsource");
6169c2c66affSColin Finck     lstrcatA(subsrc, "\\");
6170c2c66affSColin Finck 
6171c2c66affSColin Finck     lstrcpyA(sub2, subsrc);
6172c2c66affSColin Finck     lstrcatA(sub2, "sub2");
6173c2c66affSColin Finck     lstrcatA(sub2, "\\");
6174c2c66affSColin Finck 
6175c2c66affSColin Finck     /* uncompressed source */
6176c2c66affSColin Finck 
6177c2c66affSColin Finck     hdb = create_package_db();
6178c2c66affSColin Finck     ok( hdb, "failed to create database\n");
6179c2c66affSColin Finck 
6180c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6181c2c66affSColin Finck 
6182f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6183f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'subtarget:subsource'");
6184f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir2', 'SubDir', 'sub2'");
6185c2c66affSColin Finck 
6186c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
6187c2c66affSColin Finck     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
6188c2c66affSColin Finck 
6189c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6190c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6191c2c66affSColin Finck     {
6192c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
6193c2c66affSColin Finck         DeleteFileA(msifile);
6194c2c66affSColin Finck         return;
6195c2c66affSColin Finck     }
6196c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6197c2c66affSColin Finck 
6198c2c66affSColin Finck     MsiCloseHandle(hdb);
6199c2c66affSColin Finck 
6200c2c66affSColin Finck     /* invalid database handle */
6201c2c66affSColin Finck     size = MAX_PATH;
6202c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6203c2c66affSColin Finck     r = MsiGetSourcePathA(-1, "TARGETDIR", path, &size);
6204c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
6205c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
6206c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6207c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6208c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6209c2c66affSColin Finck 
6210c2c66affSColin Finck     /* NULL szFolder */
6211c2c66affSColin Finck     size = MAX_PATH;
6212c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6213c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, NULL, path, &size);
6214c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
6215c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6216c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6217c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6218c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6219c2c66affSColin Finck 
6220c2c66affSColin Finck     /* empty szFolder */
6221c2c66affSColin Finck     size = MAX_PATH;
6222c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6223c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "", path, &size);
6224c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6225c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6226c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6227c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6228c2c66affSColin Finck 
6229c2c66affSColin Finck     /* try TARGETDIR */
6230c2c66affSColin Finck     size = MAX_PATH;
6231c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6232c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6233c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6234c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6235c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6236c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6237c2c66affSColin Finck 
6238c2c66affSColin Finck     size = MAX_PATH;
6239c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6240c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6241c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6242c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6243c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6244c2c66affSColin Finck 
6245c2c66affSColin Finck     size = MAX_PATH;
6246c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6247c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6248c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6249c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6250c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6251c2c66affSColin Finck 
6252c2c66affSColin Finck     /* try SourceDir */
6253c2c66affSColin Finck     size = MAX_PATH;
6254c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6255c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6256c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6257c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6258c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6259c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6260c2c66affSColin Finck 
6261c2c66affSColin Finck     /* try SOURCEDIR */
6262c2c66affSColin Finck     size = MAX_PATH;
6263c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6264c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6265c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6266c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6267c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6268c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6269c2c66affSColin Finck 
6270c2c66affSColin Finck     /* source path does not exist, but the property exists */
6271c2c66affSColin Finck     size = MAX_PATH;
6272c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6273c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6274c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6275c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6276c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6277c2c66affSColin Finck 
6278c2c66affSColin Finck     size = MAX_PATH;
6279c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6280c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6281c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6282c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6283c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6284c2c66affSColin Finck 
6285c2c66affSColin Finck     /* try SubDir */
6286c2c66affSColin Finck     size = MAX_PATH;
6287c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6288c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6289c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6290c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6291c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6292c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6293c2c66affSColin Finck 
6294c2c66affSColin Finck     /* try SubDir2 */
6295c2c66affSColin Finck     size = MAX_PATH;
6296c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6297c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6298c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6299c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6300c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6301c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6302c2c66affSColin Finck 
6303c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6304c2c66affSColin Finck 
6305c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6306c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "cost init failed\n");
6307c2c66affSColin Finck 
6308c2c66affSColin Finck     /* try TARGETDIR after CostInitialize */
6309c2c66affSColin Finck     size = MAX_PATH;
6310c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6311c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6312c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6313c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6314c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6315c2c66affSColin Finck 
6316c2c66affSColin Finck     /* try SourceDir after CostInitialize */
6317c2c66affSColin Finck     size = MAX_PATH;
6318c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6319c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6320c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6321c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6322c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6323c2c66affSColin Finck 
6324c2c66affSColin Finck     /* try SOURCEDIR after CostInitialize */
6325c2c66affSColin Finck     size = MAX_PATH;
6326c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6327c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6328c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6329c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6330c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6331c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6332c2c66affSColin Finck 
6333c2c66affSColin Finck     /* source path does not exist, but the property exists */
6334c2c66affSColin Finck     size = MAX_PATH;
6335c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6336c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6337c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6338c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6339c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6340c2c66affSColin Finck 
6341c2c66affSColin Finck     size = MAX_PATH;
6342c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6343c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6344c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6345c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6346c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6347c2c66affSColin Finck 
6348c2c66affSColin Finck     /* try SubDir after CostInitialize */
6349c2c66affSColin Finck     size = MAX_PATH;
6350c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6351c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6352c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6353c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6354c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6355c2c66affSColin Finck 
6356c2c66affSColin Finck     /* try SubDir2 after CostInitialize */
6357c2c66affSColin Finck     size = MAX_PATH;
6358c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6359c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6360c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6361c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6362c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6363c2c66affSColin Finck 
6364c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
6365c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6366c2c66affSColin Finck 
6367c2c66affSColin Finck     /* try TARGETDIR after ResolveSource */
6368c2c66affSColin Finck     size = MAX_PATH;
6369c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6370c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6371c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6372c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6373c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6374c2c66affSColin Finck 
6375c2c66affSColin Finck     /* try SourceDir after ResolveSource */
6376c2c66affSColin Finck     size = MAX_PATH;
6377c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6378c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6379c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6380c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6381c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6382c2c66affSColin Finck 
6383c2c66affSColin Finck     /* try SOURCEDIR after ResolveSource */
6384c2c66affSColin Finck     size = MAX_PATH;
6385c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6386c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6387c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6388c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6389c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6390c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6391c2c66affSColin Finck 
6392c2c66affSColin Finck     /* source path does not exist, but the property exists */
6393c2c66affSColin Finck     size = MAX_PATH;
6394c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6395c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6396c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6397c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6398c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6399c2c66affSColin Finck 
6400c2c66affSColin Finck     size = MAX_PATH;
6401c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6402c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6403c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6404c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6405c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6406c2c66affSColin Finck 
6407c2c66affSColin Finck     /* try SubDir after ResolveSource */
6408c2c66affSColin Finck     size = MAX_PATH;
6409c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6410c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6411c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6412c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6413c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6414c2c66affSColin Finck 
6415c2c66affSColin Finck     /* try SubDir2 after ResolveSource */
6416c2c66affSColin Finck     size = MAX_PATH;
6417c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6418c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6419c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6420c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6421c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6422c2c66affSColin Finck 
6423c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
6424c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6425c2c66affSColin Finck 
6426c2c66affSColin Finck     /* try TARGETDIR after FileCost */
6427c2c66affSColin Finck     size = MAX_PATH;
6428c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6429c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6430c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6431c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6432c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6433c2c66affSColin Finck 
6434c2c66affSColin Finck     /* try SourceDir after FileCost */
6435c2c66affSColin Finck     size = MAX_PATH;
6436c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6437c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6438c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6439c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6440c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6441c2c66affSColin Finck 
6442c2c66affSColin Finck     /* try SOURCEDIR after FileCost */
6443c2c66affSColin Finck     size = MAX_PATH;
6444c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6445c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6446c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6447c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6448c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6449c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6450c2c66affSColin Finck 
6451c2c66affSColin Finck     /* source path does not exist, but the property exists */
6452c2c66affSColin Finck     size = MAX_PATH;
6453c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6454c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6455c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6456c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6457c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6458c2c66affSColin Finck 
6459c2c66affSColin Finck     size = MAX_PATH;
6460c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6461c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6462c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6463c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6464c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6465c2c66affSColin Finck 
6466c2c66affSColin Finck     /* try SubDir after FileCost */
6467c2c66affSColin Finck     size = MAX_PATH;
6468c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6469c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6470c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6471c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6472c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6473c2c66affSColin Finck 
6474c2c66affSColin Finck     /* try SubDir2 after FileCost */
6475c2c66affSColin Finck     size = MAX_PATH;
6476c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6477c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6478c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6479c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6480c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6481c2c66affSColin Finck 
6482c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
6483c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6484c2c66affSColin Finck 
6485c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6486c2c66affSColin Finck     size = MAX_PATH;
6487c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6488c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6489c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6490c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6491c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6492c2c66affSColin Finck 
6493c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6494c2c66affSColin Finck     size = MAX_PATH;
6495c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6496c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6497c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6498c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6499c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6500c2c66affSColin Finck 
6501c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6502c2c66affSColin Finck     size = MAX_PATH;
6503c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6504c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6505c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6506c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6507c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6508c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6509c2c66affSColin Finck 
6510c2c66affSColin Finck     /* source path does not exist, but the property exists */
6511c2c66affSColin Finck     size = MAX_PATH;
6512c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6513c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6514c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6515c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6516c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6517c2c66affSColin Finck 
6518c2c66affSColin Finck     size = MAX_PATH;
6519c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6520c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6521c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6522c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6523c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6524c2c66affSColin Finck 
6525c2c66affSColin Finck     /* try SubDir after CostFinalize */
6526c2c66affSColin Finck     size = MAX_PATH;
6527c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6528c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6529c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6530c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
6531c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
6532c2c66affSColin Finck 
6533c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6534c2c66affSColin Finck     size = MAX_PATH;
6535c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6536c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6537c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6538c2c66affSColin Finck     ok(!lstrcmpA(path, sub2), "Expected \"%s\", got \"%s\"\n", sub2, path);
6539c2c66affSColin Finck     ok(size == lstrlenA(sub2), "Expected %d, got %d\n", lstrlenA(sub2), size);
6540c2c66affSColin Finck 
6541c2c66affSColin Finck     /* nonexistent directory */
6542c2c66affSColin Finck     size = MAX_PATH;
6543c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6544c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "IDontExist", path, &size);
6545c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6546c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6547c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6548c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6549c2c66affSColin Finck 
6550c2c66affSColin Finck     /* NULL szPathBuf */
6551c2c66affSColin Finck     size = MAX_PATH;
6552c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", NULL, &size);
6553c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6554c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6555c2c66affSColin Finck 
6556c2c66affSColin Finck     /* NULL pcchPathBuf */
6557c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6558c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, NULL);
6559c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
6560c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
6561c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6562c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6563c2c66affSColin Finck 
6564c2c66affSColin Finck     /* pcchPathBuf is 0 */
6565c2c66affSColin Finck     size = 0;
6566c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6567c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6568c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6569c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6570c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6571c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6572c2c66affSColin Finck 
6573c2c66affSColin Finck     /* pcchPathBuf does not have room for NULL terminator */
6574c2c66affSColin Finck     size = lstrlenA(cwd);
6575c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6576c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6577c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
6578c2c66affSColin Finck     ok(!strncmp(path, cwd, lstrlenA(cwd) - 1),
6579c2c66affSColin Finck        "Expected path with no backslash, got \"%s\"\n", path);
6580c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6581c2c66affSColin Finck 
6582c2c66affSColin Finck     /* pcchPathBuf has room for NULL terminator */
6583c2c66affSColin Finck     size = lstrlenA(cwd) + 1;
6584c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6585c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6586c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6587c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6588c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6589c2c66affSColin Finck 
6590c2c66affSColin Finck     /* remove property */
6591c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SourceDir", NULL);
6592c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6593c2c66affSColin Finck 
6594c2c66affSColin Finck     /* try SourceDir again */
6595c2c66affSColin Finck     size = MAX_PATH;
6596c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6597c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6598c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6599c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6600c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6601c2c66affSColin Finck 
6602c2c66affSColin Finck     /* set property to a valid directory */
6603c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "SOURCEDIR", cwd);
6604c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6605c2c66affSColin Finck 
6606c2c66affSColin Finck     /* try SOURCEDIR again */
6607c2c66affSColin Finck     size = MAX_PATH;
6608c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6609c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6610c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6611c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6612c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6613c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6614c2c66affSColin Finck 
6615c2c66affSColin Finck     MsiCloseHandle(hpkg);
6616c2c66affSColin Finck 
6617c2c66affSColin Finck     /* compressed source */
6618c2c66affSColin Finck 
6619c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
6620c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6621c2c66affSColin Finck 
6622c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeCompressed);
6623c2c66affSColin Finck 
6624c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6625c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6626c2c66affSColin Finck 
6627c2c66affSColin Finck     /* try TARGETDIR */
6628c2c66affSColin Finck     size = MAX_PATH;
6629c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6630c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6631c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6632c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6633c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6634c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6635c2c66affSColin Finck 
6636c2c66affSColin Finck     /* try SourceDir */
6637c2c66affSColin Finck     size = MAX_PATH;
6638c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6639c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6640c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6641c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6642c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6643c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6644c2c66affSColin Finck 
6645c2c66affSColin Finck     /* try SOURCEDIR */
6646c2c66affSColin Finck     size = MAX_PATH;
6647c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6648c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6649c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6650c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6651c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6652c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6653c2c66affSColin Finck 
6654c2c66affSColin Finck     /* source path nor the property exist */
6655c2c66affSColin Finck     size = MAX_PATH;
6656c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6657c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6658c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6659c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6660c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6661c2c66affSColin Finck 
6662c2c66affSColin Finck     size = MAX_PATH;
6663c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6664c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6665c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6666c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
6667c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
6668c2c66affSColin Finck 
6669c2c66affSColin Finck     /* try SubDir */
6670c2c66affSColin Finck     size = MAX_PATH;
6671c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6672c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6673c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6674c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6675c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6676c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6677c2c66affSColin Finck 
6678c2c66affSColin Finck     /* try SubDir2 */
6679c2c66affSColin Finck     size = MAX_PATH;
6680c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6681c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6682c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
6683c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
6684c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
6685c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
6686c2c66affSColin Finck 
6687c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6688c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6689c2c66affSColin Finck 
6690c2c66affSColin Finck     /* try TARGETDIR after CostInitialize */
6691c2c66affSColin Finck     size = MAX_PATH;
6692c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6693c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6694c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6695c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6696c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6697c2c66affSColin Finck 
6698c2c66affSColin Finck     /* try SourceDir after CostInitialize */
6699c2c66affSColin Finck     size = MAX_PATH;
6700c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6701c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6702c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6703c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6704c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6705c2c66affSColin Finck 
6706c2c66affSColin Finck     /* try SOURCEDIR after CostInitialize */
6707c2c66affSColin Finck     size = MAX_PATH;
6708c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6709c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6710c2c66affSColin Finck     todo_wine
6711c2c66affSColin Finck     {
6712c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6713c2c66affSColin Finck         ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6714c2c66affSColin Finck         ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6715c2c66affSColin Finck     }
6716c2c66affSColin Finck 
6717c2c66affSColin Finck     /* source path does not exist, but the property exists */
6718c2c66affSColin Finck     size = MAX_PATH;
6719c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6720c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6721c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6722c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6723c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6724c2c66affSColin Finck 
6725c2c66affSColin Finck     size = MAX_PATH;
6726c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6727c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
6728c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6729c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6730c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6731c2c66affSColin Finck 
6732c2c66affSColin Finck     /* try SubDir after CostInitialize */
6733c2c66affSColin Finck     size = MAX_PATH;
6734c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6735c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6736c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6737c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6738c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6739c2c66affSColin Finck 
6740c2c66affSColin Finck     /* try SubDir2 after CostInitialize */
6741c2c66affSColin Finck     size = MAX_PATH;
6742c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6743c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6744c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6745c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6746c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6747c2c66affSColin Finck 
6748c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
6749c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
6750c2c66affSColin Finck 
6751c2c66affSColin Finck     /* try TARGETDIR after ResolveSource */
6752c2c66affSColin Finck     size = MAX_PATH;
6753c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6754c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6755c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6756c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6757c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6758c2c66affSColin Finck 
6759c2c66affSColin Finck     /* try SourceDir after ResolveSource */
6760c2c66affSColin Finck     size = MAX_PATH;
6761c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6762c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6763c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6764c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6765c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6766c2c66affSColin Finck 
6767c2c66affSColin Finck     /* try SOURCEDIR after ResolveSource */
6768c2c66affSColin Finck     size = MAX_PATH;
6769c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6770c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6771c2c66affSColin Finck     todo_wine
6772c2c66affSColin Finck     {
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 
6778c2c66affSColin Finck     /* source path and the property exist */
6779c2c66affSColin Finck     size = MAX_PATH;
6780c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6781c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6782c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6783c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6784c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6785c2c66affSColin Finck 
6786c2c66affSColin Finck     size = MAX_PATH;
6787c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6788c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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     /* try SubDir after ResolveSource */
6794c2c66affSColin Finck     size = MAX_PATH;
6795c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6796c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6797c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6798c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6799c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6800c2c66affSColin Finck 
6801c2c66affSColin Finck     /* try SubDir2 after ResolveSource */
6802c2c66affSColin Finck     size = MAX_PATH;
6803c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6804c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6805c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6806c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6807c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6808c2c66affSColin Finck 
6809c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
6810c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6811c2c66affSColin Finck 
6812c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6813c2c66affSColin Finck     size = MAX_PATH;
6814c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6815c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6816c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6817c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6818c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6819c2c66affSColin Finck 
6820c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6821c2c66affSColin Finck     size = MAX_PATH;
6822c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6823c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6824c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6825c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6826c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6827c2c66affSColin Finck 
6828c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6829c2c66affSColin Finck     size = MAX_PATH;
6830c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6831c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6832c2c66affSColin Finck     todo_wine
6833c2c66affSColin Finck     {
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 
6839c2c66affSColin Finck     /* source path and the property exist */
6840c2c66affSColin Finck     size = MAX_PATH;
6841c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6842c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6843c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6844c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6845c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6846c2c66affSColin Finck 
6847c2c66affSColin Finck     size = MAX_PATH;
6848c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6849c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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     /* try SubDir after CostFinalize */
6855c2c66affSColin Finck     size = MAX_PATH;
6856c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6857c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6858c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6859c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6860c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6861c2c66affSColin Finck 
6862c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6863c2c66affSColin Finck     size = MAX_PATH;
6864c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6865c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6866c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6867c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6868c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6869c2c66affSColin Finck 
6870c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
6871c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6872c2c66affSColin Finck 
6873c2c66affSColin Finck     /* try TARGETDIR after CostFinalize */
6874c2c66affSColin Finck     size = MAX_PATH;
6875c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6876c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "TARGETDIR", path, &size);
6877c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6878c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6879c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6880c2c66affSColin Finck 
6881c2c66affSColin Finck     /* try SourceDir after CostFinalize */
6882c2c66affSColin Finck     size = MAX_PATH;
6883c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6884c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
6885c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6886c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6887c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6888c2c66affSColin Finck 
6889c2c66affSColin Finck     /* try SOURCEDIR after CostFinalize */
6890c2c66affSColin Finck     size = MAX_PATH;
6891c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6892c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
6893c2c66affSColin Finck     todo_wine
6894c2c66affSColin Finck     {
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 
6900c2c66affSColin Finck     /* source path and the property exist */
6901c2c66affSColin Finck     size = MAX_PATH;
6902c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6903c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
6904c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6905c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6906c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6907c2c66affSColin Finck 
6908c2c66affSColin Finck     size = MAX_PATH;
6909c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6910c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", 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     /* try SubDir after CostFinalize */
6916c2c66affSColin Finck     size = MAX_PATH;
6917c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6918c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
6919c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6920c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6921c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6922c2c66affSColin Finck 
6923c2c66affSColin Finck     /* try SubDir2 after CostFinalize */
6924c2c66affSColin Finck     size = MAX_PATH;
6925c2c66affSColin Finck     lstrcpyA(path, "kiwi");
6926c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
6927c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
6928c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
6929c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
6930c2c66affSColin Finck 
6931c2c66affSColin Finck     MsiCloseHandle(hpkg);
6932c2c66affSColin Finck     DeleteFileA(msifile);
6933c2c66affSColin Finck }
6934c2c66affSColin Finck 
6935c2c66affSColin Finck static void test_shortlongsource(void)
6936c2c66affSColin Finck {
6937c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
6938c2c66affSColin Finck     CHAR path[MAX_PATH];
6939c2c66affSColin Finck     CHAR cwd[MAX_PATH];
6940c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
6941c2c66affSColin Finck     DWORD size;
6942c2c66affSColin Finck     UINT r;
6943c2c66affSColin Finck 
6944c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
6945c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
6946c2c66affSColin Finck 
6947c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
6948c2c66affSColin Finck     lstrcatA(subsrc, "long");
6949c2c66affSColin Finck     lstrcatA(subsrc, "\\");
6950c2c66affSColin Finck 
6951c2c66affSColin Finck     /* long file names */
6952c2c66affSColin Finck 
6953c2c66affSColin Finck     hdb = create_package_db();
6954c2c66affSColin Finck     ok( hdb, "failed to create database\n");
6955c2c66affSColin Finck 
6956c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, 0);
6957c2c66affSColin Finck 
6958f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
6959f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir', 'TARGETDIR', 'short|long'");
6960c2c66affSColin Finck 
6961c2c66affSColin Finck     /* CostInitialize:short */
6962f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir2', 'TARGETDIR', 'one|two'");
6963c2c66affSColin Finck 
6964c2c66affSColin Finck     /* CostInitialize:long */
6965f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir3', 'TARGETDIR', 'three|four'");
6966c2c66affSColin Finck 
6967c2c66affSColin Finck     /* FileCost:short */
6968f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir4', 'TARGETDIR', 'five|six'");
6969c2c66affSColin Finck 
6970c2c66affSColin Finck     /* FileCost:long */
6971f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir5', 'TARGETDIR', 'seven|eight'");
6972c2c66affSColin Finck 
6973c2c66affSColin Finck     /* CostFinalize:short */
6974f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir6', 'TARGETDIR', 'nine|ten'");
6975c2c66affSColin Finck 
6976c2c66affSColin Finck     /* CostFinalize:long */
6977f860a780SAmine Khaldi     add_directory_entry(hdb, "'SubDir7', 'TARGETDIR', 'eleven|twelve'");
6978c2c66affSColin Finck 
6979f860a780SAmine Khaldi     r = MsiDatabaseCommit(hdb);
6980f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
6981c2c66affSColin Finck 
6982c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
6983c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
6984c2c66affSColin Finck     {
6985c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
6986c2c66affSColin Finck         DeleteFileA(msifile);
6987c2c66affSColin Finck         return;
6988c2c66affSColin Finck     }
6989c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
6990c2c66affSColin Finck 
6991c2c66affSColin Finck     MsiCloseHandle(hdb);
6992c2c66affSColin Finck 
6993c2c66affSColin Finck     CreateDirectoryA("one", NULL);
6994c2c66affSColin Finck     CreateDirectoryA("four", NULL);
6995c2c66affSColin Finck 
6996c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
6997c2c66affSColin Finck 
6998c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
6999c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7000c2c66affSColin Finck 
7001c2c66affSColin Finck     CreateDirectoryA("five", NULL);
7002c2c66affSColin Finck     CreateDirectoryA("eight", NULL);
7003c2c66affSColin Finck 
7004c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7005c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7006c2c66affSColin Finck 
7007c2c66affSColin Finck     CreateDirectoryA("nine", NULL);
7008c2c66affSColin Finck     CreateDirectoryA("twelve", NULL);
7009c2c66affSColin Finck 
7010c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7011c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7012c2c66affSColin Finck 
7013c2c66affSColin Finck     /* neither short nor long source directories exist */
7014c2c66affSColin Finck     size = MAX_PATH;
7015c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7016c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7017c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7018c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7019c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7020c2c66affSColin Finck 
7021c2c66affSColin Finck     CreateDirectoryA("short", NULL);
7022c2c66affSColin Finck 
7023c2c66affSColin Finck     /* short source directory exists */
7024c2c66affSColin Finck     size = MAX_PATH;
7025c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7026c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7027c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7028c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7029c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7030c2c66affSColin Finck 
7031c2c66affSColin Finck     CreateDirectoryA("long", NULL);
7032c2c66affSColin Finck 
7033c2c66affSColin Finck     /* both short and long source directories exist */
7034c2c66affSColin Finck     size = MAX_PATH;
7035c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7036c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7037c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7038c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7039c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7040c2c66affSColin Finck 
7041c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7042c2c66affSColin Finck     lstrcatA(subsrc, "two");
7043c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7044c2c66affSColin Finck 
7045c2c66affSColin Finck     /* short dir exists before CostInitialize */
7046c2c66affSColin Finck     size = MAX_PATH;
7047c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7048c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7049c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7050c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7051c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7052c2c66affSColin Finck 
7053c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7054c2c66affSColin Finck     lstrcatA(subsrc, "four");
7055c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7056c2c66affSColin Finck 
7057c2c66affSColin Finck     /* long dir exists before CostInitialize */
7058c2c66affSColin Finck     size = MAX_PATH;
7059c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7060c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7061c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7062c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7063c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7064c2c66affSColin Finck 
7065c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7066c2c66affSColin Finck     lstrcatA(subsrc, "six");
7067c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7068c2c66affSColin Finck 
7069c2c66affSColin Finck     /* short dir exists before FileCost */
7070c2c66affSColin Finck     size = MAX_PATH;
7071c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7072c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7073c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7074c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7075c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7076c2c66affSColin Finck 
7077c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7078c2c66affSColin Finck     lstrcatA(subsrc, "eight");
7079c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7080c2c66affSColin Finck 
7081c2c66affSColin Finck     /* long dir exists before FileCost */
7082c2c66affSColin Finck     size = MAX_PATH;
7083c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7084c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7085c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7086c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7087c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7088c2c66affSColin Finck 
7089c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7090c2c66affSColin Finck     lstrcatA(subsrc, "ten");
7091c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7092c2c66affSColin Finck 
7093c2c66affSColin Finck     /* short dir exists before CostFinalize */
7094c2c66affSColin Finck     size = MAX_PATH;
7095c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7096c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7097c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7098c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7099c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7100c2c66affSColin Finck 
7101c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7102c2c66affSColin Finck     lstrcatA(subsrc, "twelve");
7103c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7104c2c66affSColin Finck 
7105c2c66affSColin Finck     /* long dir exists before CostFinalize */
7106c2c66affSColin Finck     size = MAX_PATH;
7107c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7108c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7109c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7110c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7111c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7112c2c66affSColin Finck 
7113c2c66affSColin Finck     MsiCloseHandle(hpkg);
7114c2c66affSColin Finck     RemoveDirectoryA("short");
7115c2c66affSColin Finck     RemoveDirectoryA("long");
7116c2c66affSColin Finck     RemoveDirectoryA("one");
7117c2c66affSColin Finck     RemoveDirectoryA("four");
7118c2c66affSColin Finck     RemoveDirectoryA("five");
7119c2c66affSColin Finck     RemoveDirectoryA("eight");
7120c2c66affSColin Finck     RemoveDirectoryA("nine");
7121c2c66affSColin Finck     RemoveDirectoryA("twelve");
7122c2c66affSColin Finck 
7123c2c66affSColin Finck     /* short file names */
7124c2c66affSColin Finck 
7125c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_DIRECT, &hdb);
7126c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7127c2c66affSColin Finck 
7128c2c66affSColin Finck     set_suminfo_prop(hdb, PID_WORDCOUNT, msidbSumInfoSourceTypeSFN);
7129c2c66affSColin Finck 
7130c2c66affSColin Finck     r = package_from_db(hdb, &hpkg);
7131c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
7132c2c66affSColin Finck 
7133c2c66affSColin Finck     MsiCloseHandle(hdb);
7134c2c66affSColin Finck 
7135c2c66affSColin Finck     CreateDirectoryA("one", NULL);
7136c2c66affSColin Finck     CreateDirectoryA("four", NULL);
7137c2c66affSColin Finck 
7138c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7139c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7140c2c66affSColin Finck 
7141c2c66affSColin Finck     CreateDirectoryA("five", NULL);
7142c2c66affSColin Finck     CreateDirectoryA("eight", NULL);
7143c2c66affSColin Finck 
7144c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7145c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7146c2c66affSColin Finck 
7147c2c66affSColin Finck     CreateDirectoryA("nine", NULL);
7148c2c66affSColin Finck     CreateDirectoryA("twelve", NULL);
7149c2c66affSColin Finck 
7150c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7151c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7152c2c66affSColin Finck 
7153c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7154c2c66affSColin Finck     lstrcatA(subsrc, "short");
7155c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7156c2c66affSColin Finck 
7157c2c66affSColin Finck     /* neither short nor long source directories exist */
7158c2c66affSColin Finck     size = MAX_PATH;
7159c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7160c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7161c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7162c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7163c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7164c2c66affSColin Finck 
7165c2c66affSColin Finck     CreateDirectoryA("short", NULL);
7166c2c66affSColin Finck 
7167c2c66affSColin Finck     /* short source directory exists */
7168c2c66affSColin Finck     size = MAX_PATH;
7169c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7170c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7171c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7172c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7173c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7174c2c66affSColin Finck 
7175c2c66affSColin Finck     CreateDirectoryA("long", NULL);
7176c2c66affSColin Finck 
7177c2c66affSColin Finck     /* both short and long source directories exist */
7178c2c66affSColin Finck     size = MAX_PATH;
7179c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7180c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir", path, &size);
7181c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7182c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7183c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7184c2c66affSColin Finck 
7185c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7186c2c66affSColin Finck     lstrcatA(subsrc, "one");
7187c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7188c2c66affSColin Finck 
7189c2c66affSColin Finck     /* short dir exists before CostInitialize */
7190c2c66affSColin Finck     size = MAX_PATH;
7191c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7192c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir2", path, &size);
7193c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7194c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7195c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7196c2c66affSColin Finck 
7197c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7198c2c66affSColin Finck     lstrcatA(subsrc, "three");
7199c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7200c2c66affSColin Finck 
7201c2c66affSColin Finck     /* long dir exists before CostInitialize */
7202c2c66affSColin Finck     size = MAX_PATH;
7203c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7204c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir3", path, &size);
7205c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7206c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7207c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7208c2c66affSColin Finck 
7209c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7210c2c66affSColin Finck     lstrcatA(subsrc, "five");
7211c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7212c2c66affSColin Finck 
7213c2c66affSColin Finck     /* short dir exists before FileCost */
7214c2c66affSColin Finck     size = MAX_PATH;
7215c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7216c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir4", path, &size);
7217c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7218c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7219c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7220c2c66affSColin Finck 
7221c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7222c2c66affSColin Finck     lstrcatA(subsrc, "seven");
7223c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7224c2c66affSColin Finck 
7225c2c66affSColin Finck     /* long dir exists before FileCost */
7226c2c66affSColin Finck     size = MAX_PATH;
7227c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7228c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir5", path, &size);
7229c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7230c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7231c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7232c2c66affSColin Finck 
7233c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7234c2c66affSColin Finck     lstrcatA(subsrc, "nine");
7235c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7236c2c66affSColin Finck 
7237c2c66affSColin Finck     /* short dir exists before CostFinalize */
7238c2c66affSColin Finck     size = MAX_PATH;
7239c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7240c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir6", path, &size);
7241c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7242c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7243c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7244c2c66affSColin Finck 
7245c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7246c2c66affSColin Finck     lstrcatA(subsrc, "eleven");
7247c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7248c2c66affSColin Finck 
7249c2c66affSColin Finck     /* long dir exists before CostFinalize */
7250c2c66affSColin Finck     size = MAX_PATH;
7251c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7252c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SubDir7", path, &size);
7253c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7254c2c66affSColin Finck     ok(!lstrcmpA(path, subsrc), "Expected \"%s\", got \"%s\"\n", subsrc, path);
7255c2c66affSColin Finck     ok(size == lstrlenA(subsrc), "Expected %d, got %d\n", lstrlenA(subsrc), size);
7256c2c66affSColin Finck 
7257c2c66affSColin Finck     MsiCloseHandle(hpkg);
7258c2c66affSColin Finck     RemoveDirectoryA("short");
7259c2c66affSColin Finck     RemoveDirectoryA("long");
7260c2c66affSColin Finck     RemoveDirectoryA("one");
7261c2c66affSColin Finck     RemoveDirectoryA("four");
7262c2c66affSColin Finck     RemoveDirectoryA("five");
7263c2c66affSColin Finck     RemoveDirectoryA("eight");
7264c2c66affSColin Finck     RemoveDirectoryA("nine");
7265c2c66affSColin Finck     RemoveDirectoryA("twelve");
7266c2c66affSColin Finck     DeleteFileA(msifile);
7267c2c66affSColin Finck }
7268c2c66affSColin Finck 
7269c2c66affSColin Finck static void test_sourcedir(void)
7270c2c66affSColin Finck {
7271c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
7272c2c66affSColin Finck     CHAR package[12];
7273c2c66affSColin Finck     CHAR path[MAX_PATH];
7274c2c66affSColin Finck     CHAR cwd[MAX_PATH];
7275c2c66affSColin Finck     CHAR subsrc[MAX_PATH];
7276c2c66affSColin Finck     DWORD size;
7277c2c66affSColin Finck     UINT r;
7278c2c66affSColin Finck 
7279c2c66affSColin Finck     lstrcpyA(cwd, CURR_DIR);
7280c2c66affSColin Finck     if (!is_root(CURR_DIR)) lstrcatA(cwd, "\\");
7281c2c66affSColin Finck 
7282c2c66affSColin Finck     lstrcpyA(subsrc, cwd);
7283c2c66affSColin Finck     lstrcatA(subsrc, "long");
7284c2c66affSColin Finck     lstrcatA(subsrc, "\\");
7285c2c66affSColin Finck 
7286c2c66affSColin Finck     hdb = create_package_db();
7287c2c66affSColin Finck     ok( hdb, "failed to create database\n");
7288c2c66affSColin Finck 
7289f860a780SAmine Khaldi     add_directory_entry(hdb, "'TARGETDIR', '', 'SourceDir'");
7290c2c66affSColin Finck 
7291c2c66affSColin Finck     sprintf(package, "#%u", hdb);
7292c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
7293c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7294c2c66affSColin Finck     {
7295c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7296c2c66affSColin Finck         goto error;
7297c2c66affSColin Finck     }
7298c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7299c2c66affSColin Finck 
7300c2c66affSColin Finck     /* properties only */
7301c2c66affSColin Finck 
7302c2c66affSColin Finck     /* SourceDir prop */
7303c2c66affSColin Finck     size = MAX_PATH;
7304c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7305c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7306c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7307c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7308c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7309c2c66affSColin Finck 
7310c2c66affSColin Finck     /* SOURCEDIR prop */
7311c2c66affSColin Finck     size = MAX_PATH;
7312c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7313c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7314c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7315c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7316c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7317c2c66affSColin Finck 
7318c2c66affSColin Finck     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
7319c2c66affSColin Finck 
7320c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7321c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7322c2c66affSColin Finck 
7323c2c66affSColin Finck     /* SourceDir after CostInitialize */
7324c2c66affSColin Finck     size = MAX_PATH;
7325c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7326c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7327c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7328c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7329c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7330c2c66affSColin Finck 
7331c2c66affSColin Finck     /* SOURCEDIR after CostInitialize */
7332c2c66affSColin Finck     size = MAX_PATH;
7333c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7334c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7335c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7336c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7337c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7338c2c66affSColin Finck 
7339c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7340c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7341c2c66affSColin Finck 
7342c2c66affSColin Finck     /* SourceDir after FileCost */
7343c2c66affSColin Finck     size = MAX_PATH;
7344c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7345c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7346c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7347c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7348c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7349c2c66affSColin Finck 
7350c2c66affSColin Finck     /* SOURCEDIR after FileCost */
7351c2c66affSColin Finck     size = MAX_PATH;
7352c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7353c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7354c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7355c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7356c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7357c2c66affSColin Finck 
7358c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7359c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7360c2c66affSColin Finck 
7361c2c66affSColin Finck     /* SourceDir after CostFinalize */
7362c2c66affSColin Finck     size = MAX_PATH;
7363c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7364c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7365c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7366c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7367c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7368c2c66affSColin Finck 
7369c2c66affSColin Finck     /* SOURCEDIR after CostFinalize */
7370c2c66affSColin Finck     size = MAX_PATH;
7371c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7372c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7373c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7374c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7375c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7376c2c66affSColin Finck 
7377c2c66affSColin Finck     size = MAX_PATH;
7378c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7379c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7380c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7381c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"), "Expected \"kiwi\", got \"%s\"\n", path);
7382c2c66affSColin Finck     ok(size == MAX_PATH, "Expected %d, got %d\n", MAX_PATH, size);
7383c2c66affSColin Finck 
7384c2c66affSColin Finck     /* SOURCEDIR after calling MsiGetSourcePath */
7385c2c66affSColin Finck     size = MAX_PATH;
7386c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7387c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7388c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7389c2c66affSColin Finck     todo_wine {
7390c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7391c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7392c2c66affSColin Finck     }
7393c2c66affSColin Finck 
7394c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
7395c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7396c2c66affSColin Finck 
7397c2c66affSColin Finck     /* SourceDir after ResolveSource */
7398c2c66affSColin Finck     size = MAX_PATH;
7399c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7400c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7401c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7402c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7403c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7404c2c66affSColin Finck 
7405c2c66affSColin Finck     /* SOURCEDIR after ResolveSource */
7406c2c66affSColin Finck     size = MAX_PATH;
7407c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7408c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7409c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7410c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7411c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7412c2c66affSColin Finck 
7413c2c66affSColin Finck     /* random casing */
7414c2c66affSColin Finck     size = MAX_PATH;
7415c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7416c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SoUrCeDiR", path, &size);
7417c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7418c2c66affSColin Finck     ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7419c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
7420c2c66affSColin Finck 
7421c2c66affSColin Finck     MsiCloseHandle(hpkg);
7422c2c66affSColin Finck 
7423c2c66affSColin Finck     /* reset the package state */
7424c2c66affSColin Finck     sprintf(package, "#%i", hdb);
7425c2c66affSColin Finck     r = MsiOpenPackageA(package, &hpkg);
7426c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7427c2c66affSColin Finck 
7428c2c66affSColin Finck     /* test how MsiGetSourcePath affects the properties */
7429c2c66affSColin Finck 
7430c2c66affSColin Finck     /* SourceDir prop */
7431c2c66affSColin Finck     size = MAX_PATH;
7432c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7433c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7434c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7435c2c66affSColin Finck     todo_wine
7436c2c66affSColin Finck     {
7437c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7438c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7439c2c66affSColin Finck     }
7440c2c66affSColin Finck 
7441c2c66affSColin Finck     size = MAX_PATH;
7442c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7443c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7444c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7445c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7446c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7447c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7448c2c66affSColin Finck 
7449c2c66affSColin Finck     /* SourceDir after MsiGetSourcePath */
7450c2c66affSColin Finck     size = MAX_PATH;
7451c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7452c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7453c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7454c2c66affSColin Finck     todo_wine
7455c2c66affSColin Finck     {
7456c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7457c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7458c2c66affSColin Finck     }
7459c2c66affSColin Finck 
7460c2c66affSColin Finck     /* SOURCEDIR prop */
7461c2c66affSColin Finck     size = MAX_PATH;
7462c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7463c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7464c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7465c2c66affSColin Finck     todo_wine
7466c2c66affSColin Finck     {
7467c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7468c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7469c2c66affSColin Finck     }
7470c2c66affSColin Finck 
7471c2c66affSColin Finck     size = MAX_PATH;
7472c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7473c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7474c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7475c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7476c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7477c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7478c2c66affSColin Finck 
7479c2c66affSColin Finck     /* SOURCEDIR prop after MsiGetSourcePath */
7480c2c66affSColin Finck     size = MAX_PATH;
7481c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7482c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7483c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7484c2c66affSColin Finck     todo_wine
7485c2c66affSColin Finck     {
7486c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7487c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7488c2c66affSColin Finck     }
7489c2c66affSColin Finck 
7490c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostInitialize");
7491c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7492c2c66affSColin Finck 
7493c2c66affSColin Finck     /* SourceDir after CostInitialize */
7494c2c66affSColin Finck     size = MAX_PATH;
7495c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7496c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7497c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7498c2c66affSColin Finck     todo_wine
7499c2c66affSColin Finck     {
7500c2c66affSColin Finck         ok(!lstrcmpA(path, ""), "Expected \"\", got \"%s\"\n", path);
7501c2c66affSColin Finck         ok(size == 0, "Expected 0, got %d\n", size);
7502c2c66affSColin Finck     }
7503c2c66affSColin Finck 
7504c2c66affSColin Finck     size = MAX_PATH;
7505c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7506c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SourceDir", path, &size);
7507c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7508c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7509c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7510c2c66affSColin Finck 
7511c2c66affSColin Finck     /* SourceDir after MsiGetSourcePath */
7512c2c66affSColin Finck     size = MAX_PATH;
7513c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7514c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7515c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7516c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7517c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7518c2c66affSColin Finck 
7519c2c66affSColin Finck     /* SOURCEDIR after CostInitialize */
7520c2c66affSColin Finck     size = MAX_PATH;
7521c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7522c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7523c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7524c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7525c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7526c2c66affSColin Finck 
7527c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7528c2c66affSColin Finck     size = MAX_PATH;
7529c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7530c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7531c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7532c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7533c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7534c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7535c2c66affSColin Finck 
7536c2c66affSColin Finck     r = MsiDoActionA(hpkg, "FileCost");
7537c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7538c2c66affSColin Finck 
7539c2c66affSColin Finck     /* SourceDir after FileCost */
7540c2c66affSColin Finck     size = MAX_PATH;
7541c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7542c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7543c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7544c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7545c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7546c2c66affSColin Finck 
7547c2c66affSColin Finck     /* SOURCEDIR after FileCost */
7548c2c66affSColin Finck     size = MAX_PATH;
7549c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7550c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7551c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7552c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7553c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7554c2c66affSColin Finck 
7555c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7556c2c66affSColin Finck     size = MAX_PATH;
7557c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7558c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7559c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7560c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7561c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7562c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7563c2c66affSColin Finck 
7564c2c66affSColin Finck     r = MsiDoActionA(hpkg, "CostFinalize");
7565c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7566c2c66affSColin Finck 
7567c2c66affSColin Finck     /* SourceDir after CostFinalize */
7568c2c66affSColin Finck     size = MAX_PATH;
7569c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7570c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7571c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7572c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7573c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7574c2c66affSColin Finck 
7575c2c66affSColin Finck     /* SOURCEDIR after CostFinalize */
7576c2c66affSColin Finck     size = MAX_PATH;
7577c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7578c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7579c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7580c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7581c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7582c2c66affSColin Finck 
7583c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7584c2c66affSColin Finck     size = MAX_PATH;
7585c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7586c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7587c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7588c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7589c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7590c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7591c2c66affSColin Finck 
7592c2c66affSColin Finck     r = MsiDoActionA(hpkg, "ResolveSource");
7593c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "file cost failed\n");
7594c2c66affSColin Finck 
7595c2c66affSColin Finck     /* SourceDir after ResolveSource */
7596c2c66affSColin Finck     size = MAX_PATH;
7597c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7598c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SourceDir", path, &size);
7599c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7600c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7601c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7602c2c66affSColin Finck 
7603c2c66affSColin Finck     /* SOURCEDIR after ResolveSource */
7604c2c66affSColin Finck     size = MAX_PATH;
7605c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7606c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "SOURCEDIR", path, &size);
7607c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7608c2c66affSColin Finck     ok(!lstrcmpA(path, cwd), "Expected \"%s\", got \"%s\"\n", cwd, path);
7609c2c66affSColin Finck     ok(size == lstrlenA(cwd), "Expected %d, got %d\n", lstrlenA(cwd), size);
7610c2c66affSColin Finck 
7611c2c66affSColin Finck     /* SOURCEDIR source path still does not exist */
7612c2c66affSColin Finck     size = MAX_PATH;
7613c2c66affSColin Finck     lstrcpyA(path, "kiwi");
7614c2c66affSColin Finck     r = MsiGetSourcePathA(hpkg, "SOURCEDIR", path, &size);
7615c2c66affSColin Finck     ok(r == ERROR_DIRECTORY, "Expected ERROR_DIRECTORY, got %d\n", r);
7616c2c66affSColin Finck     ok(!lstrcmpA(path, "kiwi"),
7617c2c66affSColin Finck        "Expected path to be unchanged, got \"%s\"\n", path);
7618c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
7619c2c66affSColin Finck 
7620c2c66affSColin Finck     MsiCloseHandle(hpkg);
7621c2c66affSColin Finck 
7622c2c66affSColin Finck error:
7623c2c66affSColin Finck     MsiCloseHandle(hdb);
7624c2c66affSColin Finck     DeleteFileA(msifile);
7625c2c66affSColin Finck }
7626c2c66affSColin Finck 
7627c2c66affSColin Finck struct access_res
7628c2c66affSColin Finck {
7629c2c66affSColin Finck     BOOL gothandle;
7630c2c66affSColin Finck     DWORD lasterr;
7631c2c66affSColin Finck     BOOL ignore;
7632c2c66affSColin Finck };
7633c2c66affSColin Finck 
7634c2c66affSColin Finck static const struct access_res create[16] =
7635c2c66affSColin Finck {
7636c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7637c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7638c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7639c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7640c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7641c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7642c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7643c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7644c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7645c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7646c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7647c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7648c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7649c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7650c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7651c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE }
7652c2c66affSColin Finck };
7653c2c66affSColin Finck 
7654c2c66affSColin Finck static const struct access_res create_commit[16] =
7655c2c66affSColin Finck {
7656c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7657c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7658c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7659c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7660c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7661c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7662c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7663c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7664c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7665c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7666c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7667c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE },
7668c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7669c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7670c2c66affSColin Finck     { FALSE, ERROR_SHARING_VIOLATION, FALSE },
7671c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, TRUE }
7672c2c66affSColin Finck };
7673c2c66affSColin Finck 
7674c2c66affSColin Finck static const struct access_res create_close[16] =
7675c2c66affSColin Finck {
7676c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7677c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7678c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7679c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7680c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7681c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7682c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7683c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7684c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7685c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7686c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7687c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7688c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7689c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7690c2c66affSColin Finck     { TRUE, ERROR_SUCCESS, FALSE },
7691c2c66affSColin Finck     { TRUE, ERROR_SUCCESS }
7692c2c66affSColin Finck };
7693c2c66affSColin Finck 
7694c2c66affSColin Finck static void _test_file_access(LPCSTR file, const struct access_res *ares, DWORD line)
7695c2c66affSColin Finck {
7696c2c66affSColin Finck     DWORD access = 0, share = 0;
7697c2c66affSColin Finck     DWORD lasterr;
7698c2c66affSColin Finck     HANDLE hfile;
7699c2c66affSColin Finck     int i, j, idx = 0;
7700c2c66affSColin Finck 
7701c2c66affSColin Finck     for (i = 0; i < 4; i++)
7702c2c66affSColin Finck     {
7703c2c66affSColin Finck         if (i == 0) access = 0;
7704c2c66affSColin Finck         if (i == 1) access = GENERIC_READ;
7705c2c66affSColin Finck         if (i == 2) access = GENERIC_WRITE;
7706c2c66affSColin Finck         if (i == 3) access = GENERIC_READ | GENERIC_WRITE;
7707c2c66affSColin Finck 
7708c2c66affSColin Finck         for (j = 0; j < 4; j++)
7709c2c66affSColin Finck         {
7710c2c66affSColin Finck             if (ares[idx].ignore)
7711c2c66affSColin Finck                 continue;
7712c2c66affSColin Finck 
7713c2c66affSColin Finck             if (j == 0) share = 0;
7714c2c66affSColin Finck             if (j == 1) share = FILE_SHARE_READ;
7715c2c66affSColin Finck             if (j == 2) share = FILE_SHARE_WRITE;
7716c2c66affSColin Finck             if (j == 3) share = FILE_SHARE_READ | FILE_SHARE_WRITE;
7717c2c66affSColin Finck 
7718c2c66affSColin Finck             SetLastError(0xdeadbeef);
7719c2c66affSColin Finck             hfile = CreateFileA(file, access, share, NULL, OPEN_EXISTING,
7720c2c66affSColin Finck                                 FILE_ATTRIBUTE_NORMAL, 0);
7721c2c66affSColin Finck             lasterr = GetLastError();
7722c2c66affSColin Finck 
7723c2c66affSColin Finck             ok((hfile != INVALID_HANDLE_VALUE) == ares[idx].gothandle,
7724c2c66affSColin Finck                "(%d, handle, %d): Expected %d, got %d\n",
7725c2c66affSColin Finck                line, idx, ares[idx].gothandle,
7726c2c66affSColin Finck                (hfile != INVALID_HANDLE_VALUE));
7727c2c66affSColin Finck 
7728c2c66affSColin Finck             ok(lasterr == ares[idx].lasterr, "(%d, lasterr, %d): Expected %d, got %d\n",
7729c2c66affSColin Finck                line, idx, ares[idx].lasterr, lasterr);
7730c2c66affSColin Finck 
7731c2c66affSColin Finck             CloseHandle(hfile);
7732c2c66affSColin Finck             idx++;
7733c2c66affSColin Finck         }
7734c2c66affSColin Finck     }
7735c2c66affSColin Finck }
7736c2c66affSColin Finck 
7737c2c66affSColin Finck #define test_file_access(file, ares) _test_file_access(file, ares, __LINE__)
7738c2c66affSColin Finck 
7739c2c66affSColin Finck static void test_access(void)
7740c2c66affSColin Finck {
7741c2c66affSColin Finck     MSIHANDLE hdb;
7742c2c66affSColin Finck     UINT r;
7743c2c66affSColin Finck 
7744c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7745c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7746c2c66affSColin Finck 
7747c2c66affSColin Finck     test_file_access(msifile, create);
7748c2c66affSColin Finck 
7749c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7750c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7751c2c66affSColin Finck 
7752c2c66affSColin Finck     test_file_access(msifile, create_commit);
7753c2c66affSColin Finck     MsiCloseHandle(hdb);
7754c2c66affSColin Finck 
7755c2c66affSColin Finck     test_file_access(msifile, create_close);
7756c2c66affSColin Finck     DeleteFileA(msifile);
7757c2c66affSColin Finck 
7758c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATEDIRECT, &hdb);
7759c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7760c2c66affSColin Finck 
7761c2c66affSColin Finck     test_file_access(msifile, create);
7762c2c66affSColin Finck 
7763c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7764c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7765c2c66affSColin Finck 
7766c2c66affSColin Finck     test_file_access(msifile, create_commit);
7767c2c66affSColin Finck     MsiCloseHandle(hdb);
7768c2c66affSColin Finck 
7769c2c66affSColin Finck     test_file_access(msifile, create_close);
7770c2c66affSColin Finck     DeleteFileA(msifile);
7771c2c66affSColin Finck }
7772c2c66affSColin Finck 
7773c2c66affSColin Finck static void test_emptypackage(void)
7774c2c66affSColin Finck {
7775c2c66affSColin Finck     MSIHANDLE hpkg = 0, hdb = 0, hsuminfo = 0;
7776c2c66affSColin Finck     MSIHANDLE hview = 0, hrec = 0;
7777c2c66affSColin Finck     MSICONDITION condition;
7778c2c66affSColin Finck     CHAR buffer[MAX_PATH];
7779c2c66affSColin Finck     DWORD size;
7780c2c66affSColin Finck     UINT r;
7781c2c66affSColin Finck 
7782c2c66affSColin Finck     r = MsiOpenPackageA("", &hpkg);
7783c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
7784c2c66affSColin Finck     {
7785c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
7786c2c66affSColin Finck         return;
7787c2c66affSColin Finck     }
7788c2c66affSColin Finck     todo_wine
7789c2c66affSColin Finck     {
7790c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7791c2c66affSColin Finck     }
7792c2c66affSColin Finck 
7793c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
7794c2c66affSColin Finck     todo_wine
7795c2c66affSColin Finck     {
7796c2c66affSColin Finck         ok(hdb != 0, "Expected a valid database handle\n");
7797c2c66affSColin Finck     }
7798c2c66affSColin Finck 
7799c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Tables`", &hview);
7800c2c66affSColin Finck     todo_wine
7801c2c66affSColin Finck     {
7802c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7803c2c66affSColin Finck     }
7804c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7805c2c66affSColin Finck     todo_wine
7806c2c66affSColin Finck     {
7807c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7808c2c66affSColin Finck     }
7809c2c66affSColin Finck 
7810c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7811c2c66affSColin Finck     todo_wine
7812c2c66affSColin Finck     {
7813c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7814c2c66affSColin Finck     }
7815c2c66affSColin Finck 
7816c2c66affSColin Finck     buffer[0] = 0;
7817c2c66affSColin Finck     size = MAX_PATH;
7818c2c66affSColin Finck     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7819c2c66affSColin Finck     todo_wine
7820c2c66affSColin Finck     {
7821c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7822c2c66affSColin Finck         ok(!lstrcmpA(buffer, "_Property"),
7823c2c66affSColin Finck            "Expected \"_Property\", got \"%s\"\n", buffer);
7824c2c66affSColin Finck     }
7825c2c66affSColin Finck 
7826c2c66affSColin Finck     MsiCloseHandle(hrec);
7827c2c66affSColin Finck 
7828c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7829c2c66affSColin Finck     todo_wine
7830c2c66affSColin Finck     {
7831c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7832c2c66affSColin Finck     }
7833c2c66affSColin Finck 
7834c2c66affSColin Finck     size = MAX_PATH;
7835c2c66affSColin Finck     r = MsiRecordGetStringA(hrec, 1, buffer, &size);
7836c2c66affSColin Finck     todo_wine
7837c2c66affSColin Finck     {
7838c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7839c2c66affSColin Finck         ok(!lstrcmpA(buffer, "#_FolderCache"),
7840c2c66affSColin Finck            "Expected \"_Property\", got \"%s\"\n", buffer);
7841c2c66affSColin Finck     }
7842c2c66affSColin Finck 
7843c2c66affSColin Finck     MsiCloseHandle(hrec);
7844c2c66affSColin Finck     MsiViewClose(hview);
7845c2c66affSColin Finck     MsiCloseHandle(hview);
7846c2c66affSColin Finck 
7847c2c66affSColin Finck     condition = MsiDatabaseIsTablePersistentA(hdb, "_Property");
7848c2c66affSColin Finck     todo_wine
7849c2c66affSColin Finck     {
7850c2c66affSColin Finck         ok(condition == MSICONDITION_FALSE,
7851c2c66affSColin Finck            "Expected MSICONDITION_FALSE, got %d\n", condition);
7852c2c66affSColin Finck     }
7853c2c66affSColin Finck 
7854c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
7855c2c66affSColin Finck     todo_wine
7856c2c66affSColin Finck     {
7857c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7858c2c66affSColin Finck     }
7859c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7860c2c66affSColin Finck     todo_wine
7861c2c66affSColin Finck     {
7862c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7863c2c66affSColin Finck     }
7864c2c66affSColin Finck 
7865c2c66affSColin Finck     /* _Property table is not empty */
7866c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7867c2c66affSColin Finck     todo_wine
7868c2c66affSColin Finck     {
7869c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7870c2c66affSColin Finck     }
7871c2c66affSColin Finck 
7872c2c66affSColin Finck     MsiCloseHandle(hrec);
7873c2c66affSColin Finck     MsiViewClose(hview);
7874c2c66affSColin Finck     MsiCloseHandle(hview);
7875c2c66affSColin Finck 
7876c2c66affSColin Finck     condition = MsiDatabaseIsTablePersistentA(hdb, "#_FolderCache");
7877c2c66affSColin Finck     todo_wine
7878c2c66affSColin Finck     {
7879c2c66affSColin Finck         ok(condition == MSICONDITION_FALSE,
7880c2c66affSColin Finck            "Expected MSICONDITION_FALSE, got %d\n", condition);
7881c2c66affSColin Finck     }
7882c2c66affSColin Finck 
7883c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `#_FolderCache`", &hview);
7884c2c66affSColin Finck     todo_wine
7885c2c66affSColin Finck     {
7886c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7887c2c66affSColin Finck     }
7888c2c66affSColin Finck     r = MsiViewExecute(hview, 0);
7889c2c66affSColin Finck     todo_wine
7890c2c66affSColin Finck     {
7891c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7892c2c66affSColin Finck     }
7893c2c66affSColin Finck 
7894c2c66affSColin Finck     /* #_FolderCache is not empty */
7895c2c66affSColin Finck     r = MsiViewFetch(hview, &hrec);
7896c2c66affSColin Finck     todo_wine
7897c2c66affSColin Finck     {
7898c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7899c2c66affSColin Finck     }
7900c2c66affSColin Finck 
7901c2c66affSColin Finck     MsiCloseHandle(hrec);
7902c2c66affSColin Finck     MsiViewClose(hview);
7903c2c66affSColin Finck     MsiCloseHandle(hview);
7904c2c66affSColin Finck 
7905c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Streams`", &hview);
7906c2c66affSColin Finck     todo_wine
7907c2c66affSColin Finck     {
7908c2c66affSColin Finck         ok(r == ERROR_BAD_QUERY_SYNTAX,
7909c2c66affSColin Finck            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7910c2c66affSColin Finck     }
7911c2c66affSColin Finck 
7912c2c66affSColin Finck     r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Storages`", &hview);
7913c2c66affSColin Finck     todo_wine
7914c2c66affSColin Finck     {
7915c2c66affSColin Finck         ok(r == ERROR_BAD_QUERY_SYNTAX,
7916c2c66affSColin Finck            "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
7917c2c66affSColin Finck     }
7918c2c66affSColin Finck 
7919c2c66affSColin Finck     r = MsiGetSummaryInformationA(hdb, NULL, 0, &hsuminfo);
7920c2c66affSColin Finck     todo_wine
7921c2c66affSColin Finck     {
7922c2c66affSColin Finck         ok(r == ERROR_INSTALL_PACKAGE_INVALID,
7923c2c66affSColin Finck            "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
7924c2c66affSColin Finck     }
7925c2c66affSColin Finck 
7926c2c66affSColin Finck     MsiCloseHandle(hsuminfo);
7927c2c66affSColin Finck 
7928c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7929c2c66affSColin Finck     todo_wine
7930c2c66affSColin Finck     {
7931c2c66affSColin Finck         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7932c2c66affSColin Finck     }
7933c2c66affSColin Finck 
7934c2c66affSColin Finck     MsiCloseHandle(hdb);
7935c2c66affSColin Finck     MsiCloseHandle(hpkg);
7936c2c66affSColin Finck }
7937c2c66affSColin Finck 
7938c2c66affSColin Finck static void test_MsiGetProductProperty(void)
7939c2c66affSColin Finck {
7940c2c66affSColin Finck     static const WCHAR prodcode_propW[] = {'P','r','o','d','u','c','t','C','o','d','e',0};
7941c2c66affSColin Finck     static const WCHAR nonexistentW[] = {'I','D','o','n','t','E','x','i','s','t',0};
7942c2c66affSColin Finck     static const WCHAR newpropW[] = {'N','e','w','P','r','o','p','e','r','t','y',0};
7943c2c66affSColin Finck     static const WCHAR appleW[] = {'a','p','p','l','e',0};
7944c2c66affSColin Finck     static const WCHAR emptyW[] = {0};
7945c2c66affSColin Finck     WCHAR valW[MAX_PATH];
7946c2c66affSColin Finck     MSIHANDLE hprod, hdb;
7947c2c66affSColin Finck     CHAR val[MAX_PATH];
7948c2c66affSColin Finck     CHAR path[MAX_PATH];
7949c2c66affSColin Finck     CHAR query[MAX_PATH];
7950c2c66affSColin Finck     CHAR keypath[MAX_PATH*2];
7951c2c66affSColin Finck     CHAR prodcode[MAX_PATH];
7952c2c66affSColin Finck     WCHAR prodcodeW[MAX_PATH];
7953c2c66affSColin Finck     CHAR prod_squashed[MAX_PATH];
7954c2c66affSColin Finck     WCHAR prod_squashedW[MAX_PATH];
7955c2c66affSColin Finck     HKEY prodkey, userkey, props;
7956c2c66affSColin Finck     DWORD size;
7957c2c66affSColin Finck     LONG res;
7958c2c66affSColin Finck     UINT r;
7959c2c66affSColin Finck     REGSAM access = KEY_ALL_ACCESS;
7960c2c66affSColin Finck 
7961c2c66affSColin Finck     GetCurrentDirectoryA(MAX_PATH, path);
7962c2c66affSColin Finck     lstrcatA(path, "\\");
7963c2c66affSColin Finck 
7964c2c66affSColin Finck     create_test_guid(prodcode, prod_squashed);
7965c2c66affSColin Finck     MultiByteToWideChar(CP_ACP, 0, prodcode, -1, prodcodeW, MAX_PATH);
7966c2c66affSColin Finck     squash_guid(prodcodeW, prod_squashedW);
7967c2c66affSColin Finck 
7968c2c66affSColin Finck     if (is_wow64)
7969c2c66affSColin Finck         access |= KEY_WOW64_64KEY;
7970c2c66affSColin Finck 
7971c2c66affSColin Finck     r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
7972c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7973c2c66affSColin Finck 
7974c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7975c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7976c2c66affSColin Finck 
7977c2c66affSColin Finck     r = set_summary_info(hdb);
7978c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7979c2c66affSColin Finck 
7980c2c66affSColin Finck     r = run_query(hdb,
7981c2c66affSColin Finck             "CREATE TABLE `Directory` ( "
7982c2c66affSColin Finck             "`Directory` CHAR(255) NOT NULL, "
7983c2c66affSColin Finck             "`Directory_Parent` CHAR(255), "
7984c2c66affSColin Finck             "`DefaultDir` CHAR(255) NOT NULL "
7985c2c66affSColin Finck             "PRIMARY KEY `Directory`)");
7986c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7987c2c66affSColin Finck 
7988f860a780SAmine Khaldi     create_property_table(hdb);
7989c2c66affSColin Finck 
7990f860a780SAmine Khaldi     sprintf(query, "'ProductCode', '%s'", prodcode);
7991f860a780SAmine Khaldi     r = add_property_entry(hdb, query);
7992c2c66affSColin Finck 
7993c2c66affSColin Finck     r = MsiDatabaseCommit(hdb);
7994c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
7995c2c66affSColin Finck 
7996c2c66affSColin Finck     MsiCloseHandle(hdb);
7997c2c66affSColin Finck 
7998c2c66affSColin Finck     lstrcpyA(keypath, "Software\\Classes\\Installer\\Products\\");
7999c2c66affSColin Finck     lstrcatA(keypath, prod_squashed);
8000c2c66affSColin Finck 
8001c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &prodkey, NULL);
8002c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
8003c2c66affSColin Finck     {
8004c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8005c2c66affSColin Finck         DeleteFileA(msifile);
8006c2c66affSColin Finck         return;
8007c2c66affSColin Finck     }
8008c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8009c2c66affSColin Finck 
8010c2c66affSColin Finck     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\");
8011c2c66affSColin Finck     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
8012c2c66affSColin Finck     lstrcatA(keypath, prod_squashed);
8013c2c66affSColin Finck 
8014c2c66affSColin Finck     res = RegCreateKeyExA(HKEY_LOCAL_MACHINE, keypath, 0, NULL, 0, access, NULL, &userkey, NULL);
8015c2c66affSColin Finck     if (res == ERROR_ACCESS_DENIED)
8016c2c66affSColin Finck     {
8017c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8018c2c66affSColin Finck         RegDeleteKeyA(prodkey, "");
8019c2c66affSColin Finck         RegCloseKey(prodkey);
8020c2c66affSColin Finck         return;
8021c2c66affSColin Finck     }
8022c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8023c2c66affSColin Finck 
8024c2c66affSColin Finck     res = RegCreateKeyExA(userkey, "InstallProperties", 0, NULL, 0, access, NULL, &props, NULL);
8025c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8026c2c66affSColin Finck 
8027c2c66affSColin Finck     lstrcpyA(val, path);
8028c2c66affSColin Finck     lstrcatA(val, "\\");
8029c2c66affSColin Finck     lstrcatA(val, msifile);
8030c2c66affSColin Finck     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
8031c2c66affSColin Finck                          (const BYTE *)val, lstrlenA(val) + 1);
8032c2c66affSColin Finck     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
8033c2c66affSColin Finck 
8034c2c66affSColin Finck     hprod = 0xdeadbeef;
8035c2c66affSColin Finck     r = MsiOpenProductA(prodcode, &hprod);
8036c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8037c2c66affSColin Finck     ok(hprod != 0 && hprod != 0xdeadbeef, "Expected a valid product handle\n");
8038c2c66affSColin Finck 
8039c2c66affSColin Finck     /* hProduct is invalid */
8040c2c66affSColin Finck     size = MAX_PATH;
8041c2c66affSColin Finck     lstrcpyA(val, "apple");
8042c2c66affSColin Finck     r = MsiGetProductPropertyA(0xdeadbeef, "ProductCode", val, &size);
8043c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8044c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8045c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8046c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8047c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8048c2c66affSColin Finck 
8049c2c66affSColin Finck     size = MAX_PATH;
8050c2c66affSColin Finck     lstrcpyW(valW, appleW);
8051c2c66affSColin Finck     r = MsiGetProductPropertyW(0xdeadbeef, prodcode_propW, valW, &size);
8052c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8053c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8054c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8055c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8056c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8057c2c66affSColin Finck 
8058c2c66affSColin Finck     /* szProperty is NULL */
8059c2c66affSColin Finck     size = MAX_PATH;
8060c2c66affSColin Finck     lstrcpyA(val, "apple");
8061c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, NULL, val, &size);
8062c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8063c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8064c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8065c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8066c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8067c2c66affSColin Finck 
8068c2c66affSColin Finck     size = MAX_PATH;
8069c2c66affSColin Finck     lstrcpyW(valW, appleW);
8070c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, NULL, valW, &size);
8071c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8072c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8073c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8074c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8075c2c66affSColin Finck     ok(size == MAX_PATH, "Expected size to be unchanged, got %d\n", size);
8076c2c66affSColin Finck 
8077c2c66affSColin Finck     /* szProperty is empty */
8078c2c66affSColin Finck     size = MAX_PATH;
8079c2c66affSColin Finck     lstrcpyA(val, "apple");
8080c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "", val, &size);
8081c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8082c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8083c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8084c2c66affSColin Finck 
8085c2c66affSColin Finck     size = MAX_PATH;
8086c2c66affSColin Finck     lstrcpyW(valW, appleW);
8087c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, emptyW, valW, &size);
8088c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8089c2c66affSColin Finck     ok(*valW == 0, "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8090c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8091c2c66affSColin Finck 
8092c2c66affSColin Finck     /* get the property */
8093c2c66affSColin Finck     size = MAX_PATH;
8094c2c66affSColin Finck     lstrcpyA(val, "apple");
8095c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8096c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8097c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8098c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8099c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8100c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8101c2c66affSColin Finck 
8102c2c66affSColin Finck     size = MAX_PATH;
8103c2c66affSColin Finck     lstrcpyW(valW, appleW);
8104c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8105c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8106c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8107c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8108c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8109c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8110c2c66affSColin Finck 
8111c2c66affSColin Finck     /* lpValueBuf is NULL */
8112c2c66affSColin Finck     size = MAX_PATH;
8113c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", NULL, &size);
8114c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8115c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8116c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8117c2c66affSColin Finck 
8118c2c66affSColin Finck     size = MAX_PATH;
8119c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, NULL, &size);
8120c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8121c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8122c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8123c2c66affSColin Finck 
8124c2c66affSColin Finck     /* pcchValueBuf is NULL */
8125c2c66affSColin Finck     lstrcpyA(val, "apple");
8126c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, NULL);
8127c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8128c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8129c2c66affSColin Finck     ok(!lstrcmpA(val, "apple"),
8130c2c66affSColin Finck        "Expected val to be unchanged, got \"%s\"\n", val);
8131c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8132c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8133c2c66affSColin Finck 
8134c2c66affSColin Finck     lstrcpyW(valW, appleW);
8135c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, NULL);
8136c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8137c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8138c2c66affSColin Finck     ok(!lstrcmpW(valW, appleW),
8139c2c66affSColin Finck        "Expected val to be unchanged, got %s\n", wine_dbgstr_w(valW));
8140c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8141c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8142c2c66affSColin Finck 
8143c2c66affSColin Finck     /* pcchValueBuf is too small */
8144c2c66affSColin Finck     size = 4;
8145c2c66affSColin Finck     lstrcpyA(val, "apple");
8146c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8147c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8148c2c66affSColin Finck     ok(!strncmp(val, prodcode, 3),
8149c2c66affSColin Finck        "Expected first 3 chars of \"%s\", got \"%s\"\n", prodcode, val);
8150c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8151c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8152c2c66affSColin Finck 
8153c2c66affSColin Finck     size = 4;
8154c2c66affSColin Finck     lstrcpyW(valW, appleW);
8155c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8156c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8157c2c66affSColin Finck     ok(!memcmp(valW, prodcodeW, 3 * sizeof(WCHAR)),
8158c2c66affSColin Finck        "Expected first 3 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8159c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8160c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8161c2c66affSColin Finck 
8162c2c66affSColin Finck     /* pcchValueBuf does not leave room for NULL terminator */
8163c2c66affSColin Finck     size = lstrlenA(prodcode);
8164c2c66affSColin Finck     lstrcpyA(val, "apple");
8165c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8166c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8167c2c66affSColin Finck     ok(!strncmp(val, prodcode, lstrlenA(prodcode) - 1),
8168c2c66affSColin Finck        "Expected first 37 chars of \"%s\", got \"%s\"\n", prodcode, val);
8169c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8170c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8171c2c66affSColin Finck 
8172c2c66affSColin Finck     size = lstrlenW(prodcodeW);
8173c2c66affSColin Finck     lstrcpyW(valW, appleW);
8174c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8175c2c66affSColin Finck     ok(r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %d\n", r);
8176c2c66affSColin Finck     ok(!memcmp(valW, prodcodeW, lstrlenW(prodcodeW) - 1),
8177c2c66affSColin Finck        "Expected first 37 chars of %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8178c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8179c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8180c2c66affSColin Finck 
8181c2c66affSColin Finck     /* pcchValueBuf has enough room for NULL terminator */
8182c2c66affSColin Finck     size = lstrlenA(prodcode) + 1;
8183c2c66affSColin Finck     lstrcpyA(val, "apple");
8184c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8185c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8186c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8187c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8188c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8189c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8190c2c66affSColin Finck 
8191c2c66affSColin Finck     size = lstrlenW(prodcodeW) + 1;
8192c2c66affSColin Finck     lstrcpyW(valW, appleW);
8193c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8194c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8195c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8196c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8197c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8198c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8199c2c66affSColin Finck 
8200c2c66affSColin Finck     /* nonexistent property */
8201c2c66affSColin Finck     size = MAX_PATH;
8202c2c66affSColin Finck     lstrcpyA(val, "apple");
8203c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "IDontExist", val, &size);
8204c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8205c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8206c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8207c2c66affSColin Finck 
8208c2c66affSColin Finck     size = MAX_PATH;
8209c2c66affSColin Finck     lstrcpyW(valW, appleW);
8210c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, nonexistentW, valW, &size);
8211c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8212c2c66affSColin Finck     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8213c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8214c2c66affSColin Finck 
8215c2c66affSColin Finck     r = MsiSetPropertyA(hprod, "NewProperty", "value");
8216c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8217c2c66affSColin Finck 
8218c2c66affSColin Finck     /* non-product property set */
8219c2c66affSColin Finck     size = MAX_PATH;
8220c2c66affSColin Finck     lstrcpyA(val, "apple");
8221c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "NewProperty", val, &size);
8222c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8223c2c66affSColin Finck     ok(!lstrcmpA(val, ""), "Expected \"\", got \"%s\"\n", val);
8224c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8225c2c66affSColin Finck 
8226c2c66affSColin Finck     size = MAX_PATH;
8227c2c66affSColin Finck     lstrcpyW(valW, appleW);
8228c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, newpropW, valW, &size);
8229c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8230c2c66affSColin Finck     ok(!lstrcmpW(valW, emptyW), "Expected \"\", got %s\n", wine_dbgstr_w(valW));
8231c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8232c2c66affSColin Finck 
8233c2c66affSColin Finck     r = MsiSetPropertyA(hprod, "ProductCode", "value");
8234c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8235c2c66affSColin Finck 
8236c2c66affSColin Finck     /* non-product property that is also a product property set */
8237c2c66affSColin Finck     size = MAX_PATH;
8238c2c66affSColin Finck     lstrcpyA(val, "apple");
8239c2c66affSColin Finck     r = MsiGetProductPropertyA(hprod, "ProductCode", val, &size);
8240c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8241c2c66affSColin Finck     ok(!lstrcmpA(val, prodcode),
8242c2c66affSColin Finck        "Expected \"%s\", got \"%s\"\n", prodcode, val);
8243c2c66affSColin Finck     ok(size == lstrlenA(prodcode),
8244c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenA(prodcode), size);
8245c2c66affSColin Finck 
8246c2c66affSColin Finck     size = MAX_PATH;
8247c2c66affSColin Finck     lstrcpyW(valW, appleW);
8248c2c66affSColin Finck     r = MsiGetProductPropertyW(hprod, prodcode_propW, valW, &size);
8249c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8250c2c66affSColin Finck     ok(!lstrcmpW(valW, prodcodeW),
8251c2c66affSColin Finck        "Expected %s, got %s\n", wine_dbgstr_w(prodcodeW), wine_dbgstr_w(valW));
8252c2c66affSColin Finck     ok(size == lstrlenW(prodcodeW),
8253c2c66affSColin Finck        "Expected %d, got %d\n", lstrlenW(prodcodeW), size);
8254c2c66affSColin Finck 
8255c2c66affSColin Finck     MsiCloseHandle(hprod);
8256c2c66affSColin Finck 
8257c2c66affSColin Finck     RegDeleteValueA(props, "LocalPackage");
8258c2c66affSColin Finck     delete_key(props, "", access);
8259c2c66affSColin Finck     RegCloseKey(props);
8260c2c66affSColin Finck     delete_key(userkey, "", access);
8261c2c66affSColin Finck     RegCloseKey(userkey);
8262c2c66affSColin Finck     delete_key(prodkey, "", access);
8263c2c66affSColin Finck     RegCloseKey(prodkey);
8264c2c66affSColin Finck     DeleteFileA(msifile);
8265c2c66affSColin Finck }
8266c2c66affSColin Finck 
8267c2c66affSColin Finck static void test_MsiSetProperty(void)
8268c2c66affSColin Finck {
8269c2c66affSColin Finck     MSIHANDLE hpkg, hdb, hrec;
8270c2c66affSColin Finck     CHAR buf[MAX_PATH];
8271c2c66affSColin Finck     LPCSTR query;
8272c2c66affSColin Finck     DWORD size;
8273c2c66affSColin Finck     UINT r;
8274c2c66affSColin Finck 
8275c2c66affSColin Finck     r = package_from_db(create_package_db(), &hpkg);
8276c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8277c2c66affSColin Finck     {
8278c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8279c2c66affSColin Finck         DeleteFileA(msifile);
8280c2c66affSColin Finck         return;
8281c2c66affSColin Finck     }
8282c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
8283c2c66affSColin Finck 
8284c2c66affSColin Finck     /* invalid hInstall */
8285c2c66affSColin Finck     r = MsiSetPropertyA(0, "Prop", "Val");
8286c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8287c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8288c2c66affSColin Finck 
8289c2c66affSColin Finck     /* invalid hInstall */
8290c2c66affSColin Finck     r = MsiSetPropertyA(0xdeadbeef, "Prop", "Val");
8291c2c66affSColin Finck     ok(r == ERROR_INVALID_HANDLE,
8292c2c66affSColin Finck        "Expected ERROR_INVALID_HANDLE, got %d\n", r);
8293c2c66affSColin Finck 
8294c2c66affSColin Finck     /* szName is NULL */
8295c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, NULL, "Val");
8296c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8297c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8298c2c66affSColin Finck 
8299c2c66affSColin Finck     /* both szName and szValue are NULL */
8300c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, NULL, NULL);
8301c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER,
8302c2c66affSColin Finck        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
8303c2c66affSColin Finck 
8304c2c66affSColin Finck     /* szName is empty */
8305c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "", "Val");
8306c2c66affSColin Finck     ok(r == ERROR_FUNCTION_FAILED,
8307c2c66affSColin Finck        "Expected ERROR_FUNCTION_FAILED, got %d\n", r);
8308c2c66affSColin Finck 
8309c2c66affSColin Finck     /* szName is empty and szValue is NULL */
8310c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "", NULL);
8311c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8312c2c66affSColin Finck 
8313c2c66affSColin Finck     /* set a property */
8314c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "Val");
8315c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8316c2c66affSColin Finck 
8317c2c66affSColin Finck     /* get the property */
8318c2c66affSColin Finck     size = MAX_PATH;
8319c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8320c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8321c2c66affSColin Finck     ok(!lstrcmpA(buf, "Val"), "Expected \"Val\", got \"%s\"\n", buf);
8322c2c66affSColin Finck     ok(size == 3, "Expected 3, got %d\n", size);
8323c2c66affSColin Finck 
8324c2c66affSColin Finck     /* update the property */
8325c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "Nuvo");
8326c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8327c2c66affSColin Finck 
8328c2c66affSColin Finck     /* get the property */
8329c2c66affSColin Finck     size = MAX_PATH;
8330c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8331c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8332c2c66affSColin Finck     ok(!lstrcmpA(buf, "Nuvo"), "Expected \"Nuvo\", got \"%s\"\n", buf);
8333c2c66affSColin Finck     ok(size == 4, "Expected 4, got %d\n", size);
8334c2c66affSColin Finck 
8335c2c66affSColin Finck     hdb = MsiGetActiveDatabase(hpkg);
8336c2c66affSColin Finck     ok(hdb != 0, "Expected a valid database handle\n");
8337c2c66affSColin Finck 
8338c2c66affSColin Finck     /* set prop is not in the _Property table */
8339c2c66affSColin Finck     query = "SELECT * FROM `_Property` WHERE `Property` = 'Prop'";
8340c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
8341c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX,
8342c2c66affSColin Finck        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8343c2c66affSColin Finck 
8344c2c66affSColin Finck     /* set prop is not in the Property table */
8345c2c66affSColin Finck     query = "SELECT * FROM `Property` WHERE `Property` = 'Prop'";
8346c2c66affSColin Finck     r = do_query(hdb, query, &hrec);
8347c2c66affSColin Finck     ok(r == ERROR_BAD_QUERY_SYNTAX,
8348c2c66affSColin Finck        "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
8349c2c66affSColin Finck 
8350c2c66affSColin Finck     MsiCloseHandle(hdb);
8351c2c66affSColin Finck 
8352c2c66affSColin Finck     /* szValue is an empty string */
8353c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "");
8354c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8355c2c66affSColin Finck 
8356c2c66affSColin Finck     /* try to get the property */
8357c2c66affSColin Finck     size = MAX_PATH;
8358c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8359c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8360c2c66affSColin Finck     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8361c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8362c2c66affSColin Finck 
8363c2c66affSColin Finck     /* reset the property */
8364c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", "BlueTap");
8365c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8366c2c66affSColin Finck 
8367c2c66affSColin Finck     /* delete the property */
8368c2c66affSColin Finck     r = MsiSetPropertyA(hpkg, "Prop", NULL);
8369c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8370c2c66affSColin Finck 
8371c2c66affSColin Finck     /* try to get the property */
8372c2c66affSColin Finck     size = MAX_PATH;
8373c2c66affSColin Finck     r = MsiGetPropertyA(hpkg, "Prop", buf, &size);
8374c2c66affSColin Finck     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
8375c2c66affSColin Finck     ok(!lstrcmpA(buf, ""), "Expected \"\", got \"%s\"\n", buf);
8376c2c66affSColin Finck     ok(size == 0, "Expected 0, got %d\n", size);
8377c2c66affSColin Finck 
8378c2c66affSColin Finck     MsiCloseHandle(hpkg);
8379c2c66affSColin Finck     DeleteFileA(msifile);
8380c2c66affSColin Finck }
8381c2c66affSColin Finck 
8382c2c66affSColin Finck static void test_MsiApplyMultiplePatches(void)
8383c2c66affSColin Finck {
8384c2c66affSColin Finck     UINT r, type = GetDriveTypeW(NULL);
8385c2c66affSColin Finck 
83862f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(NULL, NULL, NULL);
8387c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8388c2c66affSColin Finck 
83892f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("", NULL, NULL);
8390c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8391c2c66affSColin Finck 
83922f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";", NULL, NULL);
8393c2c66affSColin Finck     if (type == DRIVE_FIXED)
8394c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8395c2c66affSColin Finck     else
8396c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8397c2c66affSColin Finck 
83982f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("  ;", NULL, NULL);
8399c2c66affSColin Finck     if (type == DRIVE_FIXED)
8400c2c66affSColin Finck         todo_wine ok(r == ERROR_PATCH_PACKAGE_OPEN_FAILED, "Expected ERROR_PATCH_PACKAGE_OPEN_FAILED, got %u\n", r);
8401c2c66affSColin Finck     else
8402c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8403c2c66affSColin Finck 
84042f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";;", NULL, NULL);
8405c2c66affSColin Finck     if (type == DRIVE_FIXED)
8406c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8407c2c66affSColin Finck     else
8408c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8409c2c66affSColin Finck 
84102f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;", NULL, NULL);
8411c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8412c2c66affSColin Finck 
84132f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA(";nosuchpatchpackage", NULL, NULL);
8414c2c66affSColin Finck     if (type == DRIVE_FIXED)
8415c2c66affSColin Finck         todo_wine ok(r == ERROR_PATH_NOT_FOUND, "Expected ERROR_PATH_NOT_FOUND, got %u\n", r);
8416c2c66affSColin Finck     else
8417c2c66affSColin Finck         ok(r == ERROR_INVALID_NAME, "Expected ERROR_INVALID_NAME, got %u\n", r);
8418c2c66affSColin Finck 
84192f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("nosuchpatchpackage;nosuchpatchpackage", NULL, NULL);
8420c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8421c2c66affSColin Finck 
84222f8e6f71SAmine Khaldi     r = MsiApplyMultiplePatchesA("  nosuchpatchpackage  ;  nosuchpatchpackage  ", NULL, NULL);
8423c2c66affSColin Finck     todo_wine ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
8424c2c66affSColin Finck }
8425c2c66affSColin Finck 
8426c2c66affSColin Finck static void test_MsiApplyPatch(void)
8427c2c66affSColin Finck {
8428c2c66affSColin Finck     UINT r;
8429c2c66affSColin Finck 
8430c2c66affSColin Finck     r = MsiApplyPatchA(NULL, NULL, INSTALLTYPE_DEFAULT, NULL);
8431c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8432c2c66affSColin Finck 
8433c2c66affSColin Finck     r = MsiApplyPatchA("", NULL, INSTALLTYPE_DEFAULT, NULL);
8434c2c66affSColin Finck     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r);
8435c2c66affSColin Finck }
8436c2c66affSColin Finck 
8437818a84ddSwinesync static void test_costs(void)
8438c2c66affSColin Finck {
8439c2c66affSColin Finck     MSIHANDLE hdb, hpkg;
8440c2c66affSColin Finck     char package[12], drive[3];
8441c2c66affSColin Finck     DWORD len;
8442c2c66affSColin Finck     UINT r;
8443c2c66affSColin Finck     int cost, temp;
8444c2c66affSColin Finck 
8445c2c66affSColin Finck     hdb = create_package_db();
8446c2c66affSColin Finck     ok( hdb, "failed to create database\n" );
8447c2c66affSColin Finck 
8448f860a780SAmine Khaldi     create_property_table( hdb );
8449f860a780SAmine Khaldi     add_property_entry( hdb, "'ProductCode', '{379B1C47-40C1-42FA-A9BB-BEBB6F1B0172}'" );
8450f860a780SAmine Khaldi     add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
8451f860a780SAmine Khaldi     add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
8452c2c66affSColin Finck 
8453f860a780SAmine Khaldi     create_media_table( hdb );
8454f860a780SAmine Khaldi     add_media_entry( hdb, "'1', '2', 'cabinet', '', '', ''");
8455c2c66affSColin Finck 
8456f860a780SAmine Khaldi     create_file_table( hdb );
8457f860a780SAmine Khaldi     add_file_entry( hdb, "'one.txt', 'one', 'one.txt', 4096, '', '', 8192, 1" );
8458c2c66affSColin Finck 
8459f860a780SAmine Khaldi     create_component_table( hdb );
8460f860a780SAmine Khaldi     add_component_entry( hdb, "'one', '{B2F86B9D-8447-4BC5-8883-750C45AA31CA}', 'TARGETDIR', 0, '', 'one.txt'" );
8461f860a780SAmine Khaldi     add_component_entry( hdb, "'two', '{62A09F6E-0B74-4829-BDB7-CAB66F42CCE8}', 'TARGETDIR', 0, '', ''" );
8462c2c66affSColin Finck 
8463f860a780SAmine Khaldi     create_feature_table( hdb );
8464f860a780SAmine Khaldi     add_feature_entry( hdb, "'one', '', '', '', 0, 1, '', 0" );
8465f860a780SAmine Khaldi     add_feature_entry( hdb, "'two', '', '', '', 0, 1, '', 0" );
8466c2c66affSColin Finck 
8467f860a780SAmine Khaldi     create_feature_components_table( hdb );
8468f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'one', 'one'" );
8469f860a780SAmine Khaldi     add_feature_components_entry( hdb, "'two', 'two'" );
8470c2c66affSColin Finck 
8471f860a780SAmine Khaldi     create_install_execute_sequence_table( hdb );
8472f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
8473f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
8474f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
8475f860a780SAmine Khaldi     add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1100'" );
8476c2c66affSColin Finck 
8477f860a780SAmine Khaldi     r = MsiDatabaseCommit( hdb );
8478f860a780SAmine Khaldi     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8479c2c66affSColin Finck 
8480c2c66affSColin Finck     sprintf( package, "#%u", hdb );
8481c2c66affSColin Finck     r = MsiOpenPackageA( package, &hpkg );
8482c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8483c2c66affSColin Finck     {
8484c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8485c2c66affSColin Finck         goto error;
8486c2c66affSColin Finck     }
8487c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8488c2c66affSColin Finck 
8489c2c66affSColin Finck     r = MsiEnumComponentCostsA( 0, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8490c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8491c2c66affSColin Finck 
8492c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8493c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8494c2c66affSColin Finck 
8495c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, NULL, 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8496c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8497c2c66affSColin Finck 
8498c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8499c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8500c2c66affSColin Finck 
8501c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, NULL, NULL, NULL, NULL );
8502c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8503c2c66affSColin Finck 
8504c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, NULL, NULL, NULL );
8505c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8506c2c66affSColin Finck 
8507c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, NULL, NULL, NULL );
8508c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8509c2c66affSColin Finck 
8510c2c66affSColin Finck     len = sizeof(drive);
8511c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, NULL, NULL );
8512c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8513c2c66affSColin Finck 
8514c2c66affSColin Finck     len = sizeof(drive);
8515c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, NULL );
8516c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8517c2c66affSColin Finck 
8518c2c66affSColin Finck     len = sizeof(drive);
8519c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8520c2c66affSColin Finck     todo_wine ok( r == ERROR_INVALID_HANDLE_STATE, "Expected ERROR_INVALID_HANDLE_STATE, got %u\n", r );
8521c2c66affSColin Finck 
8522c2c66affSColin Finck     len = sizeof(drive);
8523c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, NULL, &len, &cost, &temp );
8524c2c66affSColin Finck     ok( r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %u\n", r );
8525c2c66affSColin Finck 
8526c2c66affSColin Finck     MsiSetInternalUI( INSTALLUILEVEL_NONE, NULL );
8527c2c66affSColin Finck 
8528c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostInitialize" );
8529c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "CostInitialize failed %u\n", r );
8530c2c66affSColin Finck 
8531c2c66affSColin Finck     r = MsiDoActionA( hpkg, "FileCost" );
8532c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "FileCost failed %u\n", r );
8533c2c66affSColin Finck 
8534c2c66affSColin Finck     len = sizeof(drive);
8535c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8536c2c66affSColin Finck     ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8537c2c66affSColin Finck 
8538c2c66affSColin Finck     r = MsiDoActionA( hpkg, "CostFinalize" );
8539c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "CostFinalize failed %u\n", r );
8540c2c66affSColin Finck 
8541c2c66affSColin Finck     /* contrary to what msdn says InstallValidate must be called too */
8542c2c66affSColin Finck     len = sizeof(drive);
8543c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8544c2c66affSColin Finck     todo_wine ok( r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %u\n", r );
8545c2c66affSColin Finck 
8546c2c66affSColin Finck     r = MsiDoActionA( hpkg, "InstallValidate" );
8547c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "InstallValidate failed %u\n", r );
8548c2c66affSColin Finck 
8549c2c66affSColin Finck     len = 0;
8550c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "three", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8551c2c66affSColin Finck     ok( r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %u\n", r );
8552c2c66affSColin Finck 
8553c2c66affSColin Finck     len = 0;
8554c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8555c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8556c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8557c2c66affSColin Finck 
8558c2c66affSColin Finck     len = 2;
8559c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8560c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8561c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8562c2c66affSColin Finck 
8563c2c66affSColin Finck     len = 2;
8564c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8565c2c66affSColin Finck     ok( r == ERROR_MORE_DATA, "Expected ERROR_MORE_DATA, got %u\n", r );
8566c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8567c2c66affSColin Finck 
8568c2c66affSColin Finck     /* install state doesn't seem to matter */
8569c2c66affSColin Finck     len = sizeof(drive);
8570c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8571c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8572c2c66affSColin Finck 
8573c2c66affSColin Finck     len = sizeof(drive);
8574c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_ABSENT, drive, &len, &cost, &temp );
8575c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8576c2c66affSColin Finck 
8577c2c66affSColin Finck     len = sizeof(drive);
8578c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_SOURCE, drive, &len, &cost, &temp );
8579c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8580c2c66affSColin Finck 
8581c2c66affSColin Finck     len = sizeof(drive);
8582c2c66affSColin Finck     drive[0] = 0;
8583c2c66affSColin Finck     cost = temp = 0xdead;
8584c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8585c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8586c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8587c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8588c2c66affSColin Finck     ok( cost && cost != 0xdead, "expected cost > 0, got %d\n", cost );
8589c2c66affSColin Finck     ok( !temp, "expected temp == 0, got %d\n", temp );
8590c2c66affSColin Finck 
8591c2c66affSColin Finck     len = sizeof(drive);
8592c2c66affSColin Finck     drive[0] = 0;
8593c2c66affSColin Finck     cost = temp = 0xdead;
8594c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "two", 0, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8595c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8596c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8597c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8598c2c66affSColin Finck     ok( !cost, "expected cost == 0, got %d\n", cost );
8599c2c66affSColin Finck     ok( !temp, "expected temp == 0, got %d\n", temp );
8600c2c66affSColin Finck 
8601c2c66affSColin Finck     len = sizeof(drive);
8602c2c66affSColin Finck     drive[0] = 0;
8603c2c66affSColin Finck     cost = temp = 0xdead;
8604c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 0, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8605c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
8606c2c66affSColin Finck     ok( len == 2, "expected len == 2, got %u\n", len );
8607c2c66affSColin Finck     ok( drive[0], "expected a drive\n" );
8608c2c66affSColin Finck     ok( !cost, "expected cost == 0, got %d\n", cost );
8609c2c66affSColin Finck     ok( temp && temp != 0xdead, "expected temp > 0, got %d\n", temp );
8610c2c66affSColin Finck 
8611c2c66affSColin Finck     /* increased index */
8612c2c66affSColin Finck     len = sizeof(drive);
8613c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "one", 1, INSTALLSTATE_LOCAL, drive, &len, &cost, &temp );
8614c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8615c2c66affSColin Finck 
8616c2c66affSColin Finck     len = sizeof(drive);
8617c2c66affSColin Finck     r = MsiEnumComponentCostsA( hpkg, "", 1, INSTALLSTATE_UNKNOWN, drive, &len, &cost, &temp );
8618c2c66affSColin Finck     ok( r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %u\n", r );
8619c2c66affSColin Finck 
8620818a84ddSwinesync     /* test MsiGetFeatureCost */
8621818a84ddSwinesync     cost = 0xdead;
8622818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, NULL, MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8623818a84ddSwinesync     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8624818a84ddSwinesync     ok( cost == 0xdead, "got %d\n", cost );
8625818a84ddSwinesync 
8626818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, NULL );
8627818a84ddSwinesync     ok( r == ERROR_INVALID_PARAMETER, "got %u\n", r);
8628818a84ddSwinesync 
8629818a84ddSwinesync     cost = 0xdead;
8630818a84ddSwinesync     r = MsiGetFeatureCostA( hpkg, "one", MSICOSTTREE_SELFONLY, INSTALLSTATE_LOCAL, &cost );
8631818a84ddSwinesync     ok( !r, "got %u\n", r);
8632818a84ddSwinesync     ok( cost == 8, "got %d\n", cost );
8633818a84ddSwinesync 
8634c2c66affSColin Finck     MsiCloseHandle( hpkg );
8635c2c66affSColin Finck error:
8636c2c66affSColin Finck     MsiCloseHandle( hdb );
8637c2c66affSColin Finck     DeleteFileA( msifile );
8638c2c66affSColin Finck }
8639c2c66affSColin Finck 
8640c2c66affSColin Finck static void test_MsiDatabaseCommit(void)
8641c2c66affSColin Finck {
8642c2c66affSColin Finck     UINT r;
8643c2c66affSColin Finck     MSIHANDLE hdb, hpkg = 0;
8644c2c66affSColin Finck     char buf[32], package[12];
8645c2c66affSColin Finck     DWORD sz;
8646c2c66affSColin Finck 
8647c2c66affSColin Finck     hdb = create_package_db();
8648c2c66affSColin Finck     ok( hdb, "failed to create database\n" );
8649c2c66affSColin Finck 
8650f860a780SAmine Khaldi     create_property_table( hdb );
8651c2c66affSColin Finck 
8652c2c66affSColin Finck     sprintf( package, "#%u", hdb );
8653c2c66affSColin Finck     r = MsiOpenPackageA( package, &hpkg );
8654c2c66affSColin Finck     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
8655c2c66affSColin Finck     {
8656c2c66affSColin Finck         skip("Not enough rights to perform tests\n");
8657c2c66affSColin Finck         goto error;
8658c2c66affSColin Finck     }
8659c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "got %u\n", r );
8660c2c66affSColin Finck 
8661c2c66affSColin Finck     r = MsiSetPropertyA( hpkg, "PROP", "value" );
8662c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "got %u\n", r );
8663c2c66affSColin Finck 
8664c2c66affSColin Finck     buf[0] = 0;
8665c2c66affSColin Finck     sz = sizeof(buf);
8666c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8667c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8668c2c66affSColin Finck     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8669c2c66affSColin Finck 
8670c2c66affSColin Finck     r = MsiDatabaseCommit( hdb );
8671c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiDatabaseCommit returned %u\n", r );
8672c2c66affSColin Finck 
8673c2c66affSColin Finck     buf[0] = 0;
8674c2c66affSColin Finck     sz = sizeof(buf);
8675c2c66affSColin Finck     r = MsiGetPropertyA( hpkg, "PROP", buf, &sz );
8676c2c66affSColin Finck     ok( r == ERROR_SUCCESS, "MsiGetPropertyA returned %u\n", r );
8677c2c66affSColin Finck     ok( !lstrcmpA( buf, "value" ), "got \"%s\"\n", buf );
8678c2c66affSColin Finck 
8679c2c66affSColin Finck     MsiCloseHandle( hpkg );
8680c2c66affSColin Finck error:
8681c2c66affSColin Finck     MsiCloseHandle( hdb );
8682c2c66affSColin Finck     DeleteFileA( msifile );
8683c2c66affSColin Finck }
8684c2c66affSColin Finck 
86852f8e6f71SAmine Khaldi static int externalui_ran;
86862f8e6f71SAmine Khaldi 
86872f8e6f71SAmine Khaldi static INT CALLBACK externalui_callback(void *context, UINT message_type, LPCSTR message)
86882f8e6f71SAmine Khaldi {
86892f8e6f71SAmine Khaldi     externalui_ran = 1;
86902f8e6f71SAmine Khaldi     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
86912f8e6f71SAmine Khaldi     return 0;
86922f8e6f71SAmine Khaldi }
86932f8e6f71SAmine Khaldi 
86942f8e6f71SAmine Khaldi static int externalui_record_ran;
86952f8e6f71SAmine Khaldi 
86962f8e6f71SAmine Khaldi static INT CALLBACK externalui_record_callback(void *context, UINT message_type, MSIHANDLE hrecord)
86972f8e6f71SAmine Khaldi {
86982f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
86992f8e6f71SAmine Khaldi     UINT r;
87002f8e6f71SAmine Khaldi     externalui_record_ran = 1;
87012f8e6f71SAmine Khaldi     ok(message_type == INSTALLMESSAGE_USER, "expected INSTALLMESSAGE_USER, got %08x\n", message_type);
87022f8e6f71SAmine Khaldi     r = MsiRecordGetFieldCount(hrecord);
87032f8e6f71SAmine Khaldi     ok(r == 1, "expected 1, got %u\n", r);
87042f8e6f71SAmine Khaldi     r = MsiRecordGetInteger(hrecord, 1);
87052f8e6f71SAmine Khaldi     ok(r == 12345, "expected 12345, got %u\n", r);
87062f8e6f71SAmine Khaldi     return retval;
87072f8e6f71SAmine Khaldi }
87082f8e6f71SAmine Khaldi 
87092f8e6f71SAmine Khaldi static void test_externalui(void)
87102f8e6f71SAmine Khaldi {
87112f8e6f71SAmine Khaldi     /* test that external UI handlers work correctly */
87122f8e6f71SAmine Khaldi 
87132f8e6f71SAmine Khaldi     INSTALLUI_HANDLERA prev;
87142f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev_record;
87152f8e6f71SAmine Khaldi     MSIHANDLE hpkg, hrecord;
87162f8e6f71SAmine Khaldi     UINT r;
87172f8e6f71SAmine Khaldi     INT retval = 0;
87182f8e6f71SAmine Khaldi 
87192f8e6f71SAmine Khaldi     prev = MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
87202f8e6f71SAmine Khaldi 
87212f8e6f71SAmine Khaldi     r = package_from_db(create_package_db(), &hpkg);
87222f8e6f71SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
87232f8e6f71SAmine Khaldi     {
87242f8e6f71SAmine Khaldi         skip("Not enough rights to perform tests\n");
87252f8e6f71SAmine Khaldi         DeleteFileA(msifile);
87262f8e6f71SAmine Khaldi         return;
87272f8e6f71SAmine Khaldi     }
87282f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected a valid package %u\n", r);
87292f8e6f71SAmine Khaldi 
87302f8e6f71SAmine Khaldi     hrecord = MsiCreateRecord(1);
87312f8e6f71SAmine Khaldi     ok(hrecord, "Expected a valid record\n");
87322f8e6f71SAmine Khaldi     r = MsiRecordSetStringA(hrecord, 0, "test message [1]");
87332f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetString failed %u\n", r);
87342f8e6f71SAmine Khaldi     r = MsiRecordSetInteger(hrecord, 1, 12345);
87352f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetInteger failed %u\n", r);
87362f8e6f71SAmine Khaldi 
87372f8e6f71SAmine Khaldi     externalui_ran = 0;
87382f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87392f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87402f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87412f8e6f71SAmine Khaldi 
87422f8e6f71SAmine Khaldi     prev = MsiSetExternalUIA(prev, 0, NULL);
87432f8e6f71SAmine Khaldi     ok(prev == externalui_callback, "wrong callback function %p\n", prev);
87442f8e6f71SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_USER, &retval, &prev_record);
87452f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
87462f8e6f71SAmine Khaldi 
87472f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87482f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87492f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87502f8e6f71SAmine Khaldi     ok(externalui_ran == 0, "external UI callback should not have run\n");
87512f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87522f8e6f71SAmine Khaldi 
87532f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_callback, INSTALLLOGMODE_USER, NULL);
87542f8e6f71SAmine Khaldi 
87552f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87562f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87572f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87582f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87592f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87602f8e6f71SAmine Khaldi 
87612f8e6f71SAmine Khaldi     retval = 1;
87622f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87632f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87642f8e6f71SAmine Khaldi     ok(r == 1, "expected 1, got %u\n", r);
87652f8e6f71SAmine Khaldi     ok(externalui_ran == 0, "external UI callback should not have run\n");
87662f8e6f71SAmine Khaldi     ok(externalui_record_ran == 1, "external UI record callback did not run\n");
87672f8e6f71SAmine Khaldi 
87682f8e6f71SAmine Khaldi     /* filter and context should be kept separately */
87692f8e6f71SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_record_callback, INSTALLLOGMODE_ERROR, &retval, &prev_record);
87702f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "MsiSetExternalUIRecord failed %u\n", r);
87712f8e6f71SAmine Khaldi 
87722f8e6f71SAmine Khaldi     externalui_ran = externalui_record_ran = 0;
87732f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
87742f8e6f71SAmine Khaldi     ok(r == 0, "expected 0, got %u\n", r);
87752f8e6f71SAmine Khaldi     ok(externalui_ran == 1, "external UI callback did not run\n");
87762f8e6f71SAmine Khaldi     ok(externalui_record_ran == 0, "external UI record callback should not have run\n");
87772f8e6f71SAmine Khaldi 
87782f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
87792f8e6f71SAmine Khaldi     DeleteFileA(msifile);
87802f8e6f71SAmine Khaldi }
87812f8e6f71SAmine Khaldi 
87822f8e6f71SAmine Khaldi struct externalui_message {
87832f8e6f71SAmine Khaldi     UINT message;
87842f8e6f71SAmine Khaldi     int field_count;
87852f8e6f71SAmine Khaldi     char field[4][100];
87862f8e6f71SAmine Khaldi     int match[4]; /* should we test for a match */
87872f8e6f71SAmine Khaldi     int optional;
87882f8e6f71SAmine Khaldi };
87892f8e6f71SAmine Khaldi 
87902f8e6f71SAmine Khaldi static struct externalui_message *sequence;
87912f8e6f71SAmine Khaldi static int sequence_count, sequence_size;
87922f8e6f71SAmine Khaldi 
87932f8e6f71SAmine Khaldi static void add_message(const struct externalui_message *msg)
87942f8e6f71SAmine Khaldi {
87952f8e6f71SAmine Khaldi     if (!sequence)
87962f8e6f71SAmine Khaldi     {
87972f8e6f71SAmine Khaldi         sequence_size = 10;
87982f8e6f71SAmine Khaldi         sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
87992f8e6f71SAmine Khaldi     }
88002f8e6f71SAmine Khaldi     if (sequence_count == sequence_size)
88012f8e6f71SAmine Khaldi     {
88022f8e6f71SAmine Khaldi         sequence_size *= 2;
88032f8e6f71SAmine Khaldi         sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
88042f8e6f71SAmine Khaldi     }
88052f8e6f71SAmine Khaldi 
88062f8e6f71SAmine Khaldi     assert(sequence);
88072f8e6f71SAmine Khaldi 
88082f8e6f71SAmine Khaldi     sequence[sequence_count++] = *msg;
88092f8e6f71SAmine Khaldi }
88102f8e6f71SAmine Khaldi 
88112f8e6f71SAmine Khaldi static void flush_sequence(void)
88122f8e6f71SAmine Khaldi {
88132f8e6f71SAmine Khaldi     HeapFree(GetProcessHeap(), 0, sequence);
88142f8e6f71SAmine Khaldi     sequence = NULL;
88152f8e6f71SAmine Khaldi     sequence_count = sequence_size = 0;
88162f8e6f71SAmine Khaldi }
88172f8e6f71SAmine Khaldi 
88182f8e6f71SAmine Khaldi static void ok_sequence_(const struct externalui_message *expected, const char *context, BOOL todo,
88192f8e6f71SAmine Khaldi                          const char *file, int line)
88202f8e6f71SAmine Khaldi {
88212f8e6f71SAmine Khaldi     static const struct externalui_message end_of_sequence = {0};
88222f8e6f71SAmine Khaldi     const struct externalui_message *actual;
88232f8e6f71SAmine Khaldi     int failcount = 0;
88242f8e6f71SAmine Khaldi     int i;
88252f8e6f71SAmine Khaldi 
88262f8e6f71SAmine Khaldi     add_message(&end_of_sequence);
88272f8e6f71SAmine Khaldi 
88282f8e6f71SAmine Khaldi     actual = sequence;
88292f8e6f71SAmine Khaldi 
88302f8e6f71SAmine Khaldi     while (expected->message && actual->message)
88312f8e6f71SAmine Khaldi     {
88322f8e6f71SAmine Khaldi         if (expected->message == actual->message)
88332f8e6f71SAmine Khaldi         {
8834f860a780SAmine Khaldi             if (expected->field_count < actual->field_count)
88352f8e6f71SAmine Khaldi             {
88362f8e6f71SAmine Khaldi                 todo_wine_if (todo)
88372f8e6f71SAmine Khaldi                     ok_(file, line) (FALSE, "%s: in msg 0x%08x expecting field count %d got %d\n",
88382f8e6f71SAmine Khaldi                                      context, expected->message, expected->field_count, actual->field_count);
88392f8e6f71SAmine Khaldi                 failcount++;
88402f8e6f71SAmine Khaldi             }
88412f8e6f71SAmine Khaldi 
88422f8e6f71SAmine Khaldi             for (i = 0; i <= actual->field_count; i++)
88432f8e6f71SAmine Khaldi             {
88442f8e6f71SAmine Khaldi                 if (expected->match[i] && strcmp(expected->field[i], actual->field[i]))
88452f8e6f71SAmine Khaldi                 {
88462f8e6f71SAmine Khaldi                     todo_wine_if (todo)
88472f8e6f71SAmine Khaldi                         ok_(file, line) (FALSE, "%s: in msg 0x%08x field %d: expected \"%s\", got \"%s\"\n",
88482f8e6f71SAmine Khaldi                                          context, expected->message, i, expected->field[i], actual->field[i]);
88492f8e6f71SAmine Khaldi                     failcount++;
88502f8e6f71SAmine Khaldi                 }
88512f8e6f71SAmine Khaldi             }
88522f8e6f71SAmine Khaldi 
88532f8e6f71SAmine Khaldi             expected++;
88542f8e6f71SAmine Khaldi             actual++;
88552f8e6f71SAmine Khaldi         }
8856f860a780SAmine Khaldi         else if (expected->optional)
8857f860a780SAmine Khaldi         {
8858f860a780SAmine Khaldi             expected++;
8859f860a780SAmine Khaldi         }
88602f8e6f71SAmine Khaldi         else
88612f8e6f71SAmine Khaldi         {
88622f8e6f71SAmine Khaldi             todo_wine_if (todo)
88632f8e6f71SAmine Khaldi                 ok_(file, line) (FALSE, "%s: the msg 0x%08x was expected, but got msg 0x%08x instead\n",
88642f8e6f71SAmine Khaldi                                  context, expected->message, actual->message);
88652f8e6f71SAmine Khaldi             failcount++;
88662f8e6f71SAmine Khaldi             if (todo)
88672f8e6f71SAmine Khaldi                 goto done;
88682f8e6f71SAmine Khaldi             expected++;
88692f8e6f71SAmine Khaldi             actual++;
88702f8e6f71SAmine Khaldi         }
88712f8e6f71SAmine Khaldi     }
88722f8e6f71SAmine Khaldi 
88732f8e6f71SAmine Khaldi     if (expected->message || actual->message)
88742f8e6f71SAmine Khaldi     {
88752f8e6f71SAmine Khaldi         todo_wine_if (todo)
88762f8e6f71SAmine Khaldi             ok_(file, line) (FALSE, "%s: the msg sequence is not complete: expected %08x - actual %08x\n",
88772f8e6f71SAmine Khaldi                              context, expected->message, actual->message);
88782f8e6f71SAmine Khaldi         failcount++;
88792f8e6f71SAmine Khaldi     }
88802f8e6f71SAmine Khaldi 
88812f8e6f71SAmine Khaldi     if(todo && !failcount) /* succeeded yet marked todo */
88822f8e6f71SAmine Khaldi     {
88832f8e6f71SAmine Khaldi         todo_wine
88842f8e6f71SAmine Khaldi             ok_(file, line)(TRUE, "%s: marked \"todo_wine\" but succeeds\n", context);
88852f8e6f71SAmine Khaldi     }
88862f8e6f71SAmine Khaldi 
88872f8e6f71SAmine Khaldi done:
88882f8e6f71SAmine Khaldi     flush_sequence();
88892f8e6f71SAmine Khaldi }
88902f8e6f71SAmine Khaldi 
88912f8e6f71SAmine Khaldi #define ok_sequence(exp, contx, todo) \
88922f8e6f71SAmine Khaldi         ok_sequence_((exp), (contx), (todo), __FILE__, __LINE__)
88932f8e6f71SAmine Khaldi 
8894f860a780SAmine Khaldi /* don't use PROGRESS, which is timing-dependent,
8895f860a780SAmine Khaldi  * or SHOWDIALOG, which due to a bug causes a hang on XP */
8896f860a780SAmine Khaldi static const INSTALLLOGMODE MSITEST_INSTALLLOGMODE =
8897f860a780SAmine Khaldi     INSTALLLOGMODE_FATALEXIT |
8898f860a780SAmine Khaldi     INSTALLLOGMODE_ERROR |
8899f860a780SAmine Khaldi     INSTALLLOGMODE_WARNING |
8900f860a780SAmine Khaldi     INSTALLLOGMODE_USER |
8901f860a780SAmine Khaldi     INSTALLLOGMODE_INFO |
8902f860a780SAmine Khaldi     INSTALLLOGMODE_FILESINUSE |
8903f860a780SAmine Khaldi     INSTALLLOGMODE_RESOLVESOURCE |
8904f860a780SAmine Khaldi     INSTALLLOGMODE_OUTOFDISKSPACE |
8905f860a780SAmine Khaldi     INSTALLLOGMODE_ACTIONSTART |
8906f860a780SAmine Khaldi     INSTALLLOGMODE_ACTIONDATA |
8907f860a780SAmine Khaldi     INSTALLLOGMODE_COMMONDATA |
8908f860a780SAmine Khaldi     INSTALLLOGMODE_INITIALIZE |
8909f860a780SAmine Khaldi     INSTALLLOGMODE_TERMINATE |
8910f860a780SAmine Khaldi     INSTALLLOGMODE_RMFILESINUSE |
8911f860a780SAmine Khaldi     INSTALLLOGMODE_INSTALLSTART |
8912f860a780SAmine Khaldi     INSTALLLOGMODE_INSTALLEND;
8913f860a780SAmine Khaldi 
89142f8e6f71SAmine Khaldi static const struct externalui_message empty_sequence[] = {
89152f8e6f71SAmine Khaldi     {0}
89162f8e6f71SAmine Khaldi };
89172f8e6f71SAmine Khaldi 
89182f8e6f71SAmine Khaldi static const struct externalui_message openpackage_nonexistent_sequence[] = {
89192f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
89202f8e6f71SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
89212f8e6f71SAmine Khaldi     {0}
89222f8e6f71SAmine Khaldi };
89232f8e6f71SAmine Khaldi 
89242f8e6f71SAmine Khaldi static const struct externalui_message openpackage_sequence[] = {
89252f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
89262f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
89272f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
89282f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
89292f8e6f71SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
89302f8e6f71SAmine Khaldi     {0}
89312f8e6f71SAmine Khaldi };
89322f8e6f71SAmine Khaldi 
89332f8e6f71SAmine Khaldi static const struct externalui_message processmessage_info_sequence[] = {
89342f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 3, {"zero", "one", "two", "three"}, {1, 1, 1, 1}},
89352f8e6f71SAmine Khaldi     {0}
89362f8e6f71SAmine Khaldi };
89372f8e6f71SAmine Khaldi 
89382f8e6f71SAmine Khaldi static const struct externalui_message processmessage_actionstart_sequence[] = {
89392f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "name", "description", "template"}, {0, 1, 1, 1}},
89402f8e6f71SAmine Khaldi     {0}
89412f8e6f71SAmine Khaldi };
89422f8e6f71SAmine Khaldi 
89432f8e6f71SAmine Khaldi static const struct externalui_message processmessage_actiondata_sequence[] = {
89442f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONDATA, 3, {"{{name: }}template", "cherry", "banana", "guava"}, {1, 1, 1, 1}},
89452f8e6f71SAmine Khaldi     {0}
89462f8e6f71SAmine Khaldi };
89472f8e6f71SAmine Khaldi 
89482f8e6f71SAmine Khaldi static const struct externalui_message processmessage_error_sequence[] = {
89492f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"", "1311", "banana", "guava"}, {0, 1, 1, 1}},
89502f8e6f71SAmine Khaldi     {0}
89512f8e6f71SAmine Khaldi };
89522f8e6f71SAmine Khaldi 
89532f8e6f71SAmine Khaldi static const struct externalui_message processmessage_internal_error_sequence[] = {
89542f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 3, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "banana", "guava"}, {1, 1, 1, 1}},
89552f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"internal error", "2726", "banana", "guava"}, {1, 1, 1, 1}},
89562f8e6f71SAmine Khaldi     {0}
89572f8e6f71SAmine Khaldi };
89582f8e6f71SAmine Khaldi 
89592f8e6f71SAmine Khaldi static const struct externalui_message processmessage_error_format_sequence[] = {
89602f8e6f71SAmine Khaldi     {INSTALLMESSAGE_USER, 3, {"", "2726", "banana", "guava"}, {0, 1, 1, 1}},
89612f8e6f71SAmine Khaldi     {0}
89622f8e6f71SAmine Khaldi };
89632f8e6f71SAmine Khaldi 
89642f8e6f71SAmine Khaldi static const struct externalui_message doaction_costinitialize_sequence[] = {
89652f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "cost description", "cost template"}, {0, 1, 1, 1}},
89662f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
89672f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
89682f8e6f71SAmine Khaldi     {0}
89692f8e6f71SAmine Khaldi };
89702f8e6f71SAmine Khaldi 
89712f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_sequence[] = {
89722f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "description", "template"}, {0, 1, 1, 1}},
89732f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
89742f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
89752f8e6f71SAmine Khaldi     {0}
89762f8e6f71SAmine Khaldi };
89772f8e6f71SAmine Khaldi 
89782f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_fullui_sequence[] = {
89792f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
89802f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
89812f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
89822f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
89832f8e6f71SAmine Khaldi     {0}
89842f8e6f71SAmine Khaldi };
89852f8e6f71SAmine Khaldi 
89862f8e6f71SAmine Khaldi static const struct externalui_message doaction_custom_cancel_sequence[] = {
89872f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
89882f8e6f71SAmine Khaldi     {0}
89892f8e6f71SAmine Khaldi };
89902f8e6f71SAmine Khaldi 
89912f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_nonexistent_sequence[] = {
89922f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
89932f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
89942f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"custom"}, {1}},
89952f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"DEBUG: Error [1]:  Action not found: [2]", "2726", "custom"}, {1, 1, 1}},
89962f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "2726", "custom"}, {0, 1, 1}},
89972f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "0"}, {0, 1, 1}},
89982f8e6f71SAmine Khaldi     {0}
89992f8e6f71SAmine Khaldi };
90002f8e6f71SAmine Khaldi 
90012f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_sequence[] = {
90022f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90032f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
90042f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90052f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "dialog", "Dialog created"}, {0, 1, 1}},
90062f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "1"}, {0, 1, 1}},
90072f8e6f71SAmine Khaldi     {0}
90082f8e6f71SAmine Khaldi };
90092f8e6f71SAmine Khaldi 
90102f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_error_sequence[] = {
90112f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "error", "", ""}, {0, 1, 1, 1}},
90122f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "error", "1"}, {0, 1, 1}},
90132f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"error"}, {1}},
90142f8e6f71SAmine Khaldi     {0}
90152f8e6f71SAmine Khaldi };
90162f8e6f71SAmine Khaldi 
90172f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_3_sequence[] = {
90182f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90192f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "0"}, {0, 1, 1}},
90202f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90212f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
90222f8e6f71SAmine Khaldi     {0}
90232f8e6f71SAmine Khaldi };
90242f8e6f71SAmine Khaldi 
90252f8e6f71SAmine Khaldi static const struct externalui_message doaction_dialog_12345_sequence[] = {
90262f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "dialog", "", ""}, {0, 1, 1, 1}},
90272f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "3"}, {0, 1, 1}},
90282f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"dialog"}, {1}},
90292f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "dialog", "12345"}, {0, 1, 1}},
90302f8e6f71SAmine Khaldi     {0}
90312f8e6f71SAmine Khaldi };
90322f8e6f71SAmine Khaldi 
90332f8e6f71SAmine Khaldi static const struct externalui_message closehandle_sequence[] = {
90342f8e6f71SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
90352f8e6f71SAmine Khaldi     {0}
90362f8e6f71SAmine Khaldi };
90372f8e6f71SAmine Khaldi 
90382f8e6f71SAmine Khaldi static INT CALLBACK externalui_message_string_callback(void *context, UINT message, LPCSTR string)
90392f8e6f71SAmine Khaldi {
90402f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
90412f8e6f71SAmine Khaldi     struct externalui_message msg;
90422f8e6f71SAmine Khaldi 
90432f8e6f71SAmine Khaldi     msg.message = message;
90442f8e6f71SAmine Khaldi     msg.field_count = 0;
90452f8e6f71SAmine Khaldi     strcpy(msg.field[0], string);
90462f8e6f71SAmine Khaldi     add_message(&msg);
90472f8e6f71SAmine Khaldi 
90482f8e6f71SAmine Khaldi     return retval;
90492f8e6f71SAmine Khaldi }
90502f8e6f71SAmine Khaldi 
90512f8e6f71SAmine Khaldi static INT CALLBACK externalui_message_callback(void *context, UINT message, MSIHANDLE hrecord)
90522f8e6f71SAmine Khaldi {
90532f8e6f71SAmine Khaldi     INT retval = context ? *((INT *)context) : 0;
90542f8e6f71SAmine Khaldi     struct externalui_message msg;
9055f860a780SAmine Khaldi     char buffer[256];
9056f860a780SAmine Khaldi     DWORD length;
9057f860a780SAmine Khaldi     UINT r;
90582f8e6f71SAmine Khaldi     int i;
90592f8e6f71SAmine Khaldi 
90602f8e6f71SAmine Khaldi     msg.message = message;
90612f8e6f71SAmine Khaldi     if (message == INSTALLMESSAGE_TERMINATE)
90622f8e6f71SAmine Khaldi     {
90632f8e6f71SAmine Khaldi         /* trying to access the record seems to hang on some versions of Windows */
90642f8e6f71SAmine Khaldi         msg.field_count = -1;
90652f8e6f71SAmine Khaldi         add_message(&msg);
90662f8e6f71SAmine Khaldi         return 1;
90672f8e6f71SAmine Khaldi     }
90682f8e6f71SAmine Khaldi     msg.field_count = MsiRecordGetFieldCount(hrecord);
90692f8e6f71SAmine Khaldi     for (i = 0; i <= msg.field_count; i++)
90702f8e6f71SAmine Khaldi     {
9071f860a780SAmine Khaldi         length = sizeof(buffer);
9072f860a780SAmine Khaldi         r = MsiRecordGetStringA(hrecord, i, buffer, &length);
9073f860a780SAmine Khaldi         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
90742f8e6f71SAmine Khaldi         memcpy(msg.field[i], buffer, min(100, length+1));
90752f8e6f71SAmine Khaldi     }
90762f8e6f71SAmine Khaldi 
9077f860a780SAmine Khaldi     /* top-level actions dump a list of all set properties; skip them since they're inconsistent */
9078f860a780SAmine Khaldi     if (message == (INSTALLMESSAGE_INFO|MB_ICONHAND) && msg.field_count > 0 && !strncmp(msg.field[0], "Property", 8))
9079f860a780SAmine Khaldi         return retval;
9080f860a780SAmine Khaldi 
90812f8e6f71SAmine Khaldi     add_message(&msg);
90822f8e6f71SAmine Khaldi 
90832f8e6f71SAmine Khaldi     return retval;
90842f8e6f71SAmine Khaldi }
90852f8e6f71SAmine Khaldi 
90862f8e6f71SAmine Khaldi static void test_externalui_message(void)
90872f8e6f71SAmine Khaldi {
90882f8e6f71SAmine Khaldi     /* test that events trigger the correct sequence of messages */
90892f8e6f71SAmine Khaldi 
90902f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
90912f8e6f71SAmine Khaldi     MSIHANDLE hdb, hpkg, hrecord;
90922f8e6f71SAmine Khaldi     INT retval = 1;
90932f8e6f71SAmine Khaldi     UINT r;
90942f8e6f71SAmine Khaldi 
90952f8e6f71SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
90962f8e6f71SAmine Khaldi 
90972f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, &retval);
9098f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, &retval, &prev);
90992f8e6f71SAmine Khaldi 
91002f8e6f71SAmine Khaldi     flush_sequence();
91012f8e6f71SAmine Khaldi 
91022f8e6f71SAmine Khaldi     CoInitialize(NULL);
91032f8e6f71SAmine Khaldi 
91042f8e6f71SAmine Khaldi     hdb = create_package_db();
91052f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
91062f8e6f71SAmine Khaldi 
91072f8e6f71SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
91082f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
91092f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
91102f8e6f71SAmine Khaldi 
91112f8e6f71SAmine Khaldi     r = run_query(hdb, "CREATE TABLE `Error` (`Error` SHORT NOT NULL, `Message` CHAR(0) PRIMARY KEY `Error`)");
91122f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to create Error table: %u\n", r);
91132f8e6f71SAmine Khaldi     r = run_query(hdb, "INSERT INTO `Error` (`Error`, `Message`) VALUES (5, 'internal error')");
91142f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Failed to insert into Error table: %u\n", r);
91152f8e6f71SAmine Khaldi 
9116f860a780SAmine Khaldi     create_actiontext_table(hdb);
9117f860a780SAmine Khaldi     add_actiontext_entry(hdb, "'custom', 'description', 'template'");
9118f860a780SAmine Khaldi     add_actiontext_entry(hdb, "'CostInitialize', 'cost description', 'cost template'");
91192f8e6f71SAmine Khaldi 
91202f8e6f71SAmine Khaldi     r = MsiOpenPackageA(NULL, &hpkg);
91212f8e6f71SAmine Khaldi     ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
91222f8e6f71SAmine Khaldi     ok_sequence(empty_sequence, "MsiOpenPackage with NULL db", FALSE);
91232f8e6f71SAmine Khaldi 
91242f8e6f71SAmine Khaldi     r = MsiOpenPackageA("nonexistent", &hpkg);
91252f8e6f71SAmine Khaldi     ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
91262f8e6f71SAmine Khaldi     ok_sequence(openpackage_nonexistent_sequence, "MsiOpenPackage with nonexistent db", FALSE);
91272f8e6f71SAmine Khaldi 
91282f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
91292f8e6f71SAmine Khaldi     if (r == ERROR_INSTALL_PACKAGE_REJECTED)
91302f8e6f71SAmine Khaldi     {
91312f8e6f71SAmine Khaldi         skip("Not enough rights to perform tests\n");
91322f8e6f71SAmine Khaldi         DeleteFileA(msifile);
91332f8e6f71SAmine Khaldi         return;
91342f8e6f71SAmine Khaldi     }
91352f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
91362f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
91372f8e6f71SAmine Khaldi 
91382f8e6f71SAmine Khaldi     /* Test MsiProcessMessage */
91392f8e6f71SAmine Khaldi     hrecord = MsiCreateRecord(3);
91402f8e6f71SAmine Khaldi     ok(hrecord, "failed to create record\n");
91412f8e6f71SAmine Khaldi 
91422f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "zero");
91432f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "one");
91442f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "two");
91452f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "three");
91462f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_INFO, hrecord);
91472f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91482f8e6f71SAmine Khaldi     ok_sequence(processmessage_info_sequence, "MsiProcessMessage(INSTALLMESSAGE_INFO)", FALSE);
91492f8e6f71SAmine Khaldi 
91502f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "name");
91512f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "description");
91522f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "template");
91532f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONSTART, hrecord);
91542f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91552f8e6f71SAmine Khaldi     ok_sequence(processmessage_actionstart_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONSTART)", FALSE);
91562f8e6f71SAmine Khaldi 
91572f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "apple");
91582f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 1, "cherry");
91592f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 2, "banana");
91602f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 3, "guava");
91612f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_ACTIONDATA, hrecord);
91622f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91632f8e6f71SAmine Khaldi     ok_sequence(processmessage_actiondata_sequence, "MsiProcessMessage(INSTALLMESSAGE_ACTIONDATA)", FALSE);
91642f8e6f71SAmine Khaldi 
91652f8e6f71SAmine Khaldi     /* non-internal error */
91662f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, NULL);
91672f8e6f71SAmine Khaldi     MsiRecordSetInteger(hrecord, 1, 1311);
91682f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
91692f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91702f8e6f71SAmine Khaldi     ok_sequence(processmessage_error_sequence, "MsiProcessMessage non-internal error", FALSE);
91712f8e6f71SAmine Khaldi 
91722f8e6f71SAmine Khaldi     /* internal error */
91732f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, NULL);
91742f8e6f71SAmine Khaldi     MsiRecordSetInteger(hrecord, 1, 2726);
91752f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
91762f8e6f71SAmine Khaldi     ok(r == 0, "Expected 0, got %d\n", r);
91772f8e6f71SAmine Khaldi     ok_sequence(processmessage_internal_error_sequence, "MsiProcessMessage internal error", FALSE);
91782f8e6f71SAmine Khaldi 
91792f8e6f71SAmine Khaldi     /* with format field */
91802f8e6f71SAmine Khaldi     MsiRecordSetStringA(hrecord, 0, "starfruit");
91812f8e6f71SAmine Khaldi     r = MsiProcessMessage(hpkg, INSTALLMESSAGE_USER, hrecord);
91822f8e6f71SAmine Khaldi     ok(r == 1, "Expected 1, got %d\n", r);
91832f8e6f71SAmine Khaldi     ok_sequence(processmessage_error_format_sequence, "MsiProcessMessage error", FALSE);
91842f8e6f71SAmine Khaldi 
91852f8e6f71SAmine Khaldi     /* Test a standard action */
91862f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "CostInitialize");
91872f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
91882f8e6f71SAmine Khaldi     ok_sequence(doaction_costinitialize_sequence, "MsiDoAction(\"CostInitialize\")", FALSE);
91892f8e6f71SAmine Khaldi 
91902f8e6f71SAmine Khaldi     /* Test a custom action */
91912f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
91922f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
91932f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_sequence, "MsiDoAction(\"custom\")", FALSE);
91942f8e6f71SAmine Khaldi 
91952f8e6f71SAmine Khaldi     /* close the package */
91962f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
91972f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
91982f8e6f71SAmine Khaldi 
91992f8e6f71SAmine Khaldi     /* Test dialogs */
92002f8e6f71SAmine Khaldi     hdb = create_package_db();
92012f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
92022f8e6f71SAmine Khaldi 
92032f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
92042f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92052f8e6f71SAmine Khaldi 
9206f860a780SAmine Khaldi     create_dialog_table(hdb);
9207f860a780SAmine Khaldi     add_dialog_entry(hdb, "'dialog', 50, 50, 100, 100, 0, 'dummy'");
92082f8e6f71SAmine Khaldi 
9209f860a780SAmine Khaldi     create_control_table(hdb);
9210f860a780SAmine Khaldi     add_control_entry(hdb, "'dialog', 'dummy', 'Text', 5, 5, 5, 5, 3, 'dummy'");
92112f8e6f71SAmine Khaldi 
92122f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
92132f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
92142f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage with valid db", FALSE);
92152f8e6f71SAmine Khaldi 
92162f8e6f71SAmine Khaldi     /* Test a custom action */
92172f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92182f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92192f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_fullui_sequence, "MsiDoAction(\"custom\")", FALSE);
92202f8e6f71SAmine Khaldi 
92212f8e6f71SAmine Khaldi     retval = 2;
92222f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92232f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %d\n", r);
92242f8e6f71SAmine Khaldi     ok_sequence(doaction_custom_cancel_sequence, "MsiDoAction(\"custom\")", FALSE);
92252f8e6f71SAmine Khaldi 
92262f8e6f71SAmine Khaldi     retval = 0;
92272f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92282f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92292f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
92302f8e6f71SAmine Khaldi 
92312f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92322f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92332f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_sequence, "MsiDoAction(\"dialog\")", FALSE);
92342f8e6f71SAmine Khaldi 
92352f8e6f71SAmine Khaldi     retval = -1;
92362f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "error");
92372f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92382f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
92392f8e6f71SAmine Khaldi 
92402f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "error");
92412f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
92422f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_error_sequence, "MsiDoAction(\"error\")", FALSE);
92432f8e6f71SAmine Khaldi 
92442f8e6f71SAmine Khaldi     retval = -2;
92452f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "custom");
92462f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_NOT_CALLED, "Expected ERROR_FUNCTION_NOT_CALLED, got %d\n", r);
92472f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_nonexistent_sequence, "MsiDoAction(\"custom\")", FALSE);
92482f8e6f71SAmine Khaldi 
92492f8e6f71SAmine Khaldi     retval = 3;
92502f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92512f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
92522f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_3_sequence, "MsiDoAction(\"dialog\")", FALSE);
92532f8e6f71SAmine Khaldi 
92542f8e6f71SAmine Khaldi     retval = 12345;
92552f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "dialog");
92562f8e6f71SAmine Khaldi     ok(r == ERROR_FUNCTION_FAILED, "Expected ERROR_INSTALL_FAILURE, got %d\n", r);
92572f8e6f71SAmine Khaldi     ok_sequence(doaction_dialog_12345_sequence, "MsiDoAction(\"dialog\")", FALSE);
92582f8e6f71SAmine Khaldi 
92592f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
92602f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
92612f8e6f71SAmine Khaldi 
92622f8e6f71SAmine Khaldi     MsiCloseHandle(hrecord);
92632f8e6f71SAmine Khaldi     CoUninitialize();
92642f8e6f71SAmine Khaldi     DeleteFileA(msifile);
92652f8e6f71SAmine Khaldi     DeleteFileA("forcecodepage.idt");
92662f8e6f71SAmine Khaldi }
92672f8e6f71SAmine Khaldi 
92682f8e6f71SAmine Khaldi static const struct externalui_message controlevent_spawn_sequence[] = {
92692f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn", "", ""}, {0, 1, 1, 1}},
92702f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn", ""}, {0, 1, 1}},
92712f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn"}, {1}},
92722f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn", "Dialog created"}, {0, 1, 1}},
92732f8e6f71SAmine Khaldi 
92742f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
92752f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", ""}, {0, 1, 1}},
92762f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
92772f8e6f71SAmine Khaldi 
92782f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child1", "Dialog created"}, {0, 1, 1}},
92792f8e6f71SAmine Khaldi 
92802f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn", "2"}, {0, 1, 1}},
92812f8e6f71SAmine Khaldi     {0}
92822f8e6f71SAmine Khaldi };
92832f8e6f71SAmine Khaldi 
92842f8e6f71SAmine Khaldi static const struct externalui_message controlevent_spawn2_sequence[] = {
92852f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "spawn2", "", ""}, {0, 1, 1, 1}},
92862f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
92872f8e6f71SAmine Khaldi     {INSTALLMESSAGE_SHOWDIALOG, 0, {"spawn2"}, {1}},
92882f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "spawn2", "Dialog created"}, {0, 1, 1}},
92892f8e6f71SAmine Khaldi 
92902f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "custom", "", ""}, {0, 1, 1, 1}},
92912f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "2"}, {0, 1, 1}},
92922f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "custom", "1"}, {0, 1, 1}},
92932f8e6f71SAmine Khaldi 
92942f8e6f71SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 2, {"", "child2", "Dialog created"}, {0, 1, 1}},
92952f8e6f71SAmine Khaldi 
92962f8e6f71SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "spawn2", "2"}, {0, 1, 1}},
92972f8e6f71SAmine Khaldi     {0}
92982f8e6f71SAmine Khaldi };
92992f8e6f71SAmine Khaldi 
93002f8e6f71SAmine Khaldi static void test_controlevent(void)
93012f8e6f71SAmine Khaldi {
93022f8e6f71SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
93032f8e6f71SAmine Khaldi     MSIHANDLE hdb, hpkg;
93042f8e6f71SAmine Khaldi     UINT r;
93052f8e6f71SAmine Khaldi 
93062f8e6f71SAmine Khaldi     if (!winetest_interactive)
93072f8e6f71SAmine Khaldi     {
93082f8e6f71SAmine Khaldi         skip("interactive ControlEvent tests\n");
93092f8e6f71SAmine Khaldi         return;
93102f8e6f71SAmine Khaldi     }
93112f8e6f71SAmine Khaldi 
93122f8e6f71SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
93132f8e6f71SAmine Khaldi 
93142f8e6f71SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9315f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
93162f8e6f71SAmine Khaldi 
93172f8e6f71SAmine Khaldi     flush_sequence();
93182f8e6f71SAmine Khaldi 
93192f8e6f71SAmine Khaldi     CoInitialize(NULL);
93202f8e6f71SAmine Khaldi 
93212f8e6f71SAmine Khaldi     hdb = create_package_db();
93222f8e6f71SAmine Khaldi     ok(hdb, "failed to create database\n");
93232f8e6f71SAmine Khaldi 
93242f8e6f71SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
93252f8e6f71SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
93262f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
93272f8e6f71SAmine Khaldi 
9328f860a780SAmine Khaldi     create_dialog_table(hdb);
9329f860a780SAmine Khaldi     add_dialog_entry(hdb, "'spawn', 50, 50, 100, 100, 3, 'button'");
9330f860a780SAmine Khaldi     add_dialog_entry(hdb, "'spawn2', 50, 50, 100, 100, 3, 'button'");
9331f860a780SAmine Khaldi     add_dialog_entry(hdb, "'child1', 50, 50, 80, 40, 3, 'exit'");
9332f860a780SAmine Khaldi     add_dialog_entry(hdb, "'child2', 50, 50, 80, 40, 3, 'exit'");
93332f8e6f71SAmine Khaldi 
9334f860a780SAmine Khaldi     create_control_table(hdb);
9335f860a780SAmine Khaldi     add_control_entry(hdb, "'spawn', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9336f860a780SAmine Khaldi     add_control_entry(hdb, "'spawn2', 'button', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9337f860a780SAmine Khaldi     add_control_entry(hdb, "'child1', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
9338f860a780SAmine Khaldi     add_control_entry(hdb, "'child2', 'exit', 'PushButton', 10, 10, 66, 17, 3, 'Click me'");
93392f8e6f71SAmine Khaldi 
9340f860a780SAmine Khaldi     create_controlevent_table(hdb);
9341f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'child1', 'exit', 'EndDialog', 'Exit', 1, 1");
9342f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'child2', 'exit', 'EndDialog', 'Exit', 1, 1");
93432f8e6f71SAmine Khaldi 
9344f860a780SAmine Khaldi     create_custom_action_table(hdb);
9345f860a780SAmine Khaldi     add_custom_action_entry(hdb, "'custom', 51, 'dummy', 'dummy value'");
93462f8e6f71SAmine Khaldi 
93472f8e6f71SAmine Khaldi     /* SpawnDialog and EndDialog should trigger after all other events */
9348f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn', 'button', 'SpawnDialog', 'child1', 1, 1");
9349f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn', 'button', 'DoAction', 'custom', 1, 2");
93502f8e6f71SAmine Khaldi 
93512f8e6f71SAmine Khaldi     /* Multiple dialog events cause only the last one to be triggered */
9352f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child1', 1, 1");
9353f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'SpawnDialog', 'child2', 1, 2");
9354f860a780SAmine Khaldi     add_controlevent_entry(hdb, "'spawn2', 'button', 'DoAction', 'custom', 1, 3");
93552f8e6f71SAmine Khaldi 
93562f8e6f71SAmine Khaldi     r = package_from_db(hdb, &hpkg);
93572f8e6f71SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
93582f8e6f71SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
93592f8e6f71SAmine Khaldi 
93602f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "spawn");
93612f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
93622f8e6f71SAmine Khaldi     ok_sequence(controlevent_spawn_sequence, "control event: spawn", FALSE);
93632f8e6f71SAmine Khaldi 
93642f8e6f71SAmine Khaldi     r = MsiDoActionA(hpkg, "spawn2");
93652f8e6f71SAmine Khaldi     ok(r == ERROR_INSTALL_USEREXIT, "expected ERROR_INSTALL_USEREXIT, got %u\n", r);
93662f8e6f71SAmine Khaldi     ok_sequence(controlevent_spawn2_sequence, "control event: spawn2", FALSE);
93672f8e6f71SAmine Khaldi 
93682f8e6f71SAmine Khaldi     MsiCloseHandle(hpkg);
93692f8e6f71SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
93702f8e6f71SAmine Khaldi 
93712f8e6f71SAmine Khaldi     CoUninitialize();
93722f8e6f71SAmine Khaldi     DeleteFileA(msifile);
93732f8e6f71SAmine Khaldi     DeleteFileA("forcecodepage.idt");
93742f8e6f71SAmine Khaldi }
93752f8e6f71SAmine Khaldi 
9376f860a780SAmine Khaldi static const struct externalui_message toplevel_install_sequence[] = {
9377f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9378f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9379f860a780SAmine Khaldi 
9380f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9381f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9382f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9383f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9384f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9385f860a780SAmine Khaldi 
9386f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9387f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9388f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9389f860a780SAmine Khaldi 
9390f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9391f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1, 1}},
9392f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9393f860a780SAmine Khaldi 
9394f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9395f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9396f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9397f860a780SAmine Khaldi 
9398f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9399f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9400f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9401f860a780SAmine Khaldi 
9402f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9403f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9404f860a780SAmine Khaldi 
9405f860a780SAmine Khaldi     /* property dump */
9406f860a780SAmine Khaldi 
9407f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9408f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9409f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9410f860a780SAmine Khaldi     {0}
9411f860a780SAmine Khaldi };
9412f860a780SAmine Khaldi 
9413f860a780SAmine Khaldi static const struct externalui_message toplevel_install_ui_sequence[] = {
9414f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9415f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9416f860a780SAmine Khaldi 
9417f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9418f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9419f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9420f860a780SAmine Khaldi 
9421f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9422f860a780SAmine Khaldi     {0}
9423f860a780SAmine Khaldi };
9424f860a780SAmine Khaldi 
9425f860a780SAmine Khaldi static const struct externalui_message toplevel_executeaction_install_sequence[] = {
9426f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9427f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9428f860a780SAmine Khaldi 
9429f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9430f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9431f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9432f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9433f860a780SAmine Khaldi 
9434f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9435f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9436f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLSTART, 2, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}"}, {1, 1, 1}, 1},
9437f860a780SAmine Khaldi 
9438f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9439f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize"}, {0, 1}},
9440f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9441f860a780SAmine Khaldi 
9442f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "FileCost", "", ""}, {0, 1, 0, 1}},
9443f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9444f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "FileCost", "1"}, {0, 1, 1}},
9445f860a780SAmine Khaldi 
9446f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostFinalize", "", ""}, {0, 1, 0, 1}},
9447f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9448f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostFinalize", "1"}, {0, 1, 1}},
9449f860a780SAmine Khaldi 
9450f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9451f860a780SAmine Khaldi     {INSTALLMESSAGE_INSTALLEND, 3, {"", "", "{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "1"}, {1, 1, 1, 1}, 1},
9452f860a780SAmine Khaldi 
9453f860a780SAmine Khaldi     /* property dump */
9454f860a780SAmine Khaldi 
9455f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9456f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9457f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9458f860a780SAmine Khaldi     {0}
9459f860a780SAmine Khaldi };
9460f860a780SAmine Khaldi 
9461f860a780SAmine Khaldi static const struct externalui_message toplevel_executeaction_costinitialize_sequence[] = {
9462f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "ExecuteAction", "", ""}, {0, 1, 1, 1}},
9463f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9464f860a780SAmine Khaldi 
9465f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9466f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9467f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9468f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9469f860a780SAmine Khaldi 
9470f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CostInitialize", "", ""}, {0, 1, 0, 1}},
9471f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", ""}, {0, 1}},
9472f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CostInitialize", "1"}, {0, 1, 1}},
9473f860a780SAmine Khaldi 
9474f860a780SAmine Khaldi     /* property dump */
9475f860a780SAmine Khaldi 
9476f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "0"}, {0, 1, 1}, 1},
9477f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 2, {"", "2", "1"}, {0, 1, 1}, 1},
9478f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "ExecuteAction", "1"}, {0, 1, 1}},
9479f860a780SAmine Khaldi     {0}
9480f860a780SAmine Khaldi };
9481f860a780SAmine Khaldi 
9482f860a780SAmine Khaldi static const struct externalui_message toplevel_msiinstallproduct_sequence[] = {
9483f860a780SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -1},
9484f860a780SAmine Khaldi 
9485f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9486f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {1, 1, 1, 1}},
9487f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9488f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9489f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9490f860a780SAmine Khaldi 
9491f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "INSTALL", "", ""}, {0, 1, 1, 1}},
9492f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", ""}, {0, 1, 1}},
9493f860a780SAmine Khaldi 
9494f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "AppSearch", "", ""}, {0, 1, 0, 0}},
9495f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", ""}, {0, 1, 1}},
9496f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "AppSearch", "0"}, {0, 1, 1}},
9497f860a780SAmine Khaldi 
9498f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "INSTALL", "1"}, {0, 1, 1}},
9499f860a780SAmine Khaldi 
9500f860a780SAmine Khaldi     /* property dump */
9501f860a780SAmine Khaldi 
9502f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9503f860a780SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
9504f860a780SAmine Khaldi     {0}
9505f860a780SAmine Khaldi };
9506f860a780SAmine Khaldi 
9507f860a780SAmine Khaldi static const struct externalui_message toplevel_msiinstallproduct_custom_sequence[] = {
9508f860a780SAmine Khaldi     {INSTALLMESSAGE_INITIALIZE, -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_INFO|MB_ICONHAND, 0, {""}, {0}},
9513f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "0", "1033", "1252"}, {0, 1, 1, 1}},
9514f860a780SAmine Khaldi     {INSTALLMESSAGE_COMMONDATA, 3, {"", "1", "", ""}, {0, 1, 0, 0}},
9515f860a780SAmine Khaldi 
9516f860a780SAmine Khaldi     {INSTALLMESSAGE_ACTIONSTART, 3, {"", "CUSTOM", "", ""}, {0, 1, 1, 1}},
9517f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", ""}, {0, 1, 1}},
9518f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO, 2, {"", "CUSTOM", "0"}, {0, 1, 1}},
9519f860a780SAmine Khaldi 
9520f860a780SAmine Khaldi     /* property dump */
9521f860a780SAmine Khaldi 
9522f860a780SAmine Khaldi     {INSTALLMESSAGE_INFO|MB_ICONHAND, 0, {""}, {0}},
9523f860a780SAmine Khaldi     {INSTALLMESSAGE_TERMINATE, -1},
9524f860a780SAmine Khaldi     {0}
9525f860a780SAmine Khaldi };
9526f860a780SAmine Khaldi 
9527f860a780SAmine Khaldi /* tests involving top-level actions: INSTALL, ExecuteAction */
9528f860a780SAmine Khaldi static void test_top_level_action(void)
9529f860a780SAmine Khaldi {
9530f860a780SAmine Khaldi     INSTALLUI_HANDLER_RECORD prev;
9531f860a780SAmine Khaldi     MSIHANDLE hdb, hpkg;
9532f860a780SAmine Khaldi     UINT r;
9533f860a780SAmine Khaldi     char msifile_absolute[MAX_PATH];
9534f860a780SAmine Khaldi 
9535f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
9536f860a780SAmine Khaldi 
9537f860a780SAmine Khaldi     MsiSetExternalUIA(externalui_message_string_callback, INSTALLLOGMODE_SHOWDIALOG, NULL);
9538f860a780SAmine Khaldi     r = MsiSetExternalUIRecord(externalui_message_callback, MSITEST_INSTALLLOGMODE, NULL, &prev);
9539f860a780SAmine Khaldi 
9540f860a780SAmine Khaldi     flush_sequence();
9541f860a780SAmine Khaldi 
9542f860a780SAmine Khaldi     CoInitialize(NULL);
9543f860a780SAmine Khaldi 
9544f860a780SAmine Khaldi     hdb = create_package_db();
9545f860a780SAmine Khaldi     ok(hdb, "failed to create database\n");
9546f860a780SAmine Khaldi 
9547f860a780SAmine Khaldi     create_file_data("forcecodepage.idt", "\r\n\r\n1252\t_ForceCodepage\r\n");
9548f860a780SAmine Khaldi     r = MsiDatabaseImportA(hdb, CURR_DIR, "forcecodepage.idt");
9549f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
9550f860a780SAmine Khaldi 
9551f860a780SAmine Khaldi     create_property_table(hdb);
9552f860a780SAmine Khaldi     add_property_entry(hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'");
9553f860a780SAmine Khaldi 
9554f860a780SAmine Khaldi     create_install_execute_sequence_table(hdb);
9555f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'CostInitialize', '', 1");
9556f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'FileCost', '', 2");
9557f860a780SAmine Khaldi     add_install_execute_sequence_entry(hdb, "'CostFinalize', '', 3");
9558f860a780SAmine Khaldi 
9559f860a780SAmine Khaldi     create_install_ui_sequence_table(hdb);
9560f860a780SAmine Khaldi     add_install_ui_sequence_entry(hdb, "'AppSearch', '', 1");
9561f860a780SAmine Khaldi 
9562f860a780SAmine Khaldi     MsiDatabaseCommit(hdb);
9563f860a780SAmine Khaldi 
9564f860a780SAmine Khaldi     /* for some reason we have to open the package from file using an absolute path */
9565f860a780SAmine Khaldi     MsiCloseHandle(hdb);
9566f860a780SAmine Khaldi     GetFullPathNameA(msifile, MAX_PATH, msifile_absolute, NULL);
9567f860a780SAmine Khaldi     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9568f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9569f860a780SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9570f860a780SAmine Khaldi 
9571f860a780SAmine Khaldi     /* test INSTALL */
9572f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "INSTALL");
9573f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9574f860a780SAmine Khaldi     ok_sequence(toplevel_install_sequence, "INSTALL (no UI)", FALSE);
9575f860a780SAmine Khaldi 
9576f860a780SAmine Khaldi     /* test INSTALL with reduced+ UI */
9577f860a780SAmine Khaldi     /* for some reason we need to re-open the package to change the internal UI */
9578f860a780SAmine Khaldi     MsiCloseHandle(hpkg);
9579f860a780SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9580f860a780SAmine Khaldi     MsiSetInternalUI(INSTALLUILEVEL_REDUCED, NULL);
9581f860a780SAmine Khaldi     r = MsiOpenPackageA(msifile_absolute, &hpkg);
9582f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "failed to create package: %u\n", r);
9583f860a780SAmine Khaldi     ok_sequence(openpackage_sequence, "MsiOpenPackage()", FALSE);
9584f860a780SAmine Khaldi 
9585f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "INSTALL");
9586f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9587f860a780SAmine Khaldi     ok_sequence(toplevel_install_ui_sequence, "INSTALL (reduced+ UI)", TRUE);
9588f860a780SAmine Khaldi 
9589f860a780SAmine Khaldi     /* test ExecuteAction with EXECUTEACTION property unset */
9590f860a780SAmine Khaldi     MsiSetPropertyA(hpkg, "EXECUTEACTION", NULL);
9591f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "ExecuteAction");
9592f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9593f860a780SAmine Khaldi     ok_sequence(toplevel_executeaction_install_sequence, "ExecuteAction: INSTALL", FALSE);
9594f860a780SAmine Khaldi 
9595f860a780SAmine Khaldi     /* test ExecuteAction with EXECUTEACTION property set */
9596f860a780SAmine Khaldi     MsiSetPropertyA(hpkg, "EXECUTEACTION", "CostInitialize");
9597f860a780SAmine Khaldi     r = MsiDoActionA(hpkg, "ExecuteAction");
9598f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9599f860a780SAmine Khaldi     ok_sequence(toplevel_executeaction_costinitialize_sequence, "ExecuteAction: CostInitialize", FALSE);
9600f860a780SAmine Khaldi 
9601f860a780SAmine Khaldi     MsiCloseHandle(hpkg);
9602f860a780SAmine Khaldi     ok_sequence(closehandle_sequence, "MsiCloseHandle()", FALSE);
9603f860a780SAmine Khaldi 
9604f860a780SAmine Khaldi     /* test MsiInstallProduct() */
9605f860a780SAmine Khaldi     r = MsiInstallProductA(msifile_absolute, NULL);
9606f860a780SAmine Khaldi     ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
9607f860a780SAmine Khaldi     ok_sequence(toplevel_msiinstallproduct_sequence, "MsiInstallProduct()", TRUE);
9608f860a780SAmine Khaldi 
9609f860a780SAmine Khaldi     r = MsiInstallProductA(msifile_absolute, "ACTION=custom");
9610f860a780SAmine Khaldi     todo_wine
9611f860a780SAmine Khaldi     ok(r == ERROR_INSTALL_FAILURE, "expected ERROR_INSTALL_FAILURE, got %u\n", r);
9612f860a780SAmine Khaldi     ok_sequence(toplevel_msiinstallproduct_custom_sequence, "MsiInstallProduct(ACTION=custom)", TRUE);
9613f860a780SAmine Khaldi 
9614f860a780SAmine Khaldi     CoUninitialize();
9615f860a780SAmine Khaldi     DeleteFileA(msifile);
9616f860a780SAmine Khaldi     DeleteFileA("forcecodepage.idt");
9617f860a780SAmine Khaldi }
9618f860a780SAmine Khaldi 
9619c2c66affSColin Finck START_TEST(package)
9620c2c66affSColin Finck {
9621c2c66affSColin Finck     STATEMGRSTATUS status;
9622c2c66affSColin Finck     BOOL ret = FALSE;
9623c2c66affSColin Finck 
9624c2c66affSColin Finck     init_functionpointers();
9625c2c66affSColin Finck 
9626c2c66affSColin Finck     if (pIsWow64Process)
9627c2c66affSColin Finck         pIsWow64Process(GetCurrentProcess(), &is_wow64);
9628c2c66affSColin Finck 
9629c2c66affSColin Finck     GetCurrentDirectoryA(MAX_PATH, CURR_DIR);
9630c2c66affSColin Finck 
9631c2c66affSColin Finck     /* Create a restore point ourselves so we circumvent the multitude of restore points
9632c2c66affSColin Finck      * that would have been created by all the installation and removal tests.
9633c2c66affSColin Finck      *
9634c2c66affSColin Finck      * This is not needed on version 5.0 where setting MSIFASTINSTALL prevents the
9635c2c66affSColin Finck      * creation of restore points.
9636c2c66affSColin Finck      */
9637c2c66affSColin Finck     if (pSRSetRestorePointA && !pMsiGetComponentPathExA)
9638c2c66affSColin Finck     {
9639c2c66affSColin Finck         memset(&status, 0, sizeof(status));
9640c2c66affSColin Finck         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
9641c2c66affSColin Finck     }
9642c2c66affSColin Finck 
9643c2c66affSColin Finck     test_createpackage();
9644c2c66affSColin Finck     test_doaction();
9645c2c66affSColin Finck     test_gettargetpath_bad();
9646c2c66affSColin Finck     test_settargetpath();
9647c2c66affSColin Finck     test_props();
9648c2c66affSColin Finck     test_property_table();
9649c2c66affSColin Finck     test_condition();
9650c2c66affSColin Finck     test_msipackage();
9651c2c66affSColin Finck     test_formatrecord2();
9652f860a780SAmine Khaldi     test_formatrecord_tables();
9653c2c66affSColin Finck     test_states();
9654c2c66affSColin Finck     test_removefiles();
9655c2c66affSColin Finck     test_appsearch();
9656c2c66affSColin Finck     test_appsearch_complocator();
9657c2c66affSColin Finck     test_appsearch_reglocator();
9658c2c66affSColin Finck     test_appsearch_inilocator();
9659c2c66affSColin Finck     test_appsearch_drlocator();
9660c2c66affSColin Finck     test_featureparents();
9661c2c66affSColin Finck     test_installprops();
9662c2c66affSColin Finck     test_launchconditions();
9663c2c66affSColin Finck     test_ccpsearch();
9664c2c66affSColin Finck     test_complocator();
9665c2c66affSColin Finck     test_MsiGetSourcePath();
9666c2c66affSColin Finck     test_shortlongsource();
9667c2c66affSColin Finck     test_sourcedir();
9668c2c66affSColin Finck     test_access();
9669c2c66affSColin Finck     test_emptypackage();
9670c2c66affSColin Finck     test_MsiGetProductProperty();
9671c2c66affSColin Finck     test_MsiSetProperty();
9672c2c66affSColin Finck     test_MsiApplyMultiplePatches();
9673c2c66affSColin Finck     test_MsiApplyPatch();
9674818a84ddSwinesync     test_costs();
9675c2c66affSColin Finck     test_MsiDatabaseCommit();
96762f8e6f71SAmine Khaldi     test_externalui();
96772f8e6f71SAmine Khaldi     test_externalui_message();
96782f8e6f71SAmine Khaldi     test_controlevent();
9679f860a780SAmine Khaldi     test_top_level_action();
9680c2c66affSColin Finck 
9681c2c66affSColin Finck     if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
9682c2c66affSColin Finck     {
9683c2c66affSColin Finck         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
9684c2c66affSColin Finck         if (ret)
9685c2c66affSColin Finck             remove_restore_point(status.llSequenceNumber);
9686c2c66affSColin Finck     }
9687c2c66affSColin Finck }
9688