ReactOS  0.4.11-dev-765-g5e024bf
package.c
Go to the documentation of this file.
1 /*
2  * tests for Microsoft Installer functionality
3  *
4  * Copyright 2005 Mike McCormack for CodeWeavers
5  * Copyright 2005 Aric Stewart for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21 
22 #define COBJMACROS
23 
24 #include <assert.h>
25 #include <stdio.h>
26 #include <windows.h>
27 #include <msidefs.h>
28 #include <msi.h>
29 #include <msiquery.h>
30 #include <srrestoreptapi.h>
31 #include <shlobj.h>
32 
33 #include "wine/test.h"
34 
35 static BOOL is_wow64;
36 static const char msifile[] = "winetest-package.msi";
37 static const WCHAR msifileW[] =
38  {'w','i','n','e','t','e','s','t','-','p','a','c','k','a','g','e','.','m','s','i',0};
39 static char CURR_DIR[MAX_PATH];
40 
41 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
43 
44 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
45 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
46 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
47 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
48 static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
49 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
50 static void (WINAPI *pGetSystemInfo)(LPSYSTEM_INFO);
51 static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
52 static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR, UINT);
53 
54 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
55 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
56 
57 static void init_functionpointers(void)
58 {
59  HMODULE hmsi = GetModuleHandleA("msi.dll");
60  HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
61  HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
62  HMODULE hshell32 = GetModuleHandleA("shell32.dll");
64 
65 #define GET_PROC(mod, func) \
66  p ## func = (void*)GetProcAddress(mod, #func);
67 
69  GET_PROC(hshell32, SHGetFolderPathA);
70 
71  GET_PROC(hadvapi32, CheckTokenMembership);
72  GET_PROC(hadvapi32, ConvertSidToStringSidA);
73  GET_PROC(hadvapi32, OpenProcessToken);
74  GET_PROC(hadvapi32, RegDeleteKeyExA)
75  GET_PROC(hadvapi32, RegDeleteKeyExW)
76  GET_PROC(hkernel32, IsWow64Process)
77  GET_PROC(hkernel32, GetNativeSystemInfo)
78  GET_PROC(hkernel32, GetSystemInfo)
80 
81  hsrclient = LoadLibraryA("srclient.dll");
82  GET_PROC(hsrclient, SRRemoveRestorePoint);
83  GET_PROC(hsrclient, SRSetRestorePointA);
84 #undef GET_PROC
85 }
86 
88 {
90  PSID Group = NULL;
91  BOOL IsInGroup;
92  HANDLE token;
93 
94  if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
95 
97  DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
98  !pCheckTokenMembership(NULL, Group, &IsInGroup))
99  {
100  trace("Could not check if the current user is an administrator\n");
101  FreeSid(Group);
102  return FALSE;
103  }
104  FreeSid(Group);
105 
106  if (!IsInGroup)
107  {
108  if (!AllocateAndInitializeSid(&NtAuthority, 2,
111  0, 0, 0, 0, 0, 0, &Group) ||
112  !pCheckTokenMembership(NULL, Group, &IsInGroup))
113  {
114  trace("Could not check if the current user is a power user\n");
115  return FALSE;
116  }
117  if (!IsInGroup)
118  {
119  /* Only administrators and power users can be powerful */
120  return TRUE;
121  }
122  }
123 
124  if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
125  {
126  BOOL ret;
128  DWORD size;
129 
130  ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
131  CloseHandle(token);
132  return (ret && type == TokenElevationTypeLimited);
133  }
134  return FALSE;
135 }
136 
138 {
139  if (pRegDeleteKeyExA)
140  return pRegDeleteKeyExA( key, subkey, access, 0 );
141  return RegDeleteKeyA( key, subkey );
142 }
143 
144 static char *get_user_sid(void)
145 {
146  HANDLE token;
147  DWORD size = 0;
148  TOKEN_USER *user;
149  char *usersid = NULL;
150 
151  if (!pConvertSidToStringSidA)
152  {
153  win_skip("ConvertSidToStringSidA is not available\n");
154  return NULL;
155  }
157  GetTokenInformation(token, TokenUser, NULL, size, &size);
158 
159  user = HeapAlloc(GetProcessHeap(), 0, size);
160  GetTokenInformation(token, TokenUser, user, size, &size);
161  pConvertSidToStringSidA(user->User.Sid, &usersid);
162  HeapFree(GetProcessHeap(), 0, user);
163 
164  CloseHandle(token);
165  return usersid;
166 }
167 
168 /* RegDeleteTreeW from dlls/advapi32/registry.c */
170 {
171  LONG ret;
172  DWORD dwMaxSubkeyLen, dwMaxValueLen;
173  DWORD dwMaxLen, dwSize;
174  WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
175  HKEY hSubKey = hKey;
176 
177  if(lpszSubKey)
178  {
179  ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
180  if (ret) return ret;
181  }
182 
183  ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
184  &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
185  if (ret) goto cleanup;
186 
187  dwMaxSubkeyLen++;
188  dwMaxValueLen++;
189  dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
190  if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
191  {
192  /* Name too big: alloc a buffer for it */
193  if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
194  {
196  goto cleanup;
197  }
198  }
199 
200  /* Recursively delete all the subkeys */
201  while (TRUE)
202  {
203  dwSize = dwMaxLen;
204  if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
205  NULL, NULL, NULL)) break;
206 
207  ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
208  if (ret) goto cleanup;
209  }
210 
211  if (lpszSubKey)
212  {
213  if (pRegDeleteKeyExW)
214  ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
215  else
216  ret = RegDeleteKeyW(hKey, lpszSubKey);
217  }
218  else
219  while (TRUE)
220  {
221  dwSize = dwMaxLen;
222  if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
223  NULL, NULL, NULL, NULL)) break;
224 
225  ret = RegDeleteValueW(hKey, lpszName);
226  if (ret) goto cleanup;
227  }
228 
229 cleanup:
230  if (lpszName != szNameBuf)
231  HeapFree(GetProcessHeap(), 0, lpszName);
232  if(lpszSubKey)
233  RegCloseKey(hSubKey);
234  return ret;
235 }
236 
238 {
239  DWORD i,n=1;
240  GUID guid;
241 
242  if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
243  return FALSE;
244 
245  for(i=0; i<8; i++)
246  out[7-i] = in[n++];
247  n++;
248  for(i=0; i<4; i++)
249  out[11-i] = in[n++];
250  n++;
251  for(i=0; i<4; i++)
252  out[15-i] = in[n++];
253  n++;
254  for(i=0; i<2; i++)
255  {
256  out[17+i*2] = in[n++];
257  out[16+i*2] = in[n++];
258  }
259  n++;
260  for( ; i<8; i++)
261  {
262  out[17+i*2] = in[n++];
263  out[16+i*2] = in[n++];
264  }
265  out[32]=0;
266  return TRUE;
267 }
268 
269 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
270 {
271  WCHAR guidW[MAX_PATH];
272  WCHAR squashedW[MAX_PATH];
273  GUID guid;
274  HRESULT hr;
275  int size;
276 
277  hr = CoCreateGuid(&guid);
278  ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
279 
280  size = StringFromGUID2(&guid, guidW, MAX_PATH);
281  ok(size == 39, "Expected 39, got %d\n", hr);
282 
283  WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
284  squash_guid(guidW, squashedW);
285  WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
286 }
287 
289  LPCSTR guid, LPSTR usersid, BOOL dir)
290 {
291  WCHAR guidW[MAX_PATH];
292  WCHAR squashedW[MAX_PATH];
293  CHAR squashed[MAX_PATH];
294  CHAR comppath[MAX_PATH];
295  CHAR prodpath[MAX_PATH];
296  CHAR path[MAX_PATH];
297  LPCSTR prod = NULL;
298  HKEY hkey;
300 
301  if (is_wow64)
302  access |= KEY_WOW64_64KEY;
303 
304  MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
305  squash_guid(guidW, squashedW);
306  WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
307 
308  if (context == MSIINSTALLCONTEXT_MACHINE)
309  {
310  prod = "3D0DAE300FACA1300AD792060BCDAA92";
311  sprintf(comppath,
312  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
313  "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
314  lstrcpyA(prodpath,
315  "SOFTWARE\\Classes\\Installer\\"
316  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
317  }
318  else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
319  {
320  prod = "7D2F387510109040002000060BECB6AB";
321  sprintf(comppath,
322  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
323  "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
324  sprintf(prodpath,
325  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
326  "Installer\\%s\\Installer\\Products\\"
327  "7D2F387510109040002000060BECB6AB", usersid);
328  }
329  else if (context == MSIINSTALLCONTEXT_USERMANAGED)
330  {
331  prod = "7D2F387510109040002000060BECB6AB";
332  sprintf(comppath,
333  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
334  "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
335  sprintf(prodpath,
336  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
337  "Installer\\Managed\\%s\\Installer\\Products\\"
338  "7D2F387510109040002000060BECB6AB", usersid);
339  }
340 
341  RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
342 
343  lstrcpyA(path, CURR_DIR);
344  lstrcatA(path, "\\");
345  if (!dir) lstrcatA(path, filename);
346 
347  RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
348  RegCloseKey(hkey);
349 
350  RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
351  RegCloseKey(hkey);
352 }
353 
355 {
356  WCHAR guidW[MAX_PATH];
357  WCHAR squashedW[MAX_PATH];
359  CHAR squashed[MAX_PATH];
360  CHAR comppath[MAX_PATH];
361  CHAR prodpath[MAX_PATH];
363 
364  if (is_wow64)
365  access |= KEY_WOW64_64KEY;
366 
367  MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
368  squash_guid(guidW, squashedW);
369  WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
370 
371  if (context == MSIINSTALLCONTEXT_MACHINE)
372  {
373  sprintf(comppath,
374  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
375  "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
376  lstrcpyA(prodpath,
377  "SOFTWARE\\Classes\\Installer\\"
378  "Products\\3D0DAE300FACA1300AD792060BCDAA92");
379  }
380  else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
381  {
382  sprintf(comppath,
383  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
384  "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
385  sprintf(prodpath,
386  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
387  "Installer\\%s\\Installer\\Products\\"
388  "7D2F387510109040002000060BECB6AB", usersid);
389  }
390  else if (context == MSIINSTALLCONTEXT_USERMANAGED)
391  {
392  sprintf(comppath,
393  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
394  "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
395  sprintf(prodpath,
396  "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
397  "Installer\\Managed\\%s\\Installer\\Products\\"
398  "7D2F387510109040002000060BECB6AB", usersid);
399  }
400 
401  MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
402  package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
403 
404  MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
405  package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
406 }
407 
408 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
409 {
410  MSIHANDLE hview = 0;
411  UINT r, ret;
412 
413  /* open a select query */
414  r = MsiDatabaseOpenViewA(hdb, query, &hview);
415  if (r != ERROR_SUCCESS)
416  return r;
417  r = MsiViewExecute(hview, 0);
418  if (r != ERROR_SUCCESS)
419  return r;
420  ret = MsiViewFetch(hview, phrec);
421  r = MsiViewClose(hview);
422  if (r != ERROR_SUCCESS)
423  return r;
424  r = MsiCloseHandle(hview);
425  if (r != ERROR_SUCCESS)
426  return r;
427  return ret;
428 }
429 
430 static UINT run_query( MSIHANDLE hdb, const char *query )
431 {
432  MSIHANDLE hview = 0;
433  UINT r;
434 
435  r = MsiDatabaseOpenViewA(hdb, query, &hview);
436  if( r != ERROR_SUCCESS )
437  return r;
438 
439  r = MsiViewExecute(hview, 0);
440  if( r == ERROR_SUCCESS )
441  r = MsiViewClose(hview);
442  MsiCloseHandle(hview);
443  return r;
444 }
445 
447 {
448  UINT r = run_query( hdb,
449  "CREATE TABLE `Component` ( "
450  "`Component` CHAR(72) NOT NULL, "
451  "`ComponentId` CHAR(38), "
452  "`Directory_` CHAR(72) NOT NULL, "
453  "`Attributes` SHORT NOT NULL, "
454  "`Condition` CHAR(255), "
455  "`KeyPath` CHAR(72) "
456  "PRIMARY KEY `Component`)" );
457  ok(r == ERROR_SUCCESS, "Failed to create Component table: %u\n", r);
458  return r;
459 }
460 
462 {
463  UINT r = run_query( hdb,
464  "CREATE TABLE `Feature` ( "
465  "`Feature` CHAR(38) NOT NULL, "
466  "`Feature_Parent` CHAR(38), "
467  "`Title` CHAR(64), "
468  "`Description` CHAR(255), "
469  "`Display` SHORT NOT NULL, "
470  "`Level` SHORT NOT NULL, "
471  "`Directory_` CHAR(72), "
472  "`Attributes` SHORT NOT NULL "
473  "PRIMARY KEY `Feature`)" );
474  ok(r == ERROR_SUCCESS, "Failed to create Feature table: %u\n", r);
475  return r;
476 }
477 
479 {
480  UINT r = run_query( hdb,
481  "CREATE TABLE `FeatureComponents` ( "
482  "`Feature_` CHAR(38) NOT NULL, "
483  "`Component_` CHAR(72) NOT NULL "
484  "PRIMARY KEY `Feature_`, `Component_` )" );
485  ok(r == ERROR_SUCCESS, "Failed to create FeatureComponents table: %u\n", r);
486  return r;
487 }
488 
490 {
491  UINT r = run_query( hdb,
492  "CREATE TABLE `File` ("
493  "`File` CHAR(72) NOT NULL, "
494  "`Component_` CHAR(72) NOT NULL, "
495  "`FileName` CHAR(255) NOT NULL, "
496  "`FileSize` LONG NOT NULL, "
497  "`Version` CHAR(72), "
498  "`Language` CHAR(20), "
499  "`Attributes` SHORT, "
500  "`Sequence` SHORT NOT NULL "
501  "PRIMARY KEY `File`)" );
502  ok(r == ERROR_SUCCESS, "Failed to create File table: %u\n", r);
503  return r;
504 }
505 
507 {
508  UINT r = run_query( hdb,
509  "CREATE TABLE `RemoveFile` ("
510  "`FileKey` CHAR(72) NOT NULL, "
511  "`Component_` CHAR(72) NOT NULL, "
512  "`FileName` CHAR(255) LOCALIZABLE, "
513  "`DirProperty` CHAR(72) NOT NULL, "
514  "`InstallMode` SHORT NOT NULL "
515  "PRIMARY KEY `FileKey`)" );
516  ok(r == ERROR_SUCCESS, "Failed to create RemoveFile table: %u\n", r);
517  return r;
518 }
519 
521 {
522  UINT r = run_query( hdb,
523  "CREATE TABLE `AppSearch` ("
524  "`Property` CHAR(72) NOT NULL, "
525  "`Signature_` CHAR(72) NOT NULL "
526  "PRIMARY KEY `Property`, `Signature_`)" );
527  ok(r == ERROR_SUCCESS, "Failed to create AppSearch table: %u\n", r);
528  return r;
529 }
530 
532 {
533  UINT r = run_query( hdb,
534  "CREATE TABLE `RegLocator` ("
535  "`Signature_` CHAR(72) NOT NULL, "
536  "`Root` SHORT NOT NULL, "
537  "`Key` CHAR(255) NOT NULL, "
538  "`Name` CHAR(255), "
539  "`Type` SHORT "
540  "PRIMARY KEY `Signature_`)" );
541  ok(r == ERROR_SUCCESS, "Failed to create RegLocator table: %u\n", r);
542  return r;
543 }
544 
546 {
547  UINT r = run_query( hdb,
548  "CREATE TABLE `Signature` ("
549  "`Signature` CHAR(72) NOT NULL, "
550  "`FileName` CHAR(255) NOT NULL, "
551  "`MinVersion` CHAR(20), "
552  "`MaxVersion` CHAR(20), "
553  "`MinSize` LONG, "
554  "`MaxSize` LONG, "
555  "`MinDate` LONG, "
556  "`MaxDate` LONG, "
557  "`Languages` CHAR(255) "
558  "PRIMARY KEY `Signature`)" );
559  ok(r == ERROR_SUCCESS, "Failed to create Signature table: %u\n", r);
560  return r;
561 }
562 
564 {
565  UINT r = run_query( hdb,
566  "CREATE TABLE `LaunchCondition` ("
567  "`Condition` CHAR(255) NOT NULL, "
568  "`Description` CHAR(255) NOT NULL "
569  "PRIMARY KEY `Condition`)" );
570  ok(r == ERROR_SUCCESS, "Failed to create LaunchCondition table: %u\n", r);
571  return r;
572 }
573 
575 {
576  UINT r = run_query( hdb,
577  "CREATE TABLE `Property` ("
578  "`Property` CHAR(72) NOT NULL, "
579  "`Value` CHAR(0) "
580  "PRIMARY KEY `Property`)" );
581  ok(r == ERROR_SUCCESS, "Failed to create Property table: %u\n", r);
582  return r;
583 }
584 
586 {
587  UINT r = run_query( hdb,
588  "CREATE TABLE `InstallExecuteSequence` ("
589  "`Action` CHAR(72) NOT NULL, "
590  "`Condition` CHAR(255), "
591  "`Sequence` SHORT "
592  "PRIMARY KEY `Action`)" );
593  ok(r == ERROR_SUCCESS, "Failed to create InstallExecuteSequence table: %u\n", r);
594  return r;
595 }
596 
598 {
599  UINT r = run_query( hdb,
600  "CREATE TABLE `InstallUISequence` ("
601  "`Action` CHAR(72) NOT NULL, "
602  "`Condition` CHAR(255), "
603  "`Sequence` SHORT "
604  "PRIMARY KEY `Action`)" );
605  ok(r == ERROR_SUCCESS, "Failed to create InstallUISequence table: %u\n", r);
606  return r;
607 }
608 
610 {
611  UINT r = run_query( hdb,
612  "CREATE TABLE `Media` ("
613  "`DiskId` SHORT NOT NULL, "
614  "`LastSequence` SHORT NOT NULL, "
615  "`DiskPrompt` CHAR(64), "
616  "`Cabinet` CHAR(255), "
617  "`VolumeLabel` CHAR(32), "
618  "`Source` CHAR(72) "
619  "PRIMARY KEY `DiskId`)" );
620  ok(r == ERROR_SUCCESS, "Failed to create Media table: %u\n", r);
621  return r;
622 }
623 
625 {
626  UINT r = run_query( hdb,
627  "CREATE TABLE `CCPSearch` ("
628  "`Signature_` CHAR(72) NOT NULL "
629  "PRIMARY KEY `Signature_`)" );
630  ok(r == ERROR_SUCCESS, "Failed to create CCPSearch table: %u\n", r);
631  return r;
632 }
633 
635 {
636  UINT r = run_query( hdb,
637  "CREATE TABLE `DrLocator` ("
638  "`Signature_` CHAR(72) NOT NULL, "
639  "`Parent` CHAR(72), "
640  "`Path` CHAR(255), "
641  "`Depth` SHORT "
642  "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
643  ok(r == ERROR_SUCCESS, "Failed to create DrLocator table: %u\n", r);
644  return r;
645 }
646 
648 {
649  UINT r = run_query( hdb,
650  "CREATE TABLE `CompLocator` ("
651  "`Signature_` CHAR(72) NOT NULL, "
652  "`ComponentId` CHAR(38) NOT NULL, "
653  "`Type` SHORT "
654  "PRIMARY KEY `Signature_`)" );
655  ok(r == ERROR_SUCCESS, "Failed to create CompLocator table: %u\n", r);
656  return r;
657 }
658 
660 {
661  UINT r = run_query( hdb,
662  "CREATE TABLE `IniLocator` ("
663  "`Signature_` CHAR(72) NOT NULL, "
664  "`FileName` CHAR(255) NOT NULL, "
665  "`Section` CHAR(96)NOT NULL, "
666  "`Key` CHAR(128)NOT NULL, "
667  "`Field` SHORT, "
668  "`Type` SHORT "
669  "PRIMARY KEY `Signature_`)" );
670  ok(r == ERROR_SUCCESS, "Failed to create IniLocator table: %u\n", r);
671  return r;
672 }
673 
675 {
676  UINT r = run_query( hdb,
677  "CREATE TABLE `CustomAction` ("
678  "`Action` CHAR(72) NOT NULL, "
679  "`Type` SHORT NOT NULL, "
680  "`Source` CHAR(75), "
681  "`Target` CHAR(255) "
682  "PRIMARY KEY `Action`)" );
683  ok(r == ERROR_SUCCESS, "Failed to create CustomAction table: %u\n", r);
684  return r;
685 }
686 
688 {
689  UINT r = run_query(hdb,
690  "CREATE TABLE `Dialog` ("
691  "`Dialog` CHAR(72) NOT NULL, "
692  "`HCentering` SHORT NOT NULL, "
693  "`VCentering` SHORT NOT NULL, "
694  "`Width` SHORT NOT NULL, "
695  "`Height` SHORT NOT NULL, "
696  "`Attributes` LONG, "
697  "`Title` CHAR(128) LOCALIZABLE, "
698  "`Control_First` CHAR(50) NOT NULL, "
699  "`Control_Default` CHAR(50), "
700  "`Control_Cancel` CHAR(50) "
701  "PRIMARY KEY `Dialog`)");
702  ok(r == ERROR_SUCCESS, "Failed to create Dialog table: %u\n", r);
703  return r;
704 }
705 
707 {
708  UINT r = run_query(hdb,
709  "CREATE TABLE `Control` ("
710  "`Dialog_` CHAR(72) NOT NULL, "
711  "`Control` CHAR(50) NOT NULL, "
712  "`Type` CHAR(20) NOT NULL, "
713  "`X` SHORT NOT NULL, "
714  "`Y` SHORT NOT NULL, "
715  "`Width` SHORT NOT NULL, "
716  "`Height` SHORT NOT NULL, "
717  "`Attributes` LONG, "
718  "`Property` CHAR(50), "
719  "`Text` CHAR(0) LOCALIZABLE, "
720  "`Control_Next` CHAR(50), "
721  "`Help` CHAR(255) LOCALIZABLE "
722  "PRIMARY KEY `Dialog_`, `Control`)");
723  ok(r == ERROR_SUCCESS, "Failed to create Control table: %u\n", r);
724  return r;
725 }
726 
728 {
729  UINT r = run_query(hdb,
730  "CREATE TABLE `ControlEvent` ("
731  "`Dialog_` CHAR(72) NOT NULL, "
732  "`Control_` CHAR(50) NOT NULL, "
733  "`Event` CHAR(50) NOT NULL, "
734  "`Argument` CHAR(255) NOT NULL, "
735  "`Condition` CHAR(255), "
736  "`Ordering` SHORT "
737  "PRIMARY KEY `Dialog_`, `Control_`, `Event`, `Argument`, `Condition`)");
738  ok(r == ERROR_SUCCESS, "Failed to create ControlEvent table: %u\n", r);
739  return r;
740 }
741 
743 {
744  UINT r = run_query(hdb,
745  "CREATE TABLE `ActionText` ("
746  "`Action` CHAR(72) NOT NULL, "
747  "`Description` CHAR(64) LOCALIZABLE, "
748  "`Template` CHAR(128) LOCALIZABLE "
749  "PRIMARY KEY `Action`)");
750  ok(r == ERROR_SUCCESS, "Failed to create ActionText table: %u\n", r);
751  return r;
752 }
753 
754 static inline UINT add_entry(const char *file, int line, const char *type, MSIHANDLE hdb, const char *values, const char *insert)
755 {
756  char *query;
757  UINT sz, r;
758 
759  sz = strlen(values) + strlen(insert) + 1;
760  query = HeapAlloc(GetProcessHeap(), 0, sz);
761  sprintf(query, insert, values);
762  r = run_query(hdb, query);
763  HeapFree(GetProcessHeap(), 0, query);
764  ok_(file, line)(r == ERROR_SUCCESS, "failed to insert into %s table: %u\n", type, r);
765  return r;
766 }
767 
768 #define add_component_entry(hdb, values) add_entry(__FILE__, __LINE__, "Component", hdb, values, \
769  "INSERT INTO `Component` " \
770  "(`Component`, `ComponentId`, `Directory_`, " \
771  "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
772 
773 #define add_directory_entry(hdb, values) add_entry(__FILE__, __LINE__, "Directory", hdb, values, \
774  "INSERT INTO `Directory` " \
775  "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
776 
777 #define add_feature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Feature", hdb, values, \
778  "INSERT INTO `Feature` " \
779  "(`Feature`, `Feature_Parent`, `Title`, `Description`, " \
780  "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
781 
782 #define add_feature_components_entry(hdb, values) add_entry(__FILE__, __LINE__, "FeatureComponents", hdb, values, \
783  "INSERT INTO `FeatureComponents` " \
784  "(`Feature_`, `Component_`) VALUES( %s )")
785 
786 #define add_file_entry(hdb, values) add_entry(__FILE__, __LINE__, "File", hdb, values, \
787  "INSERT INTO `File` " \
788  "(`File`, `Component_`, `FileName`, `FileSize`, " \
789  "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
790 
791 #define add_appsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "AppSearch", hdb, values, \
792  "INSERT INTO `AppSearch` " \
793  "(`Property`, `Signature_`) VALUES( %s )")
794 
795 #define add_signature_entry(hdb, values) add_entry(__FILE__, __LINE__, "Signature", hdb, values, \
796  "INSERT INTO `Signature` " \
797  "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`," \
798  " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) " \
799  "VALUES( %s )")
800 
801 #define add_launchcondition_entry(hdb, values) add_entry(__FILE__, __LINE__, "LaunchCondition", hdb, values, \
802  "INSERT INTO `LaunchCondition` " \
803  "(`Condition`, `Description`) VALUES( %s )")
804 
805 #define add_property_entry(hdb, values) add_entry(__FILE__, __LINE__, "Property", hdb, values, \
806  "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
807 
808 #define add_install_execute_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallExecuteSequence", hdb, values, \
809  "INSERT INTO `InstallExecuteSequence` " \
810  "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
811 
812 #define add_install_ui_sequence_entry(hdb, values) add_entry(__FILE__, __LINE__, "InstallUISequence", hdb, values, \
813  "INSERT INTO `InstallUISequence` " \
814  "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
815 
816 #define add_media_entry(hdb, values) add_entry(__FILE__, __LINE__, "Media", hdb, values, \
817  "INSERT INTO `Media` " \
818  "(`DiskId`, `LastSequence`, `DiskPrompt`, " \
819  "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
820 
821 #define add_ccpsearch_entry(hdb, values) add_entry(__FILE__, __LINE__, "CCPSearch", hdb, values, \
822  "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
823 
824 #define add_drlocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "DrLocator", hdb, values, \
825  "INSERT INTO `DrLocator` " \
826  "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
827 
828 #define add_complocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "CompLocator", hdb, values, \
829  "INSERT INTO `CompLocator` " \
830  "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
831 
832 #define add_inilocator_entry(hdb, values) add_entry(__FILE__, __LINE__, "IniLocator", hdb, values, \
833  "INSERT INTO `IniLocator` " \
834  "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) " \
835  "VALUES( %s )")
836 
837 #define add_custom_action_entry(hdb, values) add_entry(__FILE__, __LINE__, "CustomAction", hdb, values, \
838  "INSERT INTO `CustomAction` " \
839  "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
840 
841 #define add_dialog_entry(hdb, values) add_entry(__FILE__, __LINE__, "Dialog", hdb, values, \
842  "INSERT INTO `Dialog` " \
843  "(`Dialog`, `HCentering`, `VCentering`, `Width`, `Height`, `Attributes`, `Control_First`) VALUES ( %s )")
844 
845 #define add_control_entry(hdb, values) add_entry(__FILE__, __LINE__, "Control", hdb, values, \
846  "INSERT INTO `Control` " \
847  "(`Dialog_`, `Control`, `Type`, `X`, `Y`, `Width`, `Height`, `Attributes`, `Text`) VALUES( %s )");
848 
849 #define add_controlevent_entry(hdb, values) add_entry(__FILE__, __LINE__, "ControlEvent", hdb, values, \
850  "INSERT INTO `ControlEvent` " \
851  "(`Dialog_`, `Control_`, `Event`, `Argument`, `Condition`, `Ordering`) VALUES( %s )");
852 
853 #define add_actiontext_entry(hdb, values) add_entry(__FILE__, __LINE__, "ActionText", hdb, values, \
854  "INSERT INTO `ActionText` " \
855  "(`Action`, `Description`, `Template`) VALUES( %s )");
856 
857 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
858  const char *name, UINT type )
859 {
860  const char insert[] =
861  "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
862  "VALUES( '%s', %u, '%s', '%s', %u )";
863  char *query;
864  UINT sz, r;
865 
866  sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
867  query = HeapAlloc( GetProcessHeap(), 0, sz );
868  sprintf( query, insert, sig, root, path, name, type );
869  r = run_query( hdb, query );
870  HeapFree( GetProcessHeap(), 0, query );
871  ok(r == ERROR_SUCCESS, "failed to insert into reglocator table: %u\n", r); \
872  return r;
873 }
874 
876 {
877  UINT res;
879 
880  /* build summary info */
881  res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
882  ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
883 
884  res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
885  "Installation Database");
886  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
887 
888  res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
889  "Installation Database");
890  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
891 
892  res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
893  "Wine Hackers");
894  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
895 
896  res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
897  ";1033");
898  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
899 
900  res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
901  "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
902  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
903 
904  res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
905  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
906 
907  res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
908  ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
909 
910  res = MsiSummaryInfoPersist(suminfo);
911  ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
912 
913  res = MsiCloseHandle( suminfo);
914  ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
915 
916  return res;
917 }
918 
919 
921 {
922  MSIHANDLE hdb = 0;
923  UINT res;
924 
926 
927  /* create an empty database */
929  ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
930  if( res != ERROR_SUCCESS )
931  return hdb;
932 
933  res = MsiDatabaseCommit( hdb );
934  ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
935 
936  res = set_summary_info(hdb);
937  ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
938 
939  res = run_query( hdb,
940  "CREATE TABLE `Directory` ( "
941  "`Directory` CHAR(255) NOT NULL, "
942  "`Directory_Parent` CHAR(255), "
943  "`DefaultDir` CHAR(255) NOT NULL "
944  "PRIMARY KEY `Directory`)" );
945  ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
946 
947  return hdb;
948 }
949 
951 {
952  UINT res;
953  CHAR szPackage[12];
954  MSIHANDLE hPackage;
955 
956  sprintf(szPackage, "#%u", hdb);
957  res = MsiOpenPackageA(szPackage, &hPackage);
958  if (res != ERROR_SUCCESS)
959  {
960  MsiCloseHandle(hdb);
961  return res;
962  }
963 
964  res = MsiCloseHandle(hdb);
965  if (res != ERROR_SUCCESS)
966  {
967  MsiCloseHandle(hPackage);
968  return res;
969  }
970 
971  *handle = hPackage;
972  return ERROR_SUCCESS;
973 }
974 
976 {
977  HANDLE file;
978  DWORD written;
979 
980  file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
981  ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
982  if (file == INVALID_HANDLE_VALUE)
983  return;
984 
985  WriteFile(file, data, strlen(data), &written, NULL);
986  WriteFile(file, "\n", strlen("\n"), &written, NULL);
987 
988  CloseHandle(file);
989 }
990 
991 static void create_test_file(const CHAR *name)
992 {
993  create_file_data(name, name);
994 }
995 
996 typedef struct _tagVS_VERSIONINFO
997 {
1006 } VS_VERSIONINFO;
1007 
1008 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
1009 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
1010 
1012 {
1013  VS_VERSIONINFO *pVerInfo;
1014  VS_FIXEDFILEINFO *pFixedInfo;
1015  LPBYTE buffer, ofs;
1016  CHAR path[MAX_PATH];
1017  DWORD handle, size;
1018  HANDLE resource;
1019  BOOL ret = FALSE;
1020 
1022  /* Some dlls can't be updated on Vista/W2K8 */
1023  lstrcatA(path, "\\version.dll");
1024 
1025  CopyFileA(path, name, FALSE);
1026 
1027  size = GetFileVersionInfoSizeA(path, &handle);
1028  buffer = HeapAlloc(GetProcessHeap(), 0, size);
1029 
1030  GetFileVersionInfoA(path, 0, size, buffer);
1031 
1032  pVerInfo = (VS_VERSIONINFO *)buffer;
1033  ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
1034  pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
1035 
1036  pFixedInfo->dwFileVersionMS = ms;
1037  pFixedInfo->dwFileVersionLS = ls;
1038  pFixedInfo->dwProductVersionMS = ms;
1039  pFixedInfo->dwProductVersionLS = ls;
1040 
1041  resource = BeginUpdateResourceA(name, FALSE);
1042  if (!resource)
1043  goto done;
1044 
1046  MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
1047  goto done;
1048 
1049  if (!EndUpdateResourceA(resource, FALSE))
1050  goto done;
1051 
1052  ret = TRUE;
1053 
1054 done:
1055  HeapFree(GetProcessHeap(), 0, buffer);
1056  return ret;
1057 }
1058 
1060 {
1061  RESTOREPOINTINFOA spec;
1062 
1063  spec.dwEventType = event_type;
1065  spec.llSequenceNumber = status->llSequenceNumber;
1066  lstrcpyA(spec.szDescription, "msitest restore point");
1067 
1068  return pSRSetRestorePointA(&spec, status);
1069 }
1070 
1071 static void remove_restore_point(DWORD seq_number)
1072 {
1073  DWORD res;
1074 
1075  res = pSRRemoveRestorePoint(seq_number);
1076  if (res != ERROR_SUCCESS)
1077  trace("Failed to remove the restore point : %08x\n", res);
1078 }
1079 
1080 static BOOL is_root(const char *path)
1081 {
1082  return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1083 }
1084 
1085 static void test_createpackage(void)
1086 {
1087  MSIHANDLE hPackage = 0;
1088  UINT res;
1089 
1090  res = package_from_db(create_package_db(), &hPackage);
1091  if (res == ERROR_INSTALL_PACKAGE_REJECTED)
1092  {
1093  skip("Not enough rights to perform tests\n");
1095  return;
1096  }
1097  ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
1098 
1099  res = MsiCloseHandle( hPackage);
1100  ok( res == ERROR_SUCCESS , "Failed to close package\n" );
1102 }
1103 
1104 static void test_doaction( void )
1105 {
1106  MSIHANDLE hpkg;
1107  UINT r;
1108 
1109  r = MsiDoActionA( -1, NULL );
1110  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1111 
1112  r = package_from_db(create_package_db(), &hpkg);
1114  {
1115  skip("Not enough rights to perform tests\n");
1117  return;
1118  }
1119  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1120 
1121  r = MsiDoActionA(hpkg, NULL);
1122  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1123 
1124  r = MsiDoActionA(0, "boo");
1125  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1126 
1127  r = MsiDoActionA(hpkg, "boo");
1128  ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
1129 
1130  MsiCloseHandle( hpkg );
1132 }
1133 
1134 static void test_gettargetpath_bad(void)
1135 {
1136  static const WCHAR boo[] = {'b','o','o',0};
1137  static const WCHAR empty[] = {0};
1138  char buffer[0x80];
1139  WCHAR bufferW[0x80];
1140  MSIHANDLE hpkg;
1141  DWORD sz;
1142  UINT r;
1143 
1144  r = package_from_db(create_package_db(), &hpkg);
1146  {
1147  skip("Not enough rights to perform tests\n");
1149  return;
1150  }
1151  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1152 
1153  r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1154  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1155 
1156  r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1157  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1158 
1159  r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1160  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1161 
1162  r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1163  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1164 
1165  r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1166  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1167 
1168  r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1169  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1170 
1171  sz = 0;
1172  r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1173  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1174 
1175  r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1176  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1177 
1178  r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1179  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1180 
1181  r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1182  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1183 
1184  r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1185  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1186 
1187  r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1188  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1189 
1190  r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1191  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1192 
1193  sz = 0;
1194  r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1195  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1196 
1197  MsiCloseHandle( hpkg );
1199 }
1200 
1202 {
1203  UINT r;
1204  DWORD size;
1205  MSIHANDLE rec;
1206 
1207  rec = MsiCreateRecord( 1 );
1208  ok(rec, "MsiCreate record failed\n");
1209 
1210  r = MsiRecordSetStringA( rec, 0, file );
1211  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1212 
1213  size = MAX_PATH;
1214  r = MsiFormatRecordA( hpkg, rec, buff, &size );
1215  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1216 
1217  MsiCloseHandle( rec );
1218 }
1219 
1220 static void test_settargetpath(void)
1221 {
1222  char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1223  DWORD sz;
1224  MSIHANDLE hpkg;
1225  UINT r;
1226  MSIHANDLE hdb;
1227 
1228  hdb = create_package_db();
1229  ok ( hdb, "failed to create package database\n" );
1230 
1231  add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1232 
1233  create_component_table( hdb );
1234  add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1235  add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1236 
1237  create_feature_table( hdb );
1238  add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1239 
1241  add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1242  add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1243 
1244  add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1245  add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1246 
1247  create_file_table( hdb );
1248  add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1249  add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1250 
1251  r = package_from_db( hdb, &hpkg );
1253  {
1254  skip("Not enough rights to perform tests\n");
1256  return;
1257  }
1258  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1259 
1261 
1262  r = MsiDoActionA( hpkg, "CostInitialize");
1263  ok( r == ERROR_SUCCESS, "cost init failed\n");
1264 
1265  r = MsiDoActionA( hpkg, "FileCost");
1266  ok( r == ERROR_SUCCESS, "file cost failed\n");
1267 
1268  r = MsiDoActionA( hpkg, "CostFinalize");
1269  ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1270 
1271  buffer[0] = 0;
1272  sz = sizeof(buffer);
1273  r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1274  ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1275  trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1276 
1277  r = MsiSetTargetPathA( 0, NULL, NULL );
1278  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1279 
1280  r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1281  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1282 
1283  r = MsiSetTargetPathA( hpkg, "boo", NULL );
1284  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1285 
1286  r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1287  ok( r == ERROR_DIRECTORY, "wrong return val\n");
1288 
1289  sz = sizeof tempdir - 1;
1290  r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1291  sprintf( file, "%srootfile.txt", tempdir );
1292  buffer[0] = 0;
1293  query_file_path( hpkg, "[#RootFile]", buffer );
1294  ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1295  ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1296 
1297  GetTempFileNameA( tempdir, "_wt", 0, buffer );
1298  sprintf( tempdir, "%s\\subdir", buffer );
1299 
1300  r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1301  ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1302  "MsiSetTargetPath on file returned %d\n", r );
1303 
1304  r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1305  ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1306  "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1307 
1308  DeleteFileA( buffer );
1309 
1310  r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1311  ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1312 
1313  r = GetFileAttributesA( buffer );
1314  ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1315 
1316  r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1317  ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1318 
1319  buffer[0] = 0;
1320  sz = sizeof buffer - 1;
1321  lstrcatA( tempdir, "\\" );
1322  r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1323  ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1324  ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1325 
1326  sprintf( file, "%srootfile.txt", tempdir );
1327  query_file_path( hpkg, "[#RootFile]", buffer );
1328  ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1329 
1330  buffer[0] = 0;
1331  sz = sizeof(buffer);
1332  r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1333  ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1334  lstrcatA( tempdir, "TestParent\\" );
1335  ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1336 
1337  r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1338  ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1339 
1340  buffer[0] = 0;
1341  sz = sizeof(buffer);
1342  r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1343  ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1344  ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1345  "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1346 
1347  buffer[0] = 0;
1348  query_file_path( hpkg, "[#TestFile]", buffer );
1349  ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1350  "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1351 
1352  buffer[0] = 0;
1353  sz = sizeof buffer - 1;
1354  r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1355  ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1356  ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1357 
1358  r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1359  ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1360 
1361  buffer[0] = 0;
1362  sz = sizeof buffer - 1;
1363  r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1364  ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1365  ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1366 
1367  r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two " );
1368  ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1369 
1370  buffer[0] = 0;
1371  sz = sizeof buffer - 1;
1372  r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1373  ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1374  ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1375 
1376  r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1377  ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1378 
1379  buffer[0] = 0;
1380  sz = sizeof buffer - 1;
1381  r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1382  ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1383  ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1384 
1385  MsiCloseHandle( hpkg );
1386 }
1387 
1388 static void test_condition(void)
1389 {
1390  static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1391  static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1392  static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1393  static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1394  MSICONDITION r;
1395  MSIHANDLE hpkg;
1396 
1397  r = package_from_db(create_package_db(), &hpkg);
1399  {
1400  skip("Not enough rights to perform tests\n");
1402  return;
1403  }
1404  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1405 
1406  r = MsiEvaluateConditionA(0, NULL);
1407  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1408 
1409  r = MsiEvaluateConditionA(hpkg, NULL);
1410  ok( r == MSICONDITION_NONE, "wrong return val\n");
1411 
1412  r = MsiEvaluateConditionA(hpkg, "");
1413  ok( r == MSICONDITION_NONE, "wrong return val\n");
1414 
1415  r = MsiEvaluateConditionA(hpkg, "1");
1416  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1417 
1418  r = MsiEvaluateConditionA(hpkg, "0");
1419  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1420 
1421  r = MsiEvaluateConditionA(hpkg, "-1");
1422  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1423 
1424  r = MsiEvaluateConditionA(hpkg, "0 = 0");
1425  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1426 
1427  r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1428  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1429 
1430  r = MsiEvaluateConditionA(hpkg, "0 = 1");
1431  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1432 
1433  r = MsiEvaluateConditionA(hpkg, "0 > 1");
1434  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1435 
1436  r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1437  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1438 
1439  r = MsiEvaluateConditionA(hpkg, "1 > 1");
1440  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1441 
1442  r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1443  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1444 
1445  r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1446  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1447 
1448  r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1449  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1450 
1451  r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1452  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1453 
1454  r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1455  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1456 
1457  r = MsiEvaluateConditionA(hpkg, "0 < 1");
1458  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1459 
1460  r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1461  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1462 
1463  r = MsiEvaluateConditionA(hpkg, "1 < 1");
1464  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1465 
1466  r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1467  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1468 
1469  r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1470  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1471 
1472  r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1473  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1474 
1475  r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1476  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1477 
1478  r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1479  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1480 
1481  r = MsiEvaluateConditionA(hpkg, "0 >=");
1482  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1483 
1484  r = MsiEvaluateConditionA(hpkg, " ");
1485  ok( r == MSICONDITION_NONE, "wrong return val\n");
1486 
1487  r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1488  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1489 
1490  r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1491  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1492 
1493  r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1494  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1495 
1496  r = MsiEvaluateConditionA(hpkg, "not 0");
1497  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1498 
1499  r = MsiEvaluateConditionA(hpkg, "not LicView");
1500  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1501 
1502  r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1503  ok (r == MSICONDITION_TRUE, "wrong return val\n");
1504 
1505  r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1506  ok (r == MSICONDITION_FALSE, "wrong return val\n");
1507 
1508  r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1509  ok (r == MSICONDITION_TRUE, "wrong return val\n");
1510 
1511  r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1512  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1513 
1514  r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1515  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1516 
1517  r = MsiEvaluateConditionA(hpkg, "\"0\"");
1518  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1519 
1520  r = MsiEvaluateConditionA(hpkg, "1 and 2");
1521  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1522 
1523  r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1524  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1525 
1526  r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1527  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1528 
1529  r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1530  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1531 
1532  r = MsiEvaluateConditionA(hpkg, "(0)");
1533  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1534 
1535  r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1536  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1537 
1538  r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1539  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1540 
1541  r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1542  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1543 
1544  r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1545  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1546 
1547  r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1548  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1549 
1550  r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1551  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1552 
1553  r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1554  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1555 
1556  r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1557  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1558 
1559  r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1560  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1561 
1562  r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1563  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1564 
1565  r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1566  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1567 
1568  r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1569  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1570 
1571  r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1572  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1573 
1574  r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1575  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1576 
1577  r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1578  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1579 
1580  r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1581  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1582 
1583  r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1584  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1585 
1586  r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1587  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1588 
1589  r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1590  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1591 
1592  r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1593  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1594 
1595  r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1596  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1597 
1598  r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1599  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1600 
1601  r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1602  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1603 
1604  r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1605  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1606 
1607  r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1608  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1609 
1610  r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1611  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1612 
1613  r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1614  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1615 
1616  r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1617  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1618 
1619  r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1620  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1621 
1622  r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1623  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1624 
1625  r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1626  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1627 
1628  MsiSetPropertyA(hpkg, "mm", "5" );
1629 
1630  r = MsiEvaluateConditionA(hpkg, "mm = 5");
1631  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1632 
1633  r = MsiEvaluateConditionA(hpkg, "mm < 6");
1634  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1635 
1636  r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1637  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1638 
1639  r = MsiEvaluateConditionA(hpkg, "mm > 4");
1640  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1641 
1642  r = MsiEvaluateConditionA(hpkg, "mm < 12");
1643  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1644 
1645  r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1646  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1647 
1648  r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1649  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1650 
1651  r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1652  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1653 
1654  r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1655  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1656 
1657  r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1658  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1659 
1660  r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1661  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1662 
1663  r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1664  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1665 
1666  r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1667  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1668 
1669  r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1670  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1671 
1672  r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1673  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1674 
1675  r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1676  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1677 
1678  r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1679  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1680 
1681  r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1682  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1683 
1684  r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1685  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1686 
1687  r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1688  ok( r == MSICONDITION_ERROR, "wrong return val\n");
1689 
1690  r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1691  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1692 
1693  r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1694  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1695 
1696  r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1697  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1698 
1699  r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1700  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1701 
1702  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1703  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1704 
1705  r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1706  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1707 
1708  r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1709  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1710 
1711  r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1712  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1713 
1714  r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1715  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1716 
1717  r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1718  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1719 
1720  r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1721  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1722 
1723  MsiSetPropertyA(hpkg, "bandalmael", "0" );
1724  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1725  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1726 
1727  MsiSetPropertyA(hpkg, "bandalmael", "" );
1728  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1729  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1730 
1731  MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1732  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1733  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1734 
1735  MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1736  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1737  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1738 
1739  MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1740  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1741  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1742 
1743  MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1744  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1745  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1746 
1747  MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1748  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1749  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1750 
1751  MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1752  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1753  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1754 
1755  MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1756  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1757  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1758 
1759  MsiSetPropertyA(hpkg, "bandalmael", "-" );
1760  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1761  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1762 
1763  MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1764  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1765  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1766 
1767  MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1768  r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1769  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1770  r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1771  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1772 
1773  MsiSetPropertyA(hpkg, "one", "hi");
1774  MsiSetPropertyA(hpkg, "two", "hithere");
1775  r = MsiEvaluateConditionA(hpkg, "one >< two");
1776  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1777 
1778  MsiSetPropertyA(hpkg, "one", "hithere");
1779  MsiSetPropertyA(hpkg, "two", "hi");
1780  r = MsiEvaluateConditionA(hpkg, "one >< two");
1781  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1782 
1783  MsiSetPropertyA(hpkg, "one", "hello");
1784  MsiSetPropertyA(hpkg, "two", "hi");
1785  r = MsiEvaluateConditionA(hpkg, "one >< two");
1786  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1787 
1788  MsiSetPropertyA(hpkg, "one", "hellohithere");
1789  MsiSetPropertyA(hpkg, "two", "hi");
1790  r = MsiEvaluateConditionA(hpkg, "one >< two");
1791  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1792 
1793  MsiSetPropertyA(hpkg, "one", "");
1794  MsiSetPropertyA(hpkg, "two", "hi");
1795  r = MsiEvaluateConditionA(hpkg, "one >< two");
1796  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1797 
1798  MsiSetPropertyA(hpkg, "one", "hi");
1799  MsiSetPropertyA(hpkg, "two", "");
1800  r = MsiEvaluateConditionA(hpkg, "one >< two");
1801  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1802 
1803  MsiSetPropertyA(hpkg, "one", "");
1804  MsiSetPropertyA(hpkg, "two", "");
1805  r = MsiEvaluateConditionA(hpkg, "one >< two");
1806  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1807 
1808  MsiSetPropertyA(hpkg, "one", "1234");
1809  MsiSetPropertyA(hpkg, "two", "1");
1810  r = MsiEvaluateConditionA(hpkg, "one >< two");
1811  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1812 
1813  MsiSetPropertyA(hpkg, "one", "one 1234");
1814  MsiSetPropertyA(hpkg, "two", "1");
1815  r = MsiEvaluateConditionA(hpkg, "one >< two");
1816  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1817 
1818  MsiSetPropertyA(hpkg, "one", "hithere");
1819  MsiSetPropertyA(hpkg, "two", "hi");
1820  r = MsiEvaluateConditionA(hpkg, "one << two");
1821  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1822 
1823  MsiSetPropertyA(hpkg, "one", "hi");
1824  MsiSetPropertyA(hpkg, "two", "hithere");
1825  r = MsiEvaluateConditionA(hpkg, "one << two");
1826  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1827 
1828  MsiSetPropertyA(hpkg, "one", "hi");
1829  MsiSetPropertyA(hpkg, "two", "hi");
1830  r = MsiEvaluateConditionA(hpkg, "one << two");
1831  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1832 
1833  MsiSetPropertyA(hpkg, "one", "abcdhithere");
1834  MsiSetPropertyA(hpkg, "two", "hi");
1835  r = MsiEvaluateConditionA(hpkg, "one << two");
1836  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1837 
1838  MsiSetPropertyA(hpkg, "one", "");
1839  MsiSetPropertyA(hpkg, "two", "hi");
1840  r = MsiEvaluateConditionA(hpkg, "one << two");
1841  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1842 
1843  MsiSetPropertyA(hpkg, "one", "hithere");
1844  MsiSetPropertyA(hpkg, "two", "");
1845  r = MsiEvaluateConditionA(hpkg, "one << two");
1846  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1847 
1848  MsiSetPropertyA(hpkg, "one", "");
1849  MsiSetPropertyA(hpkg, "two", "");
1850  r = MsiEvaluateConditionA(hpkg, "one << two");
1851  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1852 
1853  MsiSetPropertyA(hpkg, "one", "1234");
1854  MsiSetPropertyA(hpkg, "two", "1");
1855  r = MsiEvaluateConditionA(hpkg, "one << two");
1856  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1857 
1858  MsiSetPropertyA(hpkg, "one", "1234 one");
1859  MsiSetPropertyA(hpkg, "two", "1");
1860  r = MsiEvaluateConditionA(hpkg, "one << two");
1861  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1862 
1863  MsiSetPropertyA(hpkg, "one", "hithere");
1864  MsiSetPropertyA(hpkg, "two", "there");
1865  r = MsiEvaluateConditionA(hpkg, "one >> two");
1866  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1867 
1868  MsiSetPropertyA(hpkg, "one", "hithere");
1869  MsiSetPropertyA(hpkg, "two", "hi");
1870  r = MsiEvaluateConditionA(hpkg, "one >> two");
1871  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1872 
1873  MsiSetPropertyA(hpkg, "one", "there");
1874  MsiSetPropertyA(hpkg, "two", "hithere");
1875  r = MsiEvaluateConditionA(hpkg, "one >> two");
1876  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1877 
1878  MsiSetPropertyA(hpkg, "one", "there");
1879  MsiSetPropertyA(hpkg, "two", "there");
1880  r = MsiEvaluateConditionA(hpkg, "one >> two");
1881  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1882 
1883  MsiSetPropertyA(hpkg, "one", "abcdhithere");
1884  MsiSetPropertyA(hpkg, "two", "hi");
1885  r = MsiEvaluateConditionA(hpkg, "one >> two");
1886  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1887 
1888  MsiSetPropertyA(hpkg, "one", "");
1889  MsiSetPropertyA(hpkg, "two", "there");
1890  r = MsiEvaluateConditionA(hpkg, "one >> two");
1891  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1892 
1893  MsiSetPropertyA(hpkg, "one", "there");
1894  MsiSetPropertyA(hpkg, "two", "");
1895  r = MsiEvaluateConditionA(hpkg, "one >> two");
1896  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1897 
1898  MsiSetPropertyA(hpkg, "one", "");
1899  MsiSetPropertyA(hpkg, "two", "");
1900  r = MsiEvaluateConditionA(hpkg, "one >> two");
1901  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1902 
1903  MsiSetPropertyA(hpkg, "one", "1234");
1904  MsiSetPropertyA(hpkg, "two", "4");
1905  r = MsiEvaluateConditionA(hpkg, "one >> two");
1906  ok( r == MSICONDITION_FALSE, "wrong return val\n");
1907 
1908  MsiSetPropertyA(hpkg, "one", "one 1234");
1909  MsiSetPropertyA(hpkg, "two", "4");
1910  r = MsiEvaluateConditionA(hpkg, "one >> two");
1911  ok( r == MSICONDITION_TRUE, "wrong return val\n");
1912 
1913  MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL); /* make sure it's empty */
1914 
1915  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1916  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1917 
1918  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1919  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1920 
1921  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1922  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1923 
1924  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1925  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1926 
1927  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1928  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1929 
1930  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1931  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1932 
1933  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1934  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1935 
1936  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1937  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1938 
1939  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1940  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1941 
1942  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1943  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1944 
1945  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1946  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1947 
1948  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1949  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1950 
1951  r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1952  ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1953 
1954  r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1955  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1956 
1957  r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1958  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1959 
1960  r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1961  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1962 
1963  r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1964  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1965 
1966  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1967  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1968 
1969  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1970  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1971 
1972  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1973  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1974 
1975  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1976  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1977 
1978  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1979  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1980 
1981  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1982  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1983 
1984  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1985  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1986 
1987  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1988  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1989 
1990  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1991  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1992 
1993  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1994  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1995 
1996  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1997  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1998 
1999  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
2000  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2001 
2002  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
2003  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2004 
2005  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
2006  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2007 
2008  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
2009  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2010 
2011  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
2012  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2013 
2014  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
2015  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2016 
2017  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
2018  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2019 
2020  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
2021  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2022 
2023  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
2024  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2025 
2026  MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
2027  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
2028  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2029 
2030  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
2031  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2032 
2033  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
2034  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2035 
2036  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
2037  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2038 
2039  r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
2040  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2041 
2042  MsiSetPropertyA(hpkg, "one", "1");
2043  r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
2044  ok( r == MSICONDITION_FALSE, "wrong return val\n");
2045 
2046  MsiSetPropertyA(hpkg, "X", "5.0");
2047 
2048  r = MsiEvaluateConditionA(hpkg, "X != \"\"");
2049  ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2050 
2051  r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
2052  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2053 
2054  r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
2055  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2056 
2057  r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
2058  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2059 
2060  r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
2061  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2062 
2063  r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2064  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2065 
2066  r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
2067  ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
2068 
2069  /* feature doesn't exist */
2070  r = MsiEvaluateConditionA(hpkg, "&nofeature");
2071  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2072  r = MsiEvaluateConditionA(hpkg, "&nofeature=\"\"");
2073  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2074  r = MsiEvaluateConditionA(hpkg, "!nofeature=\"\"");
2075  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2076  MsiEvaluateConditionA(hpkg, "$nocomponent=\"\"");
2077  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2078  MsiEvaluateConditionA(hpkg, "?nocomponent=\"\"");
2079  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2080 
2081  MsiSetPropertyA(hpkg, "A", "2");
2082  MsiSetPropertyA(hpkg, "X", "50");
2083 
2084  r = MsiEvaluateConditionA(hpkg, "2 <= X");
2085  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2086 
2087  r = MsiEvaluateConditionA(hpkg, "A <= X");
2088  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2089 
2090  r = MsiEvaluateConditionA(hpkg, "A <= 50");
2091  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2092 
2093  MsiSetPropertyA(hpkg, "X", "50val");
2094 
2095  r = MsiEvaluateConditionA(hpkg, "2 <= X");
2096  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2097 
2098  r = MsiEvaluateConditionA(hpkg, "A <= X");
2099  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2100 
2101  MsiSetPropertyA(hpkg, "A", "7");
2102  MsiSetPropertyA(hpkg, "X", "50");
2103 
2104  r = MsiEvaluateConditionA(hpkg, "7 <= X");
2105  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2106 
2107  r = MsiEvaluateConditionA(hpkg, "A <= X");
2108  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2109 
2110  r = MsiEvaluateConditionA(hpkg, "A <= 50");
2111  ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
2112 
2113  MsiSetPropertyA(hpkg, "X", "50val");
2114 
2115  r = MsiEvaluateConditionA(hpkg, "2 <= X");
2116  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2117 
2118  r = MsiEvaluateConditionA(hpkg, "A <= X");
2119  ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
2120 
2121  r = MsiEvaluateConditionW(hpkg, cond1);
2123  "wrong return val (%d)\n", r);
2124 
2125  r = MsiEvaluateConditionW(hpkg, cond2);
2127  "wrong return val (%d)\n", r);
2128 
2129  r = MsiEvaluateConditionW(hpkg, cond3);
2131  "wrong return val (%d)\n", r);
2132 
2133  r = MsiEvaluateConditionW(hpkg, cond4);
2135  "wrong return val (%d)\n", r);
2136 
2137  MsiCloseHandle( hpkg );
2139 }
2140 
2141 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
2142 {
2143  UINT r;
2144  DWORD sz;
2145  char buffer[2];
2146 
2147  sz = sizeof buffer;
2148  strcpy(buffer,"x");
2149  r = MsiGetPropertyA( hpkg, prop, buffer, &sz );
2150  return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
2151 }
2152 
2153 static void test_props(void)
2154 {
2155  MSIHANDLE hpkg, hdb;
2156  UINT r;
2157  DWORD sz;
2158  char buffer[0x100];
2159 
2160  hdb = create_package_db();
2161 
2162  create_property_table(hdb);
2163  add_property_entry(hdb, "'MetadataCompName', 'Photoshop.dll'");
2164 
2165  r = package_from_db( hdb, &hpkg );
2167  {
2168  skip("Not enough rights to perform tests\n");
2170  return;
2171  }
2172  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2173 
2174  /* test invalid values */
2175  r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2176  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2177 
2178  r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2179  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2180 
2181  r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2182  ok( r == ERROR_SUCCESS, "wrong return val\n");
2183 
2184  r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2185  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2186 
2187  /* test retrieving an empty/nonexistent property */
2188  sz = sizeof buffer;
2189  r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2190  ok( r == ERROR_SUCCESS, "wrong return val\n");
2191  ok( sz == 0, "wrong size returned\n");
2192 
2193  check_prop_empty( hpkg, "boo");
2194  sz = 0;
2195  strcpy(buffer,"x");
2196  r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2197  ok( r == ERROR_MORE_DATA, "wrong return val\n");
2198  ok( !strcmp(buffer,"x"), "buffer was changed\n");
2199  ok( sz == 0, "wrong size returned\n");
2200 
2201  sz = 1;
2202  strcpy(buffer,"x");
2203  r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2204  ok( r == ERROR_SUCCESS, "wrong return val\n");
2205  ok( buffer[0] == 0, "buffer was not changed\n");
2206  ok( sz == 0, "wrong size returned\n");
2207 
2208  /* set the property to something */
2209  r = MsiSetPropertyA( 0, NULL, NULL );
2210  ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
2211 
2212  r = MsiSetPropertyA( hpkg, NULL, NULL );
2213  ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2214 
2215  r = MsiSetPropertyA( hpkg, "", NULL );
2216  ok( r == ERROR_SUCCESS, "wrong return val\n");
2217 
2218  /* try set and get some illegal property identifiers */
2219  r = MsiSetPropertyA( hpkg, "", "asdf" );
2220  ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
2221 
2222  r = MsiSetPropertyA( hpkg, "=", "asdf" );
2223  ok( r == ERROR_SUCCESS, "wrong return val\n");
2224 
2225  r = MsiSetPropertyA( hpkg, " ", "asdf" );
2226  ok( r == ERROR_SUCCESS, "wrong return val\n");
2227 
2228  r = MsiSetPropertyA( hpkg, "'", "asdf" );
2229  ok( r == ERROR_SUCCESS, "wrong return val\n");
2230 
2231  sz = sizeof buffer;
2232  buffer[0]=0;
2233  r = MsiGetPropertyA( hpkg, "'", buffer, &sz );
2234  ok( r == ERROR_SUCCESS, "wrong return val\n");
2235  ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
2236 
2237  /* set empty values */
2238  r = MsiSetPropertyA( hpkg, "boo", NULL );
2239  ok( r == ERROR_SUCCESS, "wrong return val\n");
2240  ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2241 
2242  r = MsiSetPropertyA( hpkg, "boo", "" );
2243  ok( r == ERROR_SUCCESS, "wrong return val\n");
2244  ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2245 
2246  /* set a non-empty value */
2247  r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2248  ok( r == ERROR_SUCCESS, "wrong return val\n");
2249 
2250  sz = 1;
2251  strcpy(buffer,"x");
2252  r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2253  ok( r == ERROR_MORE_DATA, "wrong return val\n");
2254  ok( buffer[0] == 0, "buffer was not changed\n");
2255  ok( sz == 3, "wrong size returned\n");
2256 
2257  sz = 4;
2258  strcpy(buffer,"x");
2259  r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2260  ok( r == ERROR_SUCCESS, "wrong return val\n");
2261  ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
2262  ok( sz == 3, "wrong size returned\n");
2263 
2264  sz = 3;
2265  strcpy(buffer,"x");
2266  r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2267  ok( r == ERROR_MORE_DATA, "wrong return val\n");
2268  ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
2269  ok( sz == 3, "wrong size returned\n");
2270 
2271  r = MsiSetPropertyA(hpkg, "SourceDir", "foo");
2272  ok( r == ERROR_SUCCESS, "wrong return val\n");
2273 
2274  sz = 4;
2275  r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz);
2276  ok( r == ERROR_SUCCESS, "wrong return val\n");
2277  ok( !strcmp(buffer,""), "buffer wrong\n");
2278  ok( sz == 0, "wrong size returned\n");
2279 
2280  sz = 4;
2281  r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz);
2282  ok( r == ERROR_SUCCESS, "wrong return val\n");
2283  ok( !strcmp(buffer,""), "buffer wrong\n");
2284  ok( sz == 0, "wrong size returned\n");
2285 
2286  sz = 4;
2287  r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz);
2288  ok( r == ERROR_SUCCESS, "wrong return val\n");
2289  ok( !strcmp(buffer,"foo"), "buffer wrong\n");
2290  ok( sz == 3, "wrong size returned\n");
2291 
2292  r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll");
2293  ok( r == ERROR_SUCCESS, "wrong return val\n");
2294 
2295  sz = 0;
2296  r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz );
2297  ok( r == ERROR_SUCCESS, "return wrong\n");
2298  ok( sz == 13, "size wrong (%d)\n", sz);
2299 
2300  sz = 13;
2301  r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz );
2302  ok( r == ERROR_MORE_DATA, "return wrong\n");
2303  ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n");
2304 
2305  r = MsiSetPropertyA(hpkg, "property", "value");
2306  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2307 
2308  sz = 6;
2309  r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2310  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2311  ok( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer);
2312 
2313  r = MsiSetPropertyA(hpkg, "property", NULL);
2314  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2315 
2316  sz = 6;
2317  r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2318  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2319  ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2320 
2321  MsiCloseHandle( hpkg );
2323 }
2324 
2326 {
2327  MSIHANDLE hview, hrec;
2328  BOOL found = FALSE;
2329  CHAR buffer[MAX_PATH];
2330  DWORD sz;
2331  UINT r;
2332 
2333  r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2334  ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2335  r = MsiViewExecute(hview, 0);
2336  ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2337 
2338  if (len < 0) len = lstrlenA(val);
2339 
2340  while (r == ERROR_SUCCESS && !found)
2341  {
2342  r = MsiViewFetch(hview, &hrec);
2343  if (r != ERROR_SUCCESS) break;
2344 
2345  sz = MAX_PATH;
2346  r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2347  if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2348  {
2349  sz = MAX_PATH;
2350  r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2351  if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2352  {
2353  ok(sz == len, "wrong size %u\n", sz);
2354  found = TRUE;
2355  }
2356  }
2357 
2358  MsiCloseHandle(hrec);
2359  }
2360  MsiViewClose(hview);
2361  MsiCloseHandle(hview);
2362  return found;
2363 }
2364 
2365 static void test_property_table(void)
2366 {
2367  const char *query;
2368  UINT r;
2369  MSIHANDLE hpkg, hdb, hrec;
2370  char buffer[MAX_PATH], package[10];
2371  DWORD sz;
2372  BOOL found;
2373 
2374  hdb = create_package_db();
2375  ok( hdb, "failed to create package\n");
2376 
2377  r = package_from_db(hdb, &hpkg);
2379  {
2380  skip("Not enough rights to perform tests\n");
2382  return;
2383  }
2384  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2385 
2386  MsiCloseHandle(hdb);
2387 
2388  hdb = MsiGetActiveDatabase(hpkg);
2389 
2390  query = "CREATE TABLE `_Property` ( "
2391  "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2392  r = run_query(hdb, query);
2393  ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2394 
2395  MsiCloseHandle(hdb);
2396  MsiCloseHandle(hpkg);
2398 
2399  hdb = create_package_db();
2400  ok( hdb, "failed to create package\n");
2401 
2402  query = "CREATE TABLE `_Property` ( "
2403  "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2404  r = run_query(hdb, query);
2405  ok(r == ERROR_SUCCESS, "failed to create table\n");
2406 
2407  query = "ALTER `_Property` ADD `foo` INTEGER";
2408  r = run_query(hdb, query);
2409  ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2410 
2411  query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2412  r = run_query(hdb, query);
2413  ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2414 
2415  query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2416  r = run_query(hdb, query);
2417  ok(r == ERROR_SUCCESS, "failed to add column\n");
2418 
2419  sprintf(package, "#%i", hdb);
2420  r = MsiOpenPackageA(package, &hpkg);
2421  ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2422  if (r == ERROR_SUCCESS)
2423  MsiCloseHandle(hpkg);
2424 
2425  r = MsiCloseHandle(hdb);
2426  ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2427 
2428  hdb = create_package_db();
2429  ok (hdb, "failed to create package database\n");
2430 
2431  create_property_table(hdb);
2432  add_property_entry(hdb, "'prop', 'val'");
2433 
2435  add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2436 
2437  r = package_from_db(hdb, &hpkg);
2438  ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2439 
2440  MsiCloseHandle(hdb);
2441 
2442  sz = MAX_PATH;
2443  r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2444  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2445  ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2446 
2447  hdb = MsiGetActiveDatabase(hpkg);
2448 
2449  found = find_prop_in_property(hdb, "prop", "val", -1);
2450  ok(found, "prop should be in the _Property table\n");
2451 
2452  add_property_entry(hdb, "'dantes', 'mercedes'");
2453 
2454  query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2455  r = do_query(hdb, query, &hrec);
2456  ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2457 
2458  found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2459  ok(found == FALSE, "dantes should not be in the _Property table\n");
2460 
2461  sz = MAX_PATH;
2462  lstrcpyA(buffer, "aaa");
2463  r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2464  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2465  ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2466 
2467  r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2468  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2469 
2470  found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2471  ok(found == TRUE, "dantes should be in the _Property table\n");
2472 
2473  r = MsiDoActionA( hpkg, "EmbedNull" );
2474  ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2475 
2476  sz = MAX_PATH;
2477  memset( buffer, 'a', sizeof(buffer) );
2478  r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2479  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2480  ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2481  ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2482 
2483  found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2484  ok(found == TRUE, "prop2 should be in the _Property table\n");
2485 
2486  MsiCloseHandle(hdb);
2487  MsiCloseHandle(hpkg);
2489 }
2490 
2491 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2492 {
2493  MSIHANDLE htab = 0;
2494  UINT res;
2495 
2496  res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2497  if( res == ERROR_SUCCESS )
2498  {
2499  UINT r;
2500 
2501  r = MsiViewExecute( htab, hrec );
2502  if( r != ERROR_SUCCESS )
2503  {
2504  res = r;
2505  fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2506  }
2507 
2508  r = MsiViewClose( htab );
2509  if( r != ERROR_SUCCESS )
2510  res = r;
2511 
2512  r = MsiCloseHandle( htab );
2513  if( r != ERROR_SUCCESS )
2514  res = r;
2515  }
2516  return res;
2517 }
2518 
2519 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2520 {
2521  return try_query_param( hdb, szQuery, 0 );
2522 }
2523 
2525 {
2526  MSIHANDLE summary;
2527  UINT r;
2528 
2529  r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2530  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2531 
2532  r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2533  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2534 
2535  r = MsiSummaryInfoPersist(summary);
2536  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2537 
2538  MsiCloseHandle(summary);
2539 }
2540 
2542 {
2543  MSIHANDLE summary;
2544  UINT r;
2545 
2546  r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2547  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2548 
2549  r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2550  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2551 
2552  r = MsiSummaryInfoPersist(summary);
2553  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2554 
2555  MsiCloseHandle(summary);
2556 }
2557 
2558 static void test_msipackage(void)
2559 {
2560  MSIHANDLE hdb = 0, hpack = 100;
2561  UINT r;
2562  const char *query;
2563  char name[10];
2564 
2565  /* NULL szPackagePath */
2566  r = MsiOpenPackageA(NULL, &hpack);
2567  ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2568 
2569  /* empty szPackagePath */
2570  r = MsiOpenPackageA("", &hpack);
2572  {
2573  skip("Not enough rights to perform tests\n");
2574  return;
2575  }
2576  todo_wine
2577  {
2578  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2579  }
2580 
2581  if (r == ERROR_SUCCESS)
2582  MsiCloseHandle(hpack);
2583 
2584  /* nonexistent szPackagePath */
2585  r = MsiOpenPackageA("nonexistent", &hpack);
2586  ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2587 
2588  /* NULL hProduct */
2590  ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2591 
2592  name[0]='#';
2593  name[1]=0;
2594  r = MsiOpenPackageA(name, &hpack);
2595  ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2596 
2598  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2599 
2600  /* database exists, but is empty */
2601  sprintf(name, "#%d", hdb);
2602  r = MsiOpenPackageA(name, &hpack);
2604  "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2605 
2606  query = "CREATE TABLE `Property` ( "
2607  "`Property` CHAR(72), `Value` CHAR(0) "
2608  "PRIMARY KEY `Property`)";
2609  r = try_query(hdb, query);
2610  ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2611 
2612  query = "CREATE TABLE `InstallExecuteSequence` ("
2613  "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2614  "PRIMARY KEY `Action`)";
2615  r = try_query(hdb, query);
2616  ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2617 
2618  /* a few key tables exist */
2619  sprintf(name, "#%d", hdb);
2620  r = MsiOpenPackageA(name, &hpack);
2622  "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2623 
2624  MsiCloseHandle(hdb);
2626 
2627  /* start with a clean database to show what constitutes a valid package */
2629  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2630 
2631  sprintf(name, "#%d", hdb);
2632 
2633  /* The following summary information props must exist:
2634  * - PID_REVNUMBER
2635  * - PID_PAGECOUNT
2636  */
2637 
2638  set_summary_dword(hdb, PID_PAGECOUNT, 100);
2639  r = MsiOpenPackageA(name, &hpack);
2641  "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2642 
2643  set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2644  r = MsiOpenPackageA(name, &hpack);
2645  ok(r == ERROR_SUCCESS,
2646  "Expected ERROR_SUCCESS, got %d\n", r);
2647 
2648  MsiCloseHandle(hpack);
2649  MsiCloseHandle(hdb);
2651 }
2652 
2653 static void test_formatrecord2(void)
2654 {
2655  MSIHANDLE hpkg, hrec ;
2656  char buffer[0x100];
2657  DWORD sz;
2658  UINT r;
2659 
2660  r = package_from_db(create_package_db(), &hpkg);
2662  {
2663  skip("Not enough rights to perform tests\n");
2665  return;
2666  }
2667  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2668 
2669  r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2670  ok( r == ERROR_SUCCESS, "set property failed\n");
2671 
2672  hrec = MsiCreateRecord(2);
2673  ok(hrec, "create record failed\n");
2674 
2675  r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2676  ok( r == ERROR_SUCCESS, "format record failed\n");
2677 
2678  buffer[0] = 0;
2679  sz = sizeof buffer;
2680  r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2681  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2682 
2683  r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2684  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2685  r = MsiRecordSetStringA(hrec, 1, "hoo");
2686  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2687  sz = sizeof buffer;
2688  r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2689  ok( sz == 3, "size wrong\n");
2690  ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2691  ok( r == ERROR_SUCCESS, "format failed\n");
2692 
2693  r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2694  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2695  sz = sizeof buffer;
2696  r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2697  ok( sz == 3, "size wrong\n");
2698  ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2699  ok( r == ERROR_SUCCESS, "format failed\n");
2700 
2701  r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2702  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2703  r = MsiRecordSetStringA(hrec, 1, "hoo");
2704  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2705  sz = sizeof buffer;
2706  r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2707  ok( sz == 3, "size wrong\n");
2708  ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2709  ok( r == ERROR_SUCCESS, "format failed\n");
2710 
2711  r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2712  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2713  sz = sizeof buffer;
2714  r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2715  ok( sz == 1, "size wrong\n");
2716  ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2717  ok( r == ERROR_SUCCESS, "format failed\n");
2718 
2719  SetEnvironmentVariableA("FOO", "BAR");
2720  r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2721  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2722  sz = sizeof buffer;
2723  r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2724  ok( sz == 3, "size wrong\n");
2725  ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2726  ok( r == ERROR_SUCCESS, "format failed\n");
2727 
2728  r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2729  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2730  r = MsiRecordSetStringA(hrec, 1, "%FOO");
2731  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2732  sz = sizeof buffer;
2733  r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2734  ok( sz == 3, "size wrong\n");
2735  ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2736  ok( r == ERROR_SUCCESS, "format failed\n");
2737 
2738  MsiCloseHandle( hrec );
2739  MsiCloseHandle( hpkg );
2741 }
2742 
2743 static void test_formatrecord_tables(void)
2744 {
2745  MSIHANDLE hdb, hrec, hpkg = 0;
2746  CHAR buf[MAX_PATH];
2747  CHAR curr_dir[MAX_PATH];
2749  CHAR root[MAX_PATH];
2750  DWORD size;
2751  UINT r;
2752 
2753  GetCurrentDirectoryA( MAX_PATH, curr_dir );
2754 
2755  hdb = create_package_db();
2756  ok ( hdb, "failed to create package database\n");
2757 
2758  add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
2759  add_directory_entry( hdb, "'ReallyLongDir', 'TARGETDIR', "
2760  "'I am a really long directory'" );
2761 
2762  create_feature_table( hdb );
2763  add_feature_entry( hdb, "'occipitofrontalis', '', '', '', 2, 1, '', 0" );
2764 
2765  create_component_table( hdb );
2766  add_component_entry( hdb, "'frontal', '', 'TARGETDIR', 0, '', 'frontal_file'" );
2767  add_component_entry( hdb, "'parietal', '', 'TARGETDIR', 1, '', 'parietal_file'" );
2768  add_component_entry( hdb, "'temporal', '', 'ReallyLongDir', 0, '', 'temporal_file'" );
2769 
2771  add_feature_components_entry( hdb, "'occipitofrontalis', 'frontal'" );
2772  add_feature_components_entry( hdb, "'occipitofrontalis', 'parietal'" );
2773  add_feature_components_entry( hdb, "'occipitofrontalis', 'temporal'" );
2774 
2775  create_file_table( hdb );
2776  add_file_entry( hdb, "'frontal_file', 'frontal', 'frontal.txt', 0, '', '1033', 8192, 1" );
2777  add_file_entry( hdb, "'parietal_file', 'parietal', 'parietal.txt', 0, '', '1033', 8192, 1" );
2778  add_file_entry( hdb, "'temporal_file', 'temporal', 'temporal.txt', 0, '', '1033', 8192, 1" );
2779 
2781  add_custom_action_entry( hdb, "'MyCustom', 51, 'prop', '[!temporal_file]'" );
2782  add_custom_action_entry( hdb, "'EscapeIt1', 51, 'prop', '[\\[]Bracket Text[\\]]'" );
2783  add_custom_action_entry( hdb, "'EscapeIt2', 51, 'prop', '[\\xabcd]'" );
2784  add_custom_action_entry( hdb, "'EscapeIt3', 51, 'prop', '[abcd\\xefgh]'" );
2785  add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop', '[~]np'" );
2786 
2787  r = package_from_db( hdb, &hpkg );
2789  {
2790  skip("Not enough rights to perform tests\n");
2791  MsiCloseHandle( hdb );
2792  DeleteFileA( msifile );
2793  return;
2794  }
2795  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
2796 
2797  MsiCloseHandle( hdb );
2798 
2799  r = MsiSetPropertyA( hpkg, "imaprop", "ringer" );
2800  ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2801 
2802  hrec = MsiCreateRecord( 1 );
2803 
2804  /* property doesn't exist */
2805  size = MAX_PATH;
2806  /*MsiRecordSetStringA( hrec, 0, "[1]" ); */
2807  MsiRecordSetStringA( hrec, 1, "[idontexist]" );
2808  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2809  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2810  ok( !lstrcmpA( buf, "1: " ), "Expected '1: ', got %s\n", buf );
2811 
2812  /* property exists */
2813  size = MAX_PATH;
2814  MsiRecordSetStringA( hrec, 1, "[imaprop]" );
2815  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2816  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2817  ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2818 
2819  size = MAX_PATH;
2820  MsiRecordSetStringA( hrec, 0, "1: [1] " );
2821  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2822  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2823  ok( !lstrcmpA( buf, "1: ringer " ), "Expected '1: ringer ', got %s\n", buf );
2824 
2825  /* environment variable doesn't exist */
2826  size = MAX_PATH;
2827  MsiRecordSetStringA( hrec, 1, "[%idontexist]" );
2828  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2829  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2830  ok( !lstrcmpA( buf, "1: " ), "Expected '1: ', got %s\n", buf );
2831 
2832  /* environment variable exists */
2833  size = MAX_PATH;
2834  SetEnvironmentVariableA( "crazyvar", "crazyval" );
2835  MsiRecordSetStringA( hrec, 1, "[%crazyvar]" );
2836  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2837  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2838  ok( !lstrcmpA( buf, "1: crazyval " ), "Expected '1: crazyval ', got %s\n", buf );
2839 
2840  /* file key before CostInitialize */
2841  size = MAX_PATH;
2842  MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2843  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2844  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2845  ok( !lstrcmpA( buf, "1: " ), "Expected '1: ', got %s\n", buf );
2846 
2848 
2849  r = MsiDoActionA(hpkg, "CostInitialize");
2850  ok( r == ERROR_SUCCESS, "CostInitialize failed: %d\n", r);
2851 
2852  r = MsiDoActionA(hpkg, "FileCost");
2853  ok( r == ERROR_SUCCESS, "FileCost failed: %d\n", r);
2854 
2855  r = MsiDoActionA(hpkg, "CostFinalize");
2856  ok( r == ERROR_SUCCESS, "CostFinalize failed: %d\n", r);
2857 
2858  size = MAX_PATH;
2859  MsiGetPropertyA( hpkg, "ROOTDRIVE", root, &size );
2860 
2861  sprintf( expected, "1: %sfrontal.txt ", root);
2862 
2863  /* frontal full file key */
2864  size = MAX_PATH;
2865  MsiRecordSetStringA( hrec, 1, "[#frontal_file]" );
2866  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2867  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2868  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2869 
2870  /* frontal short file key */
2871  size = MAX_PATH;
2872  MsiRecordSetStringA( hrec, 1, "[!frontal_file]" );
2873  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2874  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2875  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2876 
2877  sprintf( expected, "1: %sI am a really long directory\\temporal.txt ", root);
2878 
2879  /* temporal full file key */
2880  size = MAX_PATH;
2881  MsiRecordSetStringA( hrec, 1, "[#temporal_file]" );
2882  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2883  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2884  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2885 
2886  /* temporal short file key */
2887  size = MAX_PATH;
2888  MsiRecordSetStringA( hrec, 1, "[!temporal_file]" );
2889  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2890  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2891  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2892 
2893  /* custom action 51, files don't exist */
2894  r = MsiDoActionA( hpkg, "MyCustom" );
2895  ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2896 
2897  sprintf( expected, "%sI am a really long directory\\temporal.txt", root);
2898 
2899  size = MAX_PATH;
2900  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2901  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2902  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2903 
2904  sprintf( buf, "%sI am a really long directory", root );
2905  CreateDirectoryA( buf, NULL );
2906 
2907  lstrcatA( buf, "\\temporal.txt" );
2908  create_test_file( buf );
2909 
2910  /* custom action 51, files exist */
2911  r = MsiDoActionA( hpkg, "MyCustom" );
2912  ok( r == ERROR_SUCCESS, "MyCustom failed: %d\n", r);
2913 
2914  size = MAX_PATH;
2915  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2916  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2917  todo_wine
2918  {
2919  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2920  }
2921 
2922  /* custom action 51, escaped text 1 */
2923  r = MsiDoActionA( hpkg, "EscapeIt1" );
2924  ok( r == ERROR_SUCCESS, "EscapeIt1 failed: %d\n", r);
2925 
2926  size = MAX_PATH;
2927  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2928  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2929  ok( !lstrcmpA( buf, "[Bracket Text]" ), "Expected '[Bracket Text]', got %s\n", buf);
2930 
2931  /* custom action 51, escaped text 2 */
2932  r = MsiDoActionA( hpkg, "EscapeIt2" );
2933  ok( r == ERROR_SUCCESS, "EscapeIt2 failed: %d\n", r);
2934 
2935  size = MAX_PATH;
2936  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2937  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2938  ok( !lstrcmpA( buf, "x" ), "Expected 'x', got %s\n", buf);
2939 
2940  /* custom action 51, escaped text 3 */
2941  r = MsiDoActionA( hpkg, "EscapeIt3" );
2942  ok( r == ERROR_SUCCESS, "EscapeIt3 failed: %d\n", r);
2943 
2944  size = MAX_PATH;
2945  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2946  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2947  ok( !lstrcmpA( buf, "" ), "Expected '', got %s\n", buf);
2948 
2949  /* custom action 51, embedded null */
2950  r = MsiDoActionA( hpkg, "EmbedNull" );
2951  ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2952 
2953  size = MAX_PATH;
2954  memset( buf, 'a', sizeof(buf) );
2955  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2956  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2957  ok( !memcmp( buf, "\0np", sizeof("\0np") ), "wrong value\n");
2958  ok( size == sizeof("\0np") - 1, "got %u\n", size );
2959 
2960  r = MsiSetPropertyA( hpkg, "prop", "[~]np" );
2961  ok( r == ERROR_SUCCESS, "cannot set property: %d\n", r);
2962 
2963  size = MAX_PATH;
2964  memset( buf, 'a', sizeof(buf) );
2965  r = MsiGetPropertyA( hpkg, "prop", buf, &size );
2966  ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2967  ok( !lstrcmpA( buf, "[~]np" ), "Expected '[~]np', got %s\n", buf);
2968 
2969  sprintf( expected, "1: %sI am a really long directory\\ ", root);
2970 
2971  /* component with INSTALLSTATE_LOCAL */
2972  size = MAX_PATH;
2973  MsiRecordSetStringA( hrec, 1, "[$temporal]" );
2974  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2975  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2976  ok( !lstrcmpA( buf, expected ), "Expected \"%s\", got \"%s\"\n", expected, buf);
2977 
2978  r = MsiSetComponentStateA( hpkg, "temporal", INSTALLSTATE_SOURCE );
2979  ok( r == ERROR_SUCCESS, "failed to set install state: %d\n", r);
2980 
2981  /* component with INSTALLSTATE_SOURCE */
2982  lstrcpyA( expected, "1: " );
2983  lstrcatA( expected, curr_dir );
2984  if (strlen(curr_dir) > 3) lstrcatA( expected, "\\" );
2985  lstrcatA( expected, " " );
2986  size = MAX_PATH;
2987  MsiRecordSetStringA( hrec, 1, "[$parietal]" );
2988  r = MsiFormatRecordA( hpkg, hrec, buf, &size );
2989  ok( r == ERROR_SUCCESS, "format record failed: %d\n", r);
2990  ok( !lstrcmpA( buf, expected ), "Expected '%s', got '%s'\n", expected, buf);
2991 
2992  sprintf( buf, "%sI am a really long directory\\temporal.txt", root );
2993  DeleteFileA( buf );
2994 
2995  sprintf( buf, "%sI am a really long directory", root );
2996  RemoveDirectoryA( buf );
2997 
2998  MsiCloseHandle( hrec );
2999  MsiCloseHandle( hpkg );
3000  DeleteFileA( msifile );
3001 }
3002 
3003 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
3004  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3005 {
3006  UINT r;
3007  INSTALLSTATE state = 0xdeadbee;
3008  INSTALLSTATE action = 0xdeadbee;
3009 
3010  r = MsiGetFeatureStateA( package, feature, &state, &action );
3011  ok( r == error, "%u: expected %d got %d\n", line, error, r );
3012  if (r == ERROR_SUCCESS)
3013  {
3014  ok( state == expected_state, "%u: expected state %d got %d\n",
3015  line, expected_state, state );
3016  todo_wine_if (todo)
3017  ok( action == expected_action, "%u: expected action %d got %d\n",
3018  line, expected_action, action );
3019  }
3020  else
3021  {
3022  ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
3023  todo_wine_if (todo)
3024  ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3025 
3026  }
3027 }
3028 
3029 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
3030  INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
3031 {
3032  UINT r;
3033  INSTALLSTATE state = 0xdeadbee;
3034  INSTALLSTATE action = 0xdeadbee;
3035 
3036  r = MsiGetComponentStateA( package, component, &state, &action );
3037  ok( r == error, "%u: expected %d got %d\n", line, error, r );
3038  if (r == ERROR_SUCCESS)
3039  {
3040  ok( state == expected_state, "%u: expected state %d got %d\n",
3041  line, expected_state, state );
3042  todo_wine_if (todo)
3043  ok( action == expected_action, "%u: expected action %d got %d\n",
3044  line, expected_action, action );
3045  }
3046  else
3047  {
3048  ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
3049  line, state );
3050  todo_wine_if (todo)
3051  ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3052  line, action );
3053  }
3054 }
3055 
3056 static void test_states(void)
3057 {
3058  static const char msifile2[] = "winetest2-package.msi";
3059  static const char msifile3[] = "winetest3-package.msi";
3060  static const char msifile4[] = "winetest4-package.msi";
3061  static const WCHAR msifile2W[] =
3062  {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
3063  static const WCHAR msifile3W[] =
3064  {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
3065  static const WCHAR msifile4W[] =
3066  {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
3067  char msi_cache_file[MAX_PATH];
3068  DWORD cache_file_name_len;
3070  MSIHANDLE hpkg;
3071  UINT r;
3072  MSIHANDLE hdb;
3073  BOOL is_broken;
3074 
3075  if (is_process_limited())
3076  {
3077  skip("process is limited\n");
3078  return;
3079  }
3080 
3081  hdb = create_package_db();
3082  ok ( hdb, "failed to create package database\n" );
3083 
3084  add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
3085 
3086  create_property_table( hdb );
3087  add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
3088  add_property_entry( hdb, "'ProductLanguage', '1033'" );
3089  add_property_entry( hdb, "'ProductName', 'MSITEST'" );
3090  add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
3091  add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
3092 
3094  add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
3095  add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
3096  add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
3097  add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
3098  add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
3099  add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
3100  add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );
3101  add_install_execute_sequence_entry( hdb, "'RegisterProduct', '', '6100'" );
3102  add_install_execute_sequence_entry( hdb, "'PublishFeatures', '', '6300'" );
3103  add_install_execute_sequence_entry( hdb, "'PublishProduct', '', '6400'" );
3104  add_install_execute_sequence_entry( hdb, "'InstallFinalize', '', '6600'" );
3105 
3106  create_media_table( hdb );
3107  add_media_entry( hdb, "'1', '3', '', '', 'DISK1', ''");
3108 
3109  create_feature_table( hdb );
3110 
3111  create_component_table( hdb );
3112 
3113  /* msidbFeatureAttributesFavorLocal */
3114  add_feature_entry( hdb, "'one', '', '', '', 2, 1, '', 0" );
3115 
3116  /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesLocalOnly */
3117  add_component_entry( hdb, "'alpha', '{467EC132-739D-4784-A37B-677AA43DBC94}', 'TARGETDIR', 0, '', 'alpha_file'" );
3118 
3119  /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSourceOnly */
3120  add_component_entry( hdb, "'beta', '{2C1F189C-24A6-4C34-B26B-994A6C026506}', 'TARGETDIR', 1, '', 'beta_file'" );
3121 
3122  /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesOptional */
3123  add_component_entry( hdb, "'gamma', '{C271E2A4-DE2E-4F70-86D1-6984AF7DE2CA}', 'TARGETDIR', 2, '', 'gamma_file'" );
3124 
3125  /* msidbFeatureAttributesFavorLocal:msidbComponentAttributesSharedDllRefCount */
3126  add_component_entry( hdb, "'theta', '{4EB3129D-81A8-48D5-9801-75600FED3DD9}', 'TARGETDIR', 8, '', 'theta_file'" );
3127 
3128  /* msidbFeatureAttributesFavorSource */
3129  add_feature_entry( hdb, "'two', '', '', '', 2, 1, '', 1" );
3130 
3131  /* msidbFeatureAttributesFavorSource:msidbComponentAttributesLocalOnly */
3132  add_component_entry( hdb, "'delta', '{938FD4F2-C648-4259-A03C-7AA3B45643F3}', 'TARGETDIR', 0, '', 'delta_file'" );
3133 
3134  /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3135  add_component_entry( hdb, "'epsilon', '{D59713B6-C11D-47F2-A395-1E5321781190}', 'TARGETDIR', 1, '', 'epsilon_file'" );
3136 
3137  /* msidbFeatureAttributesFavorSource:msidbComponentAttributesOptional */
3138  add_component_entry( hdb, "'zeta', '{377D33AB-2FAA-42B9-A629-0C0DAE9B9C7A}', 'TARGETDIR', 2, '', 'zeta_file'" );
3139 
3140  /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSharedDllRefCount */
3141  add_component_entry( hdb, "'iota', '{5D36F871-B5ED-4801-9E0F-C46B9E5C9669}', 'TARGETDIR', 8, '', 'iota_file'" );
3142 
3143  /* msidbFeatureAttributesFavorSource */
3144  add_feature_entry( hdb, "'three', '', '', '', 2, 1, '', 1" );
3145 
3146  /* msidbFeatureAttributesFavorLocal */
3147  add_feature_entry( hdb, "'four', '', '', '', 2, 1, '', 0" );
3148 
3149  /* disabled */
3150  add_feature_entry( hdb, "'five', '', '', '', 2, 0, '', 1" );
3151 
3152  /* msidbFeatureAttributesFavorSource:msidbComponentAttributesSourceOnly */
3153  add_component_entry( hdb, "'eta', '{DD89003F-0DD4-41B8-81C0-3411A7DA2695}', 'TARGETDIR', 1, '', 'eta_file'" );
3154 
3155  /* no feature parent:msidbComponentAttributesLocalOnly */
3156  add_component_entry( hdb, "'kappa', '{D6B93DC3-8DA5-4769-9888-42BFE156BB8B}', 'TARGETDIR', 1, '', 'kappa_file'" );
3157 
3158  /* msidbFeatureAttributesFavorLocal:removed */
3159  add_feature_entry( hdb, "'six', '', '', '', 2, 1, '', 0" );
3160 
3161  /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesLocalOnly */
3162  add_component_entry( hdb, "'lambda', '{6528C5E4-02A4-4636-A214-7A66A6C35B64}', 'TARGETDIR', 0, '', 'lambda_file'" );
3163 
3164  /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSourceOnly */
3165  add_component_entry( hdb, "'mu', '{97014BAB-6C56-4013-9A63-2BF913B42519}', 'TARGETDIR', 1, '', 'mu_file'" );
3166 
3167  /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesOptional */
3168  add_component_entry( hdb, "'nu', '{943DD0D8-5808-4954-8526-3B8493FEDDCD}', 'TARGETDIR', 2, '', 'nu_file'" );
3169 
3170  /* msidbFeatureAttributesFavorLocal:removed:msidbComponentAttributesSharedDllRefCount */
3171  add_component_entry( hdb, "'xi', '{D6CF9EF7-6FCF-4930-B34B-F938AEFF9BDB}', 'TARGETDIR', 8, '', 'xi_file'" );
3172 
3173  /* msidbFeatureAttributesFavorSource:removed */
3174  add_feature_entry( hdb, "'seven', '', '', '', 2, 1, '', 1" );
3175 
3176  /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesLocalOnly */
3177  add_component_entry( hdb, "'omicron', '{7B57521D-15DB-4141-9AA6-01D934A4433F}', 'TARGETDIR', 0, '', 'omicron_file'" );
3178 
3179  /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSourceOnly */
3180  add_component_entry( hdb, "'pi', '{FB85346B-378E-4492-8769-792305471C81}', 'TARGETDIR', 1, '', 'pi_file'" );
3181 
3182  /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesOptional */
3183  add_component_entry( hdb, "'rho', '{798F2047-7B0C-4783-8BB0-D703E554114B}', 'TARGETDIR', 2, '', 'rho_file'" );
3184 
3185  /* msidbFeatureAttributesFavorSource:removed:msidbComponentAttributesSharedDllRefCount */
3186  add_component_entry( hdb, "'sigma', '{5CE9DDA8-B67B-4736-9D93-99D61C5B93E7}', 'TARGETDIR', 8, '', 'sigma_file'" );
3187 
3188  /* msidbFeatureAttributesFavorLocal */
3189  add_feature_entry( hdb, "'eight', '', '', '', 2, 1, '', 0" );
3190 
3191  add_component_entry( hdb, "'tau', '{07DEB510-677C-4A6F-A0A6-7CD8EFEA77ED}', 'TARGETDIR', 1, '', 'tau_file'" );
3192 
3193  /* msidbFeatureAttributesFavorSource */
3194  add_feature_entry( hdb, "'nine', '', '', '', 2, 1, '', 1" );
3195 
3196  add_component_entry( hdb, "'phi', '{9F0594C5-35AD-43EA-94DD-8DF73FAA664D}', 'TARGETDIR', 1, '', 'phi_file'" );
3197 
3198  /* msidbFeatureAttributesFavorAdvertise */
3199  add_feature_entry( hdb, "'ten', '', '', '', 2, 1, '', 4" );
3200 
3201  add_component_entry( hdb, "'chi', '{E6B539AB-5DA9-4236-A2D2-E341A50B4C38}', 'TARGETDIR', 1, '', 'chi_file'" );
3202 
3203  /* msidbFeatureAttributesUIDisallowAbsent */
3204  add_feature_entry( hdb, "'eleven', '', '', '', 2, 1, '', 16" );
3205 
3206  add_component_entry( hdb, "'psi', '{A06B23B5-746B-427A-8A6E-FD6AC8F46A95}', 'TARGETDIR', 1, '', 'psi_file'" );
3207 
3208  /* high install level */
3209  add_feature_entry( hdb, "'twelve', '', '', '', 2, 2, '', 0" );
3210 
3211  add_component_entry( hdb, "'upsilon', '{557e0c04-ceba-4c58-86a9-4a73352e8cf6}', 'TARGETDIR', 1, '', 'upsilon_file'" );
3212 
3213  /* msidbFeatureAttributesFollowParent */
3214  add_feature_entry( hdb, "'thirteen', '', '', '', 2, 2, '', 2" );
3215 
3217  add_feature_components_entry( hdb, "'one', 'alpha'" );
3218  add_feature_components_entry( hdb, "'one', 'beta'" );
3219  add_feature_components_entry( hdb, "'one', 'gamma'" );
3220  add_feature_components_entry( hdb, "'one', 'theta'" );
3221  add_feature_components_entry( hdb, "'two', 'delta'" );
3222  add_feature_components_entry( hdb, "'two', 'epsilon'" );
3223  add_feature_components_entry( hdb, "'two', 'zeta'" );
3224  add_feature_components_entry( hdb, "'two', 'iota'" );
3225  add_feature_components_entry( hdb, "'three', 'eta'" );
3226  add_feature_components_entry( hdb, "'four', 'eta'" );
3227  add_feature_components_entry( hdb, "'five', 'eta'" );
3228  add_feature_components_entry( hdb, "'six', 'lambda'" );
3229  add_feature_components_entry( hdb, "'six', 'mu'" );
3230  add_feature_components_entry( hdb, "'six', 'nu'" );
3231  add_feature_components_entry( hdb, "'six', 'xi'" );
3232  add_feature_components_entry( hdb, "'seven', 'omicron'" );
3233  add_feature_components_entry( hdb, "'seven', 'pi'" );
3234  add_feature_components_entry( hdb, "'seven', 'rho'" );
3235  add_feature_components_entry( hdb, "'seven', 'sigma'" );
3236  add_feature_components_entry( hdb, "'eight', 'tau'" );
3237  add_feature_components_entry( hdb, "'nine', 'phi'" );
3238  add_feature_components_entry( hdb, "'ten', 'chi'" );
3239  add_feature_components_entry( hdb, "'eleven', 'psi'" );
3240  add_feature_components_entry( hdb, "'twelve', 'upsilon'" );
3241  add_feature_components_entry( hdb, "'thirteen', 'upsilon'" );
3242 
3243  create_file_table( hdb );
3244  add_file_entry( hdb, "'alpha_file', 'alpha', 'alpha.txt', 100, '', '1033', 8192, 1" );
3245  add_file_entry( hdb, "'beta_file', 'beta', 'beta.txt', 0, '', '1033', 8192, 1" );
3246  add_file_entry( hdb, "'gamma_file', 'gamma', 'gamma.txt', 0, '', '1033', 8192, 1" );
3247  add_file_entry( hdb, "'theta_file', 'theta', 'theta.txt', 0, '', '1033', 8192, 1" );
3248  add_file_entry( hdb, "'delta_file', 'delta', 'delta.txt', 0, '', '1033', 8192, 1" );
3249  add_file_entry( hdb, "'epsilon_file', 'epsilon', 'epsilon.txt', 0, '', '1033', 8192, 1" );
3250  add_file_entry( hdb, "'zeta_file', 'zeta', 'zeta.txt', 0, '', '1033', 8192, 1" );
3251  add_file_entry( hdb, "'iota_file', 'iota', 'iota.txt', 0, '', '1033', 8192, 1" );
3252 
3253  /* compressed file */
3254  add_file_entry( hdb, "'eta_file', 'eta', 'eta.txt', 0, '', '1033', 16384, 1" );
3255 
3256  add_file_entry( hdb, "'kappa_file', 'kappa', 'kappa.txt', 0, '', '1033', 8192, 1" );
3257  add_file_entry( hdb, "'lambda_file', 'lambda', 'lambda.txt', 100, '', '1033', 8192, 1" );
3258  add_file_entry( hdb, "'mu_file', 'mu', 'mu.txt', 100, '', '1033', 8192, 1" );
3259  add_file_entry( hdb, "'nu_file', 'nu', 'nu.txt', 100, '', '1033', 8192, 1" );
3260  add_file_entry( hdb, "'xi_file', 'xi', 'xi.txt', 100, '', '1033', 8192, 1" );
3261  add_file_entry( hdb, "'omicron_file', 'omicron', 'omicron.txt', 100, '', '1033', 8192, 1" );
3262  add_file_entry( hdb, "'pi_file', 'pi', 'pi.txt', 100, '', '1033', 8192, 1" );
3263  add_file_entry( hdb, "'rho_file', 'rho', 'rho.txt', 100, '', '1033', 8192, 1" );
3264  add_file_entry( hdb, "'sigma_file', 'sigma', 'sigma.txt', 100, '', '1033', 8192, 1" );
3265  add_file_entry( hdb, "'tau_file', 'tau', 'tau.txt', 100, '', '1033', 8192, 1" );
3266  add_file_entry( hdb, "'phi_file', 'phi', 'phi.txt', 100, '', '1033', 8192, 1" );
3267  add_file_entry( hdb, "'chi_file', 'chi', 'chi.txt', 100, '', '1033', 8192, 1" );
3268  add_file_entry( hdb, "'psi_file', 'psi', 'psi.txt', 100, '', '1033', 8192, 1" );
3269  add_file_entry( hdb, "'upsilon_file', 'upsilon', 'upsilon.txt', 0, '', '1033', 16384, 1" );
3270 
3271  r = MsiDatabaseCommit(hdb);
3272  ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r );
3273 
3274  /* these properties must not be in the saved msi file */
3275  add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3276  add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3277  add_property_entry( hdb, "'REMOVE', 'six,seven'");
3278  add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3279  add_property_entry( hdb, "'REINSTALLMODE', 'omus'");
3280 
3281  r = package_from_db( hdb, &hpkg );
3283  {
3284  skip("Not enough rights to perform tests\n");
3286  return;
3287  }
3288  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3289 
3290  MsiCloseHandle(hdb);
3291 
3292  CopyFileA(msifile, msifile2, FALSE);
3293  CopyFileA(msifile, msifile3, FALSE);
3294  CopyFileA(msifile, msifile4, FALSE);
3295 
3296  test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3297  test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3298 
3299  r = MsiDoActionA( hpkg, "CostInitialize");
3300  ok( r == ERROR_SUCCESS, "cost init failed\n");
3301 
3304 
3306 
3307  r = MsiDoActionA( hpkg, "FileCost");
3308  ok( r == ERROR_SUCCESS, "file cost failed\n");
3309 
3312 
3313  r = MsiDoActionA( hpkg, "CostFinalize");
3314  ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3315 
3329 
3353 
3354  MsiCloseHandle( hpkg );
3355 
3357 
3358  /* publish the features and components */
3359  r = MsiInstallProductA(msifile, "ADDLOCAL=one,four ADDSOURCE=two,three REMOVE=six,seven REINSTALL=eight,nine,ten");
3360  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3361 
3363  ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3364 
3365  /* these properties must not be in the saved msi file */
3366  add_property_entry( hdb, "'ADDLOCAL', 'one,four'");
3367  add_property_entry( hdb, "'ADDSOURCE', 'two,three'");
3368  add_property_entry( hdb, "'REMOVE', 'six,seven'");
3369  add_property_entry( hdb, "'REINSTALL', 'eight,nine,ten'");
3370 
3371  r = package_from_db( hdb, &hpkg );
3372  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3373 
3374  MsiCloseHandle(hdb);
3375 
3376  test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3377  test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3378 
3379  r = MsiDoActionA( hpkg, "CostInitialize");
3380  ok( r == ERROR_SUCCESS, "cost init failed\n");
3381 
3384 
3385  r = MsiDoActionA( hpkg, "FileCost");
3386  ok( r == ERROR_SUCCESS, "file cost failed\n");
3387 
3390 
3391  r = MsiDoActionA( hpkg, "CostFinalize");
3392  ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3393 
3407 
3431 
3432  MsiCloseHandle(hpkg);
3433 
3434  /* uninstall the product */
3435  r = MsiInstallProductA(msifile, "REMOVE=ALL");
3436  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3437 
3438  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3439  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3440  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3441  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3442 
3443  /* all features installed locally */
3444  r = MsiInstallProductA(msifile2, "ADDLOCAL=ALL");
3445  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3446 
3447  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3448  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3449  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3450  ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3451 
3452  r = MsiOpenDatabaseW(msifile2W, MSIDBOPEN_DIRECT, &hdb);
3453  ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3454 
3455  /* these properties must not be in the saved msi file */
3456  add_property_entry( hdb, "'ADDLOCAL', 'one,two,three,four,five,six,seven,eight,nine,ten,twelve'");
3457 
3458  r = package_from_db( hdb, &hpkg );
3459  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3460 
3461  test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3462  test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3463 
3464  r = MsiDoActionA( hpkg, "CostInitialize");
3465  ok( r == ERROR_SUCCESS, "cost init failed\n");
3466 
3469 
3470  r = MsiDoActionA( hpkg, "CostFinalize");
3471  ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3472 
3486 
3510 
3511  MsiCloseHandle(hpkg);
3512 
3513  /* uninstall the product */
3514  r = MsiInstallProductA(msifile2, "REMOVE=ALL");
3515  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3516 
3517  /* all features installed from source */
3518  r = MsiInstallProductA(msifile3, "ADDSOURCE=ALL");
3519  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3520 
3521  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3522  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3523  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3524  ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3525 
3526  r = MsiOpenDatabaseW(msifile3W, MSIDBOPEN_DIRECT, &hdb);
3527  ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3528 
3529  /* this property must not be in the saved msi file */
3530  add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3531 
3532  r = package_from_db( hdb, &hpkg );
3533  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3534 
3535  test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3536  test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3537 
3538  r = MsiDoActionA( hpkg, "CostInitialize");
3539  ok( r == ERROR_SUCCESS, "cost init failed\n");
3540 
3543 
3544  r = MsiDoActionA( hpkg, "FileCost");
3545  ok( r == ERROR_SUCCESS, "file cost failed\n");
3546 
3549 
3550  r = MsiDoActionA( hpkg, "CostFinalize");
3551  ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3552 
3566 
3590 
3591  MsiCloseHandle(hpkg);
3592 
3593  /* reinstall the product */
3594  r = MsiInstallProductA(msifile3, "REINSTALL=ALL");
3595  is_broken = (r == ERROR_INSTALL_FAILURE);
3596  ok(r == ERROR_SUCCESS || broken(is_broken) /* win2k3 */, "Expected ERROR_SUCCESS, got %d\n", r);
3597 
3598  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "five");
3599  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3600  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "twelve");
3601  ok(state == INSTALLSTATE_LOCAL, "state = %d\n", state);
3602 
3603  r = MsiOpenDatabaseW(msifile4W, MSIDBOPEN_DIRECT, &hdb);
3604  ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3605 
3606  /* this property must not be in the saved msi file */
3607  add_property_entry( hdb, "'ADDSOURCE', 'one,two,three,four,five,six,seven,eight,nine,ten'");
3608 
3609  r = package_from_db( hdb, &hpkg );
3610  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3611 
3612  test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3613  test_component_states( __LINE__, hpkg, "alpha", ERROR_UNKNOWN_COMPONENT, 0, 0, FALSE );
3614 
3615  r = MsiDoActionA( hpkg, "CostInitialize");
3616  ok( r == ERROR_SUCCESS, "cost init failed\n");
3617 
3620 
3621  r = MsiDoActionA( hpkg, "FileCost");
3622  ok( r == ERROR_SUCCESS, "file cost failed\n");
3623 
3626 
3627  r = MsiDoActionA( hpkg, "CostFinalize");
3628  ok( r == ERROR_SUCCESS, "cost finalize failed: %d\n", r);
3629 
3643 
3667 
3668  MsiCloseHandle(hpkg);
3669 
3670  /* test source only install */
3671  r = MsiInstallProductA(msifile, "REMOVE=ALL");
3672  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3673  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3674  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3675  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3676  ok(state == INSTALLSTATE_UNKNOWN, "state = %d\n", state);
3677 
3678  r = MsiInstallProductA(msifile, "ADDSOURCE=one");
3679  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3680  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "one");
3681  ok(state == INSTALLSTATE_SOURCE, "state = %d\n", state);
3682  state = MsiQueryFeatureStateA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}", "two");
3683  ok(state == INSTALLSTATE_ABSENT, "state = %d\n", state);
3684 
3685  /* no arguments test */
3686  cache_file_name_len = sizeof(msi_cache_file);
3687  r = MsiGetProductInfoA("{7262AC98-EEBD-4364-8CE3-D654F6A425B9}",
3688  INSTALLPROPERTY_LOCALPACKAGEA, msi_cache_file, &cache_file_name_len);
3689  ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3690  r = MsiOpenDatabaseA(msi_cache_file, (const char*)MSIDBOPEN_DIRECT, &hdb);
3691  ok(r == ERROR_SUCCESS, "failed to open database: %d\n", r);
3692 
3694  add_custom_action_entry( hdb, "'ConditionCheck1', 19, '', 'Condition check failed (1)'" );
3695  add_custom_action_entry( hdb, "'ConditionCheck2', 19, '', 'Condition check failed (2)'" );
3696  add_custom_action_entry( hdb, "'ConditionCheck3', 19, '', 'Condition check failed (3)'" );
3697  add_custom_action_entry( hdb, "'ConditionCheck4', 19, '', 'Condition check failed (4)'" );
3698  add_custom_action_entry( hdb, "'ConditionCheck5', 19, '', 'Condition check failed (5)'" );
3699  add_custom_action_entry( hdb, "'ConditionCheck6', 19, '', 'Condition check failed (6)'" );
3700  add_custom_action_entry( hdb, "'ConditionCheck7', 19, '', 'Condition check failed (7)'" );
3701  add_custom_action_entry( hdb, "'ConditionCheck8', 19, '', 'Condition check failed (8)'" );
3702 
3703  add_install_execute_sequence_entry( hdb, "'ConditionCheck1', 'REINSTALL', '798'" );
3704  add_install_execute_sequence_entry( hdb, "'ConditionCheck2', 'NOT REMOVE AND Preselected', '799'" );
3705  add_install_execute_sequence_entry( hdb, "'ConditionCheck3', 'REINSTALL', '6598'" );
3706  add_install_execute_sequence_entry( hdb, "'ConditionCheck4', 'NOT REMOVE AND Preselected', '6599'" );
3707  add_install_execute_sequence_entry( hdb, "'ConditionCheck5', 'REINSTALL', '6601'" );
3708  add_install_execute_sequence_entry( hdb, "'ConditionCheck6', 'NOT REMOVE AND Preselected', '6601'" );
3709  /* Add "one" feature action tests */
3710  add_install_execute_sequence_entry( hdb, "'ConditionCheck7', 'NOT REMOVE AND NOT(&one=-1)', '1501'" );
3711  add_install_execute_sequence_entry( hdb, "'ConditionCheck8', 'NOT REMOVE AND NOT(&one=-1)', '6602'" );
3712  r = MsiDatabaseCommit(hdb);
3713  ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed: %d\n", r);
3714  r = package_from_db( hdb, &hpkg );
3715  ok( r == ERROR_SUCCESS, "failed to create package %u\n", r );
3716  MsiCloseHandle(hdb);
3717 
3718  test_feature_states( __LINE__, hpkg, "one", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3719  test_feature_states( __LINE__, hpkg, "two", ERROR_UNKNOWN_FEATURE, 0, 0, FALSE );
3720  r = MsiDoActionA( hpkg, "CostInitialize");
3721  ok( r == ERROR_SUCCESS, "CostInitialize failed\n");
3724 
3725  r = MsiDoActionA( hpkg, "FileCost");
3726  ok( r == ERROR_SUCCESS, "FileCost failed\n");
3728  test_feature_states( __LINE__, hpkg, "two", ERROR_SUCCESS, INSTALLSTATE_UNKNOWN,