[MSI_WINETEST] Sync with Wine Staging 1.7.55. CORE-10536
[reactos.git] / rostests / winetests / msi / package.c
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 <stdio.h>
25 #include <windows.h>
26 #include <msidefs.h>
27 #include <msi.h>
28 #include <msiquery.h>
29 #include <srrestoreptapi.h>
30 #include <shlobj.h>
31
32 #include "wine/test.h"
33
34 static BOOL is_wow64;
35 static const char msifile[] = "winetest-package.msi";
36 static const WCHAR msifileW[] =
37 {'w','i','n','e','t','e','s','t','-','p','a','c','k','a','g','e','.','m','s','i',0};
38 static char CURR_DIR[MAX_PATH];
39
40 static UINT (WINAPI *pMsiApplyMultiplePatchesA)(LPCSTR, LPCSTR, LPCSTR);
41 static INSTALLSTATE (WINAPI *pMsiGetComponentPathExA)(LPCSTR, LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPSTR, LPDWORD);
42 static HRESULT (WINAPI *pSHGetFolderPathA)(HWND, int, HANDLE, DWORD, LPSTR);
43
44 static BOOL (WINAPI *pCheckTokenMembership)(HANDLE,PSID,PBOOL);
45 static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
46 static BOOL (WINAPI *pOpenProcessToken)( HANDLE, DWORD, PHANDLE );
47 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
48 static LONG (WINAPI *pRegDeleteKeyExW)(HKEY, LPCWSTR, REGSAM, DWORD);
49 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
50 static void (WINAPI *pGetSystemInfo)(LPSYSTEM_INFO);
51 static void (WINAPI *pGetNativeSystemInfo)(LPSYSTEM_INFO);
52 static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR, UINT);
53
54 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
55 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
56
57 static void init_functionpointers(void)
58 {
59 HMODULE hmsi = GetModuleHandleA("msi.dll");
60 HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
61 HMODULE hkernel32 = GetModuleHandleA("kernel32.dll");
62 HMODULE hshell32 = GetModuleHandleA("shell32.dll");
63 HMODULE hsrclient;
64
65 #define GET_PROC(mod, func) \
66 p ## func = (void*)GetProcAddress(mod, #func);
67
68 GET_PROC(hmsi, MsiApplyMultiplePatchesA);
69 GET_PROC(hmsi, MsiGetComponentPathExA);
70 GET_PROC(hshell32, SHGetFolderPathA);
71
72 GET_PROC(hadvapi32, CheckTokenMembership);
73 GET_PROC(hadvapi32, ConvertSidToStringSidA);
74 GET_PROC(hadvapi32, OpenProcessToken);
75 GET_PROC(hadvapi32, RegDeleteKeyExA)
76 GET_PROC(hadvapi32, RegDeleteKeyExW)
77 GET_PROC(hkernel32, IsWow64Process)
78 GET_PROC(hkernel32, GetNativeSystemInfo)
79 GET_PROC(hkernel32, GetSystemInfo)
80 GET_PROC(hkernel32, GetSystemWow64DirectoryA)
81
82 hsrclient = LoadLibraryA("srclient.dll");
83 GET_PROC(hsrclient, SRRemoveRestorePoint);
84 GET_PROC(hsrclient, SRSetRestorePointA);
85 #undef GET_PROC
86 }
87
88 static BOOL is_process_limited(void)
89 {
90 SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
91 PSID Group = NULL;
92 BOOL IsInGroup;
93 HANDLE token;
94
95 if (!pCheckTokenMembership || !pOpenProcessToken) return FALSE;
96
97 if (!AllocateAndInitializeSid(&NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
98 DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &Group) ||
99 !pCheckTokenMembership(NULL, Group, &IsInGroup))
100 {
101 trace("Could not check if the current user is an administrator\n");
102 FreeSid(Group);
103 return FALSE;
104 }
105 FreeSid(Group);
106
107 if (!IsInGroup)
108 {
109 if (!AllocateAndInitializeSid(&NtAuthority, 2,
110 SECURITY_BUILTIN_DOMAIN_RID,
111 DOMAIN_ALIAS_RID_POWER_USERS,
112 0, 0, 0, 0, 0, 0, &Group) ||
113 !pCheckTokenMembership(NULL, Group, &IsInGroup))
114 {
115 trace("Could not check if the current user is a power user\n");
116 return FALSE;
117 }
118 if (!IsInGroup)
119 {
120 /* Only administrators and power users can be powerful */
121 return TRUE;
122 }
123 }
124
125 if (pOpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token))
126 {
127 BOOL ret;
128 TOKEN_ELEVATION_TYPE type = TokenElevationTypeDefault;
129 DWORD size;
130
131 ret = GetTokenInformation(token, TokenElevationType, &type, sizeof(type), &size);
132 CloseHandle(token);
133 return (ret && type == TokenElevationTypeLimited);
134 }
135 return FALSE;
136 }
137
138 static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access )
139 {
140 if (pRegDeleteKeyExA)
141 return pRegDeleteKeyExA( key, subkey, access, 0 );
142 return RegDeleteKeyA( key, subkey );
143 }
144
145 static char *get_user_sid(void)
146 {
147 HANDLE token;
148 DWORD size = 0;
149 TOKEN_USER *user;
150 char *usersid = NULL;
151
152 if (!pConvertSidToStringSidA)
153 {
154 win_skip("ConvertSidToStringSidA is not available\n");
155 return NULL;
156 }
157 OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
158 GetTokenInformation(token, TokenUser, NULL, size, &size);
159
160 user = HeapAlloc(GetProcessHeap(), 0, size);
161 GetTokenInformation(token, TokenUser, user, size, &size);
162 pConvertSidToStringSidA(user->User.Sid, &usersid);
163 HeapFree(GetProcessHeap(), 0, user);
164
165 CloseHandle(token);
166 return usersid;
167 }
168
169 /* RegDeleteTreeW from dlls/advapi32/registry.c */
170 static LSTATUS package_RegDeleteTreeW(HKEY hKey, LPCWSTR lpszSubKey, REGSAM access)
171 {
172 LONG ret;
173 DWORD dwMaxSubkeyLen, dwMaxValueLen;
174 DWORD dwMaxLen, dwSize;
175 WCHAR szNameBuf[MAX_PATH], *lpszName = szNameBuf;
176 HKEY hSubKey = hKey;
177
178 if(lpszSubKey)
179 {
180 ret = RegOpenKeyExW(hKey, lpszSubKey, 0, access, &hSubKey);
181 if (ret) return ret;
182 }
183
184 ret = RegQueryInfoKeyW(hSubKey, NULL, NULL, NULL, NULL,
185 &dwMaxSubkeyLen, NULL, NULL, &dwMaxValueLen, NULL, NULL, NULL);
186 if (ret) goto cleanup;
187
188 dwMaxSubkeyLen++;
189 dwMaxValueLen++;
190 dwMaxLen = max(dwMaxSubkeyLen, dwMaxValueLen);
191 if (dwMaxLen > sizeof(szNameBuf)/sizeof(WCHAR))
192 {
193 /* Name too big: alloc a buffer for it */
194 if (!(lpszName = HeapAlloc( GetProcessHeap(), 0, dwMaxLen*sizeof(WCHAR))))
195 {
196 ret = ERROR_NOT_ENOUGH_MEMORY;
197 goto cleanup;
198 }
199 }
200
201 /* Recursively delete all the subkeys */
202 while (TRUE)
203 {
204 dwSize = dwMaxLen;
205 if (RegEnumKeyExW(hSubKey, 0, lpszName, &dwSize, NULL,
206 NULL, NULL, NULL)) break;
207
208 ret = package_RegDeleteTreeW(hSubKey, lpszName, access);
209 if (ret) goto cleanup;
210 }
211
212 if (lpszSubKey)
213 {
214 if (pRegDeleteKeyExW)
215 ret = pRegDeleteKeyExW(hKey, lpszSubKey, access, 0);
216 else
217 ret = RegDeleteKeyW(hKey, lpszSubKey);
218 }
219 else
220 while (TRUE)
221 {
222 dwSize = dwMaxLen;
223 if (RegEnumValueW(hKey, 0, lpszName, &dwSize,
224 NULL, NULL, NULL, NULL)) break;
225
226 ret = RegDeleteValueW(hKey, lpszName);
227 if (ret) goto cleanup;
228 }
229
230 cleanup:
231 if (lpszName != szNameBuf)
232 HeapFree(GetProcessHeap(), 0, lpszName);
233 if(lpszSubKey)
234 RegCloseKey(hSubKey);
235 return ret;
236 }
237
238 static BOOL squash_guid(LPCWSTR in, LPWSTR out)
239 {
240 DWORD i,n=1;
241 GUID guid;
242
243 if (FAILED(CLSIDFromString((LPCOLESTR)in, &guid)))
244 return FALSE;
245
246 for(i=0; i<8; i++)
247 out[7-i] = in[n++];
248 n++;
249 for(i=0; i<4; i++)
250 out[11-i] = in[n++];
251 n++;
252 for(i=0; i<4; i++)
253 out[15-i] = in[n++];
254 n++;
255 for(i=0; i<2; i++)
256 {
257 out[17+i*2] = in[n++];
258 out[16+i*2] = in[n++];
259 }
260 n++;
261 for( ; i<8; i++)
262 {
263 out[17+i*2] = in[n++];
264 out[16+i*2] = in[n++];
265 }
266 out[32]=0;
267 return TRUE;
268 }
269
270 static void create_test_guid(LPSTR prodcode, LPSTR squashed)
271 {
272 WCHAR guidW[MAX_PATH];
273 WCHAR squashedW[MAX_PATH];
274 GUID guid;
275 HRESULT hr;
276 int size;
277
278 hr = CoCreateGuid(&guid);
279 ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
280
281 size = StringFromGUID2(&guid, guidW, MAX_PATH);
282 ok(size == 39, "Expected 39, got %d\n", hr);
283
284 WideCharToMultiByte(CP_ACP, 0, guidW, size, prodcode, MAX_PATH, NULL, NULL);
285 squash_guid(guidW, squashedW);
286 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
287 }
288
289 static void set_component_path(LPCSTR filename, MSIINSTALLCONTEXT context,
290 LPCSTR guid, LPSTR usersid, BOOL dir)
291 {
292 WCHAR guidW[MAX_PATH];
293 WCHAR squashedW[MAX_PATH];
294 CHAR squashed[MAX_PATH];
295 CHAR comppath[MAX_PATH];
296 CHAR prodpath[MAX_PATH];
297 CHAR path[MAX_PATH];
298 LPCSTR prod = NULL;
299 HKEY hkey;
300 REGSAM access = KEY_ALL_ACCESS;
301
302 if (is_wow64)
303 access |= KEY_WOW64_64KEY;
304
305 MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
306 squash_guid(guidW, squashedW);
307 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
308
309 if (context == MSIINSTALLCONTEXT_MACHINE)
310 {
311 prod = "3D0DAE300FACA1300AD792060BCDAA92";
312 sprintf(comppath,
313 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
314 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
315 lstrcpyA(prodpath,
316 "SOFTWARE\\Classes\\Installer\\"
317 "Products\\3D0DAE300FACA1300AD792060BCDAA92");
318 }
319 else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
320 {
321 prod = "7D2F387510109040002000060BECB6AB";
322 sprintf(comppath,
323 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
324 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
325 sprintf(prodpath,
326 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
327 "Installer\\%s\\Installer\\Products\\"
328 "7D2F387510109040002000060BECB6AB", usersid);
329 }
330 else if (context == MSIINSTALLCONTEXT_USERMANAGED)
331 {
332 prod = "7D2F387510109040002000060BECB6AB";
333 sprintf(comppath,
334 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
335 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
336 sprintf(prodpath,
337 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
338 "Installer\\Managed\\%s\\Installer\\Products\\"
339 "7D2F387510109040002000060BECB6AB", usersid);
340 }
341
342 RegCreateKeyExA(HKEY_LOCAL_MACHINE, comppath, 0, NULL, 0, access, NULL, &hkey, NULL);
343
344 lstrcpyA(path, CURR_DIR);
345 lstrcatA(path, "\\");
346 if (!dir) lstrcatA(path, filename);
347
348 RegSetValueExA(hkey, prod, 0, REG_SZ, (LPBYTE)path, lstrlenA(path));
349 RegCloseKey(hkey);
350
351 RegCreateKeyExA(HKEY_LOCAL_MACHINE, prodpath, 0, NULL, 0, access, NULL, &hkey, NULL);
352 RegCloseKey(hkey);
353 }
354
355 static void delete_component_path(LPCSTR guid, MSIINSTALLCONTEXT context, LPSTR usersid)
356 {
357 WCHAR guidW[MAX_PATH];
358 WCHAR squashedW[MAX_PATH];
359 WCHAR substrW[MAX_PATH];
360 CHAR squashed[MAX_PATH];
361 CHAR comppath[MAX_PATH];
362 CHAR prodpath[MAX_PATH];
363 REGSAM access = KEY_ALL_ACCESS;
364
365 if (is_wow64)
366 access |= KEY_WOW64_64KEY;
367
368 MultiByteToWideChar(CP_ACP, 0, guid, -1, guidW, MAX_PATH);
369 squash_guid(guidW, squashedW);
370 WideCharToMultiByte(CP_ACP, 0, squashedW, -1, squashed, MAX_PATH, NULL, NULL);
371
372 if (context == MSIINSTALLCONTEXT_MACHINE)
373 {
374 sprintf(comppath,
375 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
376 "Installer\\UserData\\S-1-5-18\\Components\\%s", squashed);
377 lstrcpyA(prodpath,
378 "SOFTWARE\\Classes\\Installer\\"
379 "Products\\3D0DAE300FACA1300AD792060BCDAA92");
380 }
381 else if (context == MSIINSTALLCONTEXT_USERUNMANAGED)
382 {
383 sprintf(comppath,
384 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
385 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
386 sprintf(prodpath,
387 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
388 "Installer\\%s\\Installer\\Products\\"
389 "7D2F387510109040002000060BECB6AB", usersid);
390 }
391 else if (context == MSIINSTALLCONTEXT_USERMANAGED)
392 {
393 sprintf(comppath,
394 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
395 "Installer\\UserData\\%s\\Components\\%s", usersid, squashed);
396 sprintf(prodpath,
397 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
398 "Installer\\Managed\\%s\\Installer\\Products\\"
399 "7D2F387510109040002000060BECB6AB", usersid);
400 }
401
402 MultiByteToWideChar(CP_ACP, 0, comppath, -1, substrW, MAX_PATH);
403 package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
404
405 MultiByteToWideChar(CP_ACP, 0, prodpath, -1, substrW, MAX_PATH);
406 package_RegDeleteTreeW(HKEY_LOCAL_MACHINE, substrW, access);
407 }
408
409 static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
410 {
411 MSIHANDLE hview = 0;
412 UINT r, ret;
413
414 /* open a select query */
415 r = MsiDatabaseOpenViewA(hdb, query, &hview);
416 if (r != ERROR_SUCCESS)
417 return r;
418 r = MsiViewExecute(hview, 0);
419 if (r != ERROR_SUCCESS)
420 return r;
421 ret = MsiViewFetch(hview, phrec);
422 r = MsiViewClose(hview);
423 if (r != ERROR_SUCCESS)
424 return r;
425 r = MsiCloseHandle(hview);
426 if (r != ERROR_SUCCESS)
427 return r;
428 return ret;
429 }
430
431 static UINT run_query( MSIHANDLE hdb, const char *query )
432 {
433 MSIHANDLE hview = 0;
434 UINT r;
435
436 r = MsiDatabaseOpenViewA(hdb, query, &hview);
437 if( r != ERROR_SUCCESS )
438 return r;
439
440 r = MsiViewExecute(hview, 0);
441 if( r == ERROR_SUCCESS )
442 r = MsiViewClose(hview);
443 MsiCloseHandle(hview);
444 return r;
445 }
446
447 static UINT create_component_table( MSIHANDLE hdb )
448 {
449 return run_query( hdb,
450 "CREATE TABLE `Component` ( "
451 "`Component` CHAR(72) NOT NULL, "
452 "`ComponentId` CHAR(38), "
453 "`Directory_` CHAR(72) NOT NULL, "
454 "`Attributes` SHORT NOT NULL, "
455 "`Condition` CHAR(255), "
456 "`KeyPath` CHAR(72) "
457 "PRIMARY KEY `Component`)" );
458 }
459
460 static UINT create_feature_table( MSIHANDLE hdb )
461 {
462 return run_query( hdb,
463 "CREATE TABLE `Feature` ( "
464 "`Feature` CHAR(38) NOT NULL, "
465 "`Feature_Parent` CHAR(38), "
466 "`Title` CHAR(64), "
467 "`Description` CHAR(255), "
468 "`Display` SHORT NOT NULL, "
469 "`Level` SHORT NOT NULL, "
470 "`Directory_` CHAR(72), "
471 "`Attributes` SHORT NOT NULL "
472 "PRIMARY KEY `Feature`)" );
473 }
474
475 static UINT create_feature_components_table( MSIHANDLE hdb )
476 {
477 return run_query( hdb,
478 "CREATE TABLE `FeatureComponents` ( "
479 "`Feature_` CHAR(38) NOT NULL, "
480 "`Component_` CHAR(72) NOT NULL "
481 "PRIMARY KEY `Feature_`, `Component_` )" );
482 }
483
484 static UINT create_file_table( MSIHANDLE hdb )
485 {
486 return run_query( hdb,
487 "CREATE TABLE `File` ("
488 "`File` CHAR(72) NOT NULL, "
489 "`Component_` CHAR(72) NOT NULL, "
490 "`FileName` CHAR(255) NOT NULL, "
491 "`FileSize` LONG NOT NULL, "
492 "`Version` CHAR(72), "
493 "`Language` CHAR(20), "
494 "`Attributes` SHORT, "
495 "`Sequence` SHORT NOT NULL "
496 "PRIMARY KEY `File`)" );
497 }
498
499 static UINT create_remove_file_table( MSIHANDLE hdb )
500 {
501 return run_query( hdb,
502 "CREATE TABLE `RemoveFile` ("
503 "`FileKey` CHAR(72) NOT NULL, "
504 "`Component_` CHAR(72) NOT NULL, "
505 "`FileName` CHAR(255) LOCALIZABLE, "
506 "`DirProperty` CHAR(72) NOT NULL, "
507 "`InstallMode` SHORT NOT NULL "
508 "PRIMARY KEY `FileKey`)" );
509 }
510
511 static UINT create_appsearch_table( MSIHANDLE hdb )
512 {
513 return run_query( hdb,
514 "CREATE TABLE `AppSearch` ("
515 "`Property` CHAR(72) NOT NULL, "
516 "`Signature_` CHAR(72) NOT NULL "
517 "PRIMARY KEY `Property`, `Signature_`)" );
518 }
519
520 static UINT create_reglocator_table( MSIHANDLE hdb )
521 {
522 return run_query( hdb,
523 "CREATE TABLE `RegLocator` ("
524 "`Signature_` CHAR(72) NOT NULL, "
525 "`Root` SHORT NOT NULL, "
526 "`Key` CHAR(255) NOT NULL, "
527 "`Name` CHAR(255), "
528 "`Type` SHORT "
529 "PRIMARY KEY `Signature_`)" );
530 }
531
532 static UINT create_signature_table( MSIHANDLE hdb )
533 {
534 return run_query( hdb,
535 "CREATE TABLE `Signature` ("
536 "`Signature` CHAR(72) NOT NULL, "
537 "`FileName` CHAR(255) NOT NULL, "
538 "`MinVersion` CHAR(20), "
539 "`MaxVersion` CHAR(20), "
540 "`MinSize` LONG, "
541 "`MaxSize` LONG, "
542 "`MinDate` LONG, "
543 "`MaxDate` LONG, "
544 "`Languages` CHAR(255) "
545 "PRIMARY KEY `Signature`)" );
546 }
547
548 static UINT create_launchcondition_table( MSIHANDLE hdb )
549 {
550 return run_query( hdb,
551 "CREATE TABLE `LaunchCondition` ("
552 "`Condition` CHAR(255) NOT NULL, "
553 "`Description` CHAR(255) NOT NULL "
554 "PRIMARY KEY `Condition`)" );
555 }
556
557 static UINT create_property_table( MSIHANDLE hdb )
558 {
559 return run_query( hdb,
560 "CREATE TABLE `Property` ("
561 "`Property` CHAR(72) NOT NULL, "
562 "`Value` CHAR(0) "
563 "PRIMARY KEY `Property`)" );
564 }
565
566 static UINT create_install_execute_sequence_table( MSIHANDLE hdb )
567 {
568 return run_query( hdb,
569 "CREATE TABLE `InstallExecuteSequence` ("
570 "`Action` CHAR(72) NOT NULL, "
571 "`Condition` CHAR(255), "
572 "`Sequence` SHORT "
573 "PRIMARY KEY `Action`)" );
574 }
575
576 static UINT create_media_table( MSIHANDLE hdb )
577 {
578 return run_query( hdb,
579 "CREATE TABLE `Media` ("
580 "`DiskId` SHORT NOT NULL, "
581 "`LastSequence` SHORT NOT NULL, "
582 "`DiskPrompt` CHAR(64), "
583 "`Cabinet` CHAR(255), "
584 "`VolumeLabel` CHAR(32), "
585 "`Source` CHAR(72) "
586 "PRIMARY KEY `DiskId`)" );
587 }
588
589 static UINT create_ccpsearch_table( MSIHANDLE hdb )
590 {
591 return run_query( hdb,
592 "CREATE TABLE `CCPSearch` ("
593 "`Signature_` CHAR(72) NOT NULL "
594 "PRIMARY KEY `Signature_`)" );
595 }
596
597 static UINT create_drlocator_table( MSIHANDLE hdb )
598 {
599 return run_query( hdb,
600 "CREATE TABLE `DrLocator` ("
601 "`Signature_` CHAR(72) NOT NULL, "
602 "`Parent` CHAR(72), "
603 "`Path` CHAR(255), "
604 "`Depth` SHORT "
605 "PRIMARY KEY `Signature_`, `Parent`, `Path`)" );
606 }
607
608 static UINT create_complocator_table( MSIHANDLE hdb )
609 {
610 return run_query( hdb,
611 "CREATE TABLE `CompLocator` ("
612 "`Signature_` CHAR(72) NOT NULL, "
613 "`ComponentId` CHAR(38) NOT NULL, "
614 "`Type` SHORT "
615 "PRIMARY KEY `Signature_`)" );
616 }
617
618 static UINT create_inilocator_table( MSIHANDLE hdb )
619 {
620 return run_query( hdb,
621 "CREATE TABLE `IniLocator` ("
622 "`Signature_` CHAR(72) NOT NULL, "
623 "`FileName` CHAR(255) NOT NULL, "
624 "`Section` CHAR(96)NOT NULL, "
625 "`Key` CHAR(128)NOT NULL, "
626 "`Field` SHORT, "
627 "`Type` SHORT "
628 "PRIMARY KEY `Signature_`)" );
629 }
630
631 static UINT create_custom_action_table( MSIHANDLE hdb )
632 {
633 return run_query( hdb,
634 "CREATE TABLE `CustomAction` ("
635 "`Action` CHAR(72) NOT NULL, "
636 "`Type` SHORT NOT NULL, "
637 "`Source` CHAR(75), "
638 "`Target` CHAR(255) "
639 "PRIMARY KEY `Action`)" );
640 }
641
642 #define make_add_entry(type, qtext) \
643 static UINT add##_##type##_##entry( MSIHANDLE hdb, const char *values ) \
644 { \
645 char insert[] = qtext; \
646 char *query; \
647 UINT sz, r; \
648 sz = strlen(values) + sizeof insert; \
649 query = HeapAlloc(GetProcessHeap(),0,sz); \
650 sprintf(query,insert,values); \
651 r = run_query( hdb, query ); \
652 HeapFree(GetProcessHeap(), 0, query); \
653 return r; \
654 }
655
656 make_add_entry(component,
657 "INSERT INTO `Component` "
658 "(`Component`, `ComponentId`, `Directory_`, "
659 "`Attributes`, `Condition`, `KeyPath`) VALUES( %s )")
660
661 make_add_entry(directory,
662 "INSERT INTO `Directory` "
663 "(`Directory`,`Directory_Parent`,`DefaultDir`) VALUES( %s )")
664
665 make_add_entry(feature,
666 "INSERT INTO `Feature` "
667 "(`Feature`, `Feature_Parent`, `Title`, `Description`, "
668 "`Display`, `Level`, `Directory_`, `Attributes`) VALUES( %s )")
669
670 make_add_entry(feature_components,
671 "INSERT INTO `FeatureComponents` "
672 "(`Feature_`, `Component_`) VALUES( %s )")
673
674 make_add_entry(file,
675 "INSERT INTO `File` "
676 "(`File`, `Component_`, `FileName`, `FileSize`, "
677 "`Version`, `Language`, `Attributes`, `Sequence`) VALUES( %s )")
678
679 make_add_entry(appsearch,
680 "INSERT INTO `AppSearch` "
681 "(`Property`, `Signature_`) VALUES( %s )")
682
683 make_add_entry(signature,
684 "INSERT INTO `Signature` "
685 "(`Signature`, `FileName`, `MinVersion`, `MaxVersion`,"
686 " `MinSize`, `MaxSize`, `MinDate`, `MaxDate`, `Languages`) "
687 "VALUES( %s )")
688
689 make_add_entry(launchcondition,
690 "INSERT INTO `LaunchCondition` "
691 "(`Condition`, `Description`) VALUES( %s )")
692
693 make_add_entry(property,
694 "INSERT INTO `Property` (`Property`, `Value`) VALUES( %s )")
695
696 make_add_entry(install_execute_sequence,
697 "INSERT INTO `InstallExecuteSequence` "
698 "(`Action`, `Condition`, `Sequence`) VALUES( %s )")
699
700 make_add_entry(media,
701 "INSERT INTO `Media` "
702 "(`DiskId`, `LastSequence`, `DiskPrompt`, "
703 "`Cabinet`, `VolumeLabel`, `Source`) VALUES( %s )")
704
705 make_add_entry(ccpsearch,
706 "INSERT INTO `CCPSearch` (`Signature_`) VALUES( %s )")
707
708 make_add_entry(drlocator,
709 "INSERT INTO `DrLocator` "
710 "(`Signature_`, `Parent`, `Path`, `Depth`) VALUES( %s )")
711
712 make_add_entry(complocator,
713 "INSERT INTO `CompLocator` "
714 "(`Signature_`, `ComponentId`, `Type`) VALUES( %s )")
715
716 make_add_entry(inilocator,
717 "INSERT INTO `IniLocator` "
718 "(`Signature_`, `FileName`, `Section`, `Key`, `Field`, `Type`) "
719 "VALUES( %s )")
720
721 make_add_entry(custom_action,
722 "INSERT INTO `CustomAction` "
723 "(`Action`, `Type`, `Source`, `Target`) VALUES( %s )")
724
725 static UINT add_reglocator_entry( MSIHANDLE hdb, const char *sig, UINT root, const char *path,
726 const char *name, UINT type )
727 {
728 const char insert[] =
729 "INSERT INTO `RegLocator` (`Signature_`, `Root`, `Key`, `Name`, `Type`) "
730 "VALUES( '%s', %u, '%s', '%s', %u )";
731 char *query;
732 UINT sz, r;
733
734 sz = strlen( sig ) + 10 + strlen( path ) + strlen( name ) + 10 + sizeof( insert );
735 query = HeapAlloc( GetProcessHeap(), 0, sz );
736 sprintf( query, insert, sig, root, path, name, type );
737 r = run_query( hdb, query );
738 HeapFree( GetProcessHeap(), 0, query );
739 return r;
740 }
741
742 static UINT set_summary_info(MSIHANDLE hdb)
743 {
744 UINT res;
745 MSIHANDLE suminfo;
746
747 /* build summary info */
748 res = MsiGetSummaryInformationA(hdb, NULL, 7, &suminfo);
749 ok( res == ERROR_SUCCESS , "Failed to open summaryinfo\n" );
750
751 res = MsiSummaryInfoSetPropertyA(suminfo,2, VT_LPSTR, 0,NULL,
752 "Installation Database");
753 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
754
755 res = MsiSummaryInfoSetPropertyA(suminfo,3, VT_LPSTR, 0,NULL,
756 "Installation Database");
757 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
758
759 res = MsiSummaryInfoSetPropertyA(suminfo,4, VT_LPSTR, 0,NULL,
760 "Wine Hackers");
761 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
762
763 res = MsiSummaryInfoSetPropertyA(suminfo,7, VT_LPSTR, 0,NULL,
764 ";1033");
765 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
766
767 res = MsiSummaryInfoSetPropertyA(suminfo,9, VT_LPSTR, 0,NULL,
768 "{913B8D18-FBB6-4CAC-A239-C74C11E3FA74}");
769 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
770
771 res = MsiSummaryInfoSetPropertyA(suminfo, 14, VT_I4, 100, NULL, NULL);
772 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
773
774 res = MsiSummaryInfoSetPropertyA(suminfo, 15, VT_I4, 0, NULL, NULL);
775 ok( res == ERROR_SUCCESS , "Failed to set summary info\n" );
776
777 res = MsiSummaryInfoPersist(suminfo);
778 ok( res == ERROR_SUCCESS , "Failed to make summary info persist\n" );
779
780 res = MsiCloseHandle( suminfo);
781 ok( res == ERROR_SUCCESS , "Failed to close suminfo\n" );
782
783 return res;
784 }
785
786
787 static MSIHANDLE create_package_db(void)
788 {
789 MSIHANDLE hdb = 0;
790 UINT res;
791
792 DeleteFileA(msifile);
793
794 /* create an empty database */
795 res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb );
796 ok( res == ERROR_SUCCESS , "Failed to create database %u\n", res );
797 if( res != ERROR_SUCCESS )
798 return hdb;
799
800 res = MsiDatabaseCommit( hdb );
801 ok( res == ERROR_SUCCESS , "Failed to commit database\n" );
802
803 res = set_summary_info(hdb);
804 ok( res == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", res);
805
806 res = run_query( hdb,
807 "CREATE TABLE `Directory` ( "
808 "`Directory` CHAR(255) NOT NULL, "
809 "`Directory_Parent` CHAR(255), "
810 "`DefaultDir` CHAR(255) NOT NULL "
811 "PRIMARY KEY `Directory`)" );
812 ok( res == ERROR_SUCCESS , "Failed to create directory table\n" );
813
814 return hdb;
815 }
816
817 static UINT package_from_db(MSIHANDLE hdb, MSIHANDLE *handle)
818 {
819 UINT res;
820 CHAR szPackage[12];
821 MSIHANDLE hPackage;
822
823 sprintf(szPackage, "#%u", hdb);
824 res = MsiOpenPackageA(szPackage, &hPackage);
825 if (res != ERROR_SUCCESS)
826 {
827 MsiCloseHandle(hdb);
828 return res;
829 }
830
831 res = MsiCloseHandle(hdb);
832 if (res != ERROR_SUCCESS)
833 {
834 MsiCloseHandle(hPackage);
835 return res;
836 }
837
838 *handle = hPackage;
839 return ERROR_SUCCESS;
840 }
841
842 static void create_test_file(const CHAR *name)
843 {
844 HANDLE file;
845 DWORD written;
846
847 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
848 ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
849 WriteFile(file, name, strlen(name), &written, NULL);
850 WriteFile(file, "\n", strlen("\n"), &written, NULL);
851 CloseHandle(file);
852 }
853
854 typedef struct _tagVS_VERSIONINFO
855 {
856 WORD wLength;
857 WORD wValueLength;
858 WORD wType;
859 WCHAR szKey[1];
860 WORD wPadding1[1];
861 VS_FIXEDFILEINFO Value;
862 WORD wPadding2[1];
863 WORD wChildren[1];
864 } VS_VERSIONINFO;
865
866 #define roundoffs(a, b, r) (((BYTE *)(b) - (BYTE *)(a) + ((r) - 1)) & ~((r) - 1))
867 #define roundpos(a, b, r) (((BYTE *)(a)) + roundoffs(a, b, r))
868
869 static BOOL create_file_with_version(const CHAR *name, LONG ms, LONG ls)
870 {
871 VS_VERSIONINFO *pVerInfo;
872 VS_FIXEDFILEINFO *pFixedInfo;
873 LPBYTE buffer, ofs;
874 CHAR path[MAX_PATH];
875 DWORD handle, size;
876 HANDLE resource;
877 BOOL ret = FALSE;
878
879 GetSystemDirectoryA(path, MAX_PATH);
880 /* Some dlls can't be updated on Vista/W2K8 */
881 lstrcatA(path, "\\version.dll");
882
883 CopyFileA(path, name, FALSE);
884
885 size = GetFileVersionInfoSizeA(path, &handle);
886 buffer = HeapAlloc(GetProcessHeap(), 0, size);
887
888 GetFileVersionInfoA(path, 0, size, buffer);
889
890 pVerInfo = (VS_VERSIONINFO *)buffer;
891 ofs = (BYTE *)&pVerInfo->szKey[lstrlenW(pVerInfo->szKey) + 1];
892 pFixedInfo = (VS_FIXEDFILEINFO *)roundpos(pVerInfo, ofs, 4);
893
894 pFixedInfo->dwFileVersionMS = ms;
895 pFixedInfo->dwFileVersionLS = ls;
896 pFixedInfo->dwProductVersionMS = ms;
897 pFixedInfo->dwProductVersionLS = ls;
898
899 resource = BeginUpdateResourceA(name, FALSE);
900 if (!resource)
901 goto done;
902
903 if (!UpdateResourceA(resource, (LPCSTR)RT_VERSION, (LPCSTR)MAKEINTRESOURCE(VS_VERSION_INFO),
904 MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL), buffer, size))
905 goto done;
906
907 if (!EndUpdateResourceA(resource, FALSE))
908 goto done;
909
910 ret = TRUE;
911
912 done:
913 HeapFree(GetProcessHeap(), 0, buffer);
914 return ret;
915 }
916
917 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
918 {
919 RESTOREPOINTINFOA spec;
920
921 spec.dwEventType = event_type;
922 spec.dwRestorePtType = APPLICATION_INSTALL;
923 spec.llSequenceNumber = status->llSequenceNumber;
924 lstrcpyA(spec.szDescription, "msitest restore point");
925
926 return pSRSetRestorePointA(&spec, status);
927 }
928
929 static void remove_restore_point(DWORD seq_number)
930 {
931 DWORD res;
932
933 res = pSRRemoveRestorePoint(seq_number);
934 if (res != ERROR_SUCCESS)
935 trace("Failed to remove the restore point : %08x\n", res);
936 }
937
938 static BOOL is_root(const char *path)
939 {
940 return (isalpha(path[0]) && path[1] == ':' && path[2] == '\\' && !path[3]);
941 }
942
943 static void test_createpackage(void)
944 {
945 MSIHANDLE hPackage = 0;
946 UINT res;
947
948 res = package_from_db(create_package_db(), &hPackage);
949 if (res == ERROR_INSTALL_PACKAGE_REJECTED)
950 {
951 skip("Not enough rights to perform tests\n");
952 DeleteFileA(msifile);
953 return;
954 }
955 ok( res == ERROR_SUCCESS, " Failed to create package %u\n", res );
956
957 res = MsiCloseHandle( hPackage);
958 ok( res == ERROR_SUCCESS , "Failed to close package\n" );
959 DeleteFileA(msifile);
960 }
961
962 static void test_doaction( void )
963 {
964 MSIHANDLE hpkg;
965 UINT r;
966
967 r = MsiDoActionA( -1, NULL );
968 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
969
970 r = package_from_db(create_package_db(), &hpkg);
971 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
972 {
973 skip("Not enough rights to perform tests\n");
974 DeleteFileA(msifile);
975 return;
976 }
977 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
978
979 r = MsiDoActionA(hpkg, NULL);
980 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
981
982 r = MsiDoActionA(0, "boo");
983 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
984
985 r = MsiDoActionA(hpkg, "boo");
986 ok( r == ERROR_FUNCTION_NOT_CALLED, "wrong return val\n");
987
988 MsiCloseHandle( hpkg );
989 DeleteFileA(msifile);
990 }
991
992 static void test_gettargetpath_bad(void)
993 {
994 static const WCHAR boo[] = {'b','o','o',0};
995 static const WCHAR empty[] = {0};
996 char buffer[0x80];
997 WCHAR bufferW[0x80];
998 MSIHANDLE hpkg;
999 DWORD sz;
1000 UINT r;
1001
1002 r = package_from_db(create_package_db(), &hpkg);
1003 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1004 {
1005 skip("Not enough rights to perform tests\n");
1006 DeleteFileA(msifile);
1007 return;
1008 }
1009 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1010
1011 r = MsiGetTargetPathA( 0, NULL, NULL, NULL );
1012 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1013
1014 r = MsiGetTargetPathA( 0, NULL, NULL, &sz );
1015 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1016
1017 r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1018 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1019
1020 r = MsiGetTargetPathA( 0, "boo", NULL, NULL );
1021 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1022
1023 r = MsiGetTargetPathA( hpkg, "boo", NULL, NULL );
1024 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1025
1026 r = MsiGetTargetPathA( hpkg, "boo", buffer, NULL );
1027 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1028
1029 sz = 0;
1030 r = MsiGetTargetPathA( hpkg, "", buffer, &sz );
1031 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1032
1033 r = MsiGetTargetPathW( 0, NULL, NULL, NULL );
1034 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1035
1036 r = MsiGetTargetPathW( 0, NULL, NULL, &sz );
1037 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1038
1039 r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1040 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1041
1042 r = MsiGetTargetPathW( 0, boo, NULL, NULL );
1043 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1044
1045 r = MsiGetTargetPathW( hpkg, boo, NULL, NULL );
1046 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1047
1048 r = MsiGetTargetPathW( hpkg, boo, bufferW, NULL );
1049 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1050
1051 sz = 0;
1052 r = MsiGetTargetPathW( hpkg, empty, bufferW, &sz );
1053 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1054
1055 MsiCloseHandle( hpkg );
1056 DeleteFileA(msifile);
1057 }
1058
1059 static void query_file_path(MSIHANDLE hpkg, LPCSTR file, LPSTR buff)
1060 {
1061 UINT r;
1062 DWORD size;
1063 MSIHANDLE rec;
1064
1065 rec = MsiCreateRecord( 1 );
1066 ok(rec, "MsiCreate record failed\n");
1067
1068 r = MsiRecordSetStringA( rec, 0, file );
1069 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1070
1071 size = MAX_PATH;
1072 r = MsiFormatRecordA( hpkg, rec, buff, &size );
1073 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r );
1074
1075 MsiCloseHandle( rec );
1076 }
1077
1078 static void test_settargetpath(void)
1079 {
1080 char tempdir[MAX_PATH+8], buffer[MAX_PATH], file[MAX_PATH];
1081 DWORD sz;
1082 MSIHANDLE hpkg;
1083 UINT r;
1084 MSIHANDLE hdb;
1085
1086 hdb = create_package_db();
1087 ok ( hdb, "failed to create package database\n" );
1088
1089 r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'" );
1090 ok( r == S_OK, "failed to add directory entry: %d\n" , r );
1091
1092 r = create_component_table( hdb );
1093 ok( r == S_OK, "cannot create Component table: %d\n", r );
1094
1095 r = add_component_entry( hdb, "'RootComp', '{83e2694d-0864-4124-9323-6d37630912a1}', 'TARGETDIR', 8, '', 'RootFile'" );
1096 ok( r == S_OK, "cannot add dummy component: %d\n", r );
1097
1098 r = add_component_entry( hdb, "'TestComp', '{A3FB59C8-C293-4F7E-B8C5-F0E1D8EEE4E5}', 'TestDir', 0, '', 'TestFile'" );
1099 ok( r == S_OK, "cannot add test component: %d\n", r );
1100
1101 r = create_feature_table( hdb );
1102 ok( r == S_OK, "cannot create Feature table: %d\n", r );
1103
1104 r = add_feature_entry( hdb, "'TestFeature', '', '', '', 0, 1, '', 0" );
1105 ok( r == ERROR_SUCCESS, "cannot add TestFeature to Feature table: %d\n", r );
1106
1107 r = create_feature_components_table( hdb );
1108 ok( r == S_OK, "cannot create FeatureComponents table: %d\n", r );
1109
1110 r = add_feature_components_entry( hdb, "'TestFeature', 'RootComp'" );
1111 ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
1112
1113 r = add_feature_components_entry( hdb, "'TestFeature', 'TestComp'" );
1114 ok( r == S_OK, "cannot insert component into FeatureComponents table: %d\n", r );
1115
1116 add_directory_entry( hdb, "'TestParent', 'TARGETDIR', 'TestParent'" );
1117 add_directory_entry( hdb, "'TestDir', 'TestParent', 'TestDir'" );
1118
1119 r = create_file_table( hdb );
1120 ok( r == S_OK, "cannot create File table: %d\n", r );
1121
1122 r = add_file_entry( hdb, "'RootFile', 'RootComp', 'rootfile.txt', 0, '', '1033', 8192, 1" );
1123 ok( r == S_OK, "cannot add file to the File table: %d\n", r );
1124
1125 r = add_file_entry( hdb, "'TestFile', 'TestComp', 'testfile.txt', 0, '', '1033', 8192, 1" );
1126 ok( r == S_OK, "cannot add file to the File table: %d\n", r );
1127
1128 r = package_from_db( hdb, &hpkg );
1129 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1130 {
1131 skip("Not enough rights to perform tests\n");
1132 DeleteFileA(msifile);
1133 return;
1134 }
1135 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1136
1137 MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1138
1139 r = MsiDoActionA( hpkg, "CostInitialize");
1140 ok( r == ERROR_SUCCESS, "cost init failed\n");
1141
1142 r = MsiDoActionA( hpkg, "FileCost");
1143 ok( r == ERROR_SUCCESS, "file cost failed\n");
1144
1145 r = MsiDoActionA( hpkg, "CostFinalize");
1146 ok( r == ERROR_SUCCESS, "cost finalize failed\n");
1147
1148 buffer[0] = 0;
1149 sz = sizeof(buffer);
1150 r = MsiGetPropertyA( hpkg, "OutOfNoRbDiskSpace", buffer, &sz );
1151 ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1152 trace( "OutOfNoRbDiskSpace = \"%s\"\n", buffer );
1153
1154 r = MsiSetTargetPathA( 0, NULL, NULL );
1155 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1156
1157 r = MsiSetTargetPathA( 0, "boo", "C:\\bogusx" );
1158 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
1159
1160 r = MsiSetTargetPathA( hpkg, "boo", NULL );
1161 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
1162
1163 r = MsiSetTargetPathA( hpkg, "boo", "c:\\bogusx" );
1164 ok( r == ERROR_DIRECTORY, "wrong return val\n");
1165
1166 sz = sizeof tempdir - 1;
1167 r = MsiGetTargetPathA( hpkg, "TARGETDIR", tempdir, &sz );
1168 sprintf( file, "%srootfile.txt", tempdir );
1169 buffer[0] = 0;
1170 query_file_path( hpkg, "[#RootFile]", buffer );
1171 ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1172 ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer );
1173
1174 GetTempFileNameA( tempdir, "_wt", 0, buffer );
1175 sprintf( tempdir, "%s\\subdir", buffer );
1176
1177 r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1178 ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1179 "MsiSetTargetPath on file returned %d\n", r );
1180
1181 r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1182 ok( r == ERROR_SUCCESS || r == ERROR_DIRECTORY,
1183 "MsiSetTargetPath on 'subdir' of file returned %d\n", r );
1184
1185 DeleteFileA( buffer );
1186
1187 r = MsiSetTargetPathA( hpkg, "TARGETDIR", buffer );
1188 ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1189
1190 r = GetFileAttributesA( buffer );
1191 ok ( r == INVALID_FILE_ATTRIBUTES, "file/directory exists after MsiSetTargetPath. Attributes: %08X\n", r );
1192
1193 r = MsiSetTargetPathA( hpkg, "TARGETDIR", tempdir );
1194 ok( r == ERROR_SUCCESS, "MsiSetTargetPath on subsubdir returned %d\n", r );
1195
1196 buffer[0] = 0;
1197 sz = sizeof buffer - 1;
1198 lstrcatA( tempdir, "\\" );
1199 r = MsiGetTargetPathA( hpkg, "TARGETDIR", buffer, &sz );
1200 ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1201 ok( !lstrcmpA(buffer, tempdir), "Expected %s, got %s\n", tempdir, buffer);
1202
1203 sprintf( file, "%srootfile.txt", tempdir );
1204 query_file_path( hpkg, "[#RootFile]", buffer );
1205 ok( !lstrcmpA(buffer, file), "Expected %s, got %s\n", file, buffer);
1206
1207 buffer[0] = 0;
1208 sz = sizeof(buffer);
1209 r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1210 ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1211 lstrcatA( tempdir, "TestParent\\" );
1212 ok( !lstrcmpiA(buffer, tempdir), "Expected \"%s\", got \"%s\"\n", tempdir, buffer );
1213
1214 r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two" );
1215 ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1216
1217 buffer[0] = 0;
1218 sz = sizeof(buffer);
1219 r = MsiGetPropertyA( hpkg, "TestParent", buffer, &sz );
1220 ok( r == ERROR_SUCCESS, "MsiGetProperty returned %u\n", r );
1221 ok( lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\"),
1222 "Expected \"C:\\one\\two\\TestDir\\\", got \"%s\"\n", buffer );
1223
1224 buffer[0] = 0;
1225 query_file_path( hpkg, "[#TestFile]", buffer );
1226 ok( !lstrcmpiA(buffer, "C:\\one\\two\\TestDir\\testfile.txt"),
1227 "Expected C:\\one\\two\\TestDir\\testfile.txt, got %s\n", buffer );
1228
1229 buffer[0] = 0;
1230 sz = sizeof buffer - 1;
1231 r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1232 ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1233 ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected C:\\one\\two\\, got %s\n", buffer);
1234
1235 r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\one\\two\\three" );
1236 ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1237
1238 buffer[0] = 0;
1239 sz = sizeof buffer - 1;
1240 r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1241 ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1242 ok( !lstrcmpiA(buffer, "C:\\one\\two\\three\\"), "Expected C:\\one\\two\\three\\, got %s\n", buffer);
1243
1244 r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\one\\\\two " );
1245 ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1246
1247 buffer[0] = 0;
1248 sz = sizeof buffer - 1;
1249 r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1250 ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1251 ok( !lstrcmpiA(buffer, "C:\\one\\two\\"), "Expected \"C:\\one\\two\\\", got %s\n", buffer);
1252
1253 r = MsiSetTargetPathA( hpkg, "TestParent", "C:\\\\ Program Files \\\\ " );
1254 ok( r == ERROR_SUCCESS, "MsiSetTargetPath returned %d\n", r );
1255
1256 buffer[0] = 0;
1257 sz = sizeof buffer - 1;
1258 r = MsiGetTargetPathA( hpkg, "TestParent", buffer, &sz );
1259 ok( r == ERROR_SUCCESS, "failed to get target path: %d\n", r);
1260 ok( !lstrcmpiA(buffer, "C:\\Program Files\\"), "Expected \"C:\\Program Files\\\", got %s\n", buffer);
1261
1262 MsiCloseHandle( hpkg );
1263 }
1264
1265 static void test_condition(void)
1266 {
1267 static const WCHAR cond1[] = {'\"','a',0x30a,'\"','<','\"',0xe5,'\"',0};
1268 static const WCHAR cond2[] = {'\"','a',0x30a,'\"','>','\"',0xe5,'\"',0};
1269 static const WCHAR cond3[] = {'\"','a',0x30a,'\"','<','>','\"',0xe5,'\"',0};
1270 static const WCHAR cond4[] = {'\"','a',0x30a,'\"','=','\"',0xe5,'\"',0};
1271 MSICONDITION r;
1272 MSIHANDLE hpkg;
1273
1274 r = package_from_db(create_package_db(), &hpkg);
1275 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
1276 {
1277 skip("Not enough rights to perform tests\n");
1278 DeleteFileA(msifile);
1279 return;
1280 }
1281 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
1282
1283 r = MsiEvaluateConditionA(0, NULL);
1284 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1285
1286 r = MsiEvaluateConditionA(hpkg, NULL);
1287 ok( r == MSICONDITION_NONE, "wrong return val\n");
1288
1289 r = MsiEvaluateConditionA(hpkg, "");
1290 ok( r == MSICONDITION_NONE, "wrong return val\n");
1291
1292 r = MsiEvaluateConditionA(hpkg, "1");
1293 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1294
1295 r = MsiEvaluateConditionA(hpkg, "0");
1296 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1297
1298 r = MsiEvaluateConditionA(hpkg, "-1");
1299 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1300
1301 r = MsiEvaluateConditionA(hpkg, "0 = 0");
1302 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1303
1304 r = MsiEvaluateConditionA(hpkg, "0 <> 0");
1305 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1306
1307 r = MsiEvaluateConditionA(hpkg, "0 = 1");
1308 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1309
1310 r = MsiEvaluateConditionA(hpkg, "0 > 1");
1311 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1312
1313 r = MsiEvaluateConditionA(hpkg, "0 ~> 1");
1314 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1315
1316 r = MsiEvaluateConditionA(hpkg, "1 > 1");
1317 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1318
1319 r = MsiEvaluateConditionA(hpkg, "1 ~> 1");
1320 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1321
1322 r = MsiEvaluateConditionA(hpkg, "0 >= 1");
1323 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1324
1325 r = MsiEvaluateConditionA(hpkg, "0 ~>= 1");
1326 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1327
1328 r = MsiEvaluateConditionA(hpkg, "1 >= 1");
1329 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1330
1331 r = MsiEvaluateConditionA(hpkg, "1 ~>= 1");
1332 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1333
1334 r = MsiEvaluateConditionA(hpkg, "0 < 1");
1335 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1336
1337 r = MsiEvaluateConditionA(hpkg, "0 ~< 1");
1338 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1339
1340 r = MsiEvaluateConditionA(hpkg, "1 < 1");
1341 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1342
1343 r = MsiEvaluateConditionA(hpkg, "1 ~< 1");
1344 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1345
1346 r = MsiEvaluateConditionA(hpkg, "0 <= 1");
1347 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1348
1349 r = MsiEvaluateConditionA(hpkg, "0 ~<= 1");
1350 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1351
1352 r = MsiEvaluateConditionA(hpkg, "1 <= 1");
1353 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1354
1355 r = MsiEvaluateConditionA(hpkg, "1 ~<= 1");
1356 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1357
1358 r = MsiEvaluateConditionA(hpkg, "0 >=");
1359 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1360
1361 r = MsiEvaluateConditionA(hpkg, " ");
1362 ok( r == MSICONDITION_NONE, "wrong return val\n");
1363
1364 r = MsiEvaluateConditionA(hpkg, "LicView <> \"1\"");
1365 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1366
1367 r = MsiEvaluateConditionA(hpkg, "LicView <> \"0\"");
1368 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1369
1370 r = MsiEvaluateConditionA(hpkg, "LicView <> LicView");
1371 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1372
1373 r = MsiEvaluateConditionA(hpkg, "not 0");
1374 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1375
1376 r = MsiEvaluateConditionA(hpkg, "not LicView");
1377 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1378
1379 r = MsiEvaluateConditionA(hpkg, "\"Testing\" ~<< \"Testing\"");
1380 ok (r == MSICONDITION_TRUE, "wrong return val\n");
1381
1382 r = MsiEvaluateConditionA(hpkg, "LicView ~<< \"Testing\"");
1383 ok (r == MSICONDITION_FALSE, "wrong return val\n");
1384
1385 r = MsiEvaluateConditionA(hpkg, "Not LicView ~<< \"Testing\"");
1386 ok (r == MSICONDITION_TRUE, "wrong return val\n");
1387
1388 r = MsiEvaluateConditionA(hpkg, "not \"A\"");
1389 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1390
1391 r = MsiEvaluateConditionA(hpkg, "~not \"A\"");
1392 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1393
1394 r = MsiEvaluateConditionA(hpkg, "\"0\"");
1395 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1396
1397 r = MsiEvaluateConditionA(hpkg, "1 and 2");
1398 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1399
1400 r = MsiEvaluateConditionA(hpkg, "not 0 and 3");
1401 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1402
1403 r = MsiEvaluateConditionA(hpkg, "not 0 and 0");
1404 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1405
1406 r = MsiEvaluateConditionA(hpkg, "not 0 or 1");
1407 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1408
1409 r = MsiEvaluateConditionA(hpkg, "(0)");
1410 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1411
1412 r = MsiEvaluateConditionA(hpkg, "(((((1))))))");
1413 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1414
1415 r = MsiEvaluateConditionA(hpkg, "(((((1)))))");
1416 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1417
1418 r = MsiEvaluateConditionA(hpkg, " \"A\" < \"B\" ");
1419 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1420
1421 r = MsiEvaluateConditionA(hpkg, " \"A\" > \"B\" ");
1422 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1423
1424 r = MsiEvaluateConditionA(hpkg, " \"1\" > \"12\" ");
1425 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1426
1427 r = MsiEvaluateConditionA(hpkg, " \"100\" < \"21\" ");
1428 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1429
1430 r = MsiEvaluateConditionA(hpkg, "0 < > 0");
1431 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1432
1433 r = MsiEvaluateConditionA(hpkg, "(1<<1) == 2");
1434 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1435
1436 r = MsiEvaluateConditionA(hpkg, " \"A\" = \"a\" ");
1437 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1438
1439 r = MsiEvaluateConditionA(hpkg, " \"A\" ~ = \"a\" ");
1440 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1441
1442 r = MsiEvaluateConditionA(hpkg, " \"A\" ~= \"a\" ");
1443 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1444
1445 r = MsiEvaluateConditionA(hpkg, " \"A\" ~= 1 ");
1446 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1447
1448 r = MsiEvaluateConditionA(hpkg, " \"A\" = 1 ");
1449 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1450
1451 r = MsiEvaluateConditionA(hpkg, " 1 ~= 1 ");
1452 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1453
1454 r = MsiEvaluateConditionA(hpkg, " 1 ~= \"1\" ");
1455 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1456
1457 r = MsiEvaluateConditionA(hpkg, " 1 = \"1\" ");
1458 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1459
1460 r = MsiEvaluateConditionA(hpkg, " 0 = \"1\" ");
1461 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1462
1463 r = MsiEvaluateConditionA(hpkg, " 0 < \"100\" ");
1464 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1465
1466 r = MsiEvaluateConditionA(hpkg, " 100 > \"0\" ");
1467 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1468
1469 r = MsiEvaluateConditionA(hpkg, "1 XOR 1");
1470 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1471
1472 r = MsiEvaluateConditionA(hpkg, "1 IMP 1");
1473 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1474
1475 r = MsiEvaluateConditionA(hpkg, "1 IMP 0");
1476 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1477
1478 r = MsiEvaluateConditionA(hpkg, "0 IMP 0");
1479 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1480
1481 r = MsiEvaluateConditionA(hpkg, "0 EQV 0");
1482 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1483
1484 r = MsiEvaluateConditionA(hpkg, "0 EQV 1");
1485 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1486
1487 r = MsiEvaluateConditionA(hpkg, "1 IMP 1 OR 0");
1488 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1489
1490 r = MsiEvaluateConditionA(hpkg, "1 IMPL 1");
1491 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1492
1493 r = MsiEvaluateConditionA(hpkg, "\"ASFD\" >< \"S\" ");
1494 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1495
1496 r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"s\" ");
1497 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1498
1499 r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"\" ");
1500 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1501
1502 r = MsiEvaluateConditionA(hpkg, "\"ASFD\" ~>< \"sss\" ");
1503 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1504
1505 MsiSetPropertyA(hpkg, "mm", "5" );
1506
1507 r = MsiEvaluateConditionA(hpkg, "mm = 5");
1508 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1509
1510 r = MsiEvaluateConditionA(hpkg, "mm < 6");
1511 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1512
1513 r = MsiEvaluateConditionA(hpkg, "mm <= 5");
1514 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1515
1516 r = MsiEvaluateConditionA(hpkg, "mm > 4");
1517 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1518
1519 r = MsiEvaluateConditionA(hpkg, "mm < 12");
1520 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1521
1522 r = MsiEvaluateConditionA(hpkg, "mm = \"5\"");
1523 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1524
1525 r = MsiEvaluateConditionA(hpkg, "0 = \"\"");
1526 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1527
1528 r = MsiEvaluateConditionA(hpkg, "0 AND \"\"");
1529 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1530
1531 r = MsiEvaluateConditionA(hpkg, "1 AND \"\"");
1532 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1533
1534 r = MsiEvaluateConditionA(hpkg, "1 AND \"1\"");
1535 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1536
1537 r = MsiEvaluateConditionA(hpkg, "3 >< 1");
1538 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1539
1540 r = MsiEvaluateConditionA(hpkg, "3 >< 4");
1541 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1542
1543 r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 0");
1544 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1545
1546 r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1");
1547 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1548
1549 r = MsiEvaluateConditionA(hpkg, "NOT 1 OR 0");
1550 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1551
1552 r = MsiEvaluateConditionA(hpkg, "0 AND 1 OR 1");
1553 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1554
1555 r = MsiEvaluateConditionA(hpkg, "0 AND 0 OR 1");
1556 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1557
1558 r = MsiEvaluateConditionA(hpkg, "NOT 0 AND 1 OR 0");
1559 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1560
1561 r = MsiEvaluateConditionA(hpkg, "_1 = _1");
1562 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1563
1564 r = MsiEvaluateConditionA(hpkg, "( 1 AND 1 ) = 2");
1565 ok( r == MSICONDITION_ERROR, "wrong return val\n");
1566
1567 r = MsiEvaluateConditionA(hpkg, "NOT ( 1 AND 1 )");
1568 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1569
1570 r = MsiEvaluateConditionA(hpkg, "NOT A AND (BBBBBBBBBB=2 OR CCC=1) AND Ddddddddd");
1571 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1572
1573 r = MsiEvaluateConditionA(hpkg, "Installed<>\"\"");
1574 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1575
1576 r = MsiEvaluateConditionA(hpkg, "NOT 1 AND 0");
1577 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1578
1579 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1580 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1581
1582 r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1583 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1584
1585 r = MsiEvaluateConditionA(hpkg, "bandalmael<0");
1586 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1587
1588 r = MsiEvaluateConditionA(hpkg, "bandalmael>0");
1589 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1590
1591 r = MsiEvaluateConditionA(hpkg, "bandalmael>=0");
1592 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1593
1594 r = MsiEvaluateConditionA(hpkg, "bandalmael<=0");
1595 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1596
1597 r = MsiEvaluateConditionA(hpkg, "bandalmael~<>0");
1598 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1599
1600 MsiSetPropertyA(hpkg, "bandalmael", "0" );
1601 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1602 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1603
1604 MsiSetPropertyA(hpkg, "bandalmael", "" );
1605 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1606 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1607
1608 MsiSetPropertyA(hpkg, "bandalmael", "asdf" );
1609 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1610 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1611
1612 MsiSetPropertyA(hpkg, "bandalmael", "0asdf" );
1613 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1614 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1615
1616 MsiSetPropertyA(hpkg, "bandalmael", "0 " );
1617 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1618 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1619
1620 MsiSetPropertyA(hpkg, "bandalmael", "-0" );
1621 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1622 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1623
1624 MsiSetPropertyA(hpkg, "bandalmael", "0000000000000" );
1625 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1626 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1627
1628 MsiSetPropertyA(hpkg, "bandalmael", "--0" );
1629 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1630 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1631
1632 MsiSetPropertyA(hpkg, "bandalmael", "0x00" );
1633 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1634 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1635
1636 MsiSetPropertyA(hpkg, "bandalmael", "-" );
1637 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1638 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1639
1640 MsiSetPropertyA(hpkg, "bandalmael", "+0" );
1641 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1642 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1643
1644 MsiSetPropertyA(hpkg, "bandalmael", "0.0" );
1645 r = MsiEvaluateConditionA(hpkg, "bandalmael=0");
1646 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1647 r = MsiEvaluateConditionA(hpkg, "bandalmael<>0");
1648 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1649
1650 MsiSetPropertyA(hpkg, "one", "hi");
1651 MsiSetPropertyA(hpkg, "two", "hithere");
1652 r = MsiEvaluateConditionA(hpkg, "one >< two");
1653 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1654
1655 MsiSetPropertyA(hpkg, "one", "hithere");
1656 MsiSetPropertyA(hpkg, "two", "hi");
1657 r = MsiEvaluateConditionA(hpkg, "one >< two");
1658 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1659
1660 MsiSetPropertyA(hpkg, "one", "hello");
1661 MsiSetPropertyA(hpkg, "two", "hi");
1662 r = MsiEvaluateConditionA(hpkg, "one >< two");
1663 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1664
1665 MsiSetPropertyA(hpkg, "one", "hellohithere");
1666 MsiSetPropertyA(hpkg, "two", "hi");
1667 r = MsiEvaluateConditionA(hpkg, "one >< two");
1668 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1669
1670 MsiSetPropertyA(hpkg, "one", "");
1671 MsiSetPropertyA(hpkg, "two", "hi");
1672 r = MsiEvaluateConditionA(hpkg, "one >< two");
1673 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1674
1675 MsiSetPropertyA(hpkg, "one", "hi");
1676 MsiSetPropertyA(hpkg, "two", "");
1677 r = MsiEvaluateConditionA(hpkg, "one >< two");
1678 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1679
1680 MsiSetPropertyA(hpkg, "one", "");
1681 MsiSetPropertyA(hpkg, "two", "");
1682 r = MsiEvaluateConditionA(hpkg, "one >< two");
1683 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1684
1685 MsiSetPropertyA(hpkg, "one", "1234");
1686 MsiSetPropertyA(hpkg, "two", "1");
1687 r = MsiEvaluateConditionA(hpkg, "one >< two");
1688 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1689
1690 MsiSetPropertyA(hpkg, "one", "one 1234");
1691 MsiSetPropertyA(hpkg, "two", "1");
1692 r = MsiEvaluateConditionA(hpkg, "one >< two");
1693 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1694
1695 MsiSetPropertyA(hpkg, "one", "hithere");
1696 MsiSetPropertyA(hpkg, "two", "hi");
1697 r = MsiEvaluateConditionA(hpkg, "one << two");
1698 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1699
1700 MsiSetPropertyA(hpkg, "one", "hi");
1701 MsiSetPropertyA(hpkg, "two", "hithere");
1702 r = MsiEvaluateConditionA(hpkg, "one << two");
1703 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1704
1705 MsiSetPropertyA(hpkg, "one", "hi");
1706 MsiSetPropertyA(hpkg, "two", "hi");
1707 r = MsiEvaluateConditionA(hpkg, "one << two");
1708 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1709
1710 MsiSetPropertyA(hpkg, "one", "abcdhithere");
1711 MsiSetPropertyA(hpkg, "two", "hi");
1712 r = MsiEvaluateConditionA(hpkg, "one << two");
1713 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1714
1715 MsiSetPropertyA(hpkg, "one", "");
1716 MsiSetPropertyA(hpkg, "two", "hi");
1717 r = MsiEvaluateConditionA(hpkg, "one << two");
1718 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1719
1720 MsiSetPropertyA(hpkg, "one", "hithere");
1721 MsiSetPropertyA(hpkg, "two", "");
1722 r = MsiEvaluateConditionA(hpkg, "one << two");
1723 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1724
1725 MsiSetPropertyA(hpkg, "one", "");
1726 MsiSetPropertyA(hpkg, "two", "");
1727 r = MsiEvaluateConditionA(hpkg, "one << two");
1728 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1729
1730 MsiSetPropertyA(hpkg, "one", "1234");
1731 MsiSetPropertyA(hpkg, "two", "1");
1732 r = MsiEvaluateConditionA(hpkg, "one << two");
1733 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1734
1735 MsiSetPropertyA(hpkg, "one", "1234 one");
1736 MsiSetPropertyA(hpkg, "two", "1");
1737 r = MsiEvaluateConditionA(hpkg, "one << two");
1738 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1739
1740 MsiSetPropertyA(hpkg, "one", "hithere");
1741 MsiSetPropertyA(hpkg, "two", "there");
1742 r = MsiEvaluateConditionA(hpkg, "one >> two");
1743 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1744
1745 MsiSetPropertyA(hpkg, "one", "hithere");
1746 MsiSetPropertyA(hpkg, "two", "hi");
1747 r = MsiEvaluateConditionA(hpkg, "one >> two");
1748 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1749
1750 MsiSetPropertyA(hpkg, "one", "there");
1751 MsiSetPropertyA(hpkg, "two", "hithere");
1752 r = MsiEvaluateConditionA(hpkg, "one >> two");
1753 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1754
1755 MsiSetPropertyA(hpkg, "one", "there");
1756 MsiSetPropertyA(hpkg, "two", "there");
1757 r = MsiEvaluateConditionA(hpkg, "one >> two");
1758 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1759
1760 MsiSetPropertyA(hpkg, "one", "abcdhithere");
1761 MsiSetPropertyA(hpkg, "two", "hi");
1762 r = MsiEvaluateConditionA(hpkg, "one >> two");
1763 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1764
1765 MsiSetPropertyA(hpkg, "one", "");
1766 MsiSetPropertyA(hpkg, "two", "there");
1767 r = MsiEvaluateConditionA(hpkg, "one >> two");
1768 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1769
1770 MsiSetPropertyA(hpkg, "one", "there");
1771 MsiSetPropertyA(hpkg, "two", "");
1772 r = MsiEvaluateConditionA(hpkg, "one >> two");
1773 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1774
1775 MsiSetPropertyA(hpkg, "one", "");
1776 MsiSetPropertyA(hpkg, "two", "");
1777 r = MsiEvaluateConditionA(hpkg, "one >> two");
1778 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1779
1780 MsiSetPropertyA(hpkg, "one", "1234");
1781 MsiSetPropertyA(hpkg, "two", "4");
1782 r = MsiEvaluateConditionA(hpkg, "one >> two");
1783 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1784
1785 MsiSetPropertyA(hpkg, "one", "one 1234");
1786 MsiSetPropertyA(hpkg, "two", "4");
1787 r = MsiEvaluateConditionA(hpkg, "one >> two");
1788 ok( r == MSICONDITION_TRUE, "wrong return val\n");
1789
1790 MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", NULL); /* make sure it's empty */
1791
1792 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1793 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1794
1795 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport > \"1.1.4322\"");
1796 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1797
1798 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport >= \"1.1.4322\"");
1799 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1800
1801 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <= \"1.1.4322\"");
1802 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1803
1804 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport <> \"1.1.4322\"");
1805 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1806
1807 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport ~< \"1.1.4322\"");
1808 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1809
1810 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"abcd\"");
1811 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1812
1813 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a1.1.4322\"");
1814 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1815
1816 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322a\"");
1817 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1818
1819 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0000001.1.4322\"");
1820 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1821
1822 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1\"");
1823 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1824
1825 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322.1.1\"");
1826 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1827
1828 r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1");
1829 ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1830
1831 r = MsiEvaluateConditionA(hpkg, "\"2\" < \"1.1\"");
1832 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1833
1834 r = MsiEvaluateConditionA(hpkg, "\"2\" < \"12.1\"");
1835 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1836
1837 r = MsiEvaluateConditionA(hpkg, "\"02.1\" < \"2.11\"");
1838 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1839
1840 r = MsiEvaluateConditionA(hpkg, "\"02.1.1\" < \"2.1\"");
1841 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1842
1843 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1844 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1845
1846 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1847 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1848
1849 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"0\"");
1850 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1851
1852 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"-1\"");
1853 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1854
1855 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a\"");
1856 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1857
1858 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1859 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1860
1861 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"!\"");
1862 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1863
1864 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"/\"");
1865 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1866
1867 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \" \"");
1868 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1869
1870 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"azAZ_\"");
1871 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1872
1873 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]\"");
1874 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1875
1876 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a[a]a\"");
1877 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1878
1879 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]\"");
1880 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1881
1882 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a]a\"");
1883 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1884
1885 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a}\"");
1886 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1887
1888 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"{a\"");
1889 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1890
1891 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"[a\"");
1892 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1893
1894 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a{\"");
1895 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1896
1897 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"a]\"");
1898 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1899
1900 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"A\"");
1901 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1902
1903 MsiSetPropertyA(hpkg, "MsiNetAssemblySupport", "1.1.4322");
1904 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.4322\"");
1905 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1906
1907 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.14322\"");
1908 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1909
1910 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1.5\"");
1911 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1912
1913 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1.1\"");
1914 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1915
1916 r = MsiEvaluateConditionA(hpkg, "MsiNetAssemblySupport < \"1\"");
1917 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1918
1919 MsiSetPropertyA(hpkg, "one", "1");
1920 r = MsiEvaluateConditionA(hpkg, "one < \"1\"");
1921 ok( r == MSICONDITION_FALSE, "wrong return val\n");
1922
1923 MsiSetPropertyA(hpkg, "X", "5.0");
1924
1925 r = MsiEvaluateConditionA(hpkg, "X != \"\"");
1926 ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1927
1928 r = MsiEvaluateConditionA(hpkg, "X =\"5.0\"");
1929 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1930
1931 r = MsiEvaluateConditionA(hpkg, "X =\"5.1\"");
1932 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1933
1934 r = MsiEvaluateConditionA(hpkg, "X =\"6.0\"");
1935 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1936
1937 r = MsiEvaluateConditionA(hpkg, "X =\"5.0\" or X =\"5.1\" or X =\"6.0\"");
1938 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1939
1940 r = MsiEvaluateConditionA(hpkg, "(X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
1941 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1942
1943 r = MsiEvaluateConditionA(hpkg, "X !=\"\" and (X =\"5.0\" or X =\"5.1\" or X =\"6.0\")");
1944 ok( r == MSICONDITION_ERROR, "wrong return val (%d)\n", r);
1945
1946 /* feature doesn't exist */
1947 r = MsiEvaluateConditionA(hpkg, "&nofeature");
1948 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1949
1950 MsiSetPropertyA(hpkg, "A", "2");
1951 MsiSetPropertyA(hpkg, "X", "50");
1952
1953 r = MsiEvaluateConditionA(hpkg, "2 <= X");
1954 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1955
1956 r = MsiEvaluateConditionA(hpkg, "A <= X");
1957 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1958
1959 r = MsiEvaluateConditionA(hpkg, "A <= 50");
1960 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1961
1962 MsiSetPropertyA(hpkg, "X", "50val");
1963
1964 r = MsiEvaluateConditionA(hpkg, "2 <= X");
1965 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1966
1967 r = MsiEvaluateConditionA(hpkg, "A <= X");
1968 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1969
1970 MsiSetPropertyA(hpkg, "A", "7");
1971 MsiSetPropertyA(hpkg, "X", "50");
1972
1973 r = MsiEvaluateConditionA(hpkg, "7 <= X");
1974 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1975
1976 r = MsiEvaluateConditionA(hpkg, "A <= X");
1977 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1978
1979 r = MsiEvaluateConditionA(hpkg, "A <= 50");
1980 ok( r == MSICONDITION_TRUE, "wrong return val (%d)\n", r);
1981
1982 MsiSetPropertyA(hpkg, "X", "50val");
1983
1984 r = MsiEvaluateConditionA(hpkg, "2 <= X");
1985 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1986
1987 r = MsiEvaluateConditionA(hpkg, "A <= X");
1988 ok( r == MSICONDITION_FALSE, "wrong return val (%d)\n", r);
1989
1990 r = MsiEvaluateConditionW(hpkg, cond1);
1991 ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
1992 "wrong return val (%d)\n", r);
1993
1994 r = MsiEvaluateConditionW(hpkg, cond2);
1995 ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
1996 "wrong return val (%d)\n", r);
1997
1998 r = MsiEvaluateConditionW(hpkg, cond3);
1999 ok( r == MSICONDITION_TRUE || broken(r == MSICONDITION_FALSE),
2000 "wrong return val (%d)\n", r);
2001
2002 r = MsiEvaluateConditionW(hpkg, cond4);
2003 ok( r == MSICONDITION_FALSE || broken(r == MSICONDITION_TRUE),
2004 "wrong return val (%d)\n", r);
2005
2006 MsiCloseHandle( hpkg );
2007 DeleteFileA(msifile);
2008 }
2009
2010 static BOOL check_prop_empty( MSIHANDLE hpkg, const char * prop)
2011 {
2012 UINT r;
2013 DWORD sz;
2014 char buffer[2];
2015
2016 sz = sizeof buffer;
2017 strcpy(buffer,"x");
2018 r = MsiGetPropertyA( hpkg, prop, buffer, &sz );
2019 return r == ERROR_SUCCESS && buffer[0] == 0 && sz == 0;
2020 }
2021
2022 static void test_props(void)
2023 {
2024 MSIHANDLE hpkg, hdb;
2025 UINT r;
2026 DWORD sz;
2027 char buffer[0x100];
2028
2029 hdb = create_package_db();
2030 r = run_query( hdb,
2031 "CREATE TABLE `Property` ( "
2032 "`Property` CHAR(255) NOT NULL, "
2033 "`Value` CHAR(255) "
2034 "PRIMARY KEY `Property`)" );
2035 ok( r == ERROR_SUCCESS , "Failed\n" );
2036
2037 r = run_query(hdb,
2038 "INSERT INTO `Property` "
2039 "(`Property`, `Value`) "
2040 "VALUES( 'MetadataCompName', 'Photoshop.dll' )");
2041 ok( r == ERROR_SUCCESS , "Failed\n" );
2042
2043 r = package_from_db( hdb, &hpkg );
2044 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2045 {
2046 skip("Not enough rights to perform tests\n");
2047 DeleteFileA(msifile);
2048 return;
2049 }
2050 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2051
2052 /* test invalid values */
2053 r = MsiGetPropertyA( 0, NULL, NULL, NULL );
2054 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2055
2056 r = MsiGetPropertyA( hpkg, NULL, NULL, NULL );
2057 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2058
2059 r = MsiGetPropertyA( hpkg, "boo", NULL, NULL );
2060 ok( r == ERROR_SUCCESS, "wrong return val\n");
2061
2062 r = MsiGetPropertyA( hpkg, "boo", buffer, NULL );
2063 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2064
2065 /* test retrieving an empty/nonexistent property */
2066 sz = sizeof buffer;
2067 r = MsiGetPropertyA( hpkg, "boo", NULL, &sz );
2068 ok( r == ERROR_SUCCESS, "wrong return val\n");
2069 ok( sz == 0, "wrong size returned\n");
2070
2071 check_prop_empty( hpkg, "boo");
2072 sz = 0;
2073 strcpy(buffer,"x");
2074 r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2075 ok( r == ERROR_MORE_DATA, "wrong return val\n");
2076 ok( !strcmp(buffer,"x"), "buffer was changed\n");
2077 ok( sz == 0, "wrong size returned\n");
2078
2079 sz = 1;
2080 strcpy(buffer,"x");
2081 r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2082 ok( r == ERROR_SUCCESS, "wrong return val\n");
2083 ok( buffer[0] == 0, "buffer was not changed\n");
2084 ok( sz == 0, "wrong size returned\n");
2085
2086 /* set the property to something */
2087 r = MsiSetPropertyA( 0, NULL, NULL );
2088 ok( r == ERROR_INVALID_HANDLE, "wrong return val\n");
2089
2090 r = MsiSetPropertyA( hpkg, NULL, NULL );
2091 ok( r == ERROR_INVALID_PARAMETER, "wrong return val\n");
2092
2093 r = MsiSetPropertyA( hpkg, "", NULL );
2094 ok( r == ERROR_SUCCESS, "wrong return val\n");
2095
2096 /* try set and get some illegal property identifiers */
2097 r = MsiSetPropertyA( hpkg, "", "asdf" );
2098 ok( r == ERROR_FUNCTION_FAILED, "wrong return val\n");
2099
2100 r = MsiSetPropertyA( hpkg, "=", "asdf" );
2101 ok( r == ERROR_SUCCESS, "wrong return val\n");
2102
2103 r = MsiSetPropertyA( hpkg, " ", "asdf" );
2104 ok( r == ERROR_SUCCESS, "wrong return val\n");
2105
2106 r = MsiSetPropertyA( hpkg, "'", "asdf" );
2107 ok( r == ERROR_SUCCESS, "wrong return val\n");
2108
2109 sz = sizeof buffer;
2110 buffer[0]=0;
2111 r = MsiGetPropertyA( hpkg, "'", buffer, &sz );
2112 ok( r == ERROR_SUCCESS, "wrong return val\n");
2113 ok( !strcmp(buffer,"asdf"), "buffer was not changed\n");
2114
2115 /* set empty values */
2116 r = MsiSetPropertyA( hpkg, "boo", NULL );
2117 ok( r == ERROR_SUCCESS, "wrong return val\n");
2118 ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2119
2120 r = MsiSetPropertyA( hpkg, "boo", "" );
2121 ok( r == ERROR_SUCCESS, "wrong return val\n");
2122 ok( check_prop_empty( hpkg, "boo"), "prop wasn't empty\n");
2123
2124 /* set a non-empty value */
2125 r = MsiSetPropertyA( hpkg, "boo", "xyz" );
2126 ok( r == ERROR_SUCCESS, "wrong return val\n");
2127
2128 sz = 1;
2129 strcpy(buffer,"x");
2130 r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2131 ok( r == ERROR_MORE_DATA, "wrong return val\n");
2132 ok( buffer[0] == 0, "buffer was not changed\n");
2133 ok( sz == 3, "wrong size returned\n");
2134
2135 sz = 4;
2136 strcpy(buffer,"x");
2137 r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2138 ok( r == ERROR_SUCCESS, "wrong return val\n");
2139 ok( !strcmp(buffer,"xyz"), "buffer was not changed\n");
2140 ok( sz == 3, "wrong size returned\n");
2141
2142 sz = 3;
2143 strcpy(buffer,"x");
2144 r = MsiGetPropertyA( hpkg, "boo", buffer, &sz );
2145 ok( r == ERROR_MORE_DATA, "wrong return val\n");
2146 ok( !strcmp(buffer,"xy"), "buffer was not changed\n");
2147 ok( sz == 3, "wrong size returned\n");
2148
2149 r = MsiSetPropertyA(hpkg, "SourceDir", "foo");
2150 ok( r == ERROR_SUCCESS, "wrong return val\n");
2151
2152 sz = 4;
2153 r = MsiGetPropertyA(hpkg, "SOURCEDIR", buffer, &sz);
2154 ok( r == ERROR_SUCCESS, "wrong return val\n");
2155 ok( !strcmp(buffer,""), "buffer wrong\n");
2156 ok( sz == 0, "wrong size returned\n");
2157
2158 sz = 4;
2159 r = MsiGetPropertyA(hpkg, "SOMERANDOMNAME", buffer, &sz);
2160 ok( r == ERROR_SUCCESS, "wrong return val\n");
2161 ok( !strcmp(buffer,""), "buffer wrong\n");
2162 ok( sz == 0, "wrong size returned\n");
2163
2164 sz = 4;
2165 r = MsiGetPropertyA(hpkg, "SourceDir", buffer, &sz);
2166 ok( r == ERROR_SUCCESS, "wrong return val\n");
2167 ok( !strcmp(buffer,"foo"), "buffer wrong\n");
2168 ok( sz == 3, "wrong size returned\n");
2169
2170 r = MsiSetPropertyA(hpkg, "MetadataCompName", "Photoshop.dll");
2171 ok( r == ERROR_SUCCESS, "wrong return val\n");
2172
2173 sz = 0;
2174 r = MsiGetPropertyA(hpkg, "MetadataCompName", NULL, &sz );
2175 ok( r == ERROR_SUCCESS, "return wrong\n");
2176 ok( sz == 13, "size wrong (%d)\n", sz);
2177
2178 sz = 13;
2179 r = MsiGetPropertyA(hpkg, "MetadataCompName", buffer, &sz );
2180 ok( r == ERROR_MORE_DATA, "return wrong\n");
2181 ok( !strcmp(buffer,"Photoshop.dl"), "buffer wrong\n");
2182
2183 r = MsiSetPropertyA(hpkg, "property", "value");
2184 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2185
2186 sz = 6;
2187 r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2188 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2189 ok( !strcmp(buffer, "value"), "Expected value, got %s\n", buffer);
2190
2191 r = MsiSetPropertyA(hpkg, "property", NULL);
2192 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2193
2194 sz = 6;
2195 r = MsiGetPropertyA(hpkg, "property", buffer, &sz);
2196 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2197 ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2198
2199 MsiCloseHandle( hpkg );
2200 DeleteFileA(msifile);
2201 }
2202
2203 static BOOL find_prop_in_property(MSIHANDLE hdb, LPCSTR prop, LPCSTR val, int len)
2204 {
2205 MSIHANDLE hview, hrec;
2206 BOOL found = FALSE;
2207 CHAR buffer[MAX_PATH];
2208 DWORD sz;
2209 UINT r;
2210
2211 r = MsiDatabaseOpenViewA(hdb, "SELECT * FROM `_Property`", &hview);
2212 ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
2213 r = MsiViewExecute(hview, 0);
2214 ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n");
2215
2216 if (len < 0) len = lstrlenA(val);
2217
2218 while (r == ERROR_SUCCESS && !found)
2219 {
2220 r = MsiViewFetch(hview, &hrec);
2221 if (r != ERROR_SUCCESS) break;
2222
2223 sz = MAX_PATH;
2224 r = MsiRecordGetStringA(hrec, 1, buffer, &sz);
2225 if (r == ERROR_SUCCESS && !lstrcmpA(buffer, prop))
2226 {
2227 sz = MAX_PATH;
2228 r = MsiRecordGetStringA(hrec, 2, buffer, &sz);
2229 if (r == ERROR_SUCCESS && !memcmp(buffer, val, len) && !buffer[len])
2230 {
2231 ok(sz == len, "wrong size %u\n", sz);
2232 found = TRUE;
2233 }
2234 }
2235
2236 MsiCloseHandle(hrec);
2237 }
2238 MsiViewClose(hview);
2239 MsiCloseHandle(hview);
2240 return found;
2241 }
2242
2243 static void test_property_table(void)
2244 {
2245 const char *query;
2246 UINT r;
2247 MSIHANDLE hpkg, hdb, hrec;
2248 char buffer[MAX_PATH], package[10];
2249 DWORD sz;
2250 BOOL found;
2251
2252 hdb = create_package_db();
2253 ok( hdb, "failed to create package\n");
2254
2255 r = package_from_db(hdb, &hpkg);
2256 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2257 {
2258 skip("Not enough rights to perform tests\n");
2259 DeleteFileA(msifile);
2260 return;
2261 }
2262 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2263
2264 MsiCloseHandle(hdb);
2265
2266 hdb = MsiGetActiveDatabase(hpkg);
2267
2268 query = "CREATE TABLE `_Property` ( "
2269 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2270 r = run_query(hdb, query);
2271 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2272
2273 MsiCloseHandle(hdb);
2274 MsiCloseHandle(hpkg);
2275 DeleteFileA(msifile);
2276
2277 hdb = create_package_db();
2278 ok( hdb, "failed to create package\n");
2279
2280 query = "CREATE TABLE `_Property` ( "
2281 "`foo` INT NOT NULL, `bar` INT LOCALIZABLE PRIMARY KEY `foo`)";
2282 r = run_query(hdb, query);
2283 ok(r == ERROR_SUCCESS, "failed to create table\n");
2284
2285 query = "ALTER `_Property` ADD `foo` INTEGER";
2286 r = run_query(hdb, query);
2287 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2288
2289 query = "ALTER TABLE `_Property` ADD `foo` INTEGER";
2290 r = run_query(hdb, query);
2291 ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to add column\n");
2292
2293 query = "ALTER TABLE `_Property` ADD `extra` INTEGER";
2294 r = run_query(hdb, query);
2295 ok(r == ERROR_SUCCESS, "failed to add column\n");
2296
2297 sprintf(package, "#%i", hdb);
2298 r = MsiOpenPackageA(package, &hpkg);
2299 ok(r != ERROR_SUCCESS, "MsiOpenPackage succeeded\n");
2300 if (r == ERROR_SUCCESS)
2301 MsiCloseHandle(hpkg);
2302
2303 r = MsiCloseHandle(hdb);
2304 ok(r == ERROR_SUCCESS, "MsiCloseHandle failed %u\n", r);
2305
2306 hdb = create_package_db();
2307 ok (hdb, "failed to create package database\n");
2308
2309 r = create_property_table(hdb);
2310 ok(r == ERROR_SUCCESS, "cannot create Property table: %d\n", r);
2311
2312 r = add_property_entry(hdb, "'prop', 'val'");
2313 ok(r == ERROR_SUCCESS, "cannot add property: %d\n", r);
2314
2315 r = create_custom_action_table(hdb);
2316 ok(r == ERROR_SUCCESS, "cannot create CustomAction table: %d\n", r);
2317
2318 r = add_custom_action_entry( hdb, "'EmbedNull', 51, 'prop2', '[~]np'" );
2319 ok( r == ERROR_SUCCESS, "cannot add custom action: %d\n", r);
2320
2321 r = package_from_db(hdb, &hpkg);
2322 ok(r == ERROR_SUCCESS, "failed to create package %u\n", r);
2323
2324 MsiCloseHandle(hdb);
2325
2326 sz = MAX_PATH;
2327 r = MsiGetPropertyA(hpkg, "prop", buffer, &sz);
2328 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2329 ok(!lstrcmpA(buffer, "val"), "Expected val, got %s\n", buffer);
2330
2331 hdb = MsiGetActiveDatabase(hpkg);
2332
2333 found = find_prop_in_property(hdb, "prop", "val", -1);
2334 ok(found, "prop should be in the _Property table\n");
2335
2336 r = add_property_entry(hdb, "'dantes', 'mercedes'");
2337 ok(r == ERROR_SUCCESS, "cannot add property: %d\n", r);
2338
2339 query = "SELECT * FROM `_Property` WHERE `Property` = 'dantes'";
2340 r = do_query(hdb, query, &hrec);
2341 ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
2342
2343 found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2344 ok(found == FALSE, "dantes should not be in the _Property table\n");
2345
2346 sz = MAX_PATH;
2347 lstrcpyA(buffer, "aaa");
2348 r = MsiGetPropertyA(hpkg, "dantes", buffer, &sz);
2349 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2350 ok(!buffer[0], "Expected empty string, got %s\n", buffer);
2351
2352 r = MsiSetPropertyA(hpkg, "dantes", "mercedes");
2353 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2354
2355 found = find_prop_in_property(hdb, "dantes", "mercedes", -1);
2356 ok(found == TRUE, "dantes should be in the _Property table\n");
2357
2358 r = MsiDoActionA( hpkg, "EmbedNull" );
2359 ok( r == ERROR_SUCCESS, "EmbedNull failed: %d\n", r);
2360
2361 sz = MAX_PATH;
2362 memset( buffer, 'a', sizeof(buffer) );
2363 r = MsiGetPropertyA( hpkg, "prop2", buffer, &sz );
2364 ok( r == ERROR_SUCCESS, "get property failed: %d\n", r);
2365 ok( !memcmp( buffer, "\0np", sizeof("\0np") ), "wrong value\n");
2366 ok( sz == sizeof("\0np") - 1, "got %u\n", sz );
2367
2368 found = find_prop_in_property(hdb, "prop2", "\0np", 3);
2369 ok(found == TRUE, "prop2 should be in the _Property table\n");
2370
2371 MsiCloseHandle(hdb);
2372 MsiCloseHandle(hpkg);
2373 DeleteFileA(msifile);
2374 }
2375
2376 static UINT try_query_param( MSIHANDLE hdb, LPCSTR szQuery, MSIHANDLE hrec )
2377 {
2378 MSIHANDLE htab = 0;
2379 UINT res;
2380
2381 res = MsiDatabaseOpenViewA( hdb, szQuery, &htab );
2382 if( res == ERROR_SUCCESS )
2383 {
2384 UINT r;
2385
2386 r = MsiViewExecute( htab, hrec );
2387 if( r != ERROR_SUCCESS )
2388 {
2389 res = r;
2390 fprintf(stderr,"MsiViewExecute failed %08x\n", res);
2391 }
2392
2393 r = MsiViewClose( htab );
2394 if( r != ERROR_SUCCESS )
2395 res = r;
2396
2397 r = MsiCloseHandle( htab );
2398 if( r != ERROR_SUCCESS )
2399 res = r;
2400 }
2401 return res;
2402 }
2403
2404 static UINT try_query( MSIHANDLE hdb, LPCSTR szQuery )
2405 {
2406 return try_query_param( hdb, szQuery, 0 );
2407 }
2408
2409 static void set_summary_str(MSIHANDLE hdb, DWORD pid, LPCSTR value)
2410 {
2411 MSIHANDLE summary;
2412 UINT r;
2413
2414 r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2415 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2416
2417 r = MsiSummaryInfoSetPropertyA(summary, pid, VT_LPSTR, 0, NULL, value);
2418 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2419
2420 r = MsiSummaryInfoPersist(summary);
2421 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2422
2423 MsiCloseHandle(summary);
2424 }
2425
2426 static void set_summary_dword(MSIHANDLE hdb, DWORD pid, DWORD value)
2427 {
2428 MSIHANDLE summary;
2429 UINT r;
2430
2431 r = MsiGetSummaryInformationA(hdb, NULL, 1, &summary);
2432 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2433
2434 r = MsiSummaryInfoSetPropertyA(summary, pid, VT_I4, value, NULL, NULL);
2435 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2436
2437 r = MsiSummaryInfoPersist(summary);
2438 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2439
2440 MsiCloseHandle(summary);
2441 }
2442
2443 static void test_msipackage(void)
2444 {
2445 MSIHANDLE hdb = 0, hpack = 100;
2446 UINT r;
2447 const char *query;
2448 char name[10];
2449
2450 /* NULL szPackagePath */
2451 r = MsiOpenPackageA(NULL, &hpack);
2452 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2453
2454 /* empty szPackagePath */
2455 r = MsiOpenPackageA("", &hpack);
2456 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2457 {
2458 skip("Not enough rights to perform tests\n");
2459 return;
2460 }
2461 todo_wine
2462 {
2463 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2464 }
2465
2466 if (r == ERROR_SUCCESS)
2467 MsiCloseHandle(hpack);
2468
2469 /* nonexistent szPackagePath */
2470 r = MsiOpenPackageA("nonexistent", &hpack);
2471 ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", r);
2472
2473 /* NULL hProduct */
2474 r = MsiOpenPackageA(msifile, NULL);
2475 ok(r == ERROR_INVALID_PARAMETER, "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
2476
2477 name[0]='#';
2478 name[1]=0;
2479 r = MsiOpenPackageA(name, &hpack);
2480 ok(r == ERROR_INVALID_HANDLE, "Expected ERROR_INVALID_HANDLE, got %d\n", r);
2481
2482 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2483 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2484
2485 /* database exists, but is emtpy */
2486 sprintf(name, "#%d", hdb);
2487 r = MsiOpenPackageA(name, &hpack);
2488 ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2489 "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2490
2491 query = "CREATE TABLE `Property` ( "
2492 "`Property` CHAR(72), `Value` CHAR(0) "
2493 "PRIMARY KEY `Property`)";
2494 r = try_query(hdb, query);
2495 ok(r == ERROR_SUCCESS, "failed to create Properties table\n");
2496
2497 query = "CREATE TABLE `InstallExecuteSequence` ("
2498 "`Action` CHAR(72), `Condition` CHAR(0), `Sequence` INTEGER "
2499 "PRIMARY KEY `Action`)";
2500 r = try_query(hdb, query);
2501 ok(r == ERROR_SUCCESS, "failed to create InstallExecuteSequence table\n");
2502
2503 /* a few key tables exist */
2504 sprintf(name, "#%d", hdb);
2505 r = MsiOpenPackageA(name, &hpack);
2506 ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2507 "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2508
2509 MsiCloseHandle(hdb);
2510 DeleteFileA(msifile);
2511
2512 /* start with a clean database to show what constitutes a valid package */
2513 r = MsiOpenDatabaseW(msifileW, MSIDBOPEN_CREATE, &hdb);
2514 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2515
2516 sprintf(name, "#%d", hdb);
2517
2518 /* The following summary information props must exist:
2519 * - PID_REVNUMBER
2520 * - PID_PAGECOUNT
2521 */
2522
2523 set_summary_dword(hdb, PID_PAGECOUNT, 100);
2524 r = MsiOpenPackageA(name, &hpack);
2525 ok(r == ERROR_INSTALL_PACKAGE_INVALID,
2526 "Expected ERROR_INSTALL_PACKAGE_INVALID, got %d\n", r);
2527
2528 set_summary_str(hdb, PID_REVNUMBER, "{004757CD-5092-49C2-AD20-28E1CE0DF5F2}");
2529 r = MsiOpenPackageA(name, &hpack);
2530 ok(r == ERROR_SUCCESS,
2531 "Expected ERROR_SUCCESS, got %d\n", r);
2532
2533 MsiCloseHandle(hpack);
2534 MsiCloseHandle(hdb);
2535 DeleteFileA(msifile);
2536 }
2537
2538 static void test_formatrecord2(void)
2539 {
2540 MSIHANDLE hpkg, hrec ;
2541 char buffer[0x100];
2542 DWORD sz;
2543 UINT r;
2544
2545 r = package_from_db(create_package_db(), &hpkg);
2546 if (r == ERROR_INSTALL_PACKAGE_REJECTED)
2547 {
2548 skip("Not enough rights to perform tests\n");
2549 DeleteFileA(msifile);
2550 return;
2551 }
2552 ok( r == ERROR_SUCCESS, "failed to create package %u\n", r);
2553
2554 r = MsiSetPropertyA(hpkg, "Manufacturer", " " );
2555 ok( r == ERROR_SUCCESS, "set property failed\n");
2556
2557 hrec = MsiCreateRecord(2);
2558 ok(hrec, "create record failed\n");
2559
2560 r = MsiRecordSetStringA( hrec, 0, "[ProgramFilesFolder][Manufacturer]\\asdf");
2561 ok( r == ERROR_SUCCESS, "format record failed\n");
2562
2563 buffer[0] = 0;
2564 sz = sizeof buffer;
2565 r = MsiFormatRecordA( hpkg, hrec, buffer, &sz );
2566 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2567
2568 r = MsiRecordSetStringA(hrec, 0, "[foo][1]");
2569 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2570 r = MsiRecordSetStringA(hrec, 1, "hoo");
2571 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2572 sz = sizeof buffer;
2573 r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2574 ok( sz == 3, "size wrong\n");
2575 ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2576 ok( r == ERROR_SUCCESS, "format failed\n");
2577
2578 r = MsiRecordSetStringA(hrec, 0, "x[~]x");
2579 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2580 sz = sizeof buffer;
2581 r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2582 ok( sz == 3, "size wrong\n");
2583 ok( 0 == strcmp(buffer,"x"), "wrong output %s\n",buffer);
2584 ok( r == ERROR_SUCCESS, "format failed\n");
2585
2586 r = MsiRecordSetStringA(hrec, 0, "[foo.$%}][1]");
2587 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2588 r = MsiRecordSetStringA(hrec, 1, "hoo");
2589 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2590 sz = sizeof buffer;
2591 r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2592 ok( sz == 3, "size wrong\n");
2593 ok( 0 == strcmp(buffer,"hoo"), "wrong output %s\n",buffer);
2594 ok( r == ERROR_SUCCESS, "format failed\n");
2595
2596 r = MsiRecordSetStringA(hrec, 0, "[\\[]");
2597 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2598 sz = sizeof buffer;
2599 r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2600 ok( sz == 1, "size wrong\n");
2601 ok( 0 == strcmp(buffer,"["), "wrong output %s\n",buffer);
2602 ok( r == ERROR_SUCCESS, "format failed\n");
2603
2604 SetEnvironmentVariableA("FOO", "BAR");
2605 r = MsiRecordSetStringA(hrec, 0, "[%FOO]");
2606 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2607 sz = sizeof buffer;
2608 r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2609 ok( sz == 3, "size wrong\n");
2610 ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2611 ok( r == ERROR_SUCCESS, "format failed\n");
2612
2613 r = MsiRecordSetStringA(hrec, 0, "[[1]]");
2614 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2615 r = MsiRecordSetStringA(hrec, 1, "%FOO");
2616 ok( r == ERROR_SUCCESS, "Expected ERROR_SUCCESS got %d\n", r);
2617 sz = sizeof buffer;
2618 r = MsiFormatRecordA(hpkg, hrec, buffer, &sz);
2619 ok( sz == 3, "size wrong\n");
2620 ok( 0 == strcmp(buffer,"BAR"), "wrong output %s\n",buffer);
2621 ok( r == ERROR_SUCCESS, "format failed\n");
2622
2623 MsiCloseHandle( hrec );
2624 MsiCloseHandle( hpkg );
2625 DeleteFileA(msifile);
2626 }
2627
2628 static void test_feature_states( UINT line, MSIHANDLE package, const char *feature, UINT error,
2629 INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2630 {
2631 UINT r;
2632 INSTALLSTATE state = 0xdeadbee;
2633 INSTALLSTATE action = 0xdeadbee;
2634
2635 r = MsiGetFeatureStateA( package, feature, &state, &action );
2636 ok( r == error, "%u: expected %d got %d\n", line, error, r );
2637 if (r == ERROR_SUCCESS)
2638 {
2639 ok( state == expected_state, "%u: expected state %d got %d\n",
2640 line, expected_state, state );
2641 if (todo) todo_wine
2642 ok( action == expected_action, "%u: expected action %d got %d\n",
2643 line, expected_action, action );
2644 else
2645 ok( action == expected_action, "%u: expected action %d got %d\n",
2646 line, expected_action, action );
2647 }
2648 else
2649 {
2650 ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n", line, state );
2651 if (todo) todo_wine
2652 ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
2653 else
2654 ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n", line, action );
2655
2656 }
2657 }
2658
2659 static void test_component_states( UINT line, MSIHANDLE package, const char *component, UINT error,
2660 INSTALLSTATE expected_state, INSTALLSTATE expected_action, BOOL todo )
2661 {
2662 UINT r;
2663 INSTALLSTATE state = 0xdeadbee;
2664 INSTALLSTATE action = 0xdeadbee;
2665
2666 r = MsiGetComponentStateA( package, component, &state, &action );
2667 ok( r == error, "%u: expected %d got %d\n", line, error, r );
2668 if (r == ERROR_SUCCESS)
2669 {
2670 ok( state == expected_state, "%u: expected state %d got %d\n",
2671 line, expected_state, state );
2672 if (todo) todo_wine
2673 ok( action == expected_action, "%u: expected action %d got %d\n",
2674 line, expected_action, action );
2675 else
2676 ok( action == expected_action, "%u: expected action %d got %d\n",
2677 line, expected_action, action );
2678 }
2679 else
2680 {
2681 ok( state == 0xdeadbee, "%u: expected state 0xdeadbee got %d\n",
2682 line, state );
2683 if (todo) todo_wine
2684 ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
2685 line, action );
2686 else
2687 ok( action == 0xdeadbee, "%u: expected action 0xdeadbee got %d\n",
2688 line, action );
2689 }
2690 }
2691
2692 static void test_states(void)
2693 {
2694 static const char msifile2[] = "winetest2-package.msi";
2695 static const char msifile3[] = "winetest3-package.msi";
2696 static const char msifile4[] = "winetest4-package.msi";
2697 static const WCHAR msifile2W[] =
2698 {'w','i','n','e','t','e','s','t','2','-','p','a','c','k','a','g','e','.','m','s','i',0};
2699 static const WCHAR msifile3W[] =
2700 {'w','i','n','e','t','e','s','t','3','-','p','a','c','k','a','g','e','.','m','s','i',0};
2701 static const WCHAR msifile4W[] =
2702 {'w','i','n','e','t','e','s','t','4','-','p','a','c','k','a','g','e','.','m','s','i',0};
2703 INSTALLSTATE state;
2704 MSIHANDLE hpkg;
2705 UINT r;
2706 MSIHANDLE hdb;
2707
2708 if (is_process_limited())
2709 {
2710 skip("process is limited\n");
2711 return;
2712 }
2713
2714 hdb = create_package_db();
2715 ok ( hdb, "failed to create package database\n" );
2716
2717 r = add_directory_entry( hdb, "'TARGETDIR', '', 'SourceDir'");
2718 ok( r == ERROR_SUCCESS, "cannot add directory: %d\n", r );
2719
2720 r = create_property_table( hdb );
2721 ok( r == ERROR_SUCCESS, "cannot create Property table: %d\n", r );
2722
2723 r = add_property_entry( hdb, "'ProductCode', '{7262AC98-EEBD-4364-8CE3-D654F6A425B9}'" );
2724 ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2725
2726 r = add_property_entry( hdb, "'ProductLanguage', '1033'" );
2727 ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2728
2729 r = add_property_entry( hdb, "'ProductName', 'MSITEST'" );
2730 ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2731
2732 r = add_property_entry( hdb, "'ProductVersion', '1.1.1'" );
2733 ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2734
2735 r = add_property_entry( hdb, "'MSIFASTINSTALL', '1'" );
2736 ok( r == ERROR_SUCCESS, "cannot add property entry: %d\n", r );
2737
2738 r = create_install_execute_sequence_table( hdb );
2739 ok( r == ERROR_SUCCESS, "cannot create InstallExecuteSequence table: %d\n", r );
2740
2741 r = add_install_execute_sequence_entry( hdb, "'CostInitialize', '', '800'" );
2742 ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2743
2744 r = add_install_execute_sequence_entry( hdb, "'FileCost', '', '900'" );
2745 ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2746
2747 r = add_install_execute_sequence_entry( hdb, "'CostFinalize', '', '1000'" );
2748 ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2749
2750 r = add_install_execute_sequence_entry( hdb, "'InstallValidate', '', '1400'" );
2751 ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2752
2753 r = add_install_execute_sequence_entry( hdb, "'InstallInitialize', '', '1500'" );
2754 ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2755
2756 r = add_install_execute_sequence_entry( hdb, "'ProcessComponents', '', '1600'" );
2757 ok( r == ERROR_SUCCESS, "cannot add install execute sequence entry: %d\n", r );
2758
2759 r = add_install_execute_sequence_entry( hdb, "'UnpublishFeatures', '', '1800'" );