2 * Copyright (C) 2007 Mike McCormack for CodeWeavers
3 * Copyright (C) 2007 Misha Koshelev
5 * A test program for Microsoft Installer OLE automation functionality.
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.
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.
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
32 #include "wine/test.h"
34 static const char *msifile
= "winetest.msi";
35 static const WCHAR szMsifile
[] = {'w','i','n','e','t','e','s','t','.','m','s','i',0};
36 CHAR CURR_DIR
[MAX_PATH
];
42 static const WCHAR szProgId
[] = { 'W','i','n','d','o','w','s','I','n','s','t','a','l','l','e','r','.','I','n','s','t','a','l','l','e','r',0 };
43 static IDispatch
*pInstaller
;
45 /* msi database data */
47 static const CHAR component_dat
[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
48 "s72\tS38\ts72\ti2\tS255\tS72\n"
49 "Component\tComponent\n"
50 "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
51 "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
52 "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
53 "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
54 "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
55 "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
56 "component\t\tMSITESTDIR\t0\t1\tfile\n"
57 "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
59 static const CHAR directory_dat
[] = "Directory\tDirectory_Parent\tDefaultDir\n"
61 "Directory\tDirectory\n"
62 "CABOUTDIR\tMSITESTDIR\tcabout\n"
63 "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
64 "FIRSTDIR\tMSITESTDIR\tfirst\n"
65 "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
66 "NEWDIR\tCABOUTDIR\tnew\n"
67 "ProgramFilesFolder\tTARGETDIR\t.\n"
68 "TARGETDIR\t\tSourceDir";
70 static const CHAR feature_dat
[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
71 "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
73 "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
74 "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
75 "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
76 "Three\tOne\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
77 "Two\tOne\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
78 "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
79 "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
81 static const CHAR feature_comp_dat
[] = "Feature_\tComponent_\n"
83 "FeatureComponents\tFeature_\tComponent_\n"
89 "feature\tcomponent\n"
90 "service_feature\tservice_comp\n";
92 static const CHAR file_dat
[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
93 "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
95 "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
96 "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
97 "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
98 "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
99 "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
100 "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
101 "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
103 static const CHAR install_exec_seq_dat
[] = "Action\tCondition\tSequence\n"
105 "InstallExecuteSequence\tAction\n"
106 "AllocateRegistrySpace\tNOT Installed\t1550\n"
107 "CostFinalize\t\t1000\n"
108 "CostInitialize\t\t800\n"
110 "InstallFiles\t\t4000\n"
111 "InstallServices\t\t5000\n"
112 "InstallFinalize\t\t6600\n"
113 "InstallInitialize\t\t1500\n"
114 "InstallValidate\t\t1400\n"
115 "LaunchConditions\t\t100\n"
116 "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
118 static const CHAR media_dat
[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
119 "i2\ti4\tL64\tS255\tS32\tS72\n"
121 "1\t3\t\t\tDISK1\t\n"
122 "2\t5\t\tmsitest.cab\tDISK2\t\n";
124 static const CHAR property_dat
[] = "Property\tValue\n"
126 "Property\tProperty\n"
127 "DefaultUIFont\tDlgFont8\n"
130 "InstallMode\tTypical\n"
131 "Manufacturer\tWine\n"
132 "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
133 "ProductCode\t{F1C3AF50-8B56-4A69-A00C-00773FE42F30}\n"
135 "ProductLanguage\t1033\n"
136 "ProductName\tMSITEST\n"
137 "ProductVersion\t1.1.1\n"
138 "PROMPTROLLBACKCOST\tP\n"
140 "UpgradeCode\t{CE067E8D-2E1A-4367-B734-4EB2BDAD6565}";
142 static const CHAR registry_dat
[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
143 "s72\ti2\tl255\tL255\tL0\ts72\n"
144 "Registry\tRegistry\n"
145 "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
146 "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
147 "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
148 "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
150 static const CHAR service_install_dat
[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
151 "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
152 "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
153 "ServiceInstall\tServiceInstall\n"
154 "TestService\tTestService\tTestService\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
156 static const CHAR service_control_dat
[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
157 "s72\tl255\ti2\tL255\tI2\ts72\n"
158 "ServiceControl\tServiceControl\n"
159 "ServiceControl\tTestService\t8\t\t0\tservice_comp";
161 typedef struct _msi_table
163 const CHAR
*filename
;
168 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
170 static const msi_table tables
[] =
172 ADD_TABLE(component
),
173 ADD_TABLE(directory
),
175 ADD_TABLE(feature_comp
),
177 ADD_TABLE(install_exec_seq
),
181 ADD_TABLE(service_install
),
182 ADD_TABLE(service_control
)
189 static void write_file(const CHAR
*filename
, const char *data
, int data_size
)
193 HANDLE hf
= CreateFile(filename
, GENERIC_WRITE
, 0, NULL
,
194 CREATE_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
);
196 WriteFile(hf
, data
, data_size
, &size
, NULL
);
200 static void write_msi_summary_info(MSIHANDLE db
)
205 r
= MsiGetSummaryInformationA(db
, NULL
, 4, &summary
);
206 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
208 r
= MsiSummaryInfoSetPropertyA(summary
, PID_TEMPLATE
, VT_LPSTR
, 0, NULL
, ";1033");
209 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
211 r
= MsiSummaryInfoSetPropertyA(summary
, PID_REVNUMBER
, VT_LPSTR
, 0, NULL
,
212 "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
213 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
215 r
= MsiSummaryInfoSetPropertyA(summary
, PID_PAGECOUNT
, VT_I4
, 100, NULL
, NULL
);
216 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
218 r
= MsiSummaryInfoSetPropertyA(summary
, PID_WORDCOUNT
, VT_I4
, 0, NULL
, NULL
);
219 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
221 /* write the summary changes back to the stream */
222 r
= MsiSummaryInfoPersist(summary
);
223 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
225 MsiCloseHandle(summary
);
228 static void create_database(const CHAR
*name
, const msi_table
*tables
, int num_tables
)
234 r
= MsiOpenDatabaseA(name
, MSIDBOPEN_CREATE
, &db
);
235 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
237 /* import the tables into the database */
238 for (j
= 0; j
< num_tables
; j
++)
240 const msi_table
*table
= &tables
[j
];
242 write_file(table
->filename
, table
->data
, (table
->size
- 1) * sizeof(char));
244 r
= MsiDatabaseImportA(db
, CURR_DIR
, table
->filename
);
245 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
247 DeleteFileA(table
->filename
);
250 write_msi_summary_info(db
);
252 r
= MsiDatabaseCommit(db
);
253 ok(r
== ERROR_SUCCESS
, "Expected ERROR_SUCCESS, got %u\n", r
);
259 * Automation helpers and tests
262 /* ok-like statement which takes two unicode strings as arguments */
263 static CHAR string1
[MAX_PATH
], string2
[MAX_PATH
];
266 #define ok_w2(format, szString1, szString2) \
268 if (lstrcmpW(szString1, szString2) != 0) \
270 len = WideCharToMultiByte(CP_ACP, 0, szString1, -1, string1, MAX_PATH, NULL, NULL); \
271 ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \
273 len = WideCharToMultiByte(CP_ACP, 0, szString2, -1, string2, MAX_PATH, NULL, NULL); \
274 ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \
276 ok(0, format, string1, string2); \
279 /* exception checker */
280 static WCHAR szSource
[] = {'M','s','i',' ','A','P','I',' ','E','r','r','o','r',0};
282 #define ok_exception(hr, szDescription) \
283 if (hr == DISP_E_EXCEPTION) \
285 /* Compare wtype, source, and destination */ \
286 ok(excepinfo.wCode == 1000, "Exception info was %d, expected 1000\n", excepinfo.wCode); \
288 ok(excepinfo.bstrSource != NULL, "Exception source was NULL\n"); \
289 if (excepinfo.bstrSource) \
290 ok_w2("Exception source was \"%s\" but expected to be \"%s\"\n", excepinfo.bstrSource, szSource); \
292 ok(excepinfo.bstrDescription != NULL, "Exception description was NULL\n"); \
293 if (excepinfo.bstrDescription && lstrcmpW(excepinfo.bstrDescription, szDescription) != 0) \
295 len = WideCharToMultiByte(CP_ACP, 0, excepinfo.bstrDescription, -1, string1, MAX_PATH, NULL, NULL); \
296 ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \
298 len = WideCharToMultiByte(CP_ACP, 0, szDescription, -1, string2, MAX_PATH, NULL, NULL); \
299 ok(len, "WideCharToMultiByteChar returned error %d\n", GetLastError()); \
302 /* Our parameter names are different so the descriptions will not match */ \
303 ok(0, "Exception description was \"%s\" but expected to be \"%s\"\n", string1, string2); \
308 static DISPID
get_dispid( IDispatch
*disp
, const char *name
)
315 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, NULL
, 0 );
316 str
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
319 len
= MultiByteToWideChar(CP_ACP
, 0, name
, -1, str
, len
);
320 r
= IDispatch_GetIDsOfNames( disp
, &IID_NULL
, &str
, 1, 0, &id
);
321 HeapFree(GetProcessHeap(), 0, str
);
329 static void test_dispid(void)
331 ok( get_dispid( pInstaller
, "OpenPackage" ) == 2, "dispid wrong\n");
334 ok( get_dispid( pInstaller
, "CreateRecord" ) == 1, "dispid wrong\n");
335 ok( get_dispid( pInstaller
, "OpenProduct" ) == 3, "dispid wrong\n");
336 ok( get_dispid( pInstaller
, "OpenDatabase" ) == 4, "dispid wrong\n");
337 ok( get_dispid( pInstaller
, "SummaryInformation" ) == 5, "dispid wrong\n");
338 ok( get_dispid( pInstaller
, "UILevel" ) == 6, "dispid wrong\n");
339 ok( get_dispid( pInstaller
, "EnableLog" ) == 7, "dispid wrong\n");
340 ok( get_dispid( pInstaller
, "InstallProduct" ) == 8, "dispid wrong\n");
341 ok( get_dispid( pInstaller
, "Version" ) == 9, "dispid wrong\n");
342 ok( get_dispid( pInstaller
, "LastErrorRecord" ) == 10, "dispid wrong\n");
343 ok( get_dispid( pInstaller
, "RegistryValue" ) == 11, "dispid wrong\n");
344 ok( get_dispid( pInstaller
, "Environment" ) == 12, "dispid wrong\n");
345 ok( get_dispid( pInstaller
, "FileAttributes" ) == 13, "dispid wrong\n");
347 ok( get_dispid( pInstaller
, "FileSize" ) == 15, "dispid wrong\n");
348 ok( get_dispid( pInstaller
, "FileVersion" ) == 16, "dispid wrong\n");
349 ok( get_dispid( pInstaller
, "ProductState" ) == 17, "dispid wrong\n");
350 ok( get_dispid( pInstaller
, "ProductInfo" ) == 18, "dispid wrong\n");
351 ok( get_dispid( pInstaller
, "ConfigureProduct" ) == 19, "dispid wrong\n");
352 ok( get_dispid( pInstaller
, "ReinstallProduct" ) == 20 , "dispid wrong\n");
353 ok( get_dispid( pInstaller
, "CollectUserInfo" ) == 21, "dispid wrong\n");
354 ok( get_dispid( pInstaller
, "ApplyPatch" ) == 22, "dispid wrong\n");
355 ok( get_dispid( pInstaller
, "FeatureParent" ) == 23, "dispid wrong\n");
356 ok( get_dispid( pInstaller
, "FeatureState" ) == 24, "dispid wrong\n");
357 ok( get_dispid( pInstaller
, "UseFeature" ) == 25, "dispid wrong\n");
358 ok( get_dispid( pInstaller
, "FeatureUsageCount" ) == 26, "dispid wrong\n");
359 ok( get_dispid( pInstaller
, "FeatureUsageDate" ) == 27, "dispid wrong\n");
360 ok( get_dispid( pInstaller
, "ConfigureFeature" ) == 28, "dispid wrong\n");
361 ok( get_dispid( pInstaller
, "ReinstallFeature" ) == 29, "dispid wrong\n");
362 ok( get_dispid( pInstaller
, "ProvideComponent" ) == 30, "dispid wrong\n");
363 ok( get_dispid( pInstaller
, "ComponentPath" ) == 31, "dispid wrong\n");
364 ok( get_dispid( pInstaller
, "ProvideQualifiedComponent" ) == 32, "dispid wrong\n");
365 ok( get_dispid( pInstaller
, "QualifierDescription" ) == 33, "dispid wrong\n");
366 ok( get_dispid( pInstaller
, "ComponentQualifiers" ) == 34, "dispid wrong\n");
367 ok( get_dispid( pInstaller
, "Products" ) == 35, "dispid wrong\n");
368 ok( get_dispid( pInstaller
, "Features" ) == 36, "dispid wrong\n");
369 ok( get_dispid( pInstaller
, "Components" ) == 37, "dispid wrong\n");
370 ok( get_dispid( pInstaller
, "ComponentClients" ) == 38, "dispid wrong\n");
371 ok( get_dispid( pInstaller
, "Patches" ) == 39, "dispid wrong\n");
372 ok( get_dispid( pInstaller
, "RelatedProducts" ) == 40, "dispid wrong\n");
373 ok( get_dispid( pInstaller
, "PatchInfo" ) == 41, "dispid wrong\n");
374 ok( get_dispid( pInstaller
, "PatchTransforms" ) == 42, "dispid wrong\n");
375 ok( get_dispid( pInstaller
, "AddSource" ) == 43, "dispid wrong\n");
376 ok( get_dispid( pInstaller
, "ClearSourceList" ) == 44, "dispid wrong\n");
377 ok( get_dispid( pInstaller
, "ForceSourceListResolution" ) == 45, "dispid wrong\n");
378 ok( get_dispid( pInstaller
, "ShortcutTarget" ) == 46, "dispid wrong\n");
379 ok( get_dispid( pInstaller
, "FileHash" ) == 47, "dispid wrong\n");
380 ok( get_dispid( pInstaller
, "FileSignatureInfo" ) == 48, "dispid wrong\n");
381 ok( get_dispid( pInstaller
, "RemovePatches" ) == 49, "dispid wrong\n");
383 ok( get_dispid( pInstaller
, "ApplyMultiplePatches" ) == 51, "dispid wrong\n");
384 ok( get_dispid( pInstaller
, "ProductsEx" ) == 52, "dispid wrong\n");
386 ok( get_dispid( pInstaller
, "PatchesEx" ) == 55, "dispid wrong\n");
388 ok( get_dispid( pInstaller
, "ExtractPatchXMLData" ) == 57, "dispid wrong\n");
391 /* MSDN claims the following functions exist but IDispatch->GetIDsOfNames disagrees */
394 get_dispid( pInstaller
, "ProductElevated" );
395 get_dispid( pInstaller
, "ProductInfoFromScript" );
396 get_dispid( pInstaller
, "ProvideAssembly" );
397 get_dispid( pInstaller
, "CreateAdvertiseScript" );
398 get_dispid( pInstaller
, "AdvertiseProduct" );
399 get_dispid( pInstaller
, "PatchFiles" );
403 /* Test basic IDispatch functions */
404 static void test_dispatch(void)
406 static WCHAR szOpenPackage
[] = { 'O','p','e','n','P','a','c','k','a','g','e',0 };
407 static WCHAR szOpenPackageException
[] = {'O','p','e','n','P','a','c','k','a','g','e',',','P','a','c','k','a','g','e','P','a','t','h',',','O','p','t','i','o','n','s',0};
412 VARIANTARG vararg
[2];
413 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
415 /* Test getting ID of a function name that does not exist */
416 name
= (WCHAR
*)szMsifile
;
417 hr
= IDispatch_GetIDsOfNames(pInstaller
, &IID_NULL
, &name
, 1, LOCALE_USER_DEFAULT
, &dispid
);
418 ok(hr
== DISP_E_UNKNOWNNAME
, "IDispatch::GetIDsOfNames returned 0x%08x\n", hr
);
420 /* Test invoking this function */
421 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, NULL
, NULL
, NULL
, NULL
);
422 ok(hr
== DISP_E_MEMBERNOTFOUND
, "IDispatch::Invoke returned 0x%08x\n", hr
);
424 /* Test getting ID of a function name that does exist */
425 name
= (WCHAR
*)szOpenPackage
;
426 hr
= IDispatch_GetIDsOfNames(pInstaller
, &IID_NULL
, &name
, 1, LOCALE_USER_DEFAULT
, &dispid
);
427 ok(SUCCEEDED(hr
), "IDispatch::GetIDsOfNames returned 0x%08x\n", hr
);
429 /* Test invoking this function (without parameters passed) */
430 if (0) /* All of these crash MSI on Windows XP */
432 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, NULL
, NULL
, NULL
, NULL
);
433 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, NULL
, NULL
, &excepinfo
, NULL
);
434 VariantInit(&varresult
);
435 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, NULL
, &varresult
, &excepinfo
, NULL
);
438 /* Try with NULL params */
439 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
440 todo_wine
ok(hr
== DISP_E_TYPEMISMATCH
, "IDispatch::Invoke returned 0x%08x\n", hr
);
442 /* Try one empty parameter */
443 dispparams
.rgvarg
= vararg
;
444 dispparams
.cArgs
= 1;
445 VariantInit(&vararg
[0]);
446 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
447 todo_wine
ok(hr
== DISP_E_TYPEMISMATCH
, "IDispatch::Invoke returned 0x%08x\n", hr
);
449 /* Try one parameter, function requires two */
450 VariantInit(&vararg
[0]);
451 V_VT(&vararg
[0]) = VT_BSTR
;
452 V_BSTR(&vararg
[0]) = SysAllocString(szMsifile
);
453 hr
= IDispatch_Invoke(pInstaller
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
454 VariantClear(&vararg
[0]);
456 ok(hr
== DISP_E_EXCEPTION
, "IDispatch::Invoke returned 0x%08x\n", hr
);
457 ok_exception(hr
, szOpenPackageException
);
460 /* invocation helper function */
461 static HRESULT
invoke(IDispatch
*pDispatch
, LPCSTR szName
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, VARTYPE vtResult
)
463 OLECHAR
*name
= NULL
;
469 memset(pVarResult
, 0, sizeof(VARIANT
));
470 VariantInit(pVarResult
);
472 len
= MultiByteToWideChar(CP_ACP
, 0, szName
, -1, NULL
, 0 );
473 name
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
) );
474 if (!name
) return E_FAIL
;
475 len
= MultiByteToWideChar(CP_ACP
, 0, szName
, -1, name
, len
);
476 hr
= IDispatch_GetIDsOfNames(pDispatch
, &IID_NULL
, &name
, 1, LOCALE_USER_DEFAULT
, &dispid
);
477 HeapFree(GetProcessHeap(), 0, name
);
478 ok(SUCCEEDED(hr
), "IDispatch::GetIDsOfNames returned 0x%08x\n", hr
);
479 if (!SUCCEEDED(hr
)) return hr
;
481 memset(&excepinfo
, 0, sizeof(excepinfo
));
482 hr
= IDispatch_Invoke(pDispatch
, dispid
, &IID_NULL
, LOCALE_NEUTRAL
, wFlags
, pDispParams
, pVarResult
, &excepinfo
, NULL
);
486 ok(V_VT(pVarResult
) == vtResult
, "Variant result type is %d, expected %d\n", V_VT(pVarResult
), vtResult
);
487 if (vtResult
!= VT_EMPTY
)
489 hr
= VariantChangeTypeEx(pVarResult
, pVarResult
, LOCALE_NEUTRAL
, 0, vtResult
);
490 ok(SUCCEEDED(hr
), "VariantChangeTypeEx returned 0x%08x\n", hr
);
494 for (i
=0; i
<pDispParams
->cArgs
; i
++)
495 VariantClear(&pDispParams
->rgvarg
[i
]);
500 /* Object_Property helper functions */
502 static HRESULT
Installer_CreateRecord(int count
, IDispatch
**pRecord
)
505 VARIANTARG vararg
[1];
506 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
509 VariantInit(&vararg
[0]);
510 V_VT(&vararg
[0]) = VT_I4
;
511 V_I4(&vararg
[0]) = count
;
513 hr
= invoke(pInstaller
, "CreateRecord", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_DISPATCH
);
514 *pRecord
= V_DISPATCH(&varresult
);
518 static HRESULT
Installer_OpenPackage(LPCWSTR szPackagePath
, int options
, IDispatch
**pSession
)
521 VARIANTARG vararg
[2];
522 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
525 VariantInit(&vararg
[1]);
526 V_VT(&vararg
[1]) = VT_BSTR
;
527 V_BSTR(&vararg
[1]) = SysAllocString(szPackagePath
);
528 VariantInit(&vararg
[0]);
529 V_VT(&vararg
[0]) = VT_I4
;
530 V_I4(&vararg
[0]) = options
;
532 hr
= invoke(pInstaller
, "OpenPackage", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_DISPATCH
);
533 *pSession
= V_DISPATCH(&varresult
);
537 static HRESULT
Installer_VersionGet(LPCWSTR szVersion
)
540 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
543 hr
= invoke(pInstaller
, "Version", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_BSTR
);
544 lstrcpyW((WCHAR
*)szVersion
, V_BSTR(&varresult
));
545 VariantClear(&varresult
);
549 static HRESULT
Session_Installer(IDispatch
*pSession
, IDispatch
**pInst
)
552 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
555 hr
= invoke(pSession
, "Installer", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_DISPATCH
);
556 *pInst
= V_DISPATCH(&varresult
);
560 static HRESULT
Session_PropertyGet(IDispatch
*pSession
, LPCWSTR szName
, LPCWSTR szReturn
)
563 VARIANTARG vararg
[1];
564 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
567 VariantInit(&vararg
[0]);
568 V_VT(&vararg
[0]) = VT_BSTR
;
569 V_BSTR(&vararg
[0]) = SysAllocString(szName
);
571 hr
= invoke(pSession
, "Property", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_BSTR
);
572 lstrcpyW((WCHAR
*)szReturn
, V_BSTR(&varresult
));
573 VariantClear(&varresult
);
577 static HRESULT
Session_PropertyPut(IDispatch
*pSession
, LPCWSTR szName
, LPCWSTR szValue
)
580 VARIANTARG vararg
[2];
581 DISPID dispid
= DISPID_PROPERTYPUT
;
582 DISPPARAMS dispparams
= {vararg
, &dispid
, sizeof(vararg
)/sizeof(VARIANTARG
), 1};
584 VariantInit(&vararg
[1]);
585 V_VT(&vararg
[1]) = VT_BSTR
;
586 V_BSTR(&vararg
[1]) = SysAllocString(szName
);
587 VariantInit(&vararg
[0]);
588 V_VT(&vararg
[0]) = VT_BSTR
;
589 V_BSTR(&vararg
[0]) = SysAllocString(szValue
);
591 return invoke(pSession
, "Property", DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, VT_EMPTY
);
594 static HRESULT
Session_LanguageGet(IDispatch
*pSession
, UINT
*pLangId
)
597 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
600 hr
= invoke(pSession
, "Language", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_I4
);
601 *pLangId
= V_I4(&varresult
);
602 VariantClear(&varresult
);
606 static HRESULT
Session_ModeGet(IDispatch
*pSession
, int iFlag
, BOOL
*pMode
)
609 VARIANTARG vararg
[1];
610 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
613 VariantInit(&vararg
[0]);
614 V_VT(&vararg
[0]) = VT_I4
;
615 V_I4(&vararg
[0]) = iFlag
;
617 hr
= invoke(pSession
, "Mode", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_BOOL
);
618 *pMode
= V_BOOL(&varresult
);
619 VariantClear(&varresult
);
623 static HRESULT
Session_ModePut(IDispatch
*pSession
, int iFlag
, BOOL bMode
)
626 VARIANTARG vararg
[2];
627 DISPID dispid
= DISPID_PROPERTYPUT
;
628 DISPPARAMS dispparams
= {vararg
, &dispid
, sizeof(vararg
)/sizeof(VARIANTARG
), 1};
630 VariantInit(&vararg
[1]);
631 V_VT(&vararg
[1]) = VT_I4
;
632 V_I4(&vararg
[1]) = iFlag
;
633 VariantInit(&vararg
[0]);
634 V_VT(&vararg
[0]) = VT_BOOL
;
635 V_BOOL(&vararg
[0]) = bMode
;
637 return invoke(pSession
, "Mode", DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, VT_EMPTY
);
640 static HRESULT
Session_Database(IDispatch
*pSession
, IDispatch
**pDatabase
)
643 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
646 hr
= invoke(pSession
, "Database", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_DISPATCH
);
647 *pDatabase
= V_DISPATCH(&varresult
);
651 static HRESULT
Session_DoAction(IDispatch
*pSession
, LPCWSTR szAction
, int *iReturn
)
654 VARIANTARG vararg
[1];
655 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
658 VariantInit(&vararg
[0]);
659 V_VT(&vararg
[0]) = VT_BSTR
;
660 V_BSTR(&vararg
[0]) = SysAllocString(szAction
);
662 hr
= invoke(pSession
, "DoAction", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_I4
);
663 *iReturn
= V_I4(&varresult
);
664 VariantClear(&varresult
);
668 static HRESULT
Session_SetInstallLevel(IDispatch
*pSession
, long iInstallLevel
)
671 VARIANTARG vararg
[1];
672 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
674 VariantInit(&vararg
[0]);
675 V_VT(&vararg
[0]) = VT_I4
;
676 V_I4(&vararg
[0]) = iInstallLevel
;
678 return invoke(pSession
, "SetInstallLevel", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_EMPTY
);
681 static HRESULT
Session_FeatureCurrentState(IDispatch
*pSession
, LPCWSTR szName
, int *pState
)
684 VARIANTARG vararg
[1];
685 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
688 VariantInit(&vararg
[0]);
689 V_VT(&vararg
[0]) = VT_BSTR
;
690 V_BSTR(&vararg
[0]) = SysAllocString(szName
);
692 hr
= invoke(pSession
, "FeatureCurrentState", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_I4
);
693 *pState
= V_I4(&varresult
);
694 VariantClear(&varresult
);
698 static HRESULT
Session_FeatureRequestStateGet(IDispatch
*pSession
, LPCWSTR szName
, int *pState
)
701 VARIANTARG vararg
[1];
702 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
705 VariantInit(&vararg
[0]);
706 V_VT(&vararg
[0]) = VT_BSTR
;
707 V_BSTR(&vararg
[0]) = SysAllocString(szName
);
709 hr
= invoke(pSession
, "FeatureRequestState", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_I4
);
710 *pState
= V_I4(&varresult
);
711 VariantClear(&varresult
);
715 static HRESULT
Session_FeatureRequestStatePut(IDispatch
*pSession
, LPCWSTR szName
, int iState
)
718 VARIANTARG vararg
[2];
719 DISPID dispid
= DISPID_PROPERTYPUT
;
720 DISPPARAMS dispparams
= {vararg
, &dispid
, sizeof(vararg
)/sizeof(VARIANTARG
), 1};
722 VariantInit(&vararg
[1]);
723 V_VT(&vararg
[1]) = VT_BSTR
;
724 V_BSTR(&vararg
[1]) = SysAllocString(szName
);
725 VariantInit(&vararg
[0]);
726 V_VT(&vararg
[0]) = VT_I4
;
727 V_I4(&vararg
[0]) = iState
;
729 return invoke(pSession
, "FeatureRequestState", DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, VT_EMPTY
);
732 static HRESULT
Database_OpenView(IDispatch
*pDatabase
, LPCWSTR szSql
, IDispatch
**pView
)
735 VARIANTARG vararg
[1];
736 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
739 VariantInit(&vararg
[0]);
740 V_VT(&vararg
[0]) = VT_BSTR
;
741 V_BSTR(&vararg
[0]) = SysAllocString(szSql
);
743 hr
= invoke(pDatabase
, "OpenView", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_DISPATCH
);
744 *pView
= V_DISPATCH(&varresult
);
748 static HRESULT
View_Execute(IDispatch
*pView
, IDispatch
*pRecord
)
751 VARIANTARG vararg
[1];
752 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
754 VariantInit(&vararg
[0]);
755 V_VT(&vararg
[0]) = VT_DISPATCH
;
756 V_DISPATCH(&vararg
[0]) = pRecord
;
758 return invoke(pView
, "Execute", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_EMPTY
);
761 static HRESULT
View_Fetch(IDispatch
*pView
, IDispatch
**ppRecord
)
764 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
765 HRESULT hr
= invoke(pView
, "Fetch", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_DISPATCH
);
766 *ppRecord
= V_DISPATCH(&varresult
);
770 static HRESULT
View_Close(IDispatch
*pView
)
773 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
774 return invoke(pView
, "Close", DISPATCH_METHOD
, &dispparams
, &varresult
, VT_EMPTY
);
777 static HRESULT
Record_FieldCountGet(IDispatch
*pRecord
, int *pFieldCount
)
780 DISPPARAMS dispparams
= {NULL
, NULL
, 0, 0};
781 HRESULT hr
= invoke(pRecord
, "FieldCount", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_I4
);
782 *pFieldCount
= V_I4(&varresult
);
783 VariantClear(&varresult
);
787 static HRESULT
Record_StringDataGet(IDispatch
*pRecord
, int iField
, LPCWSTR szString
)
790 VARIANTARG vararg
[1];
791 DISPPARAMS dispparams
= {vararg
, NULL
, sizeof(vararg
)/sizeof(VARIANTARG
), 0};
794 VariantInit(&vararg
[0]);
795 V_VT(&vararg
[0]) = VT_I4
;
796 V_I4(&vararg
[0]) = iField
;
798 hr
= invoke(pRecord
, "StringData", DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, VT_BSTR
);
799 lstrcpyW((WCHAR
*)szString
, V_BSTR(&varresult
));
800 VariantClear(&varresult
);
804 static HRESULT
Record_StringDataPut(IDispatch
*pRecord
, int iField
, LPCWSTR szString
)
807 VARIANTARG vararg
[2];
808 DISPID dispid
= DISPID_PROPERTYPUT
;
809 DISPPARAMS dispparams
= {vararg
, &dispid
, sizeof(vararg
)/sizeof(VARIANTARG
), 1};
811 VariantInit(&vararg
[1]);
812 V_VT(&vararg
[1]) = VT_I4
;
813 V_I4(&vararg
[1]) = iField
;
814 VariantInit(&vararg
[0]);
815 V_VT(&vararg
[0]) = VT_BSTR
;
816 V_BSTR(&vararg
[0]) = SysAllocString(szString
);
818 return invoke(pRecord
, "StringData", DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, VT_BSTR
);
821 /* Test the various objects */
823 static void test_Database(IDispatch
*pDatabase
)
825 static WCHAR szSql
[] = { 'S','E','L','E','C','T',' ','`','F','e','a','t','u','r','e','`',' ','F','R','O','M',' ','`','F','e','a','t','u','r','e','`',' ','W','H','E','R','E',' ','`','F','e','a','t','u','r','e','_','P','a','r','e','n','t','`','=','\'','O','n','e','\'',0 };
826 static WCHAR szThree
[] = { 'T','h','r','e','e',0 };
827 static WCHAR szTwo
[] = { 'T','w','o',0 };
828 static WCHAR szStringDataField
[] = { 'S','t','r','i','n','g','D','a','t','a',',','F','i','e','l','d',0 };
829 IDispatch
*pView
= NULL
;
832 hr
= Database_OpenView(pDatabase
, szSql
, &pView
);
833 ok(SUCCEEDED(hr
), "Database_OpenView failed, hresult 0x%08x\n", hr
);
836 IDispatch
*pRecord
= NULL
;
837 WCHAR szString
[MAX_PATH
];
840 hr
= View_Execute(pView
, NULL
);
841 ok(SUCCEEDED(hr
), "View_Execute failed, hresult 0x%08x\n", hr
);
844 hr
= View_Fetch(pView
, &pRecord
);
845 ok(SUCCEEDED(hr
), "View_Fetch failed, hresult 0x%08x\n", hr
);
846 ok(pRecord
!= NULL
, "View_Fetch should not have returned NULL record\n");
849 /* Record::StringDataGet */
850 memset(szString
, 0, sizeof(szString
));
851 hr
= Record_StringDataGet(pRecord
, 1, szString
);
852 ok(SUCCEEDED(hr
), "Record_StringDataGet failed, hresult 0x%08x\n", hr
);
853 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString
, szThree
);
855 /* Record::StringDataPut with incorrect index */
856 hr
= Record_StringDataPut(pRecord
, -1, szString
);
857 ok(hr
== DISP_E_EXCEPTION
, "Record_StringDataPut failed, hresult 0x%08x\n", hr
);
858 ok_exception(hr
, szStringDataField
);
860 IDispatch_Release(pRecord
);
864 hr
= View_Fetch(pView
, &pRecord
);
865 ok(SUCCEEDED(hr
), "View_Fetch failed, hresult 0x%08x\n", hr
);
866 ok(pRecord
!= NULL
, "View_Fetch should not have returned NULL record\n");
869 /* Record::StringDataGet */
870 memset(szString
, 0, sizeof(szString
));
871 hr
= Record_StringDataGet(pRecord
, 1, szString
);
872 ok(SUCCEEDED(hr
), "Record_StringDataGet failed, hresult 0x%08x\n", hr
);
873 ok_w2("Record_StringDataGet result was %s but expected %s\n", szString
, szTwo
);
875 IDispatch_Release(pRecord
);
879 hr
= View_Fetch(pView
, &pRecord
);
880 ok(SUCCEEDED(hr
), "View_Fetch failed, hresult 0x%08x\n", hr
);
881 ok(pRecord
== NULL
, "View_Fetch should have returned NULL record\n");
883 IDispatch_Release(pRecord
);
886 hr
= View_Close(pView
);
887 ok(SUCCEEDED(hr
), "View_Close failed, hresult 0x%08x\n", hr
);
889 IDispatch_Release(pView
);
893 static void test_Session(IDispatch
*pSession
)
895 static WCHAR szProductName
[] = { 'P','r','o','d','u','c','t','N','a','m','e',0 };
896 static WCHAR szMSITEST
[] = { 'M','S','I','T','E','S','T',0 };
897 static WCHAR szOne
[] = { 'O','n','e',0 };
898 static WCHAR szCostInitialize
[] = { 'C','o','s','t','I','n','i','t','i','a','l','i','z','e',0 };
899 static WCHAR szEmpty
[] = { 0 };
900 static WCHAR szEquals
[] = { '=',0 };
901 static WCHAR szPropertyName
[] = { 'P','r','o','p','e','r','t','y',',','N','a','m','e',0 };
902 WCHAR stringw
[MAX_PATH
];
903 CHAR string
[MAX_PATH
];
907 IDispatch
*pDatabase
= NULL
, *pInst
= NULL
;
910 /* Session::Installer */
911 hr
= Session_Installer(pSession
, &pInst
);
912 ok(SUCCEEDED(hr
), "Session_Installer failed, hresult 0x%08x\n", hr
);
913 ok(pInst
!= NULL
, "Session_Installer returned NULL IDispatch pointer\n");
914 ok(pInst
== pInstaller
, "Session_Installer does not match Installer instance from CoCreateInstance\n");
916 /* Session::Property, get */
917 memset(stringw
, 0, sizeof(stringw
));
918 hr
= Session_PropertyGet(pSession
, szProductName
, stringw
);
919 ok(SUCCEEDED(hr
), "Session_PropertyGet failed, hresult 0x%08x\n", hr
);
920 if (lstrcmpW(stringw
, szMSITEST
) != 0)
922 len
= WideCharToMultiByte(CP_ACP
, 0, stringw
, -1, string
, MAX_PATH
, NULL
, NULL
);
923 ok(len
, "WideCharToMultiByteChar returned error %d\n", GetLastError());
924 ok(0, "Property \"ProductName\" expected to be \"MSITEST\" but was \"%s\"\n", string
);
927 /* Session::Property, put */
928 hr
= Session_PropertyPut(pSession
, szProductName
, szProductName
);
929 ok(SUCCEEDED(hr
), "Session_PropertyPut failed, hresult 0x%08x\n", hr
);
930 memset(stringw
, 0, sizeof(stringw
));
931 hr
= Session_PropertyGet(pSession
, szProductName
, stringw
);
932 ok(SUCCEEDED(hr
), "Session_PropertyGet failed, hresult 0x%08x\n", hr
);
933 if (lstrcmpW(stringw
, szProductName
) != 0)
935 len
= WideCharToMultiByte(CP_ACP
, 0, stringw
, -1, string
, MAX_PATH
, NULL
, NULL
);
936 ok(len
, "WideCharToMultiByteChar returned error %d\n", GetLastError());
937 ok(0, "Property \"ProductName\" expected to be \"ProductName\" but was \"%s\"\n", string
);
940 /* Try putting a property using empty property identifier */
941 hr
= Session_PropertyPut(pSession
, szEmpty
, szProductName
);
942 ok(hr
== DISP_E_EXCEPTION
, "Session_PropertyPut failed, hresult 0x%08x\n", hr
);
943 ok_exception(hr
, szPropertyName
);
945 /* Try putting a property using illegal property identifier */
946 hr
= Session_PropertyPut(pSession
, szEquals
, szProductName
);
947 ok(SUCCEEDED(hr
), "Session_PropertyPut failed, hresult 0x%08x\n", hr
);
949 /* Session::Language, get */
950 hr
= Session_LanguageGet(pSession
, &len
);
951 ok(SUCCEEDED(hr
), "Session_LanguageGet failed, hresult 0x%08x\n", hr
);
952 /* Not sure how to check the language is correct */
954 /* Session::Mode, get */
955 hr
= Session_ModeGet(pSession
, MSIRUNMODE_REBOOTATEND
, &bool);
956 ok(SUCCEEDED(hr
), "Session_ModeGet failed, hresult 0x%08x\n", hr
);
957 todo_wine
ok(!bool, "Reboot at end session mode is %d\n", bool);
959 /* Session::Mode, put */
960 hr
= Session_ModePut(pSession
, MSIRUNMODE_REBOOTATEND
, TRUE
);
961 todo_wine
ok(SUCCEEDED(hr
), "Session_ModePut failed, hresult 0x%08x\n", hr
);
962 hr
= Session_ModeGet(pSession
, MSIRUNMODE_REBOOTATEND
, &bool);
963 ok(SUCCEEDED(hr
), "Session_ModeGet failed, hresult 0x%08x\n", hr
);
964 ok(bool, "Reboot at end session mode is %d, expected 1\n", bool);
965 hr
= Session_ModePut(pSession
, MSIRUNMODE_REBOOTATEND
, FALSE
); /* set it again so we don't reboot */
966 todo_wine
ok(SUCCEEDED(hr
), "Session_ModePut failed, hresult 0x%08x\n", hr
);
968 /* Session::Database, get */
969 hr
= Session_Database(pSession
, &pDatabase
);
970 ok(SUCCEEDED(hr
), "Session_Database failed, hresult 0x%08x\n", hr
);
973 test_Database(pDatabase
);
974 IDispatch_Release(pDatabase
);
977 /* Session::DoAction(CostInitialize) must occur before the next statements */
978 hr
= Session_DoAction(pSession
, szCostInitialize
, &myint
);
979 ok(SUCCEEDED(hr
), "Session_DoAction failed, hresult 0x%08x\n", hr
);
980 ok(myint
== IDOK
, "DoAction(CostInitialize) returned %d, %d expected\n", myint
, IDOK
);
982 /* Session::SetInstallLevel */
983 hr
= Session_SetInstallLevel(pSession
, INSTALLLEVEL_MINIMUM
);
984 ok(SUCCEEDED(hr
), "Session_SetInstallLevel failed, hresult 0x%08x\n", hr
);
986 /* Session::FeatureCurrentState, get */
987 hr
= Session_FeatureCurrentState(pSession
, szOne
, &myint
);
988 ok(SUCCEEDED(hr
), "Session_FeatureCurrentState failed, hresult 0x%08x\n", hr
);
989 ok(myint
== INSTALLSTATE_UNKNOWN
, "Feature current state was %d but expected %d\n", myint
, INSTALLSTATE_UNKNOWN
);
991 /* Session::FeatureRequestState, put */
992 hr
= Session_FeatureRequestStatePut(pSession
, szOne
, INSTALLSTATE_ADVERTISED
);
993 ok(SUCCEEDED(hr
), "Session_FeatureRequestStatePut failed, hresult 0x%08x\n", hr
);
994 hr
= Session_FeatureRequestStateGet(pSession
, szOne
, &myint
);
995 ok(SUCCEEDED(hr
), "Session_FeatureRequestStateGet failed, hresult 0x%08x\n", hr
);
996 ok(myint
== INSTALLSTATE_ADVERTISED
, "Feature request state was %d but expected %d\n", myint
, INSTALLSTATE_ADVERTISED
);
999 static void test_Installer(void)
1001 static WCHAR szBackslash
[] = { '\\',0 };
1002 WCHAR szPath
[MAX_PATH
];
1005 IDispatch
*pSession
= NULL
, *pRecord
= NULL
;
1007 if (!pInstaller
) return;
1009 /* Installer::CreateRecord */
1011 hr
= Installer_CreateRecord(1, &pRecord
);
1012 ok(SUCCEEDED(hr
), "Installer_CreateRecord failed, hresult 0x%08x\n", hr
);
1013 ok(pRecord
!= NULL
, "Installer_CreateRecord should not have returned NULL record\n");
1017 int iFieldCount
= 0;
1019 /* Record::FieldCountGet */
1020 hr
= Record_FieldCountGet(pRecord
, &iFieldCount
);
1021 ok(SUCCEEDED(hr
), "Record_FiledCountGet failed, hresult 0x%08x\n", hr
);
1022 ok(iFieldCount
== 1, "Record_FieldCountGet result was %d but expected 1\n", iFieldCount
);
1024 IDispatch_Release(pRecord
);
1027 /* Prepare package */
1028 create_database(msifile
, tables
, sizeof(tables
) / sizeof(msi_table
));
1030 len
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, CURR_DIR
, -1, szPath
, MAX_PATH
);
1031 ok(len
, "MultiByteToWideChar returned error %d\n", GetLastError());
1034 lstrcatW(szPath
, szBackslash
);
1035 lstrcatW(szPath
, szMsifile
);
1037 /* Installer::OpenPackage */
1038 hr
= Installer_OpenPackage(szPath
, 0, &pSession
);
1039 ok(SUCCEEDED(hr
), "Installer_OpenPackage failed, hresult 0x%08x\n", hr
);
1042 test_Session(pSession
);
1043 IDispatch_Release(pSession
);
1046 DeleteFileA(msifile
);
1048 /* Installer::Version */
1050 memset(szPath
, 0, sizeof(szPath
));
1051 hr
= Installer_VersionGet(szPath
);
1052 ok(SUCCEEDED(hr
), "Installer_VersionGet failed, hresult 0x%08x\n", hr
);
1056 START_TEST(automation
)
1059 char temp_path
[MAX_PATH
], prev_path
[MAX_PATH
];
1064 GetCurrentDirectoryA(MAX_PATH
, prev_path
);
1065 GetTempPath(MAX_PATH
, temp_path
);
1066 SetCurrentDirectoryA(temp_path
);
1068 lstrcpyA(CURR_DIR
, temp_path
);
1069 len
= lstrlenA(CURR_DIR
);
1071 if(len
&& (CURR_DIR
[len
- 1] == '\\'))
1072 CURR_DIR
[len
- 1] = 0;
1074 hr
= OleInitialize(NULL
);
1075 ok (SUCCEEDED(hr
), "OleInitialize returned 0x%08x\n", hr
);
1076 hr
= CLSIDFromProgID(szProgId
, &clsid
);
1077 ok (SUCCEEDED(hr
), "CLSIDFromProgID returned 0x%08x\n", hr
);
1078 hr
= CoCreateInstance(&clsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void **)&pUnk
);
1079 ok(SUCCEEDED(hr
), "CoCreateInstance returned 0x%08x\n", hr
);
1083 hr
= IUnknown_QueryInterface(pUnk
, &IID_IDispatch
, (void **)&pInstaller
);
1084 ok (SUCCEEDED(hr
), "IUnknown::QueryInterface returned 0x%08x\n", hr
);
1090 hr
= IUnknown_Release(pUnk
);
1091 ok (SUCCEEDED(hr
), "IUnknown::Release returned 0x%08x\n", hr
);
1096 SetCurrentDirectoryA(prev_path
);