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