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