ReactOS  0.4.15-dev-4614-ga5a6101
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 
40 static BOOL is_wow64;
41 
42 static LONG (WINAPI *pRegDeleteKeyExA)(HKEY, LPCSTR, REGSAM, DWORD);
43 static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
44 
45 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
46 
47 static const char *msifile = "winetest-automation.msi";
51 
52 /*
53  * OLE automation data
54  **/
56 
57 /* msi database data */
58 
59 static 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 
70 static 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 
81 static 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 
91 static 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 
101 static 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 
111 static 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 
127 static 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 
132 static 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 
151 static 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 
159 typedef struct _msi_table
160 {
161  const CHAR *filename;
162  const CHAR *data;
163  int size;
164 } msi_table;
165 
166 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
167 
168 static const msi_table tables[] =
169 {
170  ADD_TABLE(component),
173  ADD_TABLE(feature_comp),
174  ADD_TABLE(file),
175  ADD_TABLE(install_exec_seq),
176  ADD_TABLE(media),
179 };
180 
181 typedef 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 {
197  ADD_INFO_LPSTR(PID_TEMPLATE, ";1033"),
198  ADD_INFO_LPSTR(PID_REVNUMBER, "{004757CA-5092-49C2-AD20-28E1CE0DF5F2}"),
203 };
204 
205 static 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;
226  HANDLE token;
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 
268 static 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 
278 static 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 
304 static 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;
314  MultiByteToWideChar( CP_ACP, 0, name, -1, nameW, len );
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 
381 static 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 
396  CloseHandle(file);
397 }
398 
399 static 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 
414 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
415 {
416  CHAR path[MAX_PATH];
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 
428 static 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 
501 static DISPID get_dispid( IDispatch *disp, const char *name )
502 {
503  LPOLESTR str;
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  {
512  MultiByteToWideChar(CP_ACP, 0, name, -1, str, len );
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 
522 typedef struct {
524  const char *name;
526 } get_did_t;
527 
528 static 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 
579 static 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 */
617 static 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");
748  DeleteFileW(path);
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 
810  DeleteFileW(path);
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 */
838 static int _invoke_todo_vtResult = 0;
839 
840 static 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 
898 static 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 
916 static HRESULT Installer_RegistryValueE(HKEY hkey, LPCWSTR szKey, BOOL *pBool)
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 
930 static 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 
946 static 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 
962 static 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 
981 static 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 
1000 static 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 
1016 static 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 
1053 static HRESULT Installer_Products(IDispatch **pStringList)
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 
1064 static 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 
1106 static 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 
1125 static HRESULT Session_Installer(IDispatch *pSession, IDispatch **pInst)
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 
1170 static 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 
1182 static 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 
1199 static HRESULT Session_ModePut(IDispatch *pSession, int iFlag, VARIANT_BOOL mode)
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 
1216 static 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 
1227 static 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 
1244 static 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 
1261 static HRESULT Session_Message(IDispatch *pSession, LONG kind, IDispatch *record, int *ret)
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 
1282 static 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 
1346 static 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 
1362 static 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 
1378 static 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 
1391 static 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 
1400 static 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 
1425 static 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 
1435 static 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 
1452 static 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 
1469 static 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 
1486 static 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 
1512 static 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 
1529 static 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 
1539 static 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 
1550 static 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 
1566 static 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 
1582 static 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);
1618  SystemTimeToVariantTime(&st, &d);
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;
1695  hr = SummaryInfo_PropertyPut(pSummaryInfo, PID_LASTSAVE_DTM, &var);
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 
1723 static 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 
1775  hr = View_Modify(pView, MSIMODIFY_REFRESH, NULL);
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 
1831 static 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 */
1998 static 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 
2171 static 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) */
2326 static UINT delete_registry_key(HKEY hkeyParent, LPCSTR subkey, REGSAM access)
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. */
2349 static 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;
2385  CHAR path[MAX_PATH];
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}",
2526  KEY_WOW64_32KEY);
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 
2561 static 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 
2700 START_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 
2720  len = lstrlenA(CURR_DIR);
2721 
2722  if(len && (CURR_DIR[len - 1] == '\\'))
2723  CURR_DIR[len - 1] = 0;
2724 
2726 
2727  hr = OleInitialize(NULL);
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();
2741  test_Installer();
2742 
2743  IDispatch_Release(pInstaller);
2744  IUnknown_Release(pUnk);
2745  }
2746 
2747  OleUninitialize();
2748 
2749  SetCurrentDirectoryA(prev_path);
2750 }
const char * var
Definition: shader.c:5666
static void delete_test_files(void)
Definition: automation.c:428
static HRESULT SummaryInfo_PropertyCountGet(IDispatch *pSummaryInfo, int *pCount)
Definition: automation.c:1566
#define DISP_E_EXCEPTION
Definition: winerror.h:2518
#define PID_TEMPLATE
Definition: suminfo.c:49
static HRESULT Session_SetInstallLevel(IDispatch *pSession, LONG iInstallLevel)
Definition: automation.c:1282
static const CHAR media_dat[]
Definition: automation.c:127
#define DISP_E_UNKNOWNNAME
Definition: winerror.h:2515
WCHAR OLECHAR
Definition: compat.h:2151
INTERNETFEATURELIST feature
Definition: misc.c:1719
LONG WINAPI RegOpenKeyA(HKEY hKey, LPCSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3257
static const CHAR registry_dat[]
Definition: automation.c:151
BOOL WINAPI WriteFile(IN HANDLE hFile, IN LPCVOID lpBuffer, IN DWORD nNumberOfBytesToWrite OPTIONAL, OUT LPDWORD lpNumberOfBytesWritten, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: rw.c:24
static HRESULT Session_PropertyPut(IDispatch *pSession, LPCWSTR szName, LPCWSTR szValue)
Definition: automation.c:1153
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:4027
static const CHAR directory_dat[]
Definition: automation.c:70
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3835
GLint level
Definition: gl.h:1546
static const WCHAR szName[]
Definition: powrprof.c:45
VOID WINAPI GetSystemTimeAsFileTime(OUT PFILETIME lpFileTime)
Definition: time.c:128
static const CHAR install_exec_seq_dat[]
Definition: automation.c:111
enum _TOKEN_ELEVATION_TYPE TOKEN_ELEVATION_TYPE
#define IDOK
Definition: winuser.h:824
static const msi_summary_info summary_info[]
Definition: automation.c:195
#define CloseHandle
Definition: compat.h:598
Definition: compat.h:2157
static void test_Installer_Products(BOOL bProductInstalled)
Definition: automation.c:2171
#define DISPATCH_PROPERTYGET
Definition: oleauto.h:1007
#define PID_CHARCOUNT
Definition: suminfo.c:58
static HRESULT Session_EvaluateCondition(IDispatch *pSession, LPCWSTR szCondition, int *iReturn)
Definition: automation.c:1244
const CHAR * szValue
Definition: automation.c:187
static HRESULT Session_Installer(IDispatch *pSession, IDispatch **pInst)
Definition: automation.c:1125
#define ERROR_SUCCESS
Definition: deptool.c:10
static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
Definition: automation.c:414
#define WideCharToMultiByte
Definition: compat.h:111
static BOOL get_program_files_dir(LPSTR buf)
Definition: automation.c:364
HRESULT hr
Definition: shlfolder.c:183
static void write_file(const CHAR *filename, const char *data, int data_size)
Definition: automation.c:268
_In_ ULONG iMode
Definition: winddi.h:3520
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
LONG WINAPI RegDeleteKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ REGSAM samDesired, _In_ DWORD Reserved)
Definition: reg.c:1252
struct _msi_summary_info msi_summary_info
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define REG_BINARY
Definition: nt_native.h:1496
static HRESULT Record_StringDataPut(IDispatch *pRecord, int iField, LPCWSTR szString)
Definition: automation.c:1452
#define TRUE
Definition: types.h:120
static HRESULT View_Modify(IDispatch *pView, int iMode, IDispatch *pRecord)
Definition: automation.c:1400
static HRESULT SummaryInfo_PropertyGet(IDispatch *pSummaryInfo, int pid, VARIANT *pVarResult, VARTYPE vtExpect)
Definition: automation.c:1539
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:3611
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
static char PROG_FILES_DIR[MAX_PATH]
Definition: automation.c:362
#define CP_ACP
Definition: compat.h:109
#define LOCALE_USER_DEFAULT
int WINAPI lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:170
static DWORD delete_key(HKEY hkey)
Definition: automation.c:1998
#define HKEY_CURRENT_USER
Definition: winreg.h:11
static HRESULT Session_PropertyGet(IDispatch *pSession, LPCWSTR szName, LPWSTR szReturn)
Definition: automation.c:1136
_In_opt_ PSID Group
Definition: rtlfuncs.h:1605
GLuint GLuint GLsizei count
Definition: gl.h:1545
PWCHAR pValue
static CHAR string2[MAX_PATH]
Definition: automation.c:449
char CHAR
Definition: xmlstorage.h:175
#define free
Definition: debug_ros.c:5
#define FILE_CURRENT
Definition: winbase.h:113
BOOL WINAPI SetEndOfFile(HANDLE hFile)
Definition: fileinfo.c:1004
static CHAR string1[MAX_PATH]
Definition: automation.c:449
static HRESULT View_Close(IDispatch *pView)
Definition: automation.c:1418
#define MB_PRECOMPOSED
Definition: winnls.h:281
#define V_I2(A)
Definition: oleauto.h:245
#define DISP_E_MEMBERNOTFOUND
Definition: winerror.h:2512
static CHAR CURR_DIR[MAX_PATH]
Definition: automation.c:49
static HRESULT View_Execute(IDispatch *pView, IDispatch *pRecord)
Definition: automation.c:1378
static HINSTANCE hkernel32
Definition: process.c:66
struct _msi_table msi_table
HRESULT WINAPI VariantCopyInd(VARIANT *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:847
static HRESULT Database_SummaryInformation(IDispatch *pDatabase, int iUpdateCount, IDispatch **pSummaryInfo)
Definition: automation.c:1362
double DATE
Definition: compat.h:2112
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3321
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define INVALID_HANDLE_VALUE
Definition: compat.h:590
int WINAPI lstrcmpA(LPCSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:18
#define todo_wine
Definition: custom.c:79
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
static HRESULT Installer_RelatedProducts(LPCWSTR szProduct, IDispatch **pStringList)
Definition: automation.c:1064
BOOL todo
Definition: automation.c:525
BOOL WINAPI CheckTokenMembership(IN HANDLE ExistingTokenHandle, IN PSID SidToCheck, OUT PBOOL IsMember)
Definition: token.c:21
#define MSI_NULL_INTEGER
Definition: msiquery.h:32
static void test_Installer_RegistryValue(void)
Definition: automation.c:2018
static BOOL create_package(LPWSTR path)
Definition: automation.c:341
static void init_functionpointers(void)
Definition: automation.c:205
OLECHAR * BSTR
Definition: compat.h:2152
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
const CHAR * data
Definition: automation.c:162
int32_t INT_PTR
Definition: typedefs.h:64
#define PID_REVNUMBER
Definition: suminfo.c:51
static HRESULT StringList_Count(IDispatch *pStringList, int *pCount)
Definition: automation.c:1529
static LONG(WINAPI *pRegDeleteKeyExA)(HKEY
char * LPSTR
Definition: xmlstorage.h:182
const char * filename
Definition: ioapi.h:135
static const WCHAR szAttribute[]
Definition: domdoc.c:1179
static LPOLESTR
Definition: stg_prop.c:27
BOOL WINAPI FileTimeToLocalFileTime(IN CONST FILETIME *lpFileTime, OUT LPFILETIME lpLocalFileTime)
Definition: time.c:221
#define lstrlenW
Definition: compat.h:609
#define E_FAIL
Definition: ddrawi.h:102
static HRESULT Record_FieldCountGet(IDispatch *pRecord, int *pFieldCount)
Definition: automation.c:1425
HRESULT WINAPI DECLSPEC_HOTPATCH CLSIDFromProgID(LPCOLESTR progid, LPCLSID clsid)
Definition: compobj.c:2602
int32_t INT
Definition: typedefs.h:58
short VARIANT_BOOL
Definition: compat.h:2149
#define PID_CODEPAGE
Definition: suminfo.c:43
static DWORD
Definition: automation.c:42
#define PID_LASTPRINTED
Definition: suminfo.c:53
#define V_I4(A)
Definition: oleauto.h:247
#define DISPATCH_METHOD
Definition: oleauto.h:1006
static HRESULT Session_FeatureRequestStateGet(IDispatch *pSession, LPCWSTR szName, int *pState)
Definition: automation.c:1312
#define V_DISPATCH(A)
Definition: oleauto.h:239
static const CHAR file_dat[]
Definition: automation.c:101
static HRESULT Session_ModeGet(IDispatch *pSession, int iFlag, VARIANT_BOOL *mode)
Definition: automation.c:1182
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
static void test_Installer(void)
Definition: automation.c:2561
#define ok_exception(hr, szDescription)
Definition: automation.c:482
#define L(x)
Definition: ntvdm.h:50
unsigned char * LPBYTE
Definition: typedefs.h:53
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
long LONG
Definition: pedump.c:60
static BOOL is_process_limited(void)
Definition: automation.c:221
#define PID_LASTSAVE_DTM
Definition: suminfo.c:55
static HRESULT Session_FeatureRequestStatePut(IDispatch *pSession, LPCWSTR szName, int iState)
Definition: automation.c:1329
FxChildList * pList
PVOID WINAPI FreeSid(PSID pSid)
Definition: security.c:700
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
LONG WINAPI RegOpenKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:3291
if SUCCEEDED(hr)
#define REG_MULTI_SZ
Definition: nt_native.h:1501
#define GENERIC_WRITE
Definition: nt_native.h:90
unsigned long MSIHANDLE
Definition: winemsi.idl:24
static UINT find_registry_key(HKEY hkeyParent, LPCSTR subkey, LPCSTR findkey, REGSAM access, HKEY *phkey)
Definition: automation.c:2349
static const CHAR component_dat[]
Definition: automation.c:59
static HRESULT Installer_OpenPackage(LPCWSTR szPackagePath, int options, IDispatch **pSession)
Definition: automation.c:962
static PVOID ptr
Definition: dispmode.c:27
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
unsigned int idx
Definition: utils.c:41
#define S_FALSE
Definition: winerror.h:2357
static const CHAR property_dat[]
Definition: automation.c:132
const WCHAR * str
START_TEST(automation)
Definition: automation.c:2700
#define GET_PROC(dll, func)
BOOL WINAPI CreateDirectoryA(IN LPCSTR lpPathName, IN LPSECURITY_ATTRIBUTES lpSecurityAttributes)
Definition: dir.c:37
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
static FILETIME systemtime
Definition: automation.c:48
static HRESULT Installer_ProductInfo(LPCWSTR szProduct, LPCWSTR szAttribute, LPWSTR szString)
Definition: automation.c:1033
BOOL WINAPI DeleteFileA(IN LPCSTR lpFileName)
Definition: delete.c:24
static BOOL(WINAPI *pIsWow64Process)(HANDLE
const char ** registry
Definition: cffdrivr.c:690
#define ADD_INFO_FILETIME(property, pftValue)
Definition: automation.c:193
const char * LPCSTR
Definition: xmlstorage.h:183
static const msi_table tables[]
Definition: automation.c:168
static void test_Installer_InstallProduct(void)
Definition: automation.c:2382
#define DISPATCH_PROPERTYPUT
Definition: oleauto.h:1008
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
int options
Definition: main.c:106
static HRESULT Record_StringDataGet(IDispatch *pRecord, int iField, LPWSTR szString)
Definition: automation.c:1435
#define SECURITY_NT_AUTHORITY
Definition: setypes.h:554
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
typedef bool(CARDLIBPROC *pCanDragProc)(CardRegion &stackobj
static HRESULT Installer_RegistryValueE(HKEY hkey, LPCWSTR szKey, BOOL *pBool)
Definition: automation.c:916
static const WCHAR nameW[]
Definition: main.c:46
static REGSAM
Definition: automation.c:42
static HRESULT Record_IntegerDataGet(IDispatch *pRecord, int iField, int *pValue)
Definition: automation.c:1469
static void write_msi_summary_info(MSIHANDLE db, const msi_summary_info *info, int num_info)
Definition: automation.c:278
BOOL WINAPI IsWow64Process(IN HANDLE hProcess, OUT PBOOL Wow64Process)
Definition: proc.c:1975
#define KEY_WOW64_64KEY
Definition: cmtypes.h:46
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:4899
static const char * msifile
Definition: automation.c:47
LPSTR WINAPI lstrcatA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:123
#define PID_THUMBNAIL
Definition: suminfo.c:59
__u8 media
Definition: mkdosfs.c:367
#define DISP_E_TYPEMISMATCH
Definition: winerror.h:2514
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
static HRESULT Installer_RegistryValueW(HKEY hkey, LPCWSTR szKey, LPCWSTR szValue, LPWSTR szString)
Definition: automation.c:930
GLsizeiptr size
Definition: glext.h:5919
static DISPID get_dispid(IDispatch *disp, const char *name)
Definition: automation.c:501
#define trace
Definition: atltest.h:70
#define SECURITY_BUILTIN_DOMAIN_RID
Definition: setypes.h:581
#define TOKEN_QUERY
Definition: setypes.h:924
#define PID_PAGECOUNT
Definition: suminfo.c:56
__wchar_t WCHAR
Definition: xmlstorage.h:180
LONG HRESULT
Definition: typedefs.h:79
static HRESULT invoke(IDispatch *pDispatch, LPCSTR szName, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, VARTYPE vtResult)
Definition: automation.c:840
static HRESULT Database_OpenView(IDispatch *pDatabase, LPCWSTR szSql, IDispatch **pView)
Definition: automation.c:1346
static HRESULT Session_FeatureCurrentState(IDispatch *pSession, LPCWSTR szName, int *pState)
Definition: automation.c:1295
BOOL WINAPI DECLSPEC_HOTPATCH SetEnvironmentVariableA(IN LPCSTR lpName, IN LPCSTR lpValue)
Definition: environ.c:218
const GUID IID_IUnknown
#define todo_wine_if(is_todo)
Definition: custom.c:76
static HRESULT View_Fetch(IDispatch *pView, IDispatch **ppRecord)
Definition: automation.c:1391
UINT WINAPI MsiSummaryInfoSetPropertyA(MSIHANDLE handle, UINT uiProperty, UINT uiDataType, INT iValue, FILETIME *pftValue, const char *szValue)
Definition: suminfo.c:937
#define MAX_PATH
Definition: compat.h:34
#define WINAPI
Definition: msvc.h:6
const char file[]
Definition: icontest.c:11
static IDispatch * pInstaller
Definition: automation.c:55
#define MSIDBOPEN_CREATE
Definition: msiquery.h:69
#define V_BOOL(A)
Definition: oleauto.h:224
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned long DWORD
Definition: ntddk_ex.h:95
PVOID HANDLE
Definition: typedefs.h:73
GLuint GLuint num
Definition: glext.h:9618
GLint left
Definition: glext.h:7726
#define MSIDBOPEN_TRANSACT
Definition: msiquery.h:67
#define ADD_INFO_I4(property, iValue)
Definition: automation.c:191
static int _invoke_todo_vtResult
Definition: automation.c:838
#define SetLastError(x)
Definition: compat.h:611
static HRESULT Installer_RegistryValue(HKEY hkey, LPCWSTR szKey, VARIANT vValue, VARIANT *pVarResult, VARTYPE vtExpect)
Definition: automation.c:898
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:85
static HRESULT SummaryInfo_PropertyPut(IDispatch *pSummaryInfo, int pid, VARIANT *pVariant)
Definition: automation.c:1550
const CHAR * filename
Definition: automation.c:161
static HRESULT Installer_CreateRecord(int count, IDispatch **pRecord)
Definition: automation.c:882
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
#define PID_EDITTIME
Definition: msidefs.h:272
#define PID_TITLE
Definition: suminfo.c:44
static HRESULT Installer_Products(IDispatch **pStringList)
Definition: automation.c:1053
const GUID IID_IDispatch
static LPCWSTR szVersion
Definition: asmcache.c:748
static HRESULT StringList_Item(IDispatch *pStringList, int iIndex, LPWSTR szString)
Definition: automation.c:1512
int ret
LONG WINAPI RegEnumKeyA(HKEY hKey, DWORD dwIndex, LPSTR lpName, DWORD cbName)
Definition: reg.c:2391
#define FILE_ATTRIBUTE_NORMAL
Definition: compat.h:137
REFCLSID clsid
Definition: msctf.c:82
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
static SID_IDENTIFIER_AUTHORITY NtAuthority
Definition: security.c:40
#define IID_NULL
Definition: guiddef.h:98
static HRESULT Installer_UILevelPut(int level)
Definition: automation.c:1092
#define V_VT(A)
Definition: oleauto.h:211
BOOL WINAPI SetCurrentDirectoryA(IN LPCSTR lpPathName)
Definition: path.c:2206
uint32_t entry
Definition: isohybrid.c:63
GLenum GLsizei len
Definition: glext.h:6722
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
LONG WINAPI RegCreateKeyW(HKEY hKey, LPCWSTR lpSubKey, PHKEY phkResult)
Definition: reg.c:1199
#define GUID_NULL
Definition: ks.h:106
#define GetCurrentProcess()
Definition: compat.h:618
static HRESULT Installer_SummaryInformation(BSTR PackagePath, int UpdateCount, IDispatch **pSumInfo)
Definition: automation.c:1106
#define V_UNKNOWN(A)
Definition: oleauto.h:281
GLenum mode
Definition: glext.h:6217
unsigned char BYTE
Definition: xxhash.c:193
#define V_BSTR(A)
Definition: oleauto.h:226
UINT WINAPI MsiCloseHandle(MSIHANDLE handle)
Definition: handle.c:269
#define broken(x)
Definition: _sntprintf.h:21
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID iid, LPVOID *ppv)
Definition: compobj.c:3325
UINT WINAPI MsiGetSummaryInformationA(MSIHANDLE hDatabase, const char *szDatabase, UINT uiUpdateCount, MSIHANDLE *pHandle)
Definition: suminfo.c:584
#define ok_w2(format, szString1, szString2)
Definition: automation.c:451
HRESULT WINAPI DECLSPEC_HOTPATCH OleInitialize(LPVOID reserved)
Definition: ole2.c:169
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
LONG WINAPI RegDeleteKeyA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey)
Definition: reg.c:1222
const char * name
Definition: automation.c:524
#define PID_CREATE_DTM
Definition: suminfo.c:54
static void test_dispid(void)
Definition: automation.c:579
DEFINE_GUID(GUID_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
static HRESULT Installer_VersionGet(LPWSTR szVersion)
Definition: automation.c:1080
struct stdole::EXCEPINFO EXCEPINFO
#define S_OK
Definition: intsafe.h:52
static VARIANTARG static DISPID
Definition: ordinal.c:49
#define CREATE_ALWAYS
Definition: disk.h:72
static LONG delete_key_portable(HKEY key, LPCSTR subkey, REGSAM access)
Definition: automation.c:257
static HRESULT Installer_InstallProduct(LPCWSTR szPackagePath, LPCWSTR szPropertyValues)
Definition: automation.c:1000
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
#define lstrcpyW
Definition: compat.h:608
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
DWORD WINAPI GetTempPathA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2054
BYTE * data
GLuint GLint GLboolean GLint GLenum access
Definition: glext.h:7866
LPCWSTR szPath
Definition: env.c:37
#define ARRAY_SIZE(a)
Definition: main.h:24
UINT WINAPI MsiDatabaseCommit(MSIHANDLE hdb)
Definition: msiquery.c:963
static BOOL is_wow64
Definition: automation.c:40
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
static void test_Session(IDispatch *pSession)
Definition: automation.c:1831
#define REG_EXPAND_SZ
Definition: nt_native.h:1494
static HRESULT Record_IntegerDataPut(IDispatch *pRecord, int iField, int iValue)
Definition: automation.c:1486
#define ok(value,...)
Definition: atltest.h:57
DWORD WINAPI GetCurrentDirectoryA(IN DWORD nBufferLength, OUT LPSTR lpBuffer)
Definition: path.c:2146
UINT WINAPI MsiOpenDatabaseW(LPCWSTR szDBPath, LPCWSTR szPersist, MSIHANDLE *phDB)
Definition: database.c:298
ACCESS_MASK REGSAM
Definition: winreg.h:69
BOOL WINAPI RemoveDirectoryA(IN LPCSTR lpPathName)
Definition: dir.c:714
unsigned short VARTYPE
Definition: compat.h:2113
FILETIME * pftValue
Definition: automation.c:186
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
BOOL WINAPI OpenProcessToken(HANDLE ProcessHandle, DWORD DesiredAccess, PHANDLE TokenHandle)
Definition: security.c:296
static void create_file(const CHAR *name, DWORD size)
Definition: automation.c:381
static PBOOL
Definition: automation.c:43
#define MultiByteToWideChar
Definition: compat.h:110
DISPID did
Definition: automation.c:523
static void test_dispatch(void)
Definition: automation.c:617
#define skip(...)
Definition: atltest.h:64
UINT WINAPI MsiSummaryInfoPersist(MSIHANDLE handle)
Definition: suminfo.c:1222
static HRESULT Session_ModePut(IDispatch *pSession, int iFlag, VARIANT_BOOL mode)
Definition: automation.c:1199
static HRESULT Installer_OpenDatabase(LPCWSTR szDatabasePath, int openmode, IDispatch **pDatabase)
Definition: automation.c:981
#define PID_WORDCOUNT
Definition: suminfo.c:57
#define PID_DICTIONARY
Definition: suminfo.c:42
static HRESULT Session_Database(IDispatch *pSession, IDispatch **pDatabase)
Definition: automation.c:1216
Definition: name.c:38
static EXCEPINFO excepinfo
Definition: automation.c:50
GLuint res
Definition: glext.h:9613
struct stdole::DISPPARAMS DISPPARAMS
static const get_did_t get_did_data[]
Definition: automation.c:528
static LPCSTR
Definition: automation.c:42
HANDLE HKEY
Definition: registry.h:26
#define REG_QWORD
Definition: sdbapi.c:597
unsigned int ULONG
Definition: retypes.h:1
GLenum GLuint id
Definition: glext.h:5579
BOOL WINAPI GetTokenInformation(HANDLE TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, LPVOID TokenInformation, DWORD TokenInformationLength, PDWORD ReturnLength)
Definition: security.c:413
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ERROR_CALL_NOT_IMPLEMENTED
Definition: compat.h:102
static HRESULT Session_DoAction(IDispatch *pSession, LPCWSTR szAction, int *iReturn)
Definition: automation.c:1227
#define LOCALE_NEUTRAL
#define malloc
Definition: debug_ros.c:4
#define KEY_WOW64_32KEY
Definition: cmtypes.h:45
UINT WINAPI MsiDatabaseImportA(MSIHANDLE handle, const char *szFolder, const char *szFilename)
Definition: database.c:853
#define DISP_E_BADINDEX
Definition: winerror.h:2520
#define ADD_TABLE(x)
Definition: automation.c:166
LPWSTR WINAPI lstrcatW(LPWSTR lpString1, LPCWSTR lpString2)
Definition: lstring.c:274
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define REG_NONE
Definition: nt_native.h:1492
#define CreateFileA(a, b, c, d, e, f, g)
Definition: compat.h:599
static const CHAR feature_dat[]
Definition: automation.c:81
WCHAR * LPWSTR
Definition: xmlstorage.h:184
static void test_SummaryInfo(IDispatch *pSummaryInfo, const msi_summary_info *info, int num_info, BOOL readonly)
Definition: automation.c:1582
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
static UINT delete_registry_key(HKEY hkeyParent, LPCSTR subkey, REGSAM access)
Definition: automation.c:2326
#define ok_w2n(format, szString1, szString2, len)
Definition: automation.c:460
void WINAPI DECLSPEC_HOTPATCH OleUninitialize(void)
Definition: ole2.c:230
#define memset(x, y, z)
Definition: compat.h:39
#define REG_DWORD
Definition: sdbapi.c:596
#define DOMAIN_ALIAS_RID_ADMINS
Definition: setypes.h:652
#define ADD_INFO_LPSTR(property, szValue)
Definition: automation.c:192
static HRESULT StringList__NewEnum(IDispatch *pList, IUnknown **ppEnumVARIANT)
Definition: automation.c:1503
static HRESULT Session_LanguageGet(IDispatch *pSession, UINT *pLangId)
Definition: automation.c:1170
static void *static void *static LPDIRECTPLAY IUnknown * pUnk
Definition: dplayx.c:30
static char * stringw(char *buf, char *end, const wchar_t *sw, int len, int field_width, int precision, int flags)
Definition: sprintf.c:335
#define win_skip
Definition: test.h:160
INT WINAPI SystemTimeToVariantTime(LPSYSTEMTIME lpSt, double *pDateOut)
Definition: variant.c:1286
static void create_database(const CHAR *name, const msi_table *tables, int num_tables, const msi_summary_info *info, int num_info)
Definition: automation.c:304
#define RegCloseKey(hKey)
Definition: registry.h:47
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
static HRESULT Installer_ProductState(LPCWSTR szProduct, int *pInstallState)
Definition: automation.c:1016
#define SetFilePointer
Definition: compat.h:602
#define d
Definition: ke_i.h:81
Definition: compat.h:2156
static void test_Database(IDispatch *pDatabase, BOOL readonly)
Definition: automation.c:1723
#define V_DATE(A)
Definition: oleauto.h:231
#define ok_awplus(format, extra, aString, wString)
Definition: automation.c:475
static void create_test_files(void)
Definition: automation.c:399
HRESULT WINAPI VariantChangeTypeEx(VARIANTARG *pvargDest, VARIANTARG *pvargSrc, LCID lcid, USHORT wFlags, VARTYPE vt)
Definition: variant.c:988
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:676
static HRESULT Installer_RegistryValueI(HKEY hkey, LPCWSTR szKey, int iValue, LPWSTR szString, VARTYPE vtResult)
Definition: automation.c:946
Definition: path.c:41
static HRESULT Session_Message(IDispatch *pSession, LONG kind, IDispatch *record, int *ret)
Definition: automation.c:1261
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
#define TEST_SUMMARYINFO_PROPERTIES_MODIFIED
Definition: automation.c:1580
static const CHAR feature_comp_dat[]
Definition: automation.c:91
Definition: fci.c:126
char temp_path[MAX_PATH]
Definition: mspatcha.c:123
#define REG_SZ
Definition: layer.c:22
GLuint const GLchar * name
Definition: glext.h:6031