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