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