ReactOS 0.4.15-dev-8191-gbc6c731
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
37static const char msifile[] = "winetest-package.msi";
38static const WCHAR msifileW[] = L"winetest-package.msi";
39static char CURR_DIR[MAX_PATH];
40
41static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42
43static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
44static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
45static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
46static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
47static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
48
49static 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
66 GET_PROC(hsrclient, SRSetRestorePointA);
67
68#undef GET_PROC
69}
70
72{
74 PSID Group = NULL;
75 BOOL IsInGroup;
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");
84 return FALSE;
85 }
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
126static char *get_user_sid(void)
127{
129 DWORD size = 0;
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
206cleanup:
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
244static 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];
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
383static 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
405static 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
745static 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
858static 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);
984 return;
985
986 WriteFile(file, data, strlen(data), &written, NULL);
987 WriteFile(file, "\n", strlen("\n"), &written, NULL);
988
990}
991
992static void create_test_file(const CHAR *name)
993{
995}
996
997typedef struct _tagVS_VERSIONINFO
998{
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;
1018 DWORD handle, size;
1020 BOOL ret = FALSE;
1021
1023 /* Some dlls can't be updated on Vista/W2K8 */
1024 lstrcatA(path, "\\version.dll");
1025
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
1055done:
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
1072static 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
1081static BOOL is_root(const char *path)
1082{
1083 return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
1084}
1085
1086static 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
1105static 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
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
1135static void test_gettargetpath_bad(void)
1136{
1137 char buffer[0x80];
1138 WCHAR bufferW[0x80];
1139 MSIHANDLE hpkg;
1140 DWORD sz;
1141 UINT r;
1142
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
1219static 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
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 );
1301 "MsiSetTargetPath on file returned %d\n", r );
1302
1303 r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1305 "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1306
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
1387static void test_condition(void)
1388{
1390 MSIHANDLE hpkg;
1391
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
2140static 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
2153static 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
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;
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
2369static 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
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
2495static 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
2523static 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
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
2562static 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
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
2657static void test_formatrecord2(void)
2658{
2659 MSIHANDLE hpkg, hrec ;
2660 char buffer[0x100];
2661 DWORD sz;
2662 UINT r;
2663
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
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];
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
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 );
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" );
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 );
3001
3002 MsiCloseHandle( hrec );
3003 MsiCloseHandle( hpkg );
3005}
3006
3007static 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 );
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 );
3028 ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
3029
3030 }
3031}
3032
3033static 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 );
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 );
3055 ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
3056 line, action );
3057 }
3058}
3059
3060static 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
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
3333 test_feature_states( __LINE__, hpkg, "eight",