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