ReactOS 0.4.16-dev-122-g325d74c
automation.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007 Mike McCormack for CodeWeavers
3 * Copyright (C) 2007 Misha Koshelev
4 *
5 * A test program for Microsoft Installer OLE automation functionality.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 */
21
22#define COBJMACROS
23
24#include <stdio.h>
25
26#include <initguid.h>
27#include <windows.h>
28#include <msiquery.h>
29#include <msidefs.h>
30#include <msi.h>
31#include <fci.h>
32#include <oaidl.h>
33
34#include "wine/test.h"
35#include "utils.h"
36
37#ifdef __REACTOS__
38#include "ole2.h"
39#endif
40
42
43DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
44
45static const char *msifile = "winetest-automation.msi";
47static EXCEPINFO excepinfo;
48
49/*
50 * OLE automation data
51 **/
53
54/* msi database data */
55
56static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
57 "s72\tS38\ts72\ti2\tS255\tS72\n"
58 "Component\tComponent\n"
59 "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
60 "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
61 "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
62 "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
63 "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
64 "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
65 "component\t\tMSITESTDIR\t0\t1\tfile\n";
66
67static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
68 "s72\tS72\tl255\n"
69 "Directory\tDirectory\n"
70 "CABOUTDIR\tMSITESTDIR\tcabout\n"
71 "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
72 "FIRSTDIR\tMSITESTDIR\tfirst\n"
73 "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
74 "NEWDIR\tCABOUTDIR\tnew\n"
75 "ProgramFilesFolder\tTARGETDIR\t.\n"
76 "TARGETDIR\t\tSourceDir\n";
77
78static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
79 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
80 "Feature\tFeature\n"
81 "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
82 "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
83 "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
84 "Three\tOne\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
85 "Two\tOne\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
86 "feature\t\t\t\t2\t1\tTARGETDIR\t0\n";
87
88static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
89 "s38\ts72\n"
90 "FeatureComponents\tFeature_\tComponent_\n"
91 "Five\tFive\n"
92 "Four\tFour\n"
93 "One\tOne\n"
94 "Three\tThree\n"
95 "Two\tTwo\n"
96 "feature\tcomponent\n";
97
98static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
99 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
100 "File\tFile\n"
101 "five.txt\tFive\tfive.txt\t1000\t\t\t0\t5\n"
102 "four.txt\tFour\tfour.txt\t1000\t\t\t0\t4\n"
103 "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
104 "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
105 "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
106 "file\tcomponent\tfilename\t100\t\t\t8192\t1\n";
107
108static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
109 "s72\tS255\tI2\n"
110 "InstallExecuteSequence\tAction\n"
111 "AllocateRegistrySpace\tNOT Installed\t1550\n"
112 "CostFinalize\t\t1000\n"
113 "CostInitialize\t\t800\n"
114 "FileCost\t\t900\n"
115 "InstallFiles\t\t4000\n"
116 "RegisterProduct\t\t6100\n"
117 "PublishProduct\t\t6400\n"
118 "InstallFinalize\t\t6600\n"
119 "InstallInitialize\t\t1500\n"
120 "InstallValidate\t\t1400\n"
121 "LaunchConditions\t\t100\n"
122 "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000\n";
123
124static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
125 "i2\ti4\tL64\tS255\tS32\tS72\n"
126 "Media\tDiskId\n"
127 "1\t5\t\t\tDISK1\t\n";
128
129static const CHAR property_dat[] = "Property\tValue\n"
130 "s72\tl0\n"
131 "Property\tProperty\n"
132 "DefaultUIFont\tDlgFont8\n"
133 "HASUIRUN\t0\n"
134 "INSTALLLEVEL\t3\n"
135 "InstallMode\tTypical\n"
136 "Manufacturer\tWine\n"
137 "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
138 "ProductCode\t{837450fa-a39b-4bc8-b321-08b393f784b3}\n"
139 "ProductID\tnone\n"
140 "ProductLanguage\t1033\n"
141 "ProductName\tMSITEST\n"
142 "ProductVersion\t1.1.1\n"
143 "PROMPTROLLBACKCOST\tP\n"
144 "Setup\tSetup\n"
145 "UpgradeCode\t{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}\n"
146 "MSIFASTINSTALL\t1\n";
147
148static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
149 "s72\ti2\tl255\tL255\tL0\ts72\n"
150 "Registry\tRegistry\n"
151 "Apples\t1\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
152 "Oranges\t1\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
153 "regdata\t1\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
154 "OrderTest\t1\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent\n";
155
156#define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
157
158static const msi_table tables[] =
159{
160 ADD_TABLE(component),
163 ADD_TABLE(feature_comp),
165 ADD_TABLE(install_exec_seq),
169};
170
171typedef struct _msi_summary_info
172{
177 const CHAR *szValue;
179
180#define ADD_INFO_I2(property, iValue) {property, VT_I2, iValue, NULL, NULL}
181#define ADD_INFO_I4(property, iValue) {property, VT_I4, iValue, NULL, NULL}
182#define ADD_INFO_LPSTR(property, szValue) {property, VT_LPSTR, 0, NULL, szValue}
183#define ADD_INFO_FILETIME(property, pftValue) {property, VT_FILETIME, 0, pftValue, NULL}
184
186{
188 ADD_INFO_LPSTR(PID_REVNUMBER, "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}"),
193};
194
195/*
196 * Database Helpers
197 */
198
199static void write_file(const CHAR *filename, const char *data, int data_size)
200{
201 DWORD size;
202
205 WriteFile(hf, data, data_size, &size, NULL);
206 CloseHandle(hf);
207}
208
209static void write_msi_summary_info(MSIHANDLE db, const msi_summary_info *info, int num_info)
210{
211 MSIHANDLE summary;
212 UINT r;
213 int j;
214
215 r = MsiGetSummaryInformationA(db, NULL, num_info, &summary);
216 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
217
218 /* import summary information into the stream */
219 for (j = 0; j < num_info; j++)
220 {
221 const msi_summary_info *entry = &info[j];
222
223 r = MsiSummaryInfoSetPropertyA(summary, entry->property, entry->datatype,
224 entry->iValue, entry->pftValue, entry->szValue);
225 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
226 }
227
228 /* write the summary changes back to the stream */
229 r = MsiSummaryInfoPersist(summary);
230 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
231
232 MsiCloseHandle(summary);
233}
234
235static void create_database_suminfo(const CHAR *name, const msi_table *tables, int num_tables,
236 const msi_summary_info *info, int num_info)
237{
238 MSIHANDLE db;
239 UINT r;
240 WCHAR *nameW;
241 int j, len;
242
243 len = MultiByteToWideChar( CP_ACP, 0, name, -1, NULL, 0 );
244 if (!(nameW = malloc( len * sizeof(WCHAR) ))) return;
246
248 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
249
250 /* import the tables into the database */
251 for (j = 0; j < num_tables; j++)
252 {
253 const msi_table *table = &tables[j];
254
255 write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
256
257 r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
258 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
259
260 DeleteFileA(table->filename);
261 }
262
263 write_msi_summary_info(db, info, num_info);
264
265 r = MsiDatabaseCommit(db);
266 ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
267
268 MsiCloseHandle(db);
269 free( nameW );
270}
271
273{
274 DWORD len;
275
276 /* Prepare package */
278
280 CURR_DIR, -1, path, MAX_PATH);
281 ok(len, "MultiByteToWideChar returned error %lu\n", GetLastError());
282 if (!len)
283 return FALSE;
284
285 lstrcatW(path, L"\\winetest-automation.msi");
286 return TRUE;
287}
288
289/*
290 * Installation helpers
291 */
292
294{
295 HKEY hkey;
297
298 if (RegOpenKeyA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
299 return FALSE;
300
301 size = MAX_PATH;
302 if (RegQueryValueExA(hkey, "ProgramFilesDir (x86)", 0, &type, (LPBYTE)buf, &size) &&
303 RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size))
304 return FALSE;
305
306 RegCloseKey(hkey);
307 return TRUE;
308}
309
310static void create_test_files(void)
311{
312 CreateDirectoryA("msitest", NULL);
313 create_file("msitest\\one.txt", 100);
314 CreateDirectoryA("msitest\\first", NULL);
315 create_file("msitest\\first\\two.txt", 100);
316 CreateDirectoryA("msitest\\second", NULL);
317 create_file("msitest\\second\\three.txt", 100);
318 CreateDirectoryA("msitest\\cabout",NULL);
319 create_file("msitest\\cabout\\four.txt", 100);
320 CreateDirectoryA("msitest\\cabout\\new",NULL);
321 create_file("msitest\\cabout\\new\\five.txt", 100);
322 create_file("msitest\\filename", 100);
323}
324
325static void delete_test_files(void)
326{
327 DeleteFileA("msitest\\cabout\\new\\five.txt");
328 DeleteFileA("msitest\\cabout\\four.txt");
329 DeleteFileA("msitest\\second\\three.txt");
330 DeleteFileA("msitest\\first\\two.txt");
331 DeleteFileA("msitest\\one.txt");
332 DeleteFileA("msitest\\filename");
333 RemoveDirectoryA("msitest\\cabout\\new");
334 RemoveDirectoryA("msitest\\cabout");
335 RemoveDirectoryA("msitest\\second");
336 RemoveDirectoryA("msitest\\first");
337 RemoveDirectoryA("msitest");
338}
339
340/*
341 * Automation helpers and tests
342 */
343
344/* ok-like statement which takes two unicode strings or one unicode and one ANSI string as arguments */
346
347#define ok_w2(format, szString1, szString2) \
348\
349 do { \
350 WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \
351 WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \
352 if (lstrcmpA(string1, string2) != 0) \
353 ok(0, format, string1, string2); \
354 } while(0);
355
356#define ok_w2n(format, szString1, szString2, len) \
357\
358 if (memcmp(szString1, szString2, len * sizeof(WCHAR)) != 0) \
359 { \
360 WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \
361 WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \
362 ok(0, format, string1, string2); \
363 }
364
365#define ok_aw(format, aString, wString) \
366\
367 WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \
368 if (lstrcmpA(string1, aString) != 0) \
369 ok(0, format, string1, aString); \
370
371#define ok_awplus(format, extra, aString, wString) \
372\
373 WideCharToMultiByte(CP_ACP, 0, wString, -1, string1, MAX_PATH, NULL, NULL); \
374 if (lstrcmpA(string1, aString) != 0) \
375 ok(0, format, extra, string1, aString); \
376
377/* exception checker */
378#define ok_exception(hr, szDescription) \
379 if (hr == DISP_E_EXCEPTION) \
380 { \
381 /* Compare wtype, source, and destination */ \
382 ok(excepinfo.wCode == 1000, "Exception info was %d, expected 1000\n", excepinfo.wCode); \
383\
384 ok(excepinfo.bstrSource != NULL, "Exception source was NULL\n"); \
385 if (excepinfo.bstrSource) \
386 ok_w2("Exception source was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrSource, L"Msi API Error"); \
387\
388 ok(excepinfo.bstrDescription != NULL, "Exception description was NULL\n"); \
389 if (excepinfo.bstrDescription) \
390 ok_w2("Exception description was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrDescription, szDescription); \
391\
392 SysFreeString(excepinfo.bstrSource); \
393 SysFreeString(excepinfo.bstrDescription); \
394 SysFreeString(excepinfo.bstrHelpFile); \
395 }
396
397static DISPID get_dispid( IDispatch *disp, const char *name )
398{
400 UINT len;
401 DISPID id = -1;
402 HRESULT r;
403
404 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
405 str = malloc( len * sizeof(WCHAR) );
406 if (str)
407 {
409 r = IDispatch_GetIDsOfNames( disp, &IID_NULL, &str, 1, 0, &id );
410 free( str );
411 if (r != S_OK)
412 return -1;
413 }
414
415 return id;
416}
417
418typedef struct {
420 const char *name;
422} get_did_t;
423
424static const get_did_t get_did_data[] = {
425 { 1, "CreateRecord" },
426 { 2, "OpenPackage" },
427 { 3, "OpenProduct" },
428 { 4, "OpenDatabase" },
429 { 5, "SummaryInformation" },
430 { 6, "UILevel" },
431 { 7, "EnableLog" },
432 { 8, "InstallProduct" },
433 { 9, "Version" },
434 { 10, "LastErrorRecord" },
435 { 11, "RegistryValue" },
436 { 12, "Environment" },
437 { 13, "FileAttributes" },
438 { 15, "FileSize" },
439 { 16, "FileVersion" },
440 { 17, "ProductState" },
441 { 18, "ProductInfo" },
442 { 19, "ConfigureProduct", TRUE },
443 { 20, "ReinstallProduct", TRUE },
444 { 21, "CollectUserInfo", TRUE },
445 { 22, "ApplyPatch", TRUE },
446 { 23, "FeatureParent", TRUE },
447 { 24, "FeatureState", TRUE },
448 { 25, "UseFeature", TRUE },
449 { 26, "FeatureUsageCount", TRUE },
450 { 27, "FeatureUsageDate", TRUE },
451 { 28, "ConfigureFeature", TRUE },
452 { 29, "ReinstallFeature", TRUE },
453 { 30, "ProvideComponent", TRUE },
454 { 31, "ComponentPath", TRUE },
455 { 32, "ProvideQualifiedComponent", TRUE },
456 { 33, "QualifierDescription", TRUE },
457 { 34, "ComponentQualifiers", TRUE },
458 { 35, "Products" },
459 { 36, "Features", TRUE },
460 { 37, "Components", TRUE },
461 { 38, "ComponentClients", TRUE },
462 { 39, "Patches", TRUE },
463 { 40, "RelatedProducts" },
464 { 41, "PatchInfo", TRUE },
465 { 42, "PatchTransforms", TRUE },
466 { 43, "AddSource", TRUE },
467 { 44, "ClearSourceList", TRUE },
468 { 45, "ForceSourceListResolution", TRUE },
469 { 46, "ShortcutTarget", TRUE },
470 { 47, "FileHash", TRUE },
471 { 48, "FileSignatureInfo", TRUE },
472 { 0 }
473};
474
475static void test_dispid(void)
476{
477 const get_did_t *ptr = get_did_data;
478 DISPID dispid;
479
480 while (ptr->name)
481 {
482 dispid = get_dispid(pInstaller, ptr->name);
483 todo_wine_if (ptr->todo)
484 ok(dispid == ptr->did, "%s: expected %ld, got %ld\n", ptr->name, ptr->did, dispid);
485 ptr++;
486 }
487
488 dispid = get_dispid(pInstaller, "RemovePatches");
489 ok(dispid == 49 || dispid == -1, "Expected 49 or -1, got %ld\n", dispid);
490 dispid = get_dispid(pInstaller, "ApplyMultiplePatches");
491 ok(dispid == 51 || dispid == -1, "Expected 51 or -1, got %ld\n", dispid);
492 dispid = get_dispid(pInstaller, "ProductsEx");
493 ok(dispid == 52 || dispid == -1, "Expected 52 or -1, got %ld\n", dispid);
494 dispid = get_dispid(pInstaller, "PatchesEx");
495 ok(dispid == 55 || dispid == -1, "Expected 55 or -1, got %ld\n", dispid);
496 dispid = get_dispid(pInstaller, "ExtractPatchXMLData");
497 ok(dispid == 57 || dispid == -1, "Expected 57 or -1, got %ld\n", dispid);
498 dispid = get_dispid( pInstaller, "ProductElevated" );
499 ok(dispid == 59 || dispid == -1, "Expected 59 or -1, got %ld\n", dispid);
500 dispid = get_dispid( pInstaller, "ProvideAssembly" );
501 ok(dispid == 60 || dispid == -1, "Expected 60 or -1, got %ld\n", dispid);
502 dispid = get_dispid( pInstaller, "ProductInfoFromScript" );
503 ok(dispid == 61 || dispid == -1, "Expected 61 or -1, got %ld\n", dispid);
504 dispid = get_dispid( pInstaller, "AdvertiseProduct" );
505 ok(dispid == 62 || dispid == -1, "Expected 62 or -1, got %ld\n", dispid);
506 dispid = get_dispid( pInstaller, "CreateAdvertiseScript" );
507 ok(dispid == 63 || dispid == -1, "Expected 63 or -1, got %ld\n", dispid);
508 dispid = get_dispid( pInstaller, "PatchFiles" );
509 ok(dispid == 65 || dispid == -1, "Expected 65 or -1, got %ld\n", dispid);
510}
511
512/* Test basic IDispatch functions */
513static void test_dispatch(void)
514{
515 HRESULT hr;
516 DISPID dispid;
517 OLECHAR *name;
518 VARIANT varresult;
519 VARIANTARG vararg[3];
521 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
522
523 /* Test getting ID of a function name that does not exist */
524 name = (WCHAR *)L"winetest-automation.msi";
525 hr = IDispatch_GetIDsOfNames(pInstaller, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
526 ok(hr == DISP_E_UNKNOWNNAME, "IDispatch::GetIDsOfNames returned %#lx\n", hr);
527
528 /* Test invoking this function */
529 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, NULL, NULL, NULL);
530 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr);
531
532 /* Test getting ID of a function name that does exist */
533 name = (WCHAR *)L"OpenPackage";
534 hr = IDispatch_GetIDsOfNames(pInstaller, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
535 ok(hr == S_OK, "IDispatch::GetIDsOfNames returned %#lx\n", hr);
536
537 /* Test invoking this function (without parameters passed) */
538 if (0) /* All of these crash MSI on Windows XP */
539 {
540 IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, NULL, NULL, NULL);
541 IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, NULL, &excepinfo, NULL);
542 VariantInit(&varresult);
543 IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, NULL, &varresult, &excepinfo, NULL);
544 }
545
546 /* Try with NULL params */
547 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
548 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr);
549
550 /* Try one empty parameter */
551 dispparams.rgvarg = vararg;
552 dispparams.cArgs = 1;
553 VariantInit(&vararg[0]);
554 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
555 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr);
556
557 /* Try two empty parameters */
558 dispparams.cArgs = 2;
559 VariantInit(&vararg[0]);
560 VariantInit(&vararg[1]);
561 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
562 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr);
563
564 /* Try one parameter, the required BSTR. Second parameter is optional.
565 * NOTE: The specified package does not exist, which is why the call fails.
566 */
567 dispparams.cArgs = 1;
568 VariantInit(&vararg[0]);
569 V_VT(&vararg[0]) = VT_BSTR;
570 V_BSTR(&vararg[0]) = SysAllocString(L"winetest-automation.msi");
571 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
572 ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr);
573 ok_exception(hr, L"OpenPackage,PackagePath,Options");
574 VariantClear(&vararg[0]);
575
576 /* Provide the required BSTR and an empty second parameter.
577 * NOTE: The specified package does not exist, which is why the call fails.
578 */
579 dispparams.cArgs = 2;
580 VariantInit(&vararg[1]);
581 V_VT(&vararg[1]) = VT_BSTR;
582 V_BSTR(&vararg[1]) = SysAllocString(L"winetest-automation.msi");
583 VariantInit(&vararg[0]);
584 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
585 ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr);
586 ok_exception(hr, L"OpenPackage,PackagePath,Options");
587 VariantClear(&vararg[1]);
588
589 /* Provide the required BSTR and two empty parameters.
590 * NOTE: The specified package does not exist, which is why the call fails.
591 */
592 dispparams.cArgs = 3;
593 VariantInit(&vararg[2]);
594 V_VT(&vararg[2]) = VT_BSTR;
595 V_BSTR(&vararg[2]) = SysAllocString(L"winetest-automation.msi");
596 VariantInit(&vararg[1]);
597 VariantInit(&vararg[0]);
598 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
599 ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr);
600 ok_exception(hr, L"OpenPackage,PackagePath,Options");
601 VariantClear(&vararg[2]);
602
603 /* Provide the required BSTR and a second parameter with the wrong type. */
604 dispparams.cArgs = 2;
605 VariantInit(&vararg[1]);
606 V_VT(&vararg[1]) = VT_BSTR;
607 V_BSTR(&vararg[1]) = SysAllocString(L"winetest-automation.msi");
608 VariantInit(&vararg[0]);
609 V_VT(&vararg[0]) = VT_BSTR;
610 V_BSTR(&vararg[0]) = SysAllocString(L"winetest-automation.msi");
611 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
612 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr);
613 VariantClear(&vararg[0]);
614 VariantClear(&vararg[1]);
615
616 /* Create a proper installer package. */
618
619 /* Try one parameter, the required BSTR. Second parameter is optional.
620 * Proper installer package exists. Path to the package is relative.
621 */
622 dispparams.cArgs = 1;
623 VariantInit(&vararg[0]);
624 V_VT(&vararg[0]) = VT_BSTR;
625 V_BSTR(&vararg[0]) = SysAllocString(L"winetest-automation.msi");
626 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
627 todo_wine ok(hr == DISP_E_EXCEPTION, "IDispatch::Invoke returned %#lx\n", hr);
628 ok_exception(hr, L"OpenPackage,PackagePath,Options");
629 VariantClear(&vararg[0]);
630 if (hr != DISP_E_EXCEPTION)
631 VariantClear(&varresult);
632
633 /* Try one parameter, the required BSTR. Second parameter is optional.
634 * Proper installer package exists. Path to the package is absolute.
635 */
636 dispparams.cArgs = 1;
637 VariantInit(&vararg[0]);
638 V_VT(&vararg[0]) = VT_BSTR;
639 V_BSTR(&vararg[0]) = SysAllocString(path);
640 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
641 if (hr == DISP_E_EXCEPTION)
642 {
643 skip("OpenPackage failed, insufficient rights?\n");
645 return;
646 }
647 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr);
648 VariantClear(&vararg[0]);
649 VariantClear(&varresult);
650
651 /* Provide the required BSTR and an empty second parameter. Proper
652 * installation package exists.
653 */
654 dispparams.cArgs = 2;
655 VariantInit(&vararg[1]);
656 V_VT(&vararg[1]) = VT_BSTR;
657 V_BSTR(&vararg[1]) = SysAllocString(path);
658 VariantInit(&vararg[0]);
659 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
660 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr);
661 VariantClear(&vararg[1]);
662 VariantClear(&varresult);
663
664 /* Provide the required BSTR and two empty parameters. Proper
665 * installation package exists.
666 */
667 dispparams.cArgs = 3;
668 VariantInit(&vararg[2]);
669 V_VT(&vararg[2]) = VT_BSTR;
670 V_BSTR(&vararg[2]) = SysAllocString(path);
671 VariantInit(&vararg[1]);
672 VariantInit(&vararg[0]);
673 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
674 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr);
675 VariantClear(&vararg[2]);
676 VariantClear(&varresult);
677
678 /* Provide the required BSTR and a second parameter with the wrong type. */
679 dispparams.cArgs = 2;
680 VariantInit(&vararg[1]);
681 V_VT(&vararg[1]) = VT_BSTR;
682 V_BSTR(&vararg[1]) = SysAllocString(path);
683 VariantInit(&vararg[0]);
684 V_VT(&vararg[0]) = VT_BSTR;
685 V_BSTR(&vararg[0]) = SysAllocString(path);
686 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
687 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch::Invoke returned %#lx\n", hr);
688 VariantClear(&vararg[0]);
689 VariantClear(&vararg[1]);
690
691 /* Provide the required BSTR and a second parameter that can be coerced to
692 * VT_I4.
693 */
694 dispparams.cArgs = 2;
695 VariantInit(&vararg[1]);
696 V_VT(&vararg[1]) = VT_BSTR;
697 V_BSTR(&vararg[1]) = SysAllocString(path);
698 VariantInit(&vararg[0]);
699 V_VT(&vararg[0]) = VT_I2;
700 V_BSTR(&vararg[0]) = 0;
701 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
702 ok(hr == S_OK, "IDispatch::Invoke returned %#lx\n", hr);
703 VariantClear(&vararg[1]);
704 VariantClear(&varresult);
705
707
708 /* Test invoking a method as a DISPATCH_PROPERTYGET or DISPATCH_PROPERTYPUT */
709 VariantInit(&vararg[0]);
710 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
711 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr);
712
713 VariantInit(&vararg[0]);
714 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
715 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr);
716
717 /* Test invoking a read-only property as DISPATCH_PROPERTYPUT or as a DISPATCH_METHOD */
718 name = (WCHAR *)L"ProductState";
719 hr = IDispatch_GetIDsOfNames(pInstaller, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
720 ok(hr == S_OK, "IDispatch::GetIDsOfNames returned %#lx\n", hr);
721
722 dispparams.rgvarg = NULL;
723 dispparams.cArgs = 0;
724 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
725 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr);
726
727 dispparams.rgvarg = NULL;
728 dispparams.cArgs = 0;
729 hr = IDispatch_Invoke(pInstaller, dispid, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
730 ok(hr == DISP_E_MEMBERNOTFOUND, "IDispatch::Invoke returned %#lx\n", hr);
731}
732
733/* invocation helper function */
735
736static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, VARTYPE vtResult)
737{
738 OLECHAR *name = NULL;
739 DISPID dispid;
740 HRESULT hr;
741 UINT i;
742 UINT len;
743
744 memset(pVarResult, 0, sizeof(VARIANT));
745 VariantInit(pVarResult);
746
747 len = MultiByteToWideChar(CP_ACP, 0, szName, -1, NULL, 0 );
748 name = malloc(len * sizeof(WCHAR));
749 if (!name) return E_FAIL;
751 hr = IDispatch_GetIDsOfNames(pDispatch, &IID_NULL, &name, 1, LOCALE_USER_DEFAULT, &dispid);
752 free(name);
753 ok(hr == S_OK, "IDispatch::GetIDsOfNames returned %#lx\n", hr);
754 if (hr != S_OK) return hr;
755
756 memset(&excepinfo, 0, sizeof(excepinfo));
757 hr = IDispatch_Invoke(pDispatch, dispid, &IID_NULL, LOCALE_NEUTRAL, wFlags, pDispParams, pVarResult, &excepinfo, NULL);
758
759 if (hr == S_OK)
760 {
762 ok(V_VT(pVarResult) == vtResult, "Variant result type is %d, expected %d\n", V_VT(pVarResult), vtResult);
763 if (vtResult != VT_EMPTY)
764 {
765 hr = VariantChangeTypeEx(pVarResult, pVarResult, LOCALE_NEUTRAL, 0, vtResult);
766 ok(hr == S_OK, "VariantChangeTypeEx returned %#lx\n", hr);
767 }
768 }
769
770 for (i=0; i<pDispParams->cArgs; i++)
771 VariantClear(&pDispParams->rgvarg[i]);
772
773 return hr;
774}
775
776/* Object_Property helper functions */
777
779{
780 VARIANT varresult;
781 VARIANTARG vararg[1];
782 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
783 HRESULT hr;
784
785 VariantInit(&vararg[0]);
786 V_VT(&vararg[0]) = VT_I4;
787 V_I4(&vararg[0]) = count;
788
789 hr = invoke(pInstaller, "CreateRecord", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH);
790 *pRecord = V_DISPATCH(&varresult);
791 return hr;
792}
793
794static HRESULT Installer_RegistryValue(HKEY hkey, LPCWSTR szKey, VARIANT vValue, VARIANT *pVarResult, VARTYPE vtExpect)
795{
796 VARIANTARG vararg[3];
797 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
798
799 VariantInit(&vararg[2]);
800 V_VT(&vararg[2]) = VT_I4;
801 V_I4(&vararg[2]) = (INT_PTR)hkey;
802 VariantInit(&vararg[1]);
803 V_VT(&vararg[1]) = VT_BSTR;
804 V_BSTR(&vararg[1]) = SysAllocString(szKey);
805 VariantInit(&vararg[0]);
806 VariantCopy(&vararg[0], &vValue);
807 VariantClear(&vValue);
808
809 return invoke(pInstaller, "RegistryValue", DISPATCH_METHOD, &dispparams, pVarResult, vtExpect);
810}
811
813{
814 VARIANT varresult;
815 VARIANTARG vararg;
816 HRESULT hr;
817
818 VariantInit(&vararg);
819 V_VT(&vararg) = VT_EMPTY;
820 hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, VT_BOOL);
821 *pBool = V_BOOL(&varresult);
822 VariantClear(&varresult);
823 return hr;
824}
825
826static HRESULT Installer_RegistryValueW(HKEY hkey, LPCWSTR szKey, LPCWSTR szValue, LPWSTR szString)
827{
828 VARIANT varresult;
829 VARIANTARG vararg;
830 HRESULT hr;
831
832 VariantInit(&vararg);
833 V_VT(&vararg) = VT_BSTR;
834 V_BSTR(&vararg) = SysAllocString(szValue);
835
836 hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, VT_BSTR);
837 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult));
838 VariantClear(&varresult);
839 return hr;
840}
841
842static HRESULT Installer_RegistryValueI(HKEY hkey, LPCWSTR szKey, int iValue, LPWSTR szString, VARTYPE vtResult)
843{
844 VARIANT varresult;
845 VARIANTARG vararg;
846 HRESULT hr;
847
848 VariantInit(&vararg);
849 V_VT(&vararg) = VT_I4;
850 V_I4(&vararg) = iValue;
851
852 hr = Installer_RegistryValue(hkey, szKey, vararg, &varresult, vtResult);
853 if (SUCCEEDED(hr) && vtResult == VT_BSTR) lstrcpyW(szString, V_BSTR(&varresult));
854 VariantClear(&varresult);
855 return hr;
856}
857
858static HRESULT Installer_OpenPackage(LPCWSTR szPackagePath, int options, IDispatch **pSession)
859{
860 VARIANT varresult;
861 VARIANTARG vararg[2];
862 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
863 HRESULT hr;
864
865 VariantInit(&vararg[1]);
866 V_VT(&vararg[1]) = VT_BSTR;
867 V_BSTR(&vararg[1]) = SysAllocString(szPackagePath);
868 VariantInit(&vararg[0]);
869 V_VT(&vararg[0]) = VT_I4;
870 V_I4(&vararg[0]) = options;
871
872 hr = invoke(pInstaller, "OpenPackage", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH);
873 *pSession = V_DISPATCH(&varresult);
874 return hr;
875}
876
877static HRESULT Installer_OpenDatabase(LPCWSTR szDatabasePath, int openmode, IDispatch **pDatabase)
878{
879 VARIANT varresult;
880 VARIANTARG vararg[2];
881 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
882 HRESULT hr;
883
884 VariantInit(&vararg[1]);
885 V_VT(&vararg[1]) = VT_BSTR;
886 V_BSTR(&vararg[1]) = SysAllocString(szDatabasePath);
887 VariantInit(&vararg[0]);
888 V_VT(&vararg[0]) = VT_I4;
889 V_I4(&vararg[0]) = openmode;
890
891 hr = invoke(pInstaller, "OpenDatabase", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH);
892 *pDatabase = V_DISPATCH(&varresult);
893 return hr;
894}
895
896static HRESULT Installer_InstallProduct(LPCWSTR szPackagePath, LPCWSTR szPropertyValues)
897{
898 VARIANT varresult;
899 VARIANTARG vararg[2];
900 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
901
902 VariantInit(&vararg[1]);
903 V_VT(&vararg[1]) = VT_BSTR;
904 V_BSTR(&vararg[1]) = SysAllocString(szPackagePath);
905 VariantInit(&vararg[0]);
906 V_VT(&vararg[0]) = VT_BSTR;
907 V_BSTR(&vararg[0]) = SysAllocString(szPropertyValues);
908
909 return invoke(pInstaller, "InstallProduct", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY);
910}
911
912static HRESULT Installer_ProductState(LPCWSTR szProduct, int *pInstallState)
913{
914 VARIANT varresult;
915 VARIANTARG vararg[1];
916 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
917 HRESULT hr;
918
919 VariantInit(&vararg[0]);
920 V_VT(&vararg[0]) = VT_BSTR;
921 V_BSTR(&vararg[0]) = SysAllocString(szProduct);
922
923 hr = invoke(pInstaller, "ProductState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
924 *pInstallState = V_I4(&varresult);
925 VariantClear(&varresult);
926 return hr;
927}
928
930{
931 VARIANT varresult;
932 VARIANTARG vararg[2];
933 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
934 HRESULT hr;
935
936 VariantInit(&vararg[1]);
937 V_VT(&vararg[1]) = VT_BSTR;
938 V_BSTR(&vararg[1]) = SysAllocString(szProduct);
939 VariantInit(&vararg[0]);
940 V_VT(&vararg[0]) = VT_BSTR;
941 V_BSTR(&vararg[0]) = SysAllocString(szAttribute);
942
943 hr = invoke(pInstaller, "ProductInfo", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR);
944 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult));
945 VariantClear(&varresult);
946 return hr;
947}
948
950{
951 VARIANT varresult;
952 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
953 HRESULT hr;
954
955 hr = invoke(pInstaller, "Products", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
956 *pStringList = V_DISPATCH(&varresult);
957 return hr;
958}
959
960static HRESULT Installer_RelatedProducts(LPCWSTR szProduct, IDispatch **pStringList)
961{
962 VARIANT varresult;
963 VARIANTARG vararg[1];
964 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
965 HRESULT hr;
966
967 VariantInit(&vararg[0]);
968 V_VT(&vararg[0]) = VT_BSTR;
969 V_BSTR(&vararg[0]) = SysAllocString(szProduct);
970
971 hr = invoke(pInstaller, "RelatedProducts", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
972 *pStringList = V_DISPATCH(&varresult);
973 return hr;
974}
975
977{
978 VARIANT varresult;
979 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
980 HRESULT hr;
981
982 hr = invoke(pInstaller, "Version", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR);
983 if (V_BSTR(&varresult)) lstrcpyW(szVersion, V_BSTR(&varresult));
984 VariantClear(&varresult);
985 return hr;
986}
987
989{
990 VARIANT varresult;
991 VARIANTARG vararg;
992 DISPID dispid = DISPID_PROPERTYPUT;
993 DISPPARAMS dispparams = {&vararg, &dispid, sizeof(vararg)/sizeof(VARIANTARG), 1};
994
995 VariantInit(&vararg);
996 V_VT(&vararg) = VT_I4;
997 V_I4(&vararg) = level;
998
999 return invoke(pInstaller, "UILevel", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1000}
1001
1002static HRESULT Installer_SummaryInformation(BSTR PackagePath, int UpdateCount, IDispatch **pSumInfo)
1003{
1004 VARIANT varresult;
1005 VARIANTARG vararg[2];
1006 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1007 HRESULT hr;
1008
1009 VariantInit(&vararg[1]);
1010 V_VT(&vararg[1]) = VT_BSTR;
1011 V_BSTR(&vararg[1]) = SysAllocString(PackagePath);
1012 VariantInit(&vararg[0]);
1013 V_VT(&vararg[0]) = VT_I4;
1014 V_I4(&vararg[0]) = UpdateCount;
1015
1016 hr = invoke(pInstaller, "SummaryInformation", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
1017 *pSumInfo = V_DISPATCH(&varresult);
1018 return hr;
1019}
1020
1022{
1023 VARIANT varresult;
1024 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1025 HRESULT hr;
1026
1027 hr = invoke(pSession, "Installer", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
1028 *pInst = V_DISPATCH(&varresult);
1029 return hr;
1030}
1031
1033{
1034 VARIANT varresult;
1035 VARIANTARG vararg[1];
1036 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1037 HRESULT hr;
1038
1039 VariantInit(&vararg[0]);
1040 V_VT(&vararg[0]) = VT_BSTR;
1041 V_BSTR(&vararg[0]) = SysAllocString(szName);
1042
1043 hr = invoke(pSession, "Property", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR);
1044 if (V_BSTR(&varresult)) lstrcpyW(szReturn, V_BSTR(&varresult));
1045 VariantClear(&varresult);
1046 return hr;
1047}
1048
1050{
1051 VARIANT varresult;
1052 VARIANTARG vararg[2];
1053 DISPID dispid = DISPID_PROPERTYPUT;
1054 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1};
1055
1056 VariantInit(&vararg[1]);
1057 V_VT(&vararg[1]) = VT_BSTR;
1058 V_BSTR(&vararg[1]) = SysAllocString(szName);
1059 VariantInit(&vararg[0]);
1060 V_VT(&vararg[0]) = VT_BSTR;
1061 V_BSTR(&vararg[0]) = SysAllocString(szValue);
1062
1063 return invoke(pSession, "Property", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1064}
1065
1066static HRESULT Session_LanguageGet(IDispatch *pSession, UINT *pLangId)
1067{
1068 VARIANT varresult;
1069 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1070 HRESULT hr;
1071
1072 hr = invoke(pSession, "Language", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1073 *pLangId = V_I4(&varresult);
1074 VariantClear(&varresult);
1075 return hr;
1076}
1077
1078static HRESULT Session_ModeGet(IDispatch *pSession, int iFlag, VARIANT_BOOL *mode)
1079{
1080 VARIANT varresult;
1081 VARIANTARG vararg[1];
1082 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1083 HRESULT hr;
1084
1085 VariantInit(&vararg[0]);
1086 V_VT(&vararg[0]) = VT_I4;
1087 V_I4(&vararg[0]) = iFlag;
1088
1089 hr = invoke(pSession, "Mode", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BOOL);
1090 *mode = V_BOOL(&varresult);
1091 VariantClear(&varresult);
1092 return hr;
1093}
1094
1096{
1097 VARIANT varresult;
1098 VARIANTARG vararg[2];
1099 DISPID dispid = DISPID_PROPERTYPUT;
1100 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1};
1101
1102 VariantInit(&vararg[1]);
1103 V_VT(&vararg[1]) = VT_I4;
1104 V_I4(&vararg[1]) = iFlag;
1105 VariantInit(&vararg[0]);
1106 V_VT(&vararg[0]) = VT_BOOL;
1107 V_BOOL(&vararg[0]) = mode;
1108
1109 return invoke(pSession, "Mode", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1110}
1111
1112static HRESULT Session_Database(IDispatch *pSession, IDispatch **pDatabase)
1113{
1114 VARIANT varresult;
1115 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1116 HRESULT hr;
1117
1118 hr = invoke(pSession, "Database", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
1119 *pDatabase = V_DISPATCH(&varresult);
1120 return hr;
1121}
1122
1123static HRESULT Session_DoAction(IDispatch *pSession, LPCWSTR szAction, int *iReturn)
1124{
1125 VARIANT varresult;
1126 VARIANTARG vararg[1];
1127 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1128 HRESULT hr;
1129
1130 VariantInit(&vararg[0]);
1131 V_VT(&vararg[0]) = VT_BSTR;
1132 V_BSTR(&vararg[0]) = SysAllocString(szAction);
1133
1134 hr = invoke(pSession, "DoAction", DISPATCH_METHOD, &dispparams, &varresult, VT_I4);
1135 *iReturn = V_I4(&varresult);
1136 VariantClear(&varresult);
1137 return hr;
1138}
1139
1140static HRESULT Session_EvaluateCondition(IDispatch *pSession, LPCWSTR szCondition, int *iReturn)
1141{
1142 VARIANT varresult;
1143 VARIANTARG vararg[1];
1144 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1145 HRESULT hr;
1146
1147 VariantInit(&vararg[0]);
1148 V_VT(&vararg[0]) = VT_BSTR;
1149 V_BSTR(&vararg[0]) = SysAllocString(szCondition);
1150
1151 hr = invoke(pSession, "EvaluateCondition", DISPATCH_METHOD, &dispparams, &varresult, VT_I4);
1152 *iReturn = V_I4(&varresult);
1153 VariantClear(&varresult);
1154 return hr;
1155}
1156
1158{
1159 VARIANT varresult;
1160 VARIANTARG vararg[2];
1161 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1162 HRESULT hr;
1163
1164 VariantInit(&varresult);
1165 V_VT(vararg) = VT_DISPATCH;
1166 V_DISPATCH(vararg) = record;
1167 V_VT(vararg+1) = VT_I4;
1168 V_I4(vararg+1) = kind;
1169
1170 hr = invoke(pSession, "Message", DISPATCH_METHOD, &dispparams, &varresult, VT_I4);
1171
1172 ok(V_VT(&varresult) == VT_I4, "V_VT(varresult) = %d\n", V_VT(&varresult));
1173 *ret = V_I4(&varresult);
1174
1175 return hr;
1176}
1177
1178static HRESULT Session_SetInstallLevel(IDispatch *pSession, LONG iInstallLevel)
1179{
1180 VARIANT varresult;
1181 VARIANTARG vararg[1];
1182 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1183
1184 VariantInit(&vararg[0]);
1185 V_VT(&vararg[0]) = VT_I4;
1186 V_I4(&vararg[0]) = iInstallLevel;
1187
1188 return invoke(pSession, "SetInstallLevel", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY);
1189}
1190
1192{
1193 VARIANT varresult;
1194 VARIANTARG vararg[1];
1195 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1196 HRESULT hr;
1197
1198 VariantInit(&vararg[0]);
1199 V_VT(&vararg[0]) = VT_BSTR;
1200 V_BSTR(&vararg[0]) = SysAllocString(szName);
1201
1202 hr = invoke(pSession, "FeatureCurrentState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1203 *pState = V_I4(&varresult);
1204 VariantClear(&varresult);
1205 return hr;
1206}
1207
1209{
1210 VARIANT varresult;
1211 VARIANTARG vararg[1];
1212 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1213 HRESULT hr;
1214
1215 VariantInit(&vararg[0]);
1216 V_VT(&vararg[0]) = VT_BSTR;
1217 V_BSTR(&vararg[0]) = SysAllocString(szName);
1218
1219 hr = invoke(pSession, "FeatureRequestState", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1220 *pState = V_I4(&varresult);
1221 VariantClear(&varresult);
1222 return hr;
1223}
1224
1226{
1227 VARIANT varresult;
1228 VARIANTARG vararg[2];
1229 DISPID dispid = DISPID_PROPERTYPUT;
1230 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1};
1231
1232 VariantInit(&vararg[1]);
1233 V_VT(&vararg[1]) = VT_BSTR;
1234 V_BSTR(&vararg[1]) = SysAllocString(szName);
1235 VariantInit(&vararg[0]);
1236 V_VT(&vararg[0]) = VT_I4;
1237 V_I4(&vararg[0]) = iState;
1238
1239 return invoke(pSession, "FeatureRequestState", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1240}
1241
1242static HRESULT Database_OpenView(IDispatch *pDatabase, LPCWSTR szSql, IDispatch **pView)
1243{
1244 VARIANT varresult;
1245 VARIANTARG vararg[1];
1246 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1247 HRESULT hr;
1248
1249 VariantInit(&vararg[0]);
1250 V_VT(&vararg[0]) = VT_BSTR;
1251 V_BSTR(&vararg[0]) = SysAllocString(szSql);
1252
1253 hr = invoke(pDatabase, "OpenView", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH);
1254 *pView = V_DISPATCH(&varresult);
1255 return hr;
1256}
1257
1258static HRESULT Database_SummaryInformation(IDispatch *pDatabase, int iUpdateCount, IDispatch **pSummaryInfo)
1259{
1260 VARIANT varresult;
1261 VARIANTARG vararg[1];
1262 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1263 HRESULT hr;
1264
1265 VariantInit(&vararg[0]);
1266 V_VT(&vararg[0]) = VT_I4;
1267 V_I4(&vararg[0]) = iUpdateCount;
1268
1269 hr = invoke(pDatabase, "SummaryInformation", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_DISPATCH);
1270 *pSummaryInfo = V_DISPATCH(&varresult);
1271 return hr;
1272}
1273
1274static HRESULT View_Execute(IDispatch *pView, IDispatch *pRecord)
1275{
1276 VARIANT varresult;
1277 VARIANTARG vararg[1];
1278 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1279
1280 VariantInit(&vararg[0]);
1281 V_VT(&vararg[0]) = VT_DISPATCH;
1282 V_DISPATCH(&vararg[0]) = pRecord;
1283
1284 return invoke(pView, "Execute", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY);
1285}
1286
1287static HRESULT View_Fetch(IDispatch *pView, IDispatch **ppRecord)
1288{
1289 VARIANT varresult;
1290 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1291 HRESULT hr = invoke(pView, "Fetch", DISPATCH_METHOD, &dispparams, &varresult, VT_DISPATCH);
1292 *ppRecord = V_DISPATCH(&varresult);
1293 return hr;
1294}
1295
1296static HRESULT View_Modify(IDispatch *pView, int iMode, IDispatch *pRecord)
1297{
1298 VARIANT varresult;
1299 VARIANTARG vararg[2];
1300 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1301
1302 VariantInit(&vararg[1]);
1303 V_VT(&vararg[1]) = VT_I4;
1304 V_I4(&vararg[1]) = iMode;
1305 VariantInit(&vararg[0]);
1306 V_VT(&vararg[0]) = VT_DISPATCH;
1307 V_DISPATCH(&vararg[0]) = pRecord;
1308 if (pRecord)
1309 IDispatch_AddRef(pRecord); /* VariantClear in invoke will call IDispatch_Release */
1310
1311 return invoke(pView, "Modify", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY);
1312}
1313
1315{
1316 VARIANT varresult;
1317 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1318 return invoke(pView, "Close", DISPATCH_METHOD, &dispparams, &varresult, VT_EMPTY);
1319}
1320
1321static HRESULT Record_FieldCountGet(IDispatch *pRecord, int *pFieldCount)
1322{
1323 VARIANT varresult;
1324 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1325 HRESULT hr = invoke(pRecord, "FieldCount", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1326 *pFieldCount = V_I4(&varresult);
1327 VariantClear(&varresult);
1328 return hr;
1329}
1330
1331static HRESULT Record_StringDataGet(IDispatch *pRecord, int iField, LPWSTR szString)
1332{
1333 VARIANT varresult;
1334 VARIANTARG vararg[1];
1335 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1336 HRESULT hr;
1337
1338 VariantInit(&vararg[0]);
1339 V_VT(&vararg[0]) = VT_I4;
1340 V_I4(&vararg[0]) = iField;
1341
1342 hr = invoke(pRecord, "StringData", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR);
1343 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult));
1344 VariantClear(&varresult);
1345 return hr;
1346}
1347
1348static HRESULT Record_StringDataPut(IDispatch *pRecord, int iField, LPCWSTR szString)
1349{
1350 VARIANT varresult;
1351 VARIANTARG vararg[2];
1352 DISPID dispid = DISPID_PROPERTYPUT;
1353 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1};
1354
1355 VariantInit(&vararg[1]);
1356 V_VT(&vararg[1]) = VT_I4;
1357 V_I4(&vararg[1]) = iField;
1358 VariantInit(&vararg[0]);
1359 V_VT(&vararg[0]) = VT_BSTR;
1360 V_BSTR(&vararg[0]) = SysAllocString(szString);
1361
1362 return invoke(pRecord, "StringData", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1363}
1364
1365static HRESULT Record_IntegerDataGet(IDispatch *pRecord, int iField, int *pValue)
1366{
1367 VARIANT varresult;
1368 VARIANTARG vararg[1];
1369 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1370 HRESULT hr;
1371
1372 VariantInit(&vararg[0]);
1373 V_VT(&vararg[0]) = VT_I4;
1374 V_I4(&vararg[0]) = iField;
1375
1376 hr = invoke(pRecord, "IntegerData", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1377 *pValue = V_I4(&varresult);
1378 VariantClear(&varresult);
1379 return hr;
1380}
1381
1382static HRESULT Record_IntegerDataPut(IDispatch *pRecord, int iField, int iValue)
1383{
1384 VARIANT varresult;
1385 VARIANTARG vararg[2];
1386 DISPID dispid = DISPID_PROPERTYPUT;
1387 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1};
1388
1389 VariantInit(&vararg[1]);
1390 V_VT(&vararg[1]) = VT_I4;
1391 V_I4(&vararg[1]) = iField;
1392 VariantInit(&vararg[0]);
1393 V_VT(&vararg[0]) = VT_I4;
1394 V_I4(&vararg[0]) = iValue;
1395
1396 return invoke(pRecord, "IntegerData", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1397}
1398
1400{
1401 VARIANT varresult;
1402 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1403 HRESULT hr = invoke(pList, "_NewEnum", DISPATCH_METHOD, &dispparams, &varresult, VT_UNKNOWN);
1404 *ppEnumVARIANT = V_UNKNOWN(&varresult);
1405 return hr;
1406}
1407
1408static HRESULT StringList_Item(IDispatch *pStringList, int iIndex, LPWSTR szString)
1409{
1410 VARIANT varresult;
1411 VARIANTARG vararg[1];
1412 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1413 HRESULT hr;
1414
1415 VariantInit(&vararg[0]);
1416 V_VT(&vararg[0]) = VT_I4;
1417 V_I4(&vararg[0]) = iIndex;
1418
1419 hr = invoke(pStringList, "Item", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_BSTR);
1420 if (V_BSTR(&varresult)) lstrcpyW(szString, V_BSTR(&varresult));
1421 VariantClear(&varresult);
1422 return hr;
1423}
1424
1425static HRESULT StringList_Count(IDispatch *pStringList, int *pCount)
1426{
1427 VARIANT varresult;
1428 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1429 HRESULT hr = invoke(pStringList, "Count", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1430 *pCount = V_I4(&varresult);
1431 VariantClear(&varresult);
1432 return hr;
1433}
1434
1435static HRESULT SummaryInfo_PropertyGet(IDispatch *pSummaryInfo, int pid, VARIANT *pVarResult, VARTYPE vtExpect)
1436{
1437 VARIANTARG vararg[1];
1438 DISPPARAMS dispparams = {vararg, NULL, ARRAY_SIZE(vararg), 0};
1439
1440 VariantInit(&vararg[0]);
1441 V_VT(&vararg[0]) = VT_I4;
1442 V_I4(&vararg[0]) = pid;
1443 return invoke(pSummaryInfo, "Property", DISPATCH_PROPERTYGET, &dispparams, pVarResult, vtExpect);
1444}
1445
1446static HRESULT SummaryInfo_PropertyPut(IDispatch *pSummaryInfo, int pid, VARIANT *pVariant)
1447{
1448 VARIANT varresult;
1449 VARIANTARG vararg[2];
1450 DISPID dispid = DISPID_PROPERTYPUT;
1451 DISPPARAMS dispparams = {vararg, &dispid, ARRAY_SIZE(vararg), 1};
1452
1453 VariantInit(&vararg[1]);
1454 V_VT(&vararg[1]) = VT_I4;
1455 V_I4(&vararg[1]) = pid;
1456 VariantInit(&vararg[0]);
1457 VariantCopyInd(vararg, pVariant);
1458
1459 return invoke(pSummaryInfo, "Property", DISPATCH_PROPERTYPUT, &dispparams, &varresult, VT_EMPTY);
1460}
1461
1462static HRESULT SummaryInfo_PropertyCountGet(IDispatch *pSummaryInfo, int *pCount)
1463{
1464 VARIANT varresult;
1465 DISPPARAMS dispparams = {NULL, NULL, 0, 0};
1466 HRESULT hr;
1467
1468 hr = invoke(pSummaryInfo, "PropertyCount", DISPATCH_PROPERTYGET, &dispparams, &varresult, VT_I4);
1469 *pCount = V_I4(&varresult);
1470 VariantClear(&varresult);
1471 return hr;
1472}
1473
1474/* Test the various objects */
1475
1476#define TEST_SUMMARYINFO_PROPERTIES_MODIFIED 4
1477
1478static void test_SummaryInfo(IDispatch *pSummaryInfo, const msi_summary_info *info, int num_info, BOOL readonly)
1479{
1480 VARIANT varresult, var;
1481 SYSTEMTIME st;
1482 HRESULT hr;
1483 int j;
1484
1485 /* SummaryInfo::PropertyCount */
1486 hr = SummaryInfo_PropertyCountGet(pSummaryInfo, &j);
1487 ok(hr == S_OK, "SummaryInfo_PropertyCount failed, hresult %#lx\n", hr);
1488 ok(j == num_info, "SummaryInfo_PropertyCount returned %d, expected %d\n", j, num_info);
1489
1490 /* SummaryInfo::Property, get for properties we have set */
1491 for (j = 0; j < num_info; j++)
1492 {
1493 const msi_summary_info *entry = &info[j];
1494
1495 int vt = entry->datatype;
1496 if (vt == VT_LPSTR) vt = VT_BSTR;
1497 else if (vt == VT_FILETIME) vt = VT_DATE;
1498 else if (vt == VT_I2) vt = VT_I4;
1499
1500 hr = SummaryInfo_PropertyGet(pSummaryInfo, entry->property, &varresult, vt);
1501 ok(hr == S_OK, "SummaryInfo_Property (pid %d) failed, hresult %#lx\n", entry->property, hr);
1502 if (V_VT(&varresult) != vt)
1503 skip("Skipping property tests due to type mismatch\n");
1504 else if (vt == VT_I4)
1505 ok(V_I4(&varresult) == entry->iValue, "SummaryInfo_Property (pid %d) I4 result expected to be %d, but was %ld\n",
1506 entry->property, entry->iValue, V_I4(&varresult));
1507 else if (vt == VT_DATE)
1508 {
1509 FILETIME ft;
1510 DATE d;
1511
1512 FileTimeToLocalFileTime(entry->pftValue, &ft);
1513 FileTimeToSystemTime(&ft, &st);
1515 ok(d == V_DATE(&varresult), "SummaryInfo_Property (pid %d) DATE result expected to be %lf, but was %lf\n", entry->property, d, V_DATE(&varresult));
1516 }
1517 else if (vt == VT_BSTR)
1518 {
1519 ok_awplus("SummaryInfo_Property (pid %d) BSTR result expected to be %s, but was %s\n", entry->property, entry->szValue, V_BSTR(&varresult));
1520 }
1521 else
1522 skip("SummaryInfo_Property (pid %d) unhandled result type %d\n", entry->property, vt);
1523
1524 VariantClear(&varresult);
1525 }
1526
1527 /* SummaryInfo::Property, get; invalid arguments */
1528
1529 /* Invalid pids */
1530 hr = SummaryInfo_PropertyGet(pSummaryInfo, -1, &varresult, VT_EMPTY);
1531 ok(hr == DISP_E_EXCEPTION, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1532 ok_exception(hr, L"Property,Pid");
1533
1534 hr = SummaryInfo_PropertyGet(pSummaryInfo, 1000, &varresult, VT_EMPTY);
1535 ok(hr == DISP_E_EXCEPTION, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1536 ok_exception(hr, L"Property,Pid");
1537
1538 /* Unsupported pids */
1539 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_DICTIONARY, &varresult, VT_EMPTY);
1540 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1541
1542 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_THUMBNAIL, &varresult, VT_EMPTY);
1543 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1544
1545 /* Pids we have not set, one for each type */
1546 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CODEPAGE, &varresult, VT_EMPTY);
1547 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1548
1549 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_TITLE, &varresult, VT_EMPTY);
1550 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1551
1552 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_EDITTIME, &varresult, VT_EMPTY);
1553 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1554
1555 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CHARCOUNT, &varresult, VT_EMPTY);
1556 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1557
1558 if (!readonly)
1559 {
1560 /* SummaryInfo::Property, put; one for each type */
1561
1562 /* VT_I2 */
1563 VariantInit(&var);
1564 V_VT(&var) = VT_I2;
1565 V_I2(&var) = 1;
1566 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_CODEPAGE, &var);
1567 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr);
1568
1569 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CODEPAGE, &varresult, VT_I4 /* NOT VT_I2 */);
1570 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1571 ok(V_I2(&var) == V_I2(&varresult), "SummaryInfo_PropertyGet expected %d, but returned %d\n", V_I2(&var), V_I2(&varresult));
1572 VariantClear(&varresult);
1573 VariantClear(&var);
1574
1575 /* VT_BSTR */
1576 V_VT(&var) = VT_BSTR;
1577 V_BSTR(&var) = SysAllocString(L"Title");
1578 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_TITLE, &var);
1579 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr);
1580
1581 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_TITLE, &varresult, V_VT(&var));
1582 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1583 ok_w2("SummaryInfo_PropertyGet expected %s, but returned %s\n", V_BSTR(&var), V_BSTR(&varresult));
1584 VariantClear(&varresult);
1585 VariantClear(&var);
1586
1587 /* VT_DATE */
1588 V_VT(&var) = VT_DATE;
1592 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr);
1593
1594 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_LASTSAVE_DTM, &varresult, V_VT(&var));
1595 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1596 ok(V_DATE(&var) == V_DATE(&varresult), "SummaryInfo_PropertyGet expected %lf, but returned %lf\n", V_DATE(&var), V_DATE(&varresult));
1597 VariantClear(&varresult);
1598 VariantClear(&var);
1599
1600 /* VT_I4 */
1601 V_VT(&var) = VT_I4;
1602 V_I4(&var) = 1000;
1603 hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_CHARCOUNT, &var);
1604 ok(hr == S_OK, "SummaryInfo_PropertyPut failed, hresult %#lx\n", hr);
1605
1606 hr = SummaryInfo_PropertyGet(pSummaryInfo, PID_CHARCOUNT, &varresult, V_VT(&var));
1607 ok(hr == S_OK, "SummaryInfo_PropertyGet failed, hresult %#lx\n", hr);
1608 ok(V_I4(&var) == V_I4(&varresult), "SummaryInfo_PropertyGet expected %ld, but returned %ld\n", V_I4(&var), V_I4(&varresult));
1609 VariantClear(&varresult);
1610 VariantClear(&var);
1611
1612 /* SummaryInfo::PropertyCount */
1613 hr = SummaryInfo_PropertyCountGet(pSummaryInfo, &j);
1614 ok(hr == S_OK, "SummaryInfo_PropertyCount failed, hresult %#lx\n", hr);
1615 ok(j == num_info+4, "SummaryInfo_PropertyCount returned %d, expected %d\n", j, num_info);
1616 }
1617}
1618
1619static void test_Database(IDispatch *pDatabase, BOOL readonly)
1620{
1621 IDispatch *pView = NULL, *pSummaryInfo = NULL;
1622 HRESULT hr;
1623
1624 hr = Database_OpenView(pDatabase, L"SELECT `Feature` FROM `Feature` WHERE `Feature_Parent`='One'", &pView);
1625 ok(hr == S_OK, "Database_OpenView failed, hresult %#lx\n", hr);
1626 if (hr == S_OK)
1627 {
1628 IDispatch *pRecord = NULL;
1629 WCHAR szString[MAX_PATH];
1630
1631 /* View::Execute */
1632 hr = View_Execute(pView, NULL);
1633 ok(hr == S_OK, "View_Execute failed, hresult %#lx\n", hr);
1634
1635 /* View::Fetch */
1636 hr = View_Fetch(pView, &pRecord);
1637 ok(hr == S_OK, "View_Fetch failed, hresult %#lx\n", hr);
1638 ok(pRecord != NULL, "View_Fetch should not have returned NULL record\n");
1639 if (pRecord)
1640 {
1641 /* Record::StringDataGet */
1642 memset(szString, 0, sizeof(szString));
1643 hr = Record_StringDataGet(pRecord, 1, szString);
1644 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr);
1645 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Three");
1646
1647 /* Record::StringDataPut with correct index */
1648 hr = Record_StringDataPut(pRecord, 1, L"Two");
1649 ok(hr == S_OK, "Record_StringDataPut failed, hresult %#lx\n", hr);
1650
1651 /* Record::StringDataGet */
1652 memset(szString, 0, sizeof(szString));
1653 hr = Record_StringDataGet(pRecord, 1, szString);
1654 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr);
1655 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Two");
1656
1657 /* Record::StringDataPut with incorrect index */
1658 hr = Record_StringDataPut(pRecord, -1, szString);
1659 ok(hr == DISP_E_EXCEPTION, "Record_StringDataPut failed, hresult %#lx\n", hr);
1660 ok_exception(hr, L"StringData,Field");
1661
1662 /* View::Modify with incorrect parameters */
1663 hr = View_Modify(pView, -5, NULL);
1664 ok(hr == DISP_E_EXCEPTION, "View_Modify failed, hresult %#lx\n", hr);
1665 ok_exception(hr, L"Modify,Mode,Record");
1666
1667 hr = View_Modify(pView, -5, pRecord);
1668 ok(hr == DISP_E_EXCEPTION, "View_Modify failed, hresult %#lx\n", hr);
1669 ok_exception(hr, L"Modify,Mode,Record");
1670
1672 ok(hr == DISP_E_EXCEPTION, "View_Modify failed, hresult %#lx\n", hr);
1673 ok_exception(hr, L"Modify,Mode,Record");
1674
1675 hr = View_Modify(pView, MSIMODIFY_REFRESH, pRecord);
1676 ok(hr == S_OK, "View_Modify failed, hresult %#lx\n", hr);
1677
1678 /* Record::StringDataGet, confirm that the record is back to its unmodified value */
1679 memset(szString, 0, sizeof(szString));
1680 hr = Record_StringDataGet(pRecord, 1, szString);
1681 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr);
1682 todo_wine ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Three");
1683
1684 IDispatch_Release(pRecord);
1685 }
1686
1687 /* View::Fetch */
1688 hr = View_Fetch(pView, &pRecord);
1689 ok(hr == S_OK, "View_Fetch failed, hresult %#lx\n", hr);
1690 ok(pRecord != NULL, "View_Fetch should not have returned NULL record\n");
1691 if (pRecord)
1692 {
1693 /* Record::StringDataGet */
1694 memset(szString, 0, sizeof(szString));
1695 hr = Record_StringDataGet(pRecord, 1, szString);
1696 ok(hr == S_OK, "Record_StringDataGet failed, hresult %#lx\n", hr);
1697 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString, L"Two");
1698
1699 IDispatch_Release(pRecord);
1700 }
1701
1702 /* View::Fetch */
1703 hr = View_Fetch(pView, &pRecord);
1704 ok(hr == S_OK, "View_Fetch failed, hresult %#lx\n", hr);
1705 ok(pRecord == NULL, "View_Fetch should have returned NULL record\n");
1706 if (pRecord)
1707 IDispatch_Release(pRecord);
1708
1709 /* View::Close */
1710 hr = View_Close(pView);
1711 ok(hr == S_OK, "View_Close failed, hresult %#lx\n", hr);
1712
1713 IDispatch_Release(pView);
1714 }
1715
1716 /* Database::SummaryInformation */
1718 ok(hr == S_OK, "Database_SummaryInformation failed, hresult %#lx\n", hr);
1719 ok(pSummaryInfo != NULL, "Database_SummaryInformation should not have returned NULL record\n");
1720 if (pSummaryInfo)
1721 {
1722 test_SummaryInfo(pSummaryInfo, summary_info, ARRAY_SIZE(summary_info), readonly);
1723 IDispatch_Release(pSummaryInfo);
1724 }
1725}
1726
1727static void test_Session(IDispatch *pSession)
1728{
1730 CHAR string[MAX_PATH];
1731 UINT len;
1733 int myint;
1734 IDispatch *pDatabase = NULL, *pInst = NULL, *record = NULL;
1735 ULONG refs_before, refs_after;
1736 HRESULT hr;
1737
1738 /* Session::Installer */
1739 hr = Session_Installer(pSession, &pInst);
1740 ok(hr == S_OK, "Session_Installer failed, hresult %#lx\n", hr);
1741 ok(pInst != NULL, "Session_Installer returned NULL IDispatch pointer\n");
1742 ok(pInst == pInstaller, "Session_Installer does not match Installer instance from CoCreateInstance\n");
1743 refs_before = IDispatch_AddRef(pInst);
1744
1745 hr = Session_Installer(pSession, &pInst);
1746 ok(hr == S_OK, "Session_Installer failed, hresult %#lx\n", hr);
1747 ok(pInst != NULL, "Session_Installer returned NULL IDispatch pointer\n");
1748 ok(pInst == pInstaller, "Session_Installer does not match Installer instance from CoCreateInstance\n");
1749 refs_after = IDispatch_Release(pInst);
1750 ok(refs_before == refs_after, "got %lu and %lu\n", refs_before, refs_after);
1751
1752 /* Session::Property, get */
1753 memset(stringw, 0, sizeof(stringw));
1754 hr = Session_PropertyGet(pSession, L"ProductName", stringw);
1755 ok(hr == S_OK, "Session_PropertyGet failed, hresult %#lx\n", hr);
1756 if (lstrcmpW(stringw, L"MSITEST") != 0)
1757 {
1758 len = WideCharToMultiByte(CP_ACP, 0, stringw, -1, string, MAX_PATH, NULL, NULL);
1759 ok(len, "WideCharToMultiByteChar returned error %lu\n", GetLastError());
1760 ok(0, "Property \"ProductName\" expected to be \"MSITEST\" but was \"%s\"\n", string);
1761 }
1762
1763 /* Session::Property, put */
1764 hr = Session_PropertyPut(pSession, L"ProductName", L"ProductName");
1765 ok(hr == S_OK, "Session_PropertyPut failed, hresult %#lx\n", hr);
1766 memset(stringw, 0, sizeof(stringw));
1767 hr = Session_PropertyGet(pSession, L"ProductName", stringw);
1768 ok(hr == S_OK, "Session_PropertyGet failed, hresult %#lx\n", hr);
1769 if (lstrcmpW(stringw, L"ProductName") != 0)
1770 {
1771 len = WideCharToMultiByte(CP_ACP, 0, stringw, -1, string, MAX_PATH, NULL, NULL);
1772 ok(len, "WideCharToMultiByteChar returned error %lu\n", GetLastError());
1773 ok(0, "Property \"ProductName\" expected to be \"ProductName\" but was \"%s\"\n", string);
1774 }
1775
1776 /* Try putting a property using empty property identifier */
1777 hr = Session_PropertyPut(pSession, L"", L"ProductName");
1778 ok(hr == DISP_E_EXCEPTION, "Session_PropertyPut failed, hresult %#lx\n", hr);
1779 ok_exception(hr, L"Property,Name");
1780
1781 /* Try putting a property using illegal property identifier */
1782 hr = Session_PropertyPut(pSession, L"=", L"ProductName");
1783 ok(hr == S_OK, "Session_PropertyPut failed, hresult %#lx\n", hr);
1784
1785 /* Session::Language, get */
1786 hr = Session_LanguageGet(pSession, &len);
1787 ok(hr == S_OK, "Session_LanguageGet failed, hresult %#lx\n", hr);
1788 /* Not sure how to check the language is correct */
1789
1790 /* Session::Mode, get */
1791 hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTATEND, &bool);
1792 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr);
1793 ok(!bool, "Reboot at end session mode is %d\n", bool);
1794
1795 hr = Session_ModeGet(pSession, MSIRUNMODE_MAINTENANCE, &bool);
1796 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr);
1797 ok(!bool, "Maintenance mode is %d\n", bool);
1798
1799 /* Session::Mode, put */
1800 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTATEND, VARIANT_TRUE);
1801 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr);
1802 hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTATEND, &bool);
1803 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr);
1804 ok(bool, "Reboot at end session mode is %d, expected 1\n", bool);
1805 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTATEND, VARIANT_FALSE); /* set it again so we don't reboot */
1806 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr);
1807
1808 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTNOW, VARIANT_TRUE);
1809 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr);
1810 ok_exception(hr, L"Mode,Flag");
1811
1812 hr = Session_ModeGet(pSession, MSIRUNMODE_REBOOTNOW, &bool);
1813 ok(hr == S_OK, "Session_ModeGet failed, hresult %#lx\n", hr);
1814 ok(bool, "Reboot now mode is %d, expected 1\n", bool);
1815
1816 hr = Session_ModePut(pSession, MSIRUNMODE_REBOOTNOW, VARIANT_FALSE); /* set it again so we don't reboot */
1817 ok(hr == S_OK, "Session_ModePut failed, hresult %#lx\n", hr);
1818 ok_exception(hr, L"Mode,Flag");
1819
1820 hr = Session_ModePut(pSession, MSIRUNMODE_MAINTENANCE, VARIANT_TRUE);
1821 ok(hr == DISP_E_EXCEPTION, "Session_ModePut failed, hresult %#lx\n", hr);
1822 ok_exception(hr, L"Mode,Flag");
1823
1824 /* Session::Database, get */
1825 hr = Session_Database(pSession, &pDatabase);
1826 ok(hr == S_OK, "Session_Database failed, hresult %#lx\n", hr);
1827 if (hr == S_OK)
1828 {
1829 test_Database(pDatabase, TRUE);
1830 IDispatch_Release(pDatabase);
1831 }
1832
1833 /* Session::EvaluateCondition */
1834 hr = Session_EvaluateCondition(pSession, NULL, &myint);
1835 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1836 ok(myint == MSICONDITION_NONE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1837
1838 hr = Session_EvaluateCondition(pSession, L"", &myint);
1839 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1840 ok(myint == MSICONDITION_NONE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1841
1842 hr = Session_EvaluateCondition(pSession, L"=", &myint);
1843 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1844 ok(myint == MSICONDITION_ERROR, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1845
1846 /* Session::DoAction(CostInitialize) must occur before the next statements */
1847 hr = Session_DoAction(pSession, L"CostInitialize", &myint);
1848 ok(hr == S_OK, "Session_DoAction failed, hresult %#lx\n", hr);
1849 ok(myint == IDOK, "DoAction(CostInitialize) returned %d, %d expected\n", myint, IDOK);
1850
1851 /* Session::SetInstallLevel */
1853 ok(hr == S_OK, "Session_SetInstallLevel failed, hresult %#lx\n", hr);
1854
1855 /* Session::FeatureCurrentState, get */
1856 hr = Session_FeatureCurrentState(pSession, L"One", &myint);
1857 ok(hr == S_OK, "Session_FeatureCurrentState failed, hresult %#lx\n", hr);
1858 ok(myint == INSTALLSTATE_UNKNOWN, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1859
1860 /* Session::Message */
1862 ok(hr == S_OK, "Installer_CreateRecord failed: %#lx\n", hr);
1863 hr = Session_Message(pSession, INSTALLMESSAGE_INFO, record, &myint);
1864 ok(hr == S_OK, "Session_Message failed: %#lx\n", hr);
1865 ok(myint == 0, "Session_Message returned %x\n", myint);
1866
1867 /* Session::EvaluateCondition */
1868 hr = Session_EvaluateCondition(pSession, L"!One>0", &myint);
1869 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1870 ok(myint == MSICONDITION_FALSE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1871
1872 hr = Session_EvaluateCondition(pSession, L"!One=-1", &myint);
1873 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1874 ok(myint == MSICONDITION_TRUE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1875
1876 /* Session::FeatureRequestState, put */
1878 ok(hr == S_OK, "Session_FeatureRequestStatePut failed, hresult %#lx\n", hr);
1879 hr = Session_FeatureRequestStateGet(pSession, L"One", &myint);
1880 ok(hr == S_OK, "Session_FeatureRequestStateGet failed, hresult %#lx\n", hr);
1881 ok(myint == INSTALLSTATE_ADVERTISED, "Feature request state was %d but expected %d\n", myint, INSTALLSTATE_ADVERTISED);
1882
1883 /* Session::EvaluateCondition */
1884 hr = Session_EvaluateCondition(pSession, L"$One=-1", &myint);
1885 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1886 ok(myint == MSICONDITION_FALSE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1887
1888 hr = Session_EvaluateCondition(pSession, L"$One>0", &myint);
1889 ok(hr == S_OK, "Session_EvaluateCondition failed, hresult %#lx\n", hr);
1890 ok(myint == MSICONDITION_TRUE, "Feature current state was %d but expected %d\n", myint, INSTALLSTATE_UNKNOWN);
1891}
1892
1893/* delete key and all its subkeys */
1894static DWORD delete_key( HKEY hkey )
1895{
1896 char name[MAX_PATH];
1897 DWORD ret;
1898
1899 while (!(ret = RegEnumKeyA(hkey, 0, name, sizeof(name))))
1900 {
1901 HKEY tmp;
1902 if (!(ret = RegOpenKeyExA( hkey, name, 0, KEY_ENUMERATE_SUB_KEYS, &tmp )))
1903 {
1904 ret = delete_key( tmp );
1905 RegCloseKey( tmp );
1906 }
1907 if (ret) break;
1908 }
1909 if (ret != ERROR_NO_MORE_ITEMS) return ret;
1910 RegDeleteKeyA( hkey, "" );
1911 return 0;
1912}
1913
1915{
1916 static const DWORD qw[2] = { 0x12345678, 0x87654321 };
1917 VARIANT varresult;
1918 VARIANTARG vararg;
1919 WCHAR szString[MAX_PATH];
1920 HKEY hkey, hkey_sub;
1921 HKEY curr_user = (HKEY)1;
1922 HRESULT hr;
1923 BOOL bRet;
1924 LONG lRet;
1925
1926 /* Delete keys */
1927 SetLastError(0xdeadbeef);
1928 lRet = RegOpenKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Test", &hkey );
1929 if (!lRet && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
1930 {
1931 win_skip("Needed W-functions are not implemented\n");
1932 return;
1933 }
1934 if (!lRet)
1935 delete_key( hkey );
1936
1937 /* Does our key exist? Shouldn't; check with all three possible value parameter types */
1938 hr = Installer_RegistryValueE(curr_user, L"Software\\Wine\\Test", &bRet);
1939 ok(hr == S_OK, "Installer_RegistryValueE failed, hresult %#lx\n", hr);
1940 ok(!bRet, "Registry key expected to not exist, but Installer_RegistryValue claims it does\n");
1941
1942 memset(szString, 0, sizeof(szString));
1943 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", NULL, szString);
1944 ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
1945
1946 memset(szString, 0, sizeof(szString));
1947 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 0, szString, VT_BSTR);
1948 ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueI failed, hresult %#lx\n", hr);
1949
1950 /* Create key */
1951 ok(!RegCreateKeyW( HKEY_CURRENT_USER, L"Software\\Wine\\Test", &hkey ), "RegCreateKeyW failed\n");
1952
1953 ok(!RegSetValueExW(hkey, L"One", 0, REG_SZ, (const BYTE *)L"One", sizeof(L"one")),
1954 "RegSetValueExW failed\n");
1955 ok(!RegSetValueExW(hkey, L"Two", 0, REG_DWORD, (const BYTE *)qw, 4),
1956 "RegSetValueExW failed\n");
1957 ok(!RegSetValueExW(hkey, L"Three", 0, REG_BINARY, (const BYTE *)qw, 4),
1958 "RegSetValueExW failed\n");
1959 bRet = SetEnvironmentVariableA("MSITEST", "Four");
1960 ok(bRet, "SetEnvironmentVariableA failed %lu\n", GetLastError());
1961 ok(!RegSetValueExW(hkey, L"Four", 0, REG_EXPAND_SZ, (const BYTE *)L"%MSITEST%", sizeof(L"%MSITEST%")),
1962 "RegSetValueExW failed\n");
1963 ok(!RegSetValueExW(hkey, L"Five\0Hi\0", 0, REG_MULTI_SZ, (const BYTE *)L"Five\0Hi\0", sizeof(L"Five\0Hi\0")),
1964 "RegSetValueExW failed\n");
1965 ok(!RegSetValueExW(hkey, L"Six", 0, REG_QWORD, (const BYTE *)qw, 8),
1966 "RegSetValueExW failed\n");
1967 ok(!RegSetValueExW(hkey, L"Seven", 0, REG_NONE, NULL, 0),
1968 "RegSetValueExW failed\n");
1969
1970 ok(!RegSetValueExW(hkey, NULL, 0, REG_SZ, (const BYTE *)L"One", sizeof(L"One")),
1971 "RegSetValueExW failed\n");
1972
1973 ok(!RegCreateKeyW( hkey, L"Eight", &hkey_sub ), "RegCreateKeyW failed\n");
1974
1975 /* Does our key exist? It should, and make sure we retrieve the correct default value */
1976 bRet = FALSE;
1977 hr = Installer_RegistryValueE(curr_user, L"Software\\Wine\\Test", &bRet);
1978 ok(hr == S_OK, "Installer_RegistryValueE failed, hresult %#lx\n", hr);
1979 ok(bRet, "Registry key expected to exist, but Installer_RegistryValue claims it does not\n");
1980
1981 memset(szString, 0, sizeof(szString));
1982 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", NULL, szString);
1983 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
1984 ok_w2("Default registry value \"%s\" does not match expected \"%s\"\n", szString, L"One");
1985
1986 /* Ask for the value of a nonexistent key */
1987 memset(szString, 0, sizeof(szString));
1988 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"%MSITEST%", szString);
1989 ok(hr == DISP_E_BADINDEX, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
1990
1991 /* Get values of keys */
1992 memset(szString, 0, sizeof(szString));
1993 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"One", szString);
1994 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
1995 ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, L"One");
1996
1997 VariantInit(&vararg);
1998 V_VT(&vararg) = VT_BSTR;
1999 V_BSTR(&vararg) = SysAllocString(L"Two");
2000 hr = Installer_RegistryValue(curr_user, L"Software\\Wine\\Test", vararg, &varresult, VT_I4);
2001 ok(hr == S_OK, "Installer_RegistryValue failed, hresult %#lx\n", hr);
2002 ok(V_I4(&varresult) == 305419896, "Registry value %ld does not match expected value\n", V_I4(&varresult));
2003 VariantClear(&varresult);
2004
2005 memset(szString, 0, sizeof(szString));
2006 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Three", szString);
2007 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
2008 ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, L"(REG_BINARY)");
2009
2010 memset(szString, 0, sizeof(szString));
2011 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Four", szString);
2012 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
2013 ok_w2("Registry value \"%s\" does not match expected \"%s\"\n", szString, L"Four");
2014
2015 /* Vista does not NULL-terminate this case */
2016 memset(szString, 0, sizeof(szString));
2017 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Five\0Hi\0", szString);
2018 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
2019 ok_w2n("Registry value \"%s\" does not match expected \"%s\"\n",
2020 szString, L"Five\nHi", lstrlenW(L"Five\nHi"));
2021
2022 memset(szString, 0, sizeof(szString));
2023 hr = Installer_RegistryValueW(curr_user, L"Software\\Wine\\Test", L"Six", szString);
2024 ok(hr == S_OK, "Installer_RegistryValueW failed, hresult %#lx\n", hr);
2025 ok(!lstrcmpW(szString, L"(REG_\?\?)") || broken(!lstrcmpW(szString, L"(REG_]")),
2026 "Registry value does not match\n");
2027
2028 VariantInit(&vararg);
2029 V_VT(&vararg) = VT_BSTR;
2030 V_BSTR(&vararg) = SysAllocString(L"Seven");
2031 hr = Installer_RegistryValue(curr_user, L"Software\\Wine\\Test", vararg, &varresult, VT_EMPTY);
2032 ok(hr == S_OK, "Installer_RegistryValue failed, hresult %#lx\n", hr);
2033
2034 /* Get string class name for the key */
2035 memset(szString, 0, sizeof(szString));
2036 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 0, szString, VT_BSTR);
2037 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr);
2038 ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, L"");
2039
2040 /* Get name of a value by positive number (RegEnumValue like), valid index */
2041 memset(szString, 0, sizeof(szString));
2042 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 2, szString, VT_BSTR);
2043 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr);
2044 /* RegEnumValue order seems different on wine */
2045 todo_wine ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, L"Two");
2046
2047 /* Get name of a value by positive number (RegEnumValue like), invalid index */
2048 memset(szString, 0, sizeof(szString));
2049 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", 10, szString, VT_EMPTY);
2050 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr);
2051
2052 /* Get name of a subkey by negative number (RegEnumValue like), valid index */
2053 memset(szString, 0, sizeof(szString));
2054 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", -1, szString, VT_BSTR);
2055 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr);
2056 ok_w2("Registry name \"%s\" does not match expected \"%s\"\n", szString, L"Eight");
2057
2058 /* Get name of a subkey by negative number (RegEnumValue like), invalid index */
2059 memset(szString, 0, sizeof(szString));
2060 hr = Installer_RegistryValueI(curr_user, L"Software\\Wine\\Test", -10, szString, VT_EMPTY);
2061 ok(hr == S_OK, "Installer_RegistryValueI failed, hresult %#lx\n", hr);
2062
2063 /* clean up */
2064 delete_key(hkey);
2065}
2066
2067static void test_Installer_Products(BOOL bProductInstalled)
2068{
2069 WCHAR szString[MAX_PATH];
2070 HRESULT hr;
2071 int idx;
2072 IUnknown *pUnk = NULL;
2073 IEnumVARIANT *pEnum = NULL;
2074 VARIANT var;
2075 ULONG celt;
2076 int iCount, iValue;
2077 IDispatch *pStringList = NULL;
2078 BOOL bProductFound = FALSE;
2079
2080 /* Installer::Products */
2081 hr = Installer_Products(&pStringList);
2082 ok(hr == S_OK, "Installer_Products failed, hresult %#lx\n", hr);
2083 if (hr == S_OK)
2084 {
2085 /* StringList::_NewEnum */
2086 hr = StringList__NewEnum(pStringList, &pUnk);
2087 ok(hr == S_OK, "StringList_NewEnum failed, hresult %#lx\n", hr);
2088 if (hr == S_OK)
2089 {
2090 hr = IUnknown_QueryInterface(pUnk, &IID_IEnumVARIANT, (void **)&pEnum);
2091 ok (hr == S_OK, "IUnknown::QueryInterface returned %#lx\n", hr);
2092 }
2093 if (!pEnum)
2094 skip("IEnumVARIANT tests\n");
2095
2096 /* StringList::Count */
2097 hr = StringList_Count(pStringList, &iCount);
2098 ok(hr == S_OK, "StringList_Count failed, hresult %#lx\n", hr);
2099
2100 for (idx=0; idx<iCount; idx++)
2101 {
2102 /* StringList::Item */
2103 memset(szString, 0, sizeof(szString));
2104 hr = StringList_Item(pStringList, idx, szString);
2105 ok(hr == S_OK, "StringList_Item failed (idx %d, count %d), hresult %#lx\n", idx, iCount, hr);
2106
2107 if (hr == S_OK)
2108 {
2109 /* Installer::ProductState */
2110 hr = Installer_ProductState(szString, &iValue);
2111 ok(hr == S_OK, "Installer_ProductState failed, hresult %#lx\n", hr);
2112 if (hr == S_OK)
2113 ok(iValue == INSTALLSTATE_DEFAULT || iValue == INSTALLSTATE_ADVERTISED,
2114 "Installer_ProductState returned %d, expected %d or %d\n", iValue, INSTALLSTATE_DEFAULT, INSTALLSTATE_ADVERTISED);
2115
2116 /* Not found our product code yet? Check */
2117 if (!bProductFound && !lstrcmpW(szString, L"{837450fa-a39b-4bc8-b321-08b393f784b3}"))
2118 bProductFound = TRUE;
2119
2120 /* IEnumVARIANT::Next */
2121 if (pEnum)
2122 {
2123 hr = IEnumVARIANT_Next(pEnum, 1, &var, &celt);
2124 ok(hr == S_OK, "IEnumVARIANT_Next failed (idx %d, count %d), hresult %#lx\n", idx, iCount, hr);
2125 ok(celt == 1, "%lu items were retrieved, expected 1\n", celt);
2126 ok(V_VT(&var) == VT_BSTR, "IEnumVARIANT_Next returned variant of type %d, expected %d\n", V_VT(&var), VT_BSTR);
2127 ok_w2("%s returned by StringList_Item does not match %s returned by IEnumVARIANT_Next\n", szString, V_BSTR(&var));
2128 VariantClear(&var);
2129 }
2130 }
2131 }
2132
2133 if (bProductInstalled)
2134 {
2135 ok(bProductInstalled == bProductFound, "Product expected to %s installed but product code was %s\n",
2136 bProductInstalled ? "be" : "not be",
2137 bProductFound ? "found" : "not found");
2138 }
2139
2140 if (pEnum)
2141 {
2142 IEnumVARIANT *pEnum2 = NULL;
2143
2144 if (0) /* Crashes on Windows XP */
2145 {
2146 /* IEnumVARIANT::Clone, NULL pointer */
2147 IEnumVARIANT_Clone(pEnum, NULL);
2148 }
2149
2150 /* IEnumVARIANT::Clone */
2151 hr = IEnumVARIANT_Clone(pEnum, &pEnum2);
2152 ok(hr == S_OK, "IEnumVARIANT_Clone failed, hresult %#lx\n", hr);
2153 if (hr == S_OK)
2154 {
2155 /* IEnumVARIANT::Clone is supposed to save the position, but it actually just goes back to the beginning */
2156
2157 /* IEnumVARIANT::Next of the clone */
2158 if (iCount)
2159 {
2160 hr = IEnumVARIANT_Next(pEnum2, 1, &var, &celt);
2161 ok(hr == S_OK, "IEnumVARIANT_Next failed, hresult %#lx\n", hr);
2162 ok(celt == 1, "%lu items were retrieved, expected 0\n", celt);
2163 ok(V_VT(&var) == VT_BSTR, "IEnumVARIANT_Next returned variant of type %d, expected %d\n", V_VT(&var), VT_BSTR);
2164 VariantClear(&var);
2165 }
2166 else
2167 skip("IEnumVARIANT::Next of clone will not return success with 0 products\n");
2168
2169 IEnumVARIANT_Release(pEnum2);
2170 }
2171
2172 /* IEnumVARIANT::Skip should fail */
2173 hr = IEnumVARIANT_Skip(pEnum, 1);
2174 ok(hr == S_FALSE, "IEnumVARIANT_Skip failed, hresult %#lx\n", hr);
2175
2176 /* IEnumVARIANT::Next, NULL variant pointer */
2177 hr = IEnumVARIANT_Next(pEnum, 1, NULL, &celt);
2178 ok(hr == S_FALSE, "IEnumVARIANT_Next failed, hresult %#lx\n", hr);
2179 ok(celt == 0, "%lu items were retrieved, expected 0\n", celt);
2180
2181 /* IEnumVARIANT::Next, should not return any more items */
2182 hr = IEnumVARIANT_Next(pEnum, 1, &var, &celt);
2183 ok(hr == S_FALSE, "IEnumVARIANT_Next failed, hresult %#lx\n", hr);
2184 ok(celt == 0, "%lu items were retrieved, expected 0\n", celt);
2185 VariantClear(&var);
2186
2187 /* IEnumVARIANT::Reset */
2188 hr = IEnumVARIANT_Reset(pEnum);
2189 ok(hr == S_OK, "IEnumVARIANT_Reset failed, hresult %#lx\n", hr);
2190
2191 if (iCount)
2192 {
2193 /* IEnumVARIANT::Skip to the last product */
2194 hr = IEnumVARIANT_Skip(pEnum, iCount-1);
2195 ok(hr == S_OK, "IEnumVARIANT_Skip failed, hresult %#lx\n", hr);
2196
2197 /* IEnumVARIANT::Next should match the very last retrieved value, also makes sure it works with
2198 * NULL celt pointer. */
2199 hr = IEnumVARIANT_Next(pEnum, 1, &var, NULL);
2200 ok(hr == S_OK, "IEnumVARIANT_Next failed (idx %d, count %d), hresult %#lx\n", idx, iCount, hr);
2201 ok(V_VT(&var) == VT_BSTR, "IEnumVARIANT_Next returned variant of type %d, expected %d\n", V_VT(&var), VT_BSTR);
2202 ok_w2("%s returned by StringList_Item does not match %s returned by IEnumVARIANT_Next\n", szString, V_BSTR(&var));
2203 VariantClear(&var);
2204 }
2205 else
2206 skip("IEnumVARIANT::Skip impossible for 0 products\n");
2207 }
2208
2209 /* StringList::Item using an invalid index */
2210 memset(szString, 0, sizeof(szString));
2211 hr = StringList_Item(pStringList, iCount, szString);
2212 ok(hr == DISP_E_BADINDEX, "StringList_Item for an invalid index did not return DISP_E_BADINDEX, hresult %#lx\n", hr);
2213
2214 if (pEnum) IEnumVARIANT_Release(pEnum);
2215 if (pUnk) IUnknown_Release(pUnk);
2216 IDispatch_Release(pStringList);
2217 }
2218}
2219
2220/* Delete a registry subkey, including all its subkeys (RegDeleteKey does not work on keys with subkeys without
2221 * deleting the subkeys first) */
2223{
2224 UINT ret;
2225 CHAR *string = NULL;
2226 HKEY hkey;
2227 DWORD dwSize;
2228
2229 ret = RegOpenKeyExA(hkeyParent, subkey, 0, access, &hkey);
2230 if (ret != ERROR_SUCCESS) return ret;
2232 if (ret != ERROR_SUCCESS) return ret;
2233 if (!(string = malloc(++dwSize))) return ERROR_NOT_ENOUGH_MEMORY;
2234
2235 while (RegEnumKeyA(hkey, 0, string, dwSize) == ERROR_SUCCESS)
2236 delete_registry_key(hkey, string, access);
2237
2238 RegCloseKey(hkey);
2239 free(string);
2240 RegDeleteKeyExA(hkeyParent, subkey, access, 0);
2241 return ERROR_SUCCESS;
2242}
2243
2244/* Find a specific registry subkey at any depth within the given key and subkey and return its parent key. */
2245static UINT find_registry_key(HKEY hkeyParent, LPCSTR subkey, LPCSTR findkey, REGSAM access, HKEY *phkey)
2246{
2247 UINT ret;
2248 CHAR *string = NULL;
2249 int idx = 0;
2250 HKEY hkey;
2251 DWORD dwSize;
2252 BOOL found = FALSE;
2253
2254 *phkey = 0;
2255
2256 ret = RegOpenKeyExA(hkeyParent, subkey, 0, access, &hkey);
2257 if (ret != ERROR_SUCCESS) return ret;
2259 if (ret != ERROR_SUCCESS) return ret;
2260 if (!(string = malloc(++dwSize))) return ERROR_NOT_ENOUGH_MEMORY;
2261
2262 while (!found &&
2263 RegEnumKeyA(hkey, idx++, string, dwSize) == ERROR_SUCCESS)
2264 {
2265 if (!strcmp(string, findkey))
2266 {
2267 *phkey = hkey;
2268 found = TRUE;
2269 }
2270 else if (find_registry_key(hkey, string, findkey, access, phkey) == ERROR_SUCCESS) found = TRUE;
2271 }
2272
2273 if (*phkey != hkey) RegCloseKey(hkey);
2274 free(string);
2275 return (found ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND);
2276}
2277
2279{
2280 HRESULT hr;
2282 WCHAR szString[MAX_PATH];
2283 LONG res;
2284 HKEY hkey;
2285 DWORD num, size, type;
2286 int iValue, iCount;
2287 IDispatch *pStringList = NULL;
2289
2290 if (!is_process_elevated())
2291 {
2292 /* In fact InstallProduct would succeed but then Windows XP
2293 * would not allow us to clean up the registry!
2294 */
2295 skip("Installer_InstallProduct (insufficient privileges)\n");
2296 return;
2297 }
2298
2299 if (is_wow64)
2301
2303
2304 /* Avoid an interactive dialog in case of insufficient privileges. */
2306 ok(hr == S_OK, "Expected UILevel property put invoke to return S_OK, got %#lx\n", hr);
2307
2308 /* Installer::InstallProduct */
2309 hr = Installer_InstallProduct(L"winetest-automation.msi", NULL);
2310 if (hr == DISP_E_EXCEPTION)
2311 {
2312 skip("InstallProduct failed, insufficient rights?\n");
2314 return;
2315 }
2316 ok(hr == S_OK, "Installer_InstallProduct failed, hresult %#lx\n", hr);
2317
2318 /* Installer::ProductState for our product code, which has been installed */
2319 hr = Installer_ProductState(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", &iValue);
2320 ok(hr == S_OK, "Installer_ProductState failed, hresult %#lx\n", hr);
2321 ok(iValue == INSTALLSTATE_DEFAULT, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_DEFAULT);
2322
2323 /* Installer::ProductInfo for our product code */
2324
2325 /* NULL attribute */
2326 memset(szString, 0, sizeof(szString));
2327 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", NULL, szString);
2328 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2329 ok_exception(hr, L"ProductInfo,Product,Attribute");
2330
2331 /* Nonexistent attribute */
2332 memset(szString, 0, sizeof(szString));
2333 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"winetest-automation.msi", szString);
2334 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2335 ok_exception(hr, L"ProductInfo,Product,Attribute");
2336
2337 /* Package name */
2338 memset(szString, 0, sizeof(szString));
2339 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"PackageName", szString);
2340 ok(hr == S_OK, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2341 todo_wine ok_w2("Installer_ProductInfo returned %s but expected %s\n", szString, L"winetest-automation.msi");
2342
2343 /* Product name */
2344 memset(szString, 0, sizeof(szString));
2345 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"ProductName", szString);
2346 ok(hr == S_OK, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2347 todo_wine ok_w2("Installer_ProductInfo returned %s but expected %s\n", szString, L"MSITEST");
2348
2349 /* Installer::Products */
2351
2352 /* Installer::RelatedProducts for our upgrade code */
2353 hr = Installer_RelatedProducts(L"{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}", &pStringList);
2354 ok(hr == S_OK, "Installer_RelatedProducts failed, hresult %#lx\n", hr);
2355 if (hr == S_OK)
2356 {
2357 /* StringList::Count */
2358 hr = StringList_Count(pStringList, &iCount);
2359 ok(hr == S_OK, "StringList_Count failed, hresult %#lx\n", hr);
2360 ok(iCount == 1, "Expected one related product but found %d\n", iCount);
2361
2362 /* StringList::Item */
2363 memset(szString, 0, sizeof(szString));
2364 hr = StringList_Item(pStringList, 0, szString);
2365 ok(hr == S_OK, "StringList_Item failed (idx 0, count %d), hresult %#lx\n", iCount, hr);
2366 ok_w2("StringList_Item returned %s but expected %s\n", szString, L"{837450fa-a39b-4bc8-b321-08b393f784b3}");
2367
2368 IDispatch_Release(pStringList);
2369 }
2370
2371 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"LocalPackage", szString);
2372 ok(hr == S_OK, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2373 DeleteFileW( szString );
2374
2375 /* Check & clean up installed files & registry keys */
2376 ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
2377 ok(delete_pf("msitest\\cabout\\new", FALSE), "Directory not created\n");
2378 ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
2379 ok(delete_pf("msitest\\cabout", FALSE), "Directory not created\n");
2380 ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
2381 ok(delete_pf("msitest\\changed", FALSE), "Directory not created\n");
2382 ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
2383 ok(delete_pf("msitest\\first", FALSE), "Directory not created\n");
2384 ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
2385 ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
2386 ok(delete_pf("msitest", FALSE), "Directory not created\n");
2387
2388 res = RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Wine\\msitest", &hkey);
2389 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2390
2391 size = MAX_PATH;
2392 type = REG_SZ;
2393 res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
2394 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2395 ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
2396
2397 size = MAX_PATH;
2398 type = REG_SZ;
2399 res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
2400 ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", res);
2401
2402 size = sizeof(num);
2403 type = REG_DWORD;
2404 res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
2405 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2406 ok(num == 314, "Expected 314, got %lu\n", num);
2407
2408 size = MAX_PATH;
2409 type = REG_SZ;
2410 res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
2411 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2412 ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
2413
2414 RegCloseKey(hkey);
2415
2416 res = RegDeleteKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Wine\\msitest");
2417 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2418
2419 /* Remove registry keys written by RegisterProduct standard action */
2421 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{837450fa-a39b-4bc8-b321-08b393f784b3}",
2422 KEY_WOW64_32KEY, 0);
2423 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2424
2426 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UpgradeCodes\\D8E760ECA1E276347B43E42BDBDA5656", access, 0);
2427 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2428
2430 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData", "af054738b93a8cb43b12803b397f483b", access, &hkey);
2431 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2432
2433 res = delete_registry_key(hkey, "af054738b93a8cb43b12803b397f483b", access);
2434 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2435 RegCloseKey(hkey);
2436
2438 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\Products\\af054738b93a8cb43b12803b397f483b", access, 0);
2439 ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %ld\n", res);
2440
2441 /* Remove registry keys written by PublishProduct standard action */
2442 res = RegOpenKeyA(HKEY_CURRENT_USER, "SOFTWARE\\Microsoft\\Installer", &hkey);
2443 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2444
2445 res = delete_registry_key(hkey, "Products\\af054738b93a8cb43b12803b397f483b", KEY_ALL_ACCESS);
2446 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2447
2448 res = RegDeleteKeyA(hkey, "UpgradeCodes\\D8E760ECA1E276347B43E42BDBDA5656");
2449 ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %ld\n", res);
2450
2451 RegCloseKey(hkey);
2452
2453 /* Delete installation files we created */
2455}
2456
2457static void test_Installer(void)
2458{
2460 HRESULT hr;
2461 IDispatch *pSession = NULL, *pDatabase = NULL, *pRecord = NULL, *pStringList = NULL, *pSumInfo = NULL;
2462 int iValue, iCount;
2463
2464 if (!pInstaller) return;
2465
2466 /* Installer::CreateRecord */
2467
2468 /* Test for error */
2469 hr = Installer_CreateRecord(-1, &pRecord);
2470 ok(hr == DISP_E_EXCEPTION, "Installer_CreateRecord failed, hresult %#lx\n", hr);
2471 ok_exception(hr, L"CreateRecord,Count");
2472
2473 /* Test for success */
2474 hr = Installer_CreateRecord(1, &pRecord);
2475 ok(hr == S_OK, "Installer_CreateRecord failed, hresult %#lx\n", hr);
2476 ok(pRecord != NULL, "Installer_CreateRecord should not have returned NULL record\n");
2477 if (pRecord)
2478 {
2479 /* Record::FieldCountGet */
2480 hr = Record_FieldCountGet(pRecord, &iValue);
2481 ok(hr == S_OK, "Record_FiledCountGet failed, hresult %#lx\n", hr);
2482 ok(iValue == 1, "Record_FieldCountGet result was %d but expected 1\n", iValue);
2483
2484 /* Record::IntegerDataGet */
2485 hr = Record_IntegerDataGet(pRecord, 1, &iValue);
2486 ok(hr == S_OK, "Record_IntegerDataGet failed, hresult %#lx\n", hr);
2487 ok(iValue == MSI_NULL_INTEGER, "Record_IntegerDataGet result was %d but expected %d\n", iValue, MSI_NULL_INTEGER);
2488
2489 /* Record::IntegerDataGet, bad index */
2490 hr = Record_IntegerDataGet(pRecord, 10, &iValue);
2491 ok(hr == S_OK, "Record_IntegerDataGet failed, hresult %#lx\n", hr);
2492 ok(iValue == MSI_NULL_INTEGER, "Record_IntegerDataGet result was %d but expected %d\n", iValue, MSI_NULL_INTEGER);
2493
2494 /* Record::IntegerDataPut */
2495 hr = Record_IntegerDataPut(pRecord, 1, 100);
2496 ok(hr == S_OK, "Record_IntegerDataPut failed, hresult %#lx\n", hr);
2497
2498 /* Record::IntegerDataPut, bad index */
2499 hr = Record_IntegerDataPut(pRecord, 10, 100);
2500 ok(hr == DISP_E_EXCEPTION, "Record_IntegerDataPut failed, hresult %#lx\n", hr);
2501 ok_exception(hr, L"IntegerData,Field");
2502
2503 /* Record::IntegerDataGet */
2504 hr = Record_IntegerDataGet(pRecord, 1, &iValue);
2505 ok(hr == S_OK, "Record_IntegerDataGet failed, hresult %#lx\n", hr);
2506 ok(iValue == 100, "Record_IntegerDataGet result was %d but expected 100\n", iValue);
2507
2508 IDispatch_Release(pRecord);
2509 }
2510
2512
2513 /* Installer::OpenPackage */
2514 hr = Installer_OpenPackage(szPath, 0, &pSession);
2515 if (hr == DISP_E_EXCEPTION)
2516 {
2517 skip("OpenPackage failed, insufficient rights?\n");
2519 return;
2520 }
2521 ok(hr == S_OK, "Installer_OpenPackage failed, hresult %#lx\n", hr);
2522 if (hr == S_OK)
2523 {
2524 test_Session(pSession);
2525 IDispatch_Release(pSession);
2526 }
2527
2528 /* Installer::OpenDatabase */
2530 ok(hr == S_OK, "Installer_OpenDatabase failed, hresult %#lx\n", hr);
2531 if (hr == S_OK)
2532 {
2533 test_Database(pDatabase, FALSE);
2534 IDispatch_Release(pDatabase);
2535 }
2536
2537 /* Installer::SummaryInformation */
2538 hr = Installer_SummaryInformation(szPath, 0, &pSumInfo);
2539 ok(hr == S_OK, "Installer_SummaryInformation failed, hresult %#lx\n", hr);
2540 if (hr == S_OK)
2541 {
2543 IDispatch_Release(pSumInfo);
2544 }
2545
2546 hr = Installer_SummaryInformation(NULL, 0, &pSumInfo);
2547 ok(hr == DISP_E_EXCEPTION, "Installer_SummaryInformation failed, hresult %#lx\n", hr);
2548
2549 /* Installer::RegistryValue */
2551
2552 /* Installer::ProductState for our product code, which should not be installed */
2553 hr = Installer_ProductState(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", &iValue);
2554 ok(hr == S_OK, "Installer_ProductState failed, hresult %#lx\n", hr);
2555 ok(iValue == INSTALLSTATE_UNKNOWN, "Installer_ProductState returned %d, expected %d\n", iValue, INSTALLSTATE_UNKNOWN);
2556
2557 /* Installer::ProductInfo for our product code, which should not be installed */
2558
2559 /* Package name */
2560 memset(szPath, 0, sizeof(szPath));
2561 hr = Installer_ProductInfo(L"{837450fa-a39b-4bc8-b321-08b393f784b3}", L"PackageName", szPath);
2562 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2563 ok_exception(hr, L"ProductInfo,Product,Attribute");
2564
2565 /* NULL attribute and NULL product code */
2566 memset(szPath, 0, sizeof(szPath));
2568 ok(hr == DISP_E_EXCEPTION, "Installer_ProductInfo failed, hresult %#lx\n", hr);
2569 ok_exception(hr, L"ProductInfo,Product,Attribute");
2570
2571 /* Installer::Products */
2573
2574 /* Installer::RelatedProducts for our upgrade code, should not find anything */
2575 hr = Installer_RelatedProducts(L"{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}", &pStringList);
2576 ok(hr == S_OK, "Installer_RelatedProducts failed, hresult %#lx\n", hr);
2577 if (hr == S_OK)
2578 {
2579 /* StringList::Count */
2580 hr = StringList_Count(pStringList, &iCount);
2581 ok(hr == S_OK, "StringList_Count failed, hresult %#lx\n", hr);
2582 ok(!iCount, "Expected no related products but found %d\n", iCount);
2583
2584 IDispatch_Release(pStringList);
2585 }
2586
2587 /* Installer::Version */
2588 memset(szPath, 0, sizeof(szPath));
2590 ok(hr == S_OK, "Installer_VersionGet failed, hresult %#lx\n", hr);
2591
2592 /* Installer::InstallProduct and other tests that depend on our product being installed */
2595}
2596
2597START_TEST(automation)
2598{
2599 DWORD len;
2600 char temp_path[MAX_PATH], prev_path[MAX_PATH];
2601 HRESULT hr;
2602 CLSID clsid;
2603 IUnknown *pUnk;
2604
2606
2608
2610
2611 GetCurrentDirectoryA(MAX_PATH, prev_path);
2614
2617
2618 if(len && (CURR_DIR[len - 1] == '\\'))
2619 CURR_DIR[len - 1] = 0;
2620
2622
2624 ok (hr == S_OK, "OleInitialize returned %#lx\n", hr);
2625 hr = CLSIDFromProgID(L"WindowsInstaller.Installer", &clsid);
2626 ok (hr == S_OK, "CLSIDFromProgID returned %#lx\n", hr);
2627 hr = CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&pUnk);
2628 ok(hr == S_OK, "CoCreateInstance returned %#lx\n", hr);
2629
2630 if (pUnk)
2631 {
2632 hr = IUnknown_QueryInterface(pUnk, &IID_IDispatch, (void **)&pInstaller);
2633 ok (hr == S_OK, "IUnknown::QueryInterface returned %#lx\n", hr);
2634
2635 test_dispid();
2636 test_dispatch();
2638
2639 IDispatch_Release(pInstaller);
2640 IUnknown_Release(pUnk);
2641 }
2642
2644 SetCurrentDirectoryA(prev_path);
2645}
static char CURR_DIR[MAX_PATH]
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ok(value,...)
Definition: atltest.h:57
#define skip(...)
Definition: atltest.h:64
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
static const WCHAR nameW[]
Definition: main.c:49
#define ARRAY_SIZE(A)
Definition: main.h:20
const GUID IID_IUnknown
HANDLE HKEY
Definition: registry.h:26
#define RegCloseKey(hKey)
Definition: registry.h:49
const char ** registry
Definition: cffdrivr.c:690
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define E_FAIL
Definition: ddrawi.h:102
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3298
LONG WINAPI RegDeleteKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1254
LONG WINAPI RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
Definition: reg.c:3583
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3234
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3268
LONG WINAPI RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cbName)
Definition: reg.c:2368
LONG WINAPI RegSetValueExW(_In_ HKEY hKey, _In_ LPCWSTR lpValueName, _In_ DWORD Reserved, _In_ DWORD dwType, _In_ CONST BYTE *lpData, _In_ DWORD cbData)
Definition: reg.c:4882
LONG WINAPI RegQueryValueExA(_In_ HKEY hkeyorg, _In_ LPCSTR name, _In_ LPDWORD reserved, _Out_opt_ LPDWORD type, _Out_opt_ LPBYTE data, _Inout_opt_ LPDWORD count)
Definition: reg.c:4009
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1201
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1224
#define CloseHandle
Definition: compat.h:739
double DATE
Definition: compat.h:2253
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
#define CP_ACP
Definition: compat.h:109
#define SetLastError(x)
Definition: compat.h:752
WCHAR OLECHAR
Definition: compat.h:2292
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:740
OLECHAR * BSTR
Definition: compat.h:2293
#define GetCurrentProcess()
Definition: compat.h:759
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
#define IsWow64Process
Definition: compat.h:760
#define MAX_PATH
Definition: compat.h:34
unsigned short VARTYPE
Definition: compat.h:2254
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
#define lstrcpyW
Definition: compat.h:749
#define WideCharToMultiByte
Definition: compat.h:111
short VARIANT_BOOL
Definition: compat.h:2290
#define MultiByteToWideChar
Definition: compat.h:110
@ VT_BSTR
Definition: compat.h:2303
@ VT_LPSTR
Definition: compat.h:2324
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_I4
Definition: compat.h:2298
@ VT_FILETIME
Definition: compat.h:2329
@ VT_DATE
Definition: compat.h:2302
@ VT_BOOL
Definition: compat.h:2306
@ VT_I2
Definition: compat.h:2297
@ VT_EMPTY
Definition: compat.h:2295
@ VT_DISPATCH
Definition: compat.h:2304
#define lstrlenW
Definition: compat.h:750
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:221
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4242
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4194
UINT WINAPI MsiDatabaseImportA(MSIHANDLE handle, const char *szFolder, const char *szFilename)
Definition: database.c:863
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, const char *szValue)
Definition: suminfo.c:942
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, const char *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:589
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE handle)
Definition: suminfo.c:1227
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
Definition: compobj.c:2602
HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
Definition: ole2.c:169
void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
Definition: ole2.c:230
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
static BOOL is_process_elevated(void)
Definition: dplayx.c:6742
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
FxChildList * pList
PWCHAR pValue
GLint level
Definition: gl.h:1546
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLsizeiptr size
Definition: glext.h:5919
GLuint res
Definition: glext.h:9613
GLenum mode
Definition: glext.h:6217
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLuint id
Definition: glext.h:5910
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
const char * filename
Definition: ioapi.h:137
uint32_t entry
Definition: isohybrid.c:63
#define d
Definition: ke_i.h:81
#define GUID_NULL
Definition: ks.h:106
#define REG_SZ
Definition: layer.c:22
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
__u8 media
Definition: mkdosfs.c:9
#define CREATE_ALWAYS
Definition: disk.h:72
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
LPCWSTR szPath
Definition: env.c:37
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static PVOID ptr
Definition: dispmode.c:27
const char * var
Definition: shader.c:5666
#define create_file(name, size)
Definition: asmcache.c:813
static LPCWSTR szVersion
Definition: asmcache.c:748
void restart_as_admin_elevated(void)
Definition: action.c:6478
static HRESULT SummaryInfo_PropertyGet(IDispatch *pSummaryInfo, int pid, VARIANT *pVarResult, VARTYPE vtExpect)
Definition: automation.c:1435
static const CHAR registry_dat[]
Definition: automation.c:148
static const CHAR property_dat[]
Definition: automation.c:129
static HRESULT View_Execute(IDispatch *pView, IDispatch *pRecord)
Definition: automation.c:1274
static void test_Installer_Products(BOOL bProductInstalled)
Definition: automation.c:2067
static CHAR string2[MAX_PATH]
Definition: automation.c:345
static HRESULT View_Fetch(IDispatch *pView, IDispatch **ppRecord)
Definition: automation.c:1287
static HRESULT Installer_CreateRecord(int count, IDispatch **pRecord)
Definition: automation.c:778
static HRESULT Session_DoAction(IDispatch *pSession, LPCWSTR szAction, int *iReturn)
Definition: automation.c:1123
static HRESULT Record_IntegerDataGet(IDispatch *pRecord, int iField, int *pValue)
Definition: automation.c:1365
#define TEST_SUMMARYINFO_PROPERTIES_MODIFIED
Definition: automation.c:1476
static const CHAR directory_dat[]
Definition: automation.c:67
static HRESULT Session_Database(IDispatch *pSession, IDispatch **pDatabase)
Definition: automation.c:1112
static HRESULT StringList_Count(IDispatch *pStringList, int *pCount)
Definition: automation.c:1425
static void delete_test_files(void)
Definition: automation.c:325
static HRESULT Session_LanguageGet(IDispatch *pSession, UINT *pLangId)
Definition: automation.c:1066
static const msi_summary_info summary_info[]
Definition: automation.c:185
static HRESULT Installer_VersionGet(LPWSTR szVersion)
Definition: automation.c:976
#define ADD_INFO_FILETIME(property, pftValue)
Definition: automation.c:183
static HRESULT Installer_SummaryInformation(BSTR PackagePath, int UpdateCount, IDispatch **pSumInfo)
Definition: automation.c:1002
static const CHAR file_dat[]
Definition: automation.c:98
static HRESULT Installer_ProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szString)
Definition: automation.c:929
static void test_Database(IDispatch *pDatabase, BOOL readonly)
Definition: automation.c:1619
static HRESULT Record_StringDataGet(IDispatch *pRecord, int iField, LPWSTR szString)
Definition: automation.c:1331
static HRESULT StringList__NewEnum(IDispatch *pList, IUnknown **ppEnumVARIANT)
Definition: automation.c:1399
static HRESULT Session_PropertyGet(IDispatch *pSession, LPCWSTR szName, LPWSTR szReturn)
Definition: automation.c:1032
static HRESULT Session_EvaluateCondition(IDispatch *pSession, LPCWSTR szCondition, int *iReturn)
Definition: automation.c:1140
static HRESULT Session_SetInstallLevel(IDispatch *pSession, LONG iInstallLevel)
Definition: automation.c:1178
static void test_Installer(void)
Definition: automation.c:2457
static void test_Installer_RegistryValue(void)
Definition: automation.c:1914
static void test_Session(IDispatch *pSession)
Definition: automation.c:1727
static const CHAR install_exec_seq_dat[]
Definition: automation.c:108
static HRESULT Installer_OpenPackage(LPCWSTR szPackagePath, int options, IDispatch **pSession)
Definition: automation.c:858
static FILETIME systemtime
Definition: automation.c:46
static HRESULT Database_OpenView(IDispatch *pDatabase, LPCWSTR szSql, IDispatch **pView)
Definition: automation.c:1242
static void create_database_suminfo(const CHAR *name, const msi_table *tables, int num_tables, const msi_summary_info *info, int num_info)
Definition: automation.c:235
#define ok_w2n(format, szString1, szString2, len)
Definition: automation.c:356
static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, VARTYPE vtResult)
Definition: automation.c:736
#define ok_w2(format, szString1, szString2)
Definition: automation.c:347
static void test_Installer_InstallProduct(void)
Definition: automation.c:2278
static HRESULT Record_StringDataPut(IDispatch *pRecord, int iField, LPCWSTR szString)
Definition: automation.c:1348
static HRESULT Installer_ProductState(LPCWSTR szProduct, int *pInstallState)
Definition: automation.c:912
static BOOL is_wow64
Definition: automation.c:41
static HRESULT Record_IntegerDataPut(IDispatch *pRecord, int iField, int iValue)
Definition: automation.c:1382
static HRESULT StringList_Item(IDispatch *pStringList, int iIndex, LPWSTR szString)
Definition: automation.c:1408
static HRESULT Session_ModePut(IDispatch *pSession, int iFlag, VARIANT_BOOL mode)
Definition: automation.c:1095
static void create_test_files(void)
Definition: automation.c:310
static UINT find_registry_key(HKEY hkeyParent, LPCSTR subkey, LPCSTR findkey, REGSAM access, HKEY *phkey)
Definition: automation.c:2245
static HRESULT View_Modify(IDispatch *pView, int iMode, IDispatch *pRecord)
Definition: automation.c:1296
static HRESULT Installer_Products(IDispatch **pStringList)
Definition: automation.c:949
static HRESULT SummaryInfo_PropertyCountGet(IDispatch *pSummaryInfo, int *pCount)
Definition: automation.c:1462
static HRESULT Installer_RegistryValueE(HKEY hkey, LPCWSTR szKey, BOOL *pBool)
Definition: automation.c:812
static void test_SummaryInfo(IDispatch *pSummaryInfo, const msi_summary_info *info, int num_info, BOOL readonly)
Definition: automation.c:1478
struct _msi_summary_info msi_summary_info
static const CHAR feature_dat[]
Definition: automation.c:78
static const char * msifile
Definition: automation.c:45
static CHAR string1[MAX_PATH]
Definition: automation.c:345
static const msi_table tables[]
Definition: automation.c:158
static EXCEPINFO excepinfo
Definition: automation.c:47
static HRESULT Database_SummaryInformation(IDispatch *pDatabase, int iUpdateCount, IDispatch **pSummaryInfo)
Definition: automation.c:1258
#define ok_exception(hr, szDescription)
Definition: automation.c:378
static void test_dispatch(void)
Definition: automation.c:513
#define ok_awplus(format, extra, aString, wString)
Definition: automation.c:371
static HRESULT Installer_RegistryValue(HKEY hkey, LPCWSTR szKey, VARIANT vValue, VARIANT *pVarResult, VARTYPE vtExpect)
Definition: automation.c:794
static HRESULT View_Close(IDispatch *pView)
Definition: automation.c:1314
static HRESULT Session_FeatureRequestStateGet(IDispatch *pSession, LPCWSTR szName, int *pState)
Definition: automation.c:1208
static HRESULT SummaryInfo_PropertyPut(IDispatch *pSummaryInfo, int pid, VARIANT *pVariant)
Definition: automation.c:1446
static const get_did_t get_did_data[]
Definition: automation.c:424
static UINT delete_registry_key(HKEY hkeyParent, LPCSTR subkey, REGSAM access)
Definition: automation.c:2222
static int _invoke_todo_vtResult
Definition: automation.c:734
static HRESULT Installer_UILevelPut(int level)
Definition: automation.c:988
static HRESULT Installer_RegistryValueI(HKEY hkey, LPCWSTR szKey, int iValue, LPWSTR szString, VARTYPE vtResult)
Definition: automation.c:842
static const CHAR component_dat[]
Definition: automation.c:56
static const CHAR media_dat[]
Definition: automation.c:124
static DISPID get_dispid(IDispatch *disp, const char *name)
Definition: automation.c:397
static HRESULT Installer_RegistryValueW(HKEY hkey, LPCWSTR szKey, LPCWSTR szValue, LPWSTR szString)
Definition: automation.c:826
static BOOL create_package(LPWSTR path)
Definition: automation.c:272
static HRESULT Session_Installer(IDispatch *pSession, IDispatch **pInst)
Definition: automation.c:1021
static HRESULT Installer_RelatedProducts(LPCWSTR szProduct, IDispatch **pStringList)
Definition: automation.c:960
#define ADD_TABLE(x)
Definition: automation.c:156
#define ADD_INFO_I4(property, iValue)
Definition: automation.c:181
static HRESULT Installer_InstallProduct(LPCWSTR szPackagePath, LPCWSTR szPropertyValues)
Definition: automation.c:896
static void test_dispid(void)
Definition: automation.c:475
static HRESULT Session_FeatureRequestStatePut(IDispatch *pSession, LPCWSTR szName, int iState)
Definition: automation.c:1225
static HRESULT Session_PropertyPut(IDispatch *pSession, LPCWSTR szName, LPCWSTR szValue)
Definition: automation.c:1049
static void write_msi_summary_info(MSIHANDLE db, const msi_summary_info *info, int num_info)
Definition: automation.c:209
static const CHAR feature_comp_dat[]
Definition: automation.c:88
static HRESULT Session_ModeGet(IDispatch *pSession, int iFlag, VARIANT_BOOL *mode)
Definition: automation.c:1078
static HRESULT Record_FieldCountGet(IDispatch *pRecord, int *pFieldCount)
Definition: automation.c:1321
#define ADD_INFO_LPSTR(property, szValue)
Definition: automation.c:182
static void write_file(const CHAR *filename, const char *data, int data_size)
Definition: automation.c:199
static IDispatch * pInstaller
Definition: automation.c:52
static HRESULT Session_FeatureCurrentState(IDispatch *pSession, LPCWSTR szName, int *pState)
Definition: automation.c:1191
static HRESULT Installer_OpenDatabase(LPCWSTR szDatabasePath, int openmode, IDispatch **pDatabase)
Definition: automation.c:877
static HRESULT Session_Message(IDispatch *pSession, LONG kind, IDispatch *record, int *ret)
Definition: automation.c:1157
static BOOL get_program_files_dir(LPSTR buf)
Definition: automation.c:293
#define todo_wine_if(is_todo)
Definition: custom.c:86
#define todo_wine
Definition: custom.c:89
BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
Definition: install.c:2433
char PROG_FILES_DIR[MAX_PATH]
Definition: install.c:50
#define PID_TEMPLATE
Definition: suminfo.c:49
#define PID_CHARCOUNT
Definition: suminfo.c:58
#define PID_PAGECOUNT
Definition: suminfo.c:56
#define PID_THUMBNAIL
Definition: suminfo.c:59
#define PID_WORDCOUNT
Definition: suminfo.c:57
#define PID_DICTIONARY
Definition: suminfo.c:42
#define PID_TITLE
Definition: suminfo.c:44
#define PID_REVNUMBER
Definition: suminfo.c:51
#define PID_LASTPRINTED
Definition: suminfo.c:53
#define PID_CREATE_DTM
Definition: suminfo.c:54
#define PID_CODEPAGE
Definition: suminfo.c:43
#define PID_LASTSAVE_DTM
Definition: suminfo.c:55
static const WCHAR szAttribute[]
Definition: domdoc.c:1179
static LPOLESTR
Definition: stg_prop.c:27
static VARIANTARG static DISPID
Definition: ordinal.c:52
INTERNETFEATURELIST feature
Definition: misc.c:1719
REFCLSID clsid
Definition: msctf.c:82
@ INSTALLMESSAGE_INFO
Definition: msi.h:98
@ INSTALLSTATE_UNKNOWN
Definition: msi.h:42
@ INSTALLSTATE_DEFAULT
Definition: msi.h:48
@ INSTALLSTATE_ADVERTISED
Definition: msi.h:44
@ INSTALLLEVEL_MINIMUM
Definition: msi.h:88
@ INSTALLUILEVEL_NONE
Definition: msi.h:66
#define PID_EDITTIME
Definition: msidefs.h:272
UINT WINAPI MsiDatabaseCommit(MSIHANDLE hdb)
Definition: msiquery.c:962
@ MSIMODIFY_REFRESH
Definition: msiquery.h:51
#define MSIDBOPEN_CREATE
Definition: msiquery.h:69
@ MSICONDITION_FALSE
Definition: msiquery.h:26
@ MSICONDITION_ERROR
Definition: msiquery.h:29
@ MSICONDITION_NONE
Definition: msiquery.h:28
@ MSICONDITION_TRUE
Definition: msiquery.h:27
#define MSIDBOPEN_TRANSACT
Definition: msiquery.h:67
#define MSI_NULL_INTEGER
Definition: msiquery.h:32
@ MSIRUNMODE_MAINTENANCE
Definition: msiquery.h:85
@ MSIRUNMODE_REBOOTATEND
Definition: msiquery.h:89
@ MSIRUNMODE_REBOOTNOW
Definition: msiquery.h:90
char temp_path[MAX_PATH]
Definition: mspatcha.c:123
unsigned int UINT
Definition: ndis.h:50
#define bool
Definition: nsiface.idl:72
#define REG_BINARY
Definition: nt_native.h:1496
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define REG_NONE
Definition: nt_native.h:1492
#define GENERIC_WRITE
Definition: nt_native.h:90
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
#define LOCALE_NEUTRAL
#define LOCALE_USER_DEFAULT
#define L(x)
Definition: ntvdm.h:50
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
#define V_BOOL(A)
Definition: oleauto.h:224
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define DISPATCH_PROPERTYPUT
Definition: oleauto.h:1008
#define DISPATCH_METHOD
Definition: oleauto.h:1006
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define V_I4(A)
Definition: oleauto.h:247
#define V_DISPATCH(A)
Definition: oleauto.h:239
#define DISPATCH_PROPERTYGET
Definition: oleauto.h:1007
#define V_DATE(A)
Definition: oleauto.h:231
#define V_I2(A)
Definition: oleauto.h:245
const GUID IID_IDispatch
long LONG
Definition: pedump.c:60
static const WCHAR szName[]
Definition: powrprof.c:45
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
#define IID_NULL
Definition: guiddef.h:98
#define delete_key(r, p, s)
Definition: reg_test.h:64
const WCHAR * str
#define REG_QWORD
Definition: sdbapi.c:597
#define REG_DWORD
Definition: sdbapi.c:596
#define win_skip
Definition: test.h:163
#define memset(x, y, z)
Definition: compat.h:39
HRESULT hr
Definition: shlfolder.c:183
FILETIME * pftValue
Definition: automation.c:176
const CHAR * szValue
Definition: automation.c:177
Definition: fci.c:127
DISPID did
Definition: automation.c:419
const char * name
Definition: automation.c:420
BOOL todo
Definition: automation.c:421
Definition: name.c:39
BYTE * data
int32_t INT_PTR
Definition: typedefs.h:64
unsigned char * LPBYTE
Definition: typedefs.h:53
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:988
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
Definition: variant.c:1286
HRESULT WINAPI VariantCopyInd(VARIANT *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:847
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
int ret
static char * stringw(char *buf, char *end, const wchar_t *sw, int len, int field_width, int precision, int flags)
Definition: sprintf.c:335
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
_In_ ULONG iMode
Definition: winddi.h:3520
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
unsigned long MSIHANDLE
Definition: winemsi.idl:27
#define S_FALSE
Definition: winerror.h:2357
#define DISP_E_MEMBERNOTFOUND
Definition: winerror.h:2512
#define DISP_E_EXCEPTION
Definition: winerror.h:2518
#define DISP_E_BADINDEX
Definition: winerror.h:2520
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:2514
#define DISP_E_UNKNOWNNAME
Definition: winerror.h:2515
#define MB_PRECOMPOSED
Definition: winnls.h:281
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define HKEY_CURRENT_USER
Definition: winreg.h:11
ACCESS_MASK REGSAM
Definition: winreg.h:69
#define IDOK
Definition: winuser.h:833
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
char CHAR
Definition: xmlstorage.h:175
unsigned char BYTE
Definition: xxhash.c:193