winmm: Fix a failing mixer test on 98 and ME.
[wine] / dlls / msi / tests / install.c
1 /*
2  * Copyright (C) 2006 James Hawkins
3  *
4  * A test program for installing MSI products.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define _WIN32_MSI 300
22 #define COBJMACROS
23
24 #include <stdio.h>
25
26 #include <windows.h>
27 #include <msiquery.h>
28 #include <msidefs.h>
29 #include <msi.h>
30 #include <fci.h>
31 #include <objidl.h>
32 #include <srrestoreptapi.h>
33
34 #include "wine/test.h"
35
36 static UINT (WINAPI *pMsiQueryComponentStateA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
38 static UINT (WINAPI *pMsiSourceListEnumSourcesA)
39     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
40 static UINT (WINAPI *pMsiSourceListGetInfoA)
41     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
42
43 static HMODULE hsrclient = 0;
44 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
45 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
46
47 static const char *msifile = "msitest.msi";
48 static const char *msifile2 = "winetest2.msi";
49 static const char *mstfile = "winetest.mst";
50 static CHAR CURR_DIR[MAX_PATH];
51 static CHAR PROG_FILES_DIR[MAX_PATH];
52 static CHAR COMMON_FILES_DIR[MAX_PATH];
53
54 /* msi database data */
55
56 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
57                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
58                                     "Component\tComponent\n"
59                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
60                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
61                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
62                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
63                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
64                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
65                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
66                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
67
68 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
69                                     "s72\tS72\tl255\n"
70                                     "Directory\tDirectory\n"
71                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
72                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
73                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
74                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
75                                     "NEWDIR\tCABOUTDIR\tnew\n"
76                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
77                                     "TARGETDIR\t\tSourceDir";
78
79 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
80                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
81                                   "Feature\tFeature\n"
82                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
83                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
84                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
85                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
86                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
87                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
88                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
89
90 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
91                                        "s38\ts72\n"
92                                        "FeatureComponents\tFeature_\tComponent_\n"
93                                        "Five\tFive\n"
94                                        "Four\tFour\n"
95                                        "One\tOne\n"
96                                        "Three\tThree\n"
97                                        "Two\tTwo\n"
98                                        "feature\tcomponent\n"
99                                        "service_feature\tservice_comp\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\t16384\t5\n"
105                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\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                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
111
112 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
113                                            "s72\tS255\tI2\n"
114                                            "InstallExecuteSequence\tAction\n"
115                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
116                                            "CostFinalize\t\t1000\n"
117                                            "CostInitialize\t\t800\n"
118                                            "FileCost\t\t900\n"
119                                            "ResolveSource\t\t950\n"
120                                            "MoveFiles\t\t1700\n"
121                                            "InstallFiles\t\t4000\n"
122                                            "DuplicateFiles\t\t4500\n"
123                                            "InstallServices\t\t5000\n"
124                                            "InstallFinalize\t\t6600\n"
125                                            "InstallInitialize\t\t1500\n"
126                                            "InstallValidate\t\t1400\n"
127                                            "LaunchConditions\t\t100\n"
128                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
129
130 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
131                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
132                                 "Media\tDiskId\n"
133                                 "1\t3\t\t\tDISK1\t\n"
134                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
135
136 static const CHAR property_dat[] = "Property\tValue\n"
137                                    "s72\tl0\n"
138                                    "Property\tProperty\n"
139                                    "DefaultUIFont\tDlgFont8\n"
140                                    "HASUIRUN\t0\n"
141                                    "INSTALLLEVEL\t3\n"
142                                    "InstallMode\tTypical\n"
143                                    "Manufacturer\tWine\n"
144                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
145                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
146                                    "ProductID\tnone\n"
147                                    "ProductLanguage\t1033\n"
148                                    "ProductName\tMSITEST\n"
149                                    "ProductVersion\t1.1.1\n"
150                                    "PROMPTROLLBACKCOST\tP\n"
151                                    "Setup\tSetup\n"
152                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
153                                    "AdminProperties\tPOSTADMIN\n"
154                                    "ROOTDRIVE\tC:\\\n"
155                                    "SERVNAME\tTestService\n"
156                                    "SERVDISP\tTestServiceDisp\n";
157
158 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
159                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
160                                    "Registry\tRegistry\n"
161                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
162                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
163                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
164                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
165
166 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
167                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
168                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
169                                           "ServiceInstall\tServiceInstall\n"
170                                           "TestService\t[SERVNAME]\t[SERVDISP]\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
171
172 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
173                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
174                                           "ServiceControl\tServiceControl\n"
175                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
176
177 /* tables for test_continuouscabs */
178 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
179                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
180                                        "Component\tComponent\n"
181                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
182                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
183                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
184
185 static const CHAR cc2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
186                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
187                                         "Component\tComponent\n"
188                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
189                                         "augustus\t\tMSITESTDIR\t0\t0\taugustus\n"
190                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
191
192 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
193                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
194                                      "Feature\tFeature\n"
195                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
196
197 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
198                                           "s38\ts72\n"
199                                           "FeatureComponents\tFeature_\tComponent_\n"
200                                           "feature\tmaximus\n"
201                                           "feature\taugustus\n"
202                                           "feature\tcaesar";
203
204 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
205                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
206                                   "File\tFile\n"
207                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
208                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
209                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
210
211 static const CHAR cc2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
212                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
213                                    "File\tFile\n"
214                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
215                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
216                                    "tiberius\tmaximus\ttiberius\t500\t\t\t16384\t3\n"
217                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
218
219 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
220                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
221                                    "Media\tDiskId\n"
222                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
223                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
224                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
225
226 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
227                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
228                                   "File\tFile\n"
229                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
230                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
231                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
232
233 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
234                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
235                                    "Media\tDiskId\n"
236                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
237                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
238                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
239
240 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
241                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
242                                     "Media\tDiskId\n"
243                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
244                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
245                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
246
247 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
248                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
249                                   "File\tFile\n"
250                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
251                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
252                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
253
254 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
255                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
256                                    "Media\tDiskId\n"
257                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
258
259 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
260                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
261                                    "Media\tDiskId\n"
262                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
263                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
264                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
265
266 /* tables for test_uiLevelFlags */
267 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
268                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
269                                        "Component\tComponent\n"
270                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
271                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
272                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
273
274 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
275                                            "s72\tS255\tI2\n"
276                                            "InstallUISequence\tAction\n"
277                                            "SetUIProperty\t\t5\n"
278                                            "ExecuteAction\t\t1100\n";
279
280 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
281                                            "s72\ti2\tS64\tS0\tS255\n"
282                                            "CustomAction\tAction\n"
283                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
284
285 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
286                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
287                                         "Component\tComponent\n"
288                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
289
290 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
291                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
292                                       "Feature\tFeature\n"
293                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
294                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
295
296 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
297                                            "s38\ts72\n"
298                                            "FeatureComponents\tFeature_\tComponent_\n"
299                                            "feature\tmaximus\n"
300                                            "montecristo\tmaximus";
301
302 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
303                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
304                                    "File\tFile\n"
305                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
306
307 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
308                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
309                                     "Media\tDiskId\n"
310                                     "1\t1\t\t\tDISK1\t\n";
311
312 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
313                                                "s72\tS255\tI2\n"
314                                                "InstallExecuteSequence\tAction\n"
315                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
316                                                "CostFinalize\t\t1000\n"
317                                                "CostInitialize\t\t800\n"
318                                                "FileCost\t\t900\n"
319                                                "InstallFiles\t\t4000\n"
320                                                "InstallFinalize\t\t6600\n"
321                                                "InstallInitialize\t\t1500\n"
322                                                "InstallValidate\t\t1400\n"
323                                                "LaunchConditions\t\t100\n"
324                                                "SetDirProperty\t\t950";
325
326 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
327                                             "s72\ti2\tS64\tS0\tS255\n"
328                                             "CustomAction\tAction\n"
329                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
330
331 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
332                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
333                                         "Component\tComponent\n"
334                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
335                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
336                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
337                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
338
339 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
340                                            "s38\ts72\n"
341                                            "FeatureComponents\tFeature_\tComponent_\n"
342                                            "feature\tmaximus\n"
343                                            "feature\taugustus\n"
344                                            "feature\tcaesar\n"
345                                            "feature\tgaius";
346
347 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
348                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
349                                    "File\tFile\n"
350                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
351                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
352                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
353                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
354
355 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
356                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
357                                     "Media\tDiskId\n"
358                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
359                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
360                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
361
362 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
363                                               "s72\tS255\tI2\n"
364                                               "InstallExecuteSequence\tAction\n"
365                                               "CostFinalize\t\t1000\n"
366                                               "CostInitialize\t\t800\n"
367                                               "FileCost\t\t900\n"
368                                               "InstallFiles\t\t4000\n"
369                                               "InstallServices\t\t5000\n"
370                                               "InstallFinalize\t\t6600\n"
371                                               "InstallInitialize\t\t1500\n"
372                                               "RunInstall\t\t1600\n"
373                                               "InstallValidate\t\t1400\n"
374                                               "LaunchConditions\t\t100";
375
376 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
377                                             "s72\ti2\tS64\tS0\tS255\n"
378                                             "CustomAction\tAction\n"
379                                             "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
380
381 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
382                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
383                                        "Component\tComponent\n"
384                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
385
386 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
387                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
388                                         "Component\tComponent\n"
389                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
390
391 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
392                                            "s38\ts72\n"
393                                            "FeatureComponents\tFeature_\tComponent_\n"
394                                            "feature\taugustus";
395
396 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
397                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
398                                    "File\tFile\n"
399                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
400
401 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
402                                             "s72\ti2\tS64\tS0\tS255\n"
403                                             "CustomAction\tAction\n"
404                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
405
406 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
407                                                "s72\tS255\tI2\n"
408                                                "InstallExecuteSequence\tAction\n"
409                                                "CostFinalize\t\t1000\n"
410                                                "CostInitialize\t\t800\n"
411                                                "FileCost\t\t900\n"
412                                                "SetFolderProp\t\t950\n"
413                                                "InstallFiles\t\t4000\n"
414                                                "InstallServices\t\t5000\n"
415                                                "InstallFinalize\t\t6600\n"
416                                                "InstallInitialize\t\t1500\n"
417                                                "InstallValidate\t\t1400\n"
418                                                "LaunchConditions\t\t100";
419
420 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
421                                              "s72\tS255\tI2\n"
422                                              "InstallUISequence\tAction\n"
423                                              "CostInitialize\t\t800\n"
424                                              "FileCost\t\t900\n"
425                                              "CostFinalize\t\t1000\n"
426                                              "ExecuteAction\t\t1100\n";
427
428 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
429                                               "s72\tS255\tI2\n"
430                                               "InstallExecuteSequence\tAction\n"
431                                               "ValidateProductID\t\t700\n"
432                                               "CostInitialize\t\t800\n"
433                                               "FileCost\t\t900\n"
434                                               "CostFinalize\t\t1000\n"
435                                               "InstallValidate\t\t1400\n"
436                                               "InstallInitialize\t\t1500\n"
437                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
438                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
439                                               "RemoveFiles\t\t3500\n"
440                                               "InstallFiles\t\t4000\n"
441                                               "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
442                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
443                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
444                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
445                                               "InstallFinalize\t\t6600";
446
447 static const CHAR ppc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
448                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
449                                         "Component\tComponent\n"
450                                         "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n"
451                                         "augustus\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\taugustus\n";
452
453 static const CHAR ppc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
454                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
455                                    "File\tFile\n"
456                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1\n"
457                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t2";
458
459 static const CHAR ppc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
460                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
461                                     "Media\tDiskId\n"
462                                     "1\t2\t\t\tDISK1\t\n";
463
464 static const CHAR ppc_feature_comp_dat[] = "Feature_\tComponent_\n"
465                                            "s38\ts72\n"
466                                            "FeatureComponents\tFeature_\tComponent_\n"
467                                            "feature\tmaximus\n"
468                                            "feature\taugustus\n"
469                                            "montecristo\tmaximus";
470
471 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
472                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
473                                        "Component\tComponent\n"
474                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
475
476 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
477                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
478                                         "Component\tComponent\n"
479                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
480
481 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
482                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
483                                         "Component\tComponent\n"
484                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
485
486 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
487                                             "s72\ti2\tS64\tS0\tS255\n"
488                                             "CustomAction\tAction\n"
489                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
490
491 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
492                                              "s72\tS255\tI2\n"
493                                              "AdminExecuteSequence\tAction\n"
494                                              "CostFinalize\t\t1000\n"
495                                              "CostInitialize\t\t800\n"
496                                              "FileCost\t\t900\n"
497                                              "SetPOSTADMIN\t\t950\n"
498                                              "InstallFiles\t\t4000\n"
499                                              "InstallFinalize\t\t6600\n"
500                                              "InstallInitialize\t\t1500\n"
501                                              "InstallValidate\t\t1400\n"
502                                              "LaunchConditions\t\t100";
503
504 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
505                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
506                                         "Component\tComponent\n"
507                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718\taugustus\n";
508
509 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
510                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
511                                         "Component\tComponent\n"
512                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
513                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
514                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
515
516 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
517                                            "s38\ts72\n"
518                                            "FeatureComponents\tFeature_\tComponent_\n"
519                                            "feature\thydrogen\n"
520                                            "feature\thelium\n"
521                                            "feature\tlithium";
522
523 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
524                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
525                                    "File\tFile\n"
526                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
527                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
528                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
529
530 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
531                                                "s72\tS255\tI2\n"
532                                                "InstallExecuteSequence\tAction\n"
533                                                "ValidateProductID\t\t700\n"
534                                                "CostInitialize\t\t800\n"
535                                                "FileCost\t\t900\n"
536                                                "CostFinalize\t\t1000\n"
537                                                "InstallValidate\t\t1400\n"
538                                                "InstallInitialize\t\t1500\n"
539                                                "ProcessComponents\t\t1600\n"
540                                                "UnpublishFeatures\t\t1800\n"
541                                                "RemoveFiles\t\t3500\n"
542                                                "InstallFiles\t\t4000\n"
543                                                "RegisterProduct\t\t6100\n"
544                                                "PublishFeatures\t\t6300\n"
545                                                "PublishProduct\t\t6400\n"
546                                                "InstallFinalize\t\t6600";
547
548 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
549                                            "s72\ts72\tS255\ts72\tI2\n"
550                                            "RemoveFile\tFileKey\n"
551                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
552                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
553                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
554                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
555                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
556                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
557                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
558                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
559                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n"
560                                            "nanoacre\thydrogen\t\tCABOUTDIR\t3\n";
561
562 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
563                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
564                                         "MoveFile\tFileKey\n"
565                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
566                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
567                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
568                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
569                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
570                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
571                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
572                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
573                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
574                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
575                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
576                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
577                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
578                                         "pakistan\taugustus\tperu\tsfn|poland\tSourceDir\tMSITESTDIR\t1\n"
579                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
580                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
581                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
582                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
583
584 static const CHAR mc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
585                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
586                                         "Component\tComponent\n"
587                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
588                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
589                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
590                                         "gaius\t\tMSITESTDIR\t0\tGAIUS=1\tgaius\n";
591
592 static const CHAR mc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
593                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
594                                   "File\tFile\n"
595                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
596                                   "augustus\taugustus\taugustus\t500\t\t\t0\t2\n"
597                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3\n"
598                                   "gaius\tgaius\tgaius\t500\t\t\t16384\t4";
599
600 static const CHAR mc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
601                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
602                                    "Media\tDiskId\n"
603                                    "1\t1\t\ttest1.cab\tDISK1\t\n"
604                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
605                                    "3\t3\t\ttest3.cab\tDISK3\t\n"
606                                    "4\t4\t\ttest3.cab\tDISK3\t\n";
607
608 static const CHAR mc_file_hash_dat[] = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"
609                                        "s72\ti2\ti4\ti4\ti4\ti4\n"
610                                        "MsiFileHash\tFile_\n"
611                                        "caesar\t0\t850433704\t-241429251\t675791761\t-1221108824";
612
613 static const CHAR df_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
614                                        "s72\tS72\tl255\n"
615                                        "Directory\tDirectory\n"
616                                        "THIS\tMSITESTDIR\tthis\n"
617                                        "DOESNOT\tTHIS\tdoesnot\n"
618                                        "NONEXISTENT\tDOESNOT\texist\n"
619                                        "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
620                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
621                                        "TARGETDIR\t\tSourceDir";
622
623 static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestName\tDestFolder\n"
624                                             "s72\ts72\ts72\tS255\tS72\n"
625                                             "DuplicateFile\tFileKey\n"
626                                             "maximus\tmaximus\tmaximus\taugustus\t\n"
627                                             "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n";
628
629 static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
630                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
631                                         "Component\tComponent\n"
632                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
633
634 static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
635                                        "s72\ti2\tl255\tL255\tL0\ts72\n"
636                                        "Registry\tRegistry\n"
637                                        "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus";
638
639 static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
640                                          "s72\tS38\ts72\ti2\tS255\tS72\n"
641                                          "Component\tComponent\n"
642                                          "augustus\t\tMSITESTDIR\t0\tMYPROP=42\taugustus\n";
643
644 static const CHAR ca51_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
645                                                 "s72\tS255\tI2\n"
646                                                 "InstallExecuteSequence\tAction\n"
647                                                 "ValidateProductID\t\t700\n"
648                                                 "GoodSetProperty\t\t725\n"
649                                                 "BadSetProperty\t\t750\n"
650                                                 "CostInitialize\t\t800\n"
651                                                 "ResolveSource\t\t810\n"
652                                                 "FileCost\t\t900\n"
653                                                 "SetSourceDir\tSRCDIR\t910\n"
654                                                 "CostFinalize\t\t1000\n"
655                                                 "InstallValidate\t\t1400\n"
656                                                 "InstallInitialize\t\t1500\n"
657                                                 "InstallFiles\t\t4000\n"
658                                                 "InstallFinalize\t\t6600";
659
660 static const CHAR ca51_custom_action_dat[] = "Action\tType\tSource\tTarget\n"
661                                              "s72\ti2\tS64\tS0\n"
662                                              "CustomAction\tAction\n"
663                                              "GoodSetProperty\t51\tMYPROP\t42\n"
664                                              "BadSetProperty\t51\t\tMYPROP\n"
665                                              "SetSourceDir\t51\tSourceDir\t[SRCDIR]\n";
666
667 static const CHAR is_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
668                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
669                                      "Feature\tFeature\n"
670                                      "one\t\t\t\t2\t1\t\t0\n" /* favorLocal */
671                                      "two\t\t\t\t2\t1\t\t1\n" /* favorSource */
672                                      "three\t\t\t\t2\t1\t\t4\n" /* favorAdvertise */
673                                      "four\t\t\t\t2\t0\t\t0"; /* disabled */
674
675 static const CHAR is_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
676                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
677                                        "Component\tComponent\n"
678                                        "alpha\t\tMSITESTDIR\t0\t\talpha_file\n" /* favorLocal:Local */
679                                        "beta\t\tMSITESTDIR\t1\t\tbeta_file\n" /* favorLocal:Source */
680                                        "gamma\t\tMSITESTDIR\t2\t\tgamma_file\n" /* favorLocal:Optional */
681                                        "theta\t\tMSITESTDIR\t0\t\ttheta_file\n" /* favorSource:Local */
682                                        "delta\t\tMSITESTDIR\t1\t\tdelta_file\n" /* favorSource:Source */
683                                        "epsilon\t\tMSITESTDIR\t2\t\tepsilon_file\n" /* favorSource:Optional */
684                                        "zeta\t\tMSITESTDIR\t0\t\tzeta_file\n" /* favorAdvertise:Local */
685                                        "iota\t\tMSITESTDIR\t1\t\tiota_file\n" /* favorAdvertise:Source */
686                                        "eta\t\tMSITESTDIR\t2\t\teta_file\n" /* favorAdvertise:Optional */
687                                        "kappa\t\tMSITESTDIR\t0\t\tkappa_file\n" /* disabled:Local */
688                                        "lambda\t\tMSITESTDIR\t1\t\tlambda_file\n" /* disabled:Source */
689                                        "mu\t\tMSITESTDIR\t2\t\tmu_file\n"; /* disabled:Optional */
690
691 static const CHAR is_feature_comp_dat[] = "Feature_\tComponent_\n"
692                                           "s38\ts72\n"
693                                           "FeatureComponents\tFeature_\tComponent_\n"
694                                           "one\talpha\n"
695                                           "one\tbeta\n"
696                                           "one\tgamma\n"
697                                           "two\ttheta\n"
698                                           "two\tdelta\n"
699                                           "two\tepsilon\n"
700                                           "three\tzeta\n"
701                                           "three\tiota\n"
702                                           "three\teta\n"
703                                           "four\tkappa\n"
704                                           "four\tlambda\n"
705                                           "four\tmu";
706
707 static const CHAR is_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
708                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
709                                   "File\tFile\n"
710                                   "alpha_file\talpha\talpha\t500\t\t\t8192\t1\n"
711                                   "beta_file\tbeta\tbeta\t500\t\t\t8291\t2\n"
712                                   "gamma_file\tgamma\tgamma\t500\t\t\t8192\t3\n"
713                                   "theta_file\ttheta\ttheta\t500\t\t\t8192\t4\n"
714                                   "delta_file\tdelta\tdelta\t500\t\t\t8192\t5\n"
715                                   "epsilon_file\tepsilon\tepsilon\t500\t\t\t8192\t6\n"
716                                   "zeta_file\tzeta\tzeta\t500\t\t\t8192\t7\n"
717                                   "iota_file\tiota\tiota\t500\t\t\t8192\t8\n"
718                                   "eta_file\teta\teta\t500\t\t\t8192\t9\n"
719                                   "kappa_file\tkappa\tkappa\t500\t\t\t8192\t10\n"
720                                   "lambda_file\tlambda\tlambda\t500\t\t\t8192\t11\n"
721                                   "mu_file\tmu\tmu\t500\t\t\t8192\t12";
722
723 static const CHAR is_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
724                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
725                                    "Media\tDiskId\n"
726                                    "1\t12\t\t\tDISK1\t\n";
727
728 static const CHAR sp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
729                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
730                                         "Component\tComponent\n"
731                                         "augustus\t\tTWODIR\t0\t\taugustus\n";
732
733 static const CHAR sp_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
734                                        "s72\tS72\tl255\n"
735                                        "Directory\tDirectory\n"
736                                        "TARGETDIR\t\tSourceDir\n"
737                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
738                                        "MSITESTDIR\tProgramFilesFolder\tmsitest:.\n"
739                                        "ONEDIR\tMSITESTDIR\t.:shortone|longone\n"
740                                        "TWODIR\tONEDIR\t.:shorttwo|longtwo";
741
742 static const CHAR mcp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
743                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
744                                         "Component\tComponent\n"
745                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
746                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
747                                         "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
748
749 static const CHAR mcp_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
750                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
751                                       "Feature\tFeature\n"
752                                       "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
753                                       "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
754                                       "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
755
756 static const CHAR mcp_feature_comp_dat[] = "Feature_\tComponent_\n"
757                                            "s38\ts72\n"
758                                            "FeatureComponents\tFeature_\tComponent_\n"
759                                            "hydroxyl\thydrogen\n"
760                                            "heliox\thelium\n"
761                                            "lithia\tlithium";
762
763 static const CHAR mcomp_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
764                                      "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
765                                      "File\tFile\n"
766                                      "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
767                                      "helium\thelium\thelium\t0\t\t\t8192\t1\n"
768                                      "lithium\tlithium\tlithium\t0\t\t\t8192\t1\n"
769                                      "beryllium\tmissingcomp\tberyllium\t0\t\t\t8192\t1";
770
771 static const CHAR ai_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
772                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
773                                   "File\tFile\n"
774                                   "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
775                                   "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
776                                   "one.txt\tOne\tone.txt\t1000\t\t\t16384\t1\n"
777                                   "three.txt\tThree\tthree.txt\t1000\t\t\t16384\t3\n"
778                                   "two.txt\tTwo\ttwo.txt\t1000\t\t\t16384\t2\n"
779                                   "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
780                                   "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
781
782 typedef struct _msi_table
783 {
784     const CHAR *filename;
785     const CHAR *data;
786     int size;
787 } msi_table;
788
789 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
790
791 static const msi_table tables[] =
792 {
793     ADD_TABLE(component),
794     ADD_TABLE(directory),
795     ADD_TABLE(feature),
796     ADD_TABLE(feature_comp),
797     ADD_TABLE(file),
798     ADD_TABLE(install_exec_seq),
799     ADD_TABLE(media),
800     ADD_TABLE(property),
801     ADD_TABLE(registry),
802     ADD_TABLE(service_install),
803     ADD_TABLE(service_control)
804 };
805
806 static const msi_table cc_tables[] =
807 {
808     ADD_TABLE(cc_component),
809     ADD_TABLE(directory),
810     ADD_TABLE(cc_feature),
811     ADD_TABLE(cc_feature_comp),
812     ADD_TABLE(cc_file),
813     ADD_TABLE(install_exec_seq),
814     ADD_TABLE(cc_media),
815     ADD_TABLE(property),
816 };
817
818 static const msi_table cc2_tables[] =
819 {
820     ADD_TABLE(cc2_component),
821     ADD_TABLE(directory),
822     ADD_TABLE(cc_feature),
823     ADD_TABLE(cc_feature_comp),
824     ADD_TABLE(cc2_file),
825     ADD_TABLE(install_exec_seq),
826     ADD_TABLE(cc_media),
827     ADD_TABLE(property),
828 };
829
830 static const msi_table co_tables[] =
831 {
832     ADD_TABLE(cc_component),
833     ADD_TABLE(directory),
834     ADD_TABLE(cc_feature),
835     ADD_TABLE(cc_feature_comp),
836     ADD_TABLE(co_file),
837     ADD_TABLE(install_exec_seq),
838     ADD_TABLE(co_media),
839     ADD_TABLE(property),
840 };
841
842 static const msi_table co2_tables[] =
843 {
844     ADD_TABLE(cc_component),
845     ADD_TABLE(directory),
846     ADD_TABLE(cc_feature),
847     ADD_TABLE(cc_feature_comp),
848     ADD_TABLE(cc_file),
849     ADD_TABLE(install_exec_seq),
850     ADD_TABLE(co2_media),
851     ADD_TABLE(property),
852 };
853
854 static const msi_table mm_tables[] =
855 {
856     ADD_TABLE(cc_component),
857     ADD_TABLE(directory),
858     ADD_TABLE(cc_feature),
859     ADD_TABLE(cc_feature_comp),
860     ADD_TABLE(mm_file),
861     ADD_TABLE(install_exec_seq),
862     ADD_TABLE(mm_media),
863     ADD_TABLE(property),
864 };
865
866 static const msi_table ss_tables[] =
867 {
868     ADD_TABLE(cc_component),
869     ADD_TABLE(directory),
870     ADD_TABLE(cc_feature),
871     ADD_TABLE(cc_feature_comp),
872     ADD_TABLE(cc_file),
873     ADD_TABLE(install_exec_seq),
874     ADD_TABLE(ss_media),
875     ADD_TABLE(property),
876 };
877
878 static const msi_table ui_tables[] =
879 {
880     ADD_TABLE(ui_component),
881     ADD_TABLE(directory),
882     ADD_TABLE(cc_feature),
883     ADD_TABLE(cc_feature_comp),
884     ADD_TABLE(cc_file),
885     ADD_TABLE(install_exec_seq),
886     ADD_TABLE(ui_install_ui_seq),
887     ADD_TABLE(ui_custom_action),
888     ADD_TABLE(cc_media),
889     ADD_TABLE(property),
890 };
891
892 static const msi_table rof_tables[] =
893 {
894     ADD_TABLE(rof_component),
895     ADD_TABLE(directory),
896     ADD_TABLE(rof_feature),
897     ADD_TABLE(rof_feature_comp),
898     ADD_TABLE(rof_file),
899     ADD_TABLE(install_exec_seq),
900     ADD_TABLE(rof_media),
901     ADD_TABLE(property),
902 };
903
904 static const msi_table sdp_tables[] =
905 {
906     ADD_TABLE(rof_component),
907     ADD_TABLE(directory),
908     ADD_TABLE(rof_feature),
909     ADD_TABLE(rof_feature_comp),
910     ADD_TABLE(rof_file),
911     ADD_TABLE(sdp_install_exec_seq),
912     ADD_TABLE(sdp_custom_action),
913     ADD_TABLE(rof_media),
914     ADD_TABLE(property),
915 };
916
917 static const msi_table cie_tables[] =
918 {
919     ADD_TABLE(cie_component),
920     ADD_TABLE(directory),
921     ADD_TABLE(cc_feature),
922     ADD_TABLE(cie_feature_comp),
923     ADD_TABLE(cie_file),
924     ADD_TABLE(install_exec_seq),
925     ADD_TABLE(cie_media),
926     ADD_TABLE(property),
927 };
928
929 static const msi_table ci_tables[] =
930 {
931     ADD_TABLE(ci_component),
932     ADD_TABLE(directory),
933     ADD_TABLE(rof_feature),
934     ADD_TABLE(rof_feature_comp),
935     ADD_TABLE(rof_file),
936     ADD_TABLE(ci_install_exec_seq),
937     ADD_TABLE(rof_media),
938     ADD_TABLE(property),
939     ADD_TABLE(ci_custom_action),
940 };
941
942 static const msi_table ci2_tables[] =
943 {
944     ADD_TABLE(ci2_component),
945     ADD_TABLE(directory),
946     ADD_TABLE(rof_feature),
947     ADD_TABLE(ci2_feature_comp),
948     ADD_TABLE(ci2_file),
949     ADD_TABLE(install_exec_seq),
950     ADD_TABLE(rof_media),
951     ADD_TABLE(property),
952 };
953
954 static const msi_table spf_tables[] =
955 {
956     ADD_TABLE(ci_component),
957     ADD_TABLE(directory),
958     ADD_TABLE(rof_feature),
959     ADD_TABLE(rof_feature_comp),
960     ADD_TABLE(rof_file),
961     ADD_TABLE(spf_install_exec_seq),
962     ADD_TABLE(rof_media),
963     ADD_TABLE(property),
964     ADD_TABLE(spf_custom_action),
965     ADD_TABLE(spf_install_ui_seq),
966 };
967
968 static const msi_table pp_tables[] =
969 {
970     ADD_TABLE(ci_component),
971     ADD_TABLE(directory),
972     ADD_TABLE(rof_feature),
973     ADD_TABLE(rof_feature_comp),
974     ADD_TABLE(rof_file),
975     ADD_TABLE(pp_install_exec_seq),
976     ADD_TABLE(rof_media),
977     ADD_TABLE(property),
978 };
979
980 static const msi_table ppc_tables[] =
981 {
982     ADD_TABLE(ppc_component),
983     ADD_TABLE(directory),
984     ADD_TABLE(rof_feature),
985     ADD_TABLE(ppc_feature_comp),
986     ADD_TABLE(ppc_file),
987     ADD_TABLE(pp_install_exec_seq),
988     ADD_TABLE(ppc_media),
989     ADD_TABLE(property),
990 };
991
992 static const msi_table tp_tables[] =
993 {
994     ADD_TABLE(tp_component),
995     ADD_TABLE(directory),
996     ADD_TABLE(rof_feature),
997     ADD_TABLE(ci2_feature_comp),
998     ADD_TABLE(ci2_file),
999     ADD_TABLE(install_exec_seq),
1000     ADD_TABLE(rof_media),
1001     ADD_TABLE(property),
1002 };
1003
1004 static const msi_table cwd_tables[] =
1005 {
1006     ADD_TABLE(cwd_component),
1007     ADD_TABLE(directory),
1008     ADD_TABLE(rof_feature),
1009     ADD_TABLE(ci2_feature_comp),
1010     ADD_TABLE(ci2_file),
1011     ADD_TABLE(install_exec_seq),
1012     ADD_TABLE(rof_media),
1013     ADD_TABLE(property),
1014 };
1015
1016 static const msi_table adm_tables[] =
1017 {
1018     ADD_TABLE(adm_component),
1019     ADD_TABLE(directory),
1020     ADD_TABLE(rof_feature),
1021     ADD_TABLE(ci2_feature_comp),
1022     ADD_TABLE(ci2_file),
1023     ADD_TABLE(install_exec_seq),
1024     ADD_TABLE(rof_media),
1025     ADD_TABLE(property),
1026     ADD_TABLE(adm_custom_action),
1027     ADD_TABLE(adm_admin_exec_seq),
1028 };
1029
1030 static const msi_table amp_tables[] =
1031 {
1032     ADD_TABLE(amp_component),
1033     ADD_TABLE(directory),
1034     ADD_TABLE(rof_feature),
1035     ADD_TABLE(ci2_feature_comp),
1036     ADD_TABLE(ci2_file),
1037     ADD_TABLE(install_exec_seq),
1038     ADD_TABLE(rof_media),
1039     ADD_TABLE(property),
1040 };
1041
1042 static const msi_table rem_tables[] =
1043 {
1044     ADD_TABLE(rem_component),
1045     ADD_TABLE(directory),
1046     ADD_TABLE(rof_feature),
1047     ADD_TABLE(rem_feature_comp),
1048     ADD_TABLE(rem_file),
1049     ADD_TABLE(rem_install_exec_seq),
1050     ADD_TABLE(rof_media),
1051     ADD_TABLE(property),
1052     ADD_TABLE(rem_remove_files),
1053 };
1054
1055 static const msi_table mov_tables[] =
1056 {
1057     ADD_TABLE(cwd_component),
1058     ADD_TABLE(directory),
1059     ADD_TABLE(rof_feature),
1060     ADD_TABLE(ci2_feature_comp),
1061     ADD_TABLE(ci2_file),
1062     ADD_TABLE(install_exec_seq),
1063     ADD_TABLE(rof_media),
1064     ADD_TABLE(property),
1065     ADD_TABLE(mov_move_file),
1066 };
1067
1068 static const msi_table mc_tables[] =
1069 {
1070     ADD_TABLE(mc_component),
1071     ADD_TABLE(directory),
1072     ADD_TABLE(cc_feature),
1073     ADD_TABLE(cie_feature_comp),
1074     ADD_TABLE(mc_file),
1075     ADD_TABLE(install_exec_seq),
1076     ADD_TABLE(mc_media),
1077     ADD_TABLE(property),
1078     ADD_TABLE(mc_file_hash),
1079 };
1080
1081 static const msi_table df_tables[] =
1082 {
1083     ADD_TABLE(rof_component),
1084     ADD_TABLE(df_directory),
1085     ADD_TABLE(rof_feature),
1086     ADD_TABLE(rof_feature_comp),
1087     ADD_TABLE(rof_file),
1088     ADD_TABLE(install_exec_seq),
1089     ADD_TABLE(rof_media),
1090     ADD_TABLE(property),
1091     ADD_TABLE(df_duplicate_file),
1092 };
1093
1094 static const msi_table wrv_tables[] =
1095 {
1096     ADD_TABLE(wrv_component),
1097     ADD_TABLE(directory),
1098     ADD_TABLE(rof_feature),
1099     ADD_TABLE(ci2_feature_comp),
1100     ADD_TABLE(ci2_file),
1101     ADD_TABLE(install_exec_seq),
1102     ADD_TABLE(rof_media),
1103     ADD_TABLE(property),
1104     ADD_TABLE(wrv_registry),
1105 };
1106
1107 static const msi_table sf_tables[] =
1108 {
1109     ADD_TABLE(wrv_component),
1110     ADD_TABLE(directory),
1111     ADD_TABLE(rof_feature),
1112     ADD_TABLE(ci2_feature_comp),
1113     ADD_TABLE(ci2_file),
1114     ADD_TABLE(install_exec_seq),
1115     ADD_TABLE(rof_media),
1116     ADD_TABLE(property),
1117 };
1118
1119 static const msi_table ca51_tables[] =
1120 {
1121     ADD_TABLE(ca51_component),
1122     ADD_TABLE(directory),
1123     ADD_TABLE(rof_feature),
1124     ADD_TABLE(ci2_feature_comp),
1125     ADD_TABLE(ci2_file),
1126     ADD_TABLE(ca51_install_exec_seq),
1127     ADD_TABLE(rof_media),
1128     ADD_TABLE(property),
1129     ADD_TABLE(ca51_custom_action),
1130 };
1131
1132 static const msi_table is_tables[] =
1133 {
1134     ADD_TABLE(is_component),
1135     ADD_TABLE(directory),
1136     ADD_TABLE(is_feature),
1137     ADD_TABLE(is_feature_comp),
1138     ADD_TABLE(is_file),
1139     ADD_TABLE(install_exec_seq),
1140     ADD_TABLE(is_media),
1141     ADD_TABLE(property),
1142 };
1143
1144 static const msi_table sp_tables[] =
1145 {
1146     ADD_TABLE(sp_component),
1147     ADD_TABLE(sp_directory),
1148     ADD_TABLE(rof_feature),
1149     ADD_TABLE(ci2_feature_comp),
1150     ADD_TABLE(ci2_file),
1151     ADD_TABLE(install_exec_seq),
1152     ADD_TABLE(rof_media),
1153     ADD_TABLE(property),
1154 };
1155
1156 static const msi_table mcp_tables[] =
1157 {
1158     ADD_TABLE(mcp_component),
1159     ADD_TABLE(directory),
1160     ADD_TABLE(mcp_feature),
1161     ADD_TABLE(mcp_feature_comp),
1162     ADD_TABLE(rem_file),
1163     ADD_TABLE(rem_install_exec_seq),
1164     ADD_TABLE(rof_media),
1165     ADD_TABLE(property),
1166 };
1167
1168 static const msi_table mcomp_tables[] =
1169 {
1170     ADD_TABLE(mcp_component),
1171     ADD_TABLE(directory),
1172     ADD_TABLE(mcp_feature),
1173     ADD_TABLE(mcp_feature_comp),
1174     ADD_TABLE(mcomp_file),
1175     ADD_TABLE(rem_install_exec_seq),
1176     ADD_TABLE(rof_media),
1177     ADD_TABLE(property),
1178 };
1179
1180 static const msi_table ai_tables[] =
1181 {
1182     ADD_TABLE(component),
1183     ADD_TABLE(directory),
1184     ADD_TABLE(feature),
1185     ADD_TABLE(feature_comp),
1186     ADD_TABLE(ai_file),
1187     ADD_TABLE(install_exec_seq),
1188     ADD_TABLE(media),
1189     ADD_TABLE(property)
1190 };
1191
1192 /* cabinet definitions */
1193
1194 /* make the max size large so there is only one cab file */
1195 #define MEDIA_SIZE          0x7FFFFFFF
1196 #define FOLDER_THRESHOLD    900000
1197
1198 /* the FCI callbacks */
1199
1200 static void *mem_alloc(ULONG cb)
1201 {
1202     return HeapAlloc(GetProcessHeap(), 0, cb);
1203 }
1204
1205 static void mem_free(void *memory)
1206 {
1207     HeapFree(GetProcessHeap(), 0, memory);
1208 }
1209
1210 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
1211 {
1212     sprintf(pccab->szCab, pv, pccab->iCab);
1213     return TRUE;
1214 }
1215
1216 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
1217 {
1218     return 0;
1219 }
1220
1221 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
1222                        BOOL fContinuation, void *pv)
1223 {
1224     return 0;
1225 }
1226
1227 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
1228 {
1229     HANDLE handle;
1230     DWORD dwAccess = 0;
1231     DWORD dwShareMode = 0;
1232     DWORD dwCreateDisposition = OPEN_EXISTING;
1233     
1234     dwAccess = GENERIC_READ | GENERIC_WRITE;
1235     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
1236     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1237
1238     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
1239         dwCreateDisposition = OPEN_EXISTING;
1240     else
1241         dwCreateDisposition = CREATE_NEW;
1242
1243     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
1244                          dwCreateDisposition, 0, NULL);
1245
1246     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
1247
1248     return (INT_PTR)handle;
1249 }
1250
1251 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1252 {
1253     HANDLE handle = (HANDLE)hf;
1254     DWORD dwRead;
1255     BOOL res;
1256     
1257     res = ReadFile(handle, memory, cb, &dwRead, NULL);
1258     ok(res, "Failed to ReadFile\n");
1259
1260     return dwRead;
1261 }
1262
1263 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1264 {
1265     HANDLE handle = (HANDLE)hf;
1266     DWORD dwWritten;
1267     BOOL res;
1268
1269     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1270     ok(res, "Failed to WriteFile\n");
1271
1272     return dwWritten;
1273 }
1274
1275 static int fci_close(INT_PTR hf, int *err, void *pv)
1276 {
1277     HANDLE handle = (HANDLE)hf;
1278     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1279
1280     return 0;
1281 }
1282
1283 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
1284 {
1285     HANDLE handle = (HANDLE)hf;
1286     DWORD ret;
1287     
1288     ret = SetFilePointer(handle, dist, NULL, seektype);
1289     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1290
1291     return ret;
1292 }
1293
1294 static int fci_delete(char *pszFile, int *err, void *pv)
1295 {
1296     BOOL ret = DeleteFileA(pszFile);
1297     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1298
1299     return 0;
1300 }
1301
1302 static void init_functionpointers(void)
1303 {
1304     HMODULE hmsi = GetModuleHandleA("msi.dll");
1305
1306 #define GET_PROC(mod, func) \
1307     p ## func = (void*)GetProcAddress(mod, #func); \
1308     if(!p ## func) \
1309       trace("GetProcAddress(%s) failed\n", #func);
1310
1311     GET_PROC(hmsi, MsiQueryComponentStateA);
1312     GET_PROC(hmsi, MsiSourceListEnumSourcesA);
1313     GET_PROC(hmsi, MsiSourceListGetInfoA);
1314
1315     hsrclient = LoadLibraryA("srclient.dll");
1316     GET_PROC(hsrclient, SRRemoveRestorePoint);
1317     GET_PROC(hsrclient, SRSetRestorePointA);
1318
1319 #undef GET_PROC
1320 }
1321
1322 static void get_user_sid(LPSTR *usersid)
1323 {
1324     HANDLE token;
1325     BYTE buf[1024];
1326     DWORD size;
1327     PTOKEN_USER user;
1328     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
1329     static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
1330
1331     *usersid = NULL;
1332     pConvertSidToStringSidA = (void *)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
1333     if (!pConvertSidToStringSidA)
1334         return;
1335
1336     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1337     size = sizeof(buf);
1338     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
1339     user = (PTOKEN_USER)buf;
1340     pConvertSidToStringSidA(user->User.Sid, usersid);
1341 }
1342
1343 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1344 {
1345     CHAR buffer[0x20];
1346     UINT r;
1347     DWORD sz;
1348
1349     sz = sizeof buffer;
1350     r = MsiRecordGetString(rec, field, buffer, &sz);
1351     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1352 }
1353
1354 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1355 {
1356     LPSTR tempname;
1357
1358     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1359     GetTempFileNameA(".", "xx", 0, tempname);
1360
1361     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1362     {
1363         lstrcpyA(pszTempName, tempname);
1364         HeapFree(GetProcessHeap(), 0, tempname);
1365         return TRUE;
1366     }
1367
1368     HeapFree(GetProcessHeap(), 0, tempname);
1369
1370     return FALSE;
1371 }
1372
1373 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1374                              USHORT *pattribs, int *err, void *pv)
1375 {
1376     BY_HANDLE_FILE_INFORMATION finfo;
1377     FILETIME filetime;
1378     HANDLE handle;
1379     DWORD attrs;
1380     BOOL res;
1381
1382     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1383                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1384
1385     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1386
1387     res = GetFileInformationByHandle(handle, &finfo);
1388     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1389    
1390     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1391     FileTimeToDosDateTime(&filetime, pdate, ptime);
1392
1393     attrs = GetFileAttributes(pszName);
1394     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1395
1396     return (INT_PTR)handle;
1397 }
1398
1399 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1400 {
1401     char path[MAX_PATH];
1402     char filename[MAX_PATH];
1403
1404     lstrcpyA(path, CURR_DIR);
1405     lstrcatA(path, "\\");
1406     lstrcatA(path, file);
1407
1408     lstrcpyA(filename, file);
1409
1410     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
1411                       progress, get_open_info, compress);
1412 }
1413
1414 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
1415 {
1416     ZeroMemory(pCabParams, sizeof(CCAB));
1417
1418     pCabParams->cb = max_size;
1419     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
1420     pCabParams->setID = 0xbeef;
1421     pCabParams->iCab = 1;
1422     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1423     lstrcatA(pCabParams->szCabPath, "\\");
1424     lstrcpyA(pCabParams->szCab, name);
1425 }
1426
1427 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1428 {
1429     CCAB cabParams;
1430     LPCSTR ptr;
1431     HFCI hfci;
1432     ERF erf;
1433     BOOL res;
1434
1435     set_cab_parameters(&cabParams, name, max_size);
1436
1437     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1438                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1439                       get_temp_file, &cabParams, NULL);
1440
1441     ok(hfci != NULL, "Failed to create an FCI context\n");
1442
1443     ptr = files;
1444     while (*ptr)
1445     {
1446         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1447         ok(res, "Failed to add file: %s\n", ptr);
1448         ptr += lstrlen(ptr) + 1;
1449     }
1450
1451     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1452     ok(res, "Failed to flush the cabinet\n");
1453
1454     res = FCIDestroy(hfci);
1455     ok(res, "Failed to destroy the cabinet\n");
1456 }
1457
1458 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1459 {
1460     HKEY hkey;
1461     DWORD type, size;
1462
1463     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1464                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1465         return FALSE;
1466
1467     size = MAX_PATH;
1468     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1469         RegCloseKey(hkey);
1470         return FALSE;
1471     }
1472
1473     size = MAX_PATH;
1474     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1475         RegCloseKey(hkey);
1476         return FALSE;
1477     }
1478
1479     RegCloseKey(hkey);
1480     return TRUE;
1481 }
1482
1483 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1484 {
1485     HANDLE file;
1486     DWORD written;
1487
1488     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1489     if (file == INVALID_HANDLE_VALUE)
1490         return;
1491
1492     WriteFile(file, data, strlen(data), &written, NULL);
1493
1494     if (size)
1495     {
1496         SetFilePointer(file, size, NULL, FILE_BEGIN);
1497         SetEndOfFile(file);
1498     }
1499
1500     CloseHandle(file);
1501 }
1502
1503 #define create_file(name, size) create_file_data(name, name, size)
1504
1505 static void create_test_files(void)
1506 {
1507     CreateDirectoryA("msitest", NULL);
1508     create_file("msitest\\one.txt", 100);
1509     CreateDirectoryA("msitest\\first", NULL);
1510     create_file("msitest\\first\\two.txt", 100);
1511     CreateDirectoryA("msitest\\second", NULL);
1512     create_file("msitest\\second\\three.txt", 100);
1513
1514     create_file("four.txt", 100);
1515     create_file("five.txt", 100);
1516     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1517
1518     create_file("msitest\\filename", 100);
1519     create_file("msitest\\service.exe", 100);
1520
1521     DeleteFileA("four.txt");
1522     DeleteFileA("five.txt");
1523 }
1524
1525 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1526 {
1527     CHAR path[MAX_PATH];
1528
1529     lstrcpyA(path, PROG_FILES_DIR);
1530     lstrcatA(path, "\\");
1531     lstrcatA(path, rel_path);
1532
1533     if (is_file)
1534         return DeleteFileA(path);
1535     else
1536         return RemoveDirectoryA(path);
1537 }
1538
1539 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1540 {
1541     CHAR path[MAX_PATH];
1542
1543     lstrcpyA(path, COMMON_FILES_DIR);
1544     lstrcatA(path, "\\");
1545     lstrcatA(path, rel_path);
1546
1547     if (is_file)
1548         return DeleteFileA(path);
1549     else
1550         return RemoveDirectoryA(path);
1551 }
1552
1553 static void delete_test_files(void)
1554 {
1555     DeleteFileA("msitest.msi");
1556     DeleteFileA("msitest.cab");
1557     DeleteFileA("msitest\\second\\three.txt");
1558     DeleteFileA("msitest\\first\\two.txt");
1559     DeleteFileA("msitest\\one.txt");
1560     DeleteFileA("msitest\\service.exe");
1561     DeleteFileA("msitest\\filename");
1562     RemoveDirectoryA("msitest\\second");
1563     RemoveDirectoryA("msitest\\first");
1564     RemoveDirectoryA("msitest");
1565 }
1566
1567 static void write_file(const CHAR *filename, const char *data, int data_size)
1568 {
1569     DWORD size;
1570
1571     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1572                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1573
1574     WriteFile(hf, data, data_size, &size, NULL);
1575     CloseHandle(hf);
1576 }
1577
1578 static void write_msi_summary_info(MSIHANDLE db, INT wordcount)
1579 {
1580     MSIHANDLE summary;
1581     UINT r;
1582
1583     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1584     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1585
1586     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1587     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1588
1589     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1590                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1591     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1592
1593     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1594     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1595
1596     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1597     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1598
1599     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1601
1602     /* write the summary changes back to the stream */
1603     r = MsiSummaryInfoPersist(summary);
1604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1605
1606     MsiCloseHandle(summary);
1607 }
1608
1609 #define create_database(name, tables, num_tables) \
1610     create_database_wordcount(name, tables, num_tables, 0);
1611
1612 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1613                                       int num_tables, INT wordcount)
1614 {
1615     MSIHANDLE db;
1616     UINT r;
1617     int j;
1618
1619     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1620     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1621
1622     /* import the tables into the database */
1623     for (j = 0; j < num_tables; j++)
1624     {
1625         const msi_table *table = &tables[j];
1626
1627         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1628
1629         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1630         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1631
1632         DeleteFileA(table->filename);
1633     }
1634
1635     write_msi_summary_info(db, wordcount);
1636
1637     r = MsiDatabaseCommit(db);
1638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1639
1640     MsiCloseHandle(db);
1641 }
1642
1643 static void check_service_is_installed(void)
1644 {
1645     SC_HANDLE scm, service;
1646     BOOL res;
1647
1648     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1649     ok(scm != NULL, "Failed to open the SC Manager\n");
1650
1651     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1652     ok(service != NULL, "Failed to open TestService\n");
1653
1654     res = DeleteService(service);
1655     ok(res, "Failed to delete TestService\n");
1656
1657     CloseServiceHandle(service);
1658     CloseServiceHandle(scm);
1659 }
1660
1661 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1662 {
1663     RESTOREPOINTINFOA spec;
1664
1665     spec.dwEventType = event_type;
1666     spec.dwRestorePtType = APPLICATION_INSTALL;
1667     spec.llSequenceNumber = status->llSequenceNumber;
1668     lstrcpyA(spec.szDescription, "msitest restore point");
1669
1670     return pSRSetRestorePointA(&spec, status);
1671 }
1672
1673 static void remove_restore_point(DWORD seq_number)
1674 {
1675     DWORD res;
1676
1677     res = pSRRemoveRestorePoint(seq_number);
1678     if (res != ERROR_SUCCESS)
1679         trace("Failed to remove the restore point : %08x\n", res);
1680 }
1681
1682 static void test_MsiInstallProduct(void)
1683 {
1684     UINT r;
1685     CHAR path[MAX_PATH];
1686     LONG res;
1687     HKEY hkey;
1688     DWORD num, size, type;
1689     SC_HANDLE scm;
1690
1691     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1692     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1693     {
1694         skip("Services are not implemented, we are most likely on win9x\n");
1695         return;
1696     }
1697     CloseServiceHandle(scm);
1698
1699     create_test_files();
1700     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1701
1702     r = MsiInstallProductA(msifile, NULL);
1703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1704
1705     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1706     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1707     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1708     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1709     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1710     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1711     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1712     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1713     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1714     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1715     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1716     ok(delete_pf("msitest", FALSE), "File not installed\n");
1717
1718     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1720
1721     size = MAX_PATH;
1722     type = REG_SZ;
1723     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1724     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1725     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1726
1727     size = MAX_PATH;
1728     type = REG_SZ;
1729     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1730     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1731
1732     size = sizeof(num);
1733     type = REG_DWORD;
1734     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1735     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1736     ok(num == 314, "Expected 314, got %d\n", num);
1737
1738     size = MAX_PATH;
1739     type = REG_SZ;
1740     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1741     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1742     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1743
1744     check_service_is_installed();
1745
1746     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1747
1748     delete_test_files();
1749 }
1750
1751 static void test_MsiSetComponentState(void)
1752 {
1753     INSTALLSTATE installed, action;
1754     MSIHANDLE package;
1755     char path[MAX_PATH];
1756     UINT r;
1757
1758     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1759
1760     CoInitialize(NULL);
1761
1762     lstrcpy(path, CURR_DIR);
1763     lstrcat(path, "\\");
1764     lstrcat(path, msifile);
1765
1766     r = MsiOpenPackage(path, &package);
1767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1768
1769     r = MsiDoAction(package, "CostInitialize");
1770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1771
1772     r = MsiDoAction(package, "FileCost");
1773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1774
1775     r = MsiDoAction(package, "CostFinalize");
1776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1777
1778     r = MsiGetComponentState(package, "dangler", &installed, &action);
1779     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1780     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1781     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1782
1783     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1784     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1785
1786     MsiCloseHandle(package);
1787     CoUninitialize();
1788
1789     DeleteFileA(msifile);
1790 }
1791
1792 static void test_packagecoltypes(void)
1793 {
1794     MSIHANDLE hdb, view, rec;
1795     char path[MAX_PATH];
1796     LPCSTR query;
1797     UINT r, count;
1798
1799     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1800
1801     CoInitialize(NULL);
1802
1803     lstrcpy(path, CURR_DIR);
1804     lstrcat(path, "\\");
1805     lstrcat(path, msifile);
1806
1807     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1809
1810     query = "SELECT * FROM `Media`";
1811     r = MsiDatabaseOpenView( hdb, query, &view );
1812     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1813
1814     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1815     count = MsiRecordGetFieldCount( rec );
1816     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1817     ok(count == 6, "Expected 6, got %d\n", count);
1818     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1819     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1820     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1821     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1822     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1823     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1824     MsiCloseHandle(rec);
1825
1826     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1827     count = MsiRecordGetFieldCount( rec );
1828     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1829     ok(count == 6, "Expected 6, got %d\n", count);
1830     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1831     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1832     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1833     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1834     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1835     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1836
1837     MsiCloseHandle(rec);
1838     MsiCloseHandle(view);
1839     MsiCloseHandle(hdb);
1840     CoUninitialize();
1841
1842     DeleteFile(msifile);
1843 }
1844
1845 static void create_cc_test_files(void)
1846 {
1847     CCAB cabParams;
1848     HFCI hfci;
1849     ERF erf;
1850     static CHAR cab_context[] = "test%d.cab";
1851     BOOL res;
1852
1853     create_file("maximus", 500);
1854     create_file("augustus", 50000);
1855     create_file("tiberius", 500);
1856     create_file("caesar", 500);
1857
1858     set_cab_parameters(&cabParams, "test1.cab", 40000);
1859
1860     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1861                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1862                       get_temp_file, &cabParams, cab_context);
1863     ok(hfci != NULL, "Failed to create an FCI context\n");
1864
1865     res = add_file(hfci, "maximus", tcompTYPE_NONE);
1866     ok(res, "Failed to add file maximus\n");
1867
1868     res = add_file(hfci, "augustus", tcompTYPE_NONE);
1869     ok(res, "Failed to add file augustus\n");
1870
1871     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
1872     ok(res, "Failed to add file tiberius\n");
1873
1874     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1875     ok(res, "Failed to flush the cabinet\n");
1876
1877     res = FCIDestroy(hfci);
1878     ok(res, "Failed to destroy the cabinet\n");
1879
1880     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1881
1882     DeleteFile("maximus");
1883     DeleteFile("augustus");
1884     DeleteFile("tiberius");
1885     DeleteFile("caesar");
1886 }
1887
1888 static void delete_cab_files(void)
1889 {
1890     SHFILEOPSTRUCT shfl;
1891     CHAR path[MAX_PATH+10];
1892
1893     lstrcpyA(path, CURR_DIR);
1894     lstrcatA(path, "\\*.cab");
1895     path[strlen(path) + 1] = '\0';
1896
1897     shfl.hwnd = NULL;
1898     shfl.wFunc = FO_DELETE;
1899     shfl.pFrom = path;
1900     shfl.pTo = NULL;
1901     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1902
1903     SHFileOperation(&shfl);
1904 }
1905
1906 static void test_continuouscabs(void)
1907 {
1908     UINT r;
1909
1910     create_cc_test_files();
1911     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1912
1913     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1914
1915     r = MsiInstallProductA(msifile, NULL);
1916     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1917     {
1918         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1919         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1920         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1921         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1922         ok(delete_pf("msitest", FALSE), "File not installed\n");
1923     }
1924
1925     delete_cab_files();
1926     DeleteFile(msifile);
1927
1928     create_cc_test_files();
1929     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
1930
1931     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1932
1933     r = MsiInstallProductA(msifile, NULL);
1934     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1935     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1936     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1937     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
1938     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1939     ok(delete_pf("msitest", FALSE), "File not installed\n");
1940
1941     delete_cab_files();
1942     DeleteFile(msifile);
1943 }
1944
1945 static void test_caborder(void)
1946 {
1947     UINT r;
1948
1949     create_file("imperator", 100);
1950     create_file("maximus", 500);
1951     create_file("augustus", 50000);
1952     create_file("caesar", 500);
1953
1954     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1955
1956     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1957
1958     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1959     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1960     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1961
1962     r = MsiInstallProductA(msifile, NULL);
1963     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1964     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1965     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1966     todo_wine
1967     {
1968         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1969         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1970     }
1971
1972     delete_cab_files();
1973
1974     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1975     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1976     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1977
1978     r = MsiInstallProductA(msifile, NULL);
1979     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1980     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1981     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1982     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1983     todo_wine
1984     {
1985         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1986     }
1987
1988     delete_cab_files();
1989     DeleteFile(msifile);
1990
1991     create_cc_test_files();
1992     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1993
1994     r = MsiInstallProductA(msifile, NULL);
1995     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1996     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1997     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1998     todo_wine
1999     {
2000         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2001         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2002     }
2003
2004     delete_cab_files();
2005     DeleteFile(msifile);
2006
2007     create_cc_test_files();
2008     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
2009
2010     r = MsiInstallProductA(msifile, NULL);
2011     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2012     todo_wine
2013     {
2014         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2015         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2016         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2017         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2018     }
2019
2020     delete_cab_files();
2021     DeleteFile("imperator");
2022     DeleteFile("maximus");
2023     DeleteFile("augustus");
2024     DeleteFile("caesar");
2025     DeleteFile(msifile);
2026 }
2027
2028 static void test_mixedmedia(void)
2029 {
2030     UINT r;
2031
2032     CreateDirectoryA("msitest", NULL);
2033     create_file("msitest\\maximus", 500);
2034     create_file("msitest\\augustus", 500);
2035     create_file("caesar", 500);
2036
2037     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
2038
2039     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2040
2041     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
2042
2043     r = MsiInstallProductA(msifile, NULL);
2044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2045     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2046     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2047     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2048     ok(delete_pf("msitest", FALSE), "File not installed\n");
2049
2050     /* Delete the files in the temp (current) folder */
2051     DeleteFile("msitest\\maximus");
2052     DeleteFile("msitest\\augustus");
2053     RemoveDirectory("msitest");
2054     DeleteFile("caesar");
2055     DeleteFile("test1.cab");
2056     DeleteFile(msifile);
2057 }
2058
2059 static void test_samesequence(void)
2060 {
2061     UINT r;
2062
2063     create_cc_test_files();
2064     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
2065
2066     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2067
2068     r = MsiInstallProductA(msifile, NULL);
2069     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2070     {
2071         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2072         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2073         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2074         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2075         ok(delete_pf("msitest", FALSE), "File not installed\n");
2076     }
2077
2078     delete_cab_files();
2079     DeleteFile(msifile);
2080 }
2081
2082 static void test_uiLevelFlags(void)
2083 {
2084     UINT r;
2085
2086     create_cc_test_files();
2087     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
2088
2089     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
2090
2091     r = MsiInstallProductA(msifile, NULL);
2092     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2093     {
2094         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2095         ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
2096         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2097         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2098         ok(delete_pf("msitest", FALSE), "File not installed\n");
2099     }
2100
2101     delete_cab_files();
2102     DeleteFile(msifile);
2103 }
2104
2105 static BOOL file_matches(LPSTR path)
2106 {
2107     CHAR buf[MAX_PATH];
2108     HANDLE file;
2109     DWORD size;
2110
2111     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2112                       NULL, OPEN_EXISTING, 0, NULL);
2113
2114     ZeroMemory(buf, MAX_PATH);
2115     ReadFile(file, buf, 15, &size, NULL);
2116     CloseHandle(file);
2117
2118     return !lstrcmp(buf, "msitest\\maximus");
2119 }
2120
2121 static void test_readonlyfile(void)
2122 {
2123     UINT r;
2124     DWORD size;
2125     HANDLE file;
2126     CHAR path[MAX_PATH];
2127
2128     CreateDirectoryA("msitest", NULL);
2129     create_file("msitest\\maximus", 500);
2130     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
2131
2132     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2133
2134     lstrcpy(path, PROG_FILES_DIR);
2135     lstrcat(path, "\\msitest");
2136     CreateDirectory(path, NULL);
2137
2138     lstrcat(path, "\\maximus");
2139     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2140                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
2141
2142     WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL);
2143     CloseHandle(file);
2144
2145     r = MsiInstallProductA(msifile, NULL);
2146     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2147     ok(file_matches(path), "Expected file to be overwritten\n");
2148     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2149     ok(delete_pf("msitest", FALSE), "File not installed\n");
2150
2151     /* Delete the files in the temp (current) folder */
2152     DeleteFile("msitest\\maximus");
2153     RemoveDirectory("msitest");
2154     DeleteFile(msifile);
2155 }
2156
2157 static void test_setdirproperty(void)
2158 {
2159     UINT r;
2160
2161     CreateDirectoryA("msitest", NULL);
2162     create_file("msitest\\maximus", 500);
2163     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
2164
2165     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2166
2167     r = MsiInstallProductA(msifile, NULL);
2168     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2169     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
2170     ok(delete_cf("msitest", FALSE), "File not installed\n");
2171
2172     /* Delete the files in the temp (current) folder */
2173     DeleteFile(msifile);
2174     DeleteFile("msitest\\maximus");
2175     RemoveDirectory("msitest");
2176 }
2177
2178 static void test_cabisextracted(void)
2179 {
2180     UINT r;
2181
2182     CreateDirectoryA("msitest", NULL);
2183     create_file("msitest\\gaius", 500);
2184     create_file("maximus", 500);
2185     create_file("augustus", 500);
2186     create_file("caesar", 500);
2187
2188     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2189     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
2190     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2191
2192     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
2193
2194     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2195
2196     r = MsiInstallProductA(msifile, NULL);
2197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2198     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2199     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2200     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2201     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
2202     ok(delete_pf("msitest", FALSE), "File not installed\n");
2203
2204     /* Delete the files in the temp (current) folder */
2205     delete_cab_files();
2206     DeleteFile(msifile);
2207     DeleteFile("maximus");
2208     DeleteFile("augustus");
2209     DeleteFile("caesar");
2210     DeleteFile("msitest\\gaius");
2211     RemoveDirectory("msitest");
2212 }
2213
2214 static void test_concurrentinstall(void)
2215 {
2216     UINT r;
2217     CHAR path[MAX_PATH];
2218
2219     CreateDirectoryA("msitest", NULL);
2220     CreateDirectoryA("msitest\\msitest", NULL);
2221     create_file("msitest\\maximus", 500);
2222     create_file("msitest\\msitest\\augustus", 500);
2223
2224     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
2225
2226     lstrcpyA(path, CURR_DIR);
2227     lstrcatA(path, "\\msitest\\concurrent.msi");
2228     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
2229
2230     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2231
2232     r = MsiInstallProductA(msifile, NULL);
2233     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2234     if (!delete_pf("msitest\\augustus", TRUE))
2235         trace("concurrent installs not supported\n");
2236     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2237     ok(delete_pf("msitest", FALSE), "File not installed\n");
2238
2239     DeleteFile(path);
2240
2241     r = MsiInstallProductA(msifile, NULL);
2242     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2243     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2244     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2245     ok(delete_pf("msitest", FALSE), "File not installed\n");
2246
2247     DeleteFile(msifile);
2248     DeleteFile("msitest\\msitest\\augustus");
2249     DeleteFile("msitest\\maximus");
2250     RemoveDirectory("msitest\\msitest");
2251     RemoveDirectory("msitest");
2252 }
2253
2254 static void test_setpropertyfolder(void)
2255 {
2256     UINT r;
2257     CHAR path[MAX_PATH];
2258
2259     lstrcpyA(path, PROG_FILES_DIR);
2260     lstrcatA(path, "\\msitest\\added");
2261
2262     CreateDirectoryA("msitest", NULL);
2263     create_file("msitest\\maximus", 500);
2264
2265     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
2266
2267     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2268
2269     r = MsiInstallProductA(msifile, NULL);
2270     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2271     if (GetFileAttributesA(path) == FILE_ATTRIBUTE_DIRECTORY)
2272     {
2273         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
2274         ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
2275         ok(delete_pf("msitest", FALSE), "File not installed\n");
2276     }
2277     else
2278     {
2279         trace("changing folder property not supported\n");
2280         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2281         ok(delete_pf("msitest", FALSE), "File not installed\n");
2282     }
2283
2284     /* Delete the files in the temp (current) folder */
2285     DeleteFile(msifile);
2286     DeleteFile("msitest\\maximus");
2287     RemoveDirectory("msitest");
2288 }
2289
2290 static BOOL file_exists(LPCSTR file)
2291 {
2292     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2293 }
2294
2295 static BOOL pf_exists(LPCSTR file)
2296 {
2297     CHAR path[MAX_PATH];
2298
2299     lstrcpyA(path, PROG_FILES_DIR);
2300     lstrcatA(path, "\\");
2301     lstrcatA(path, file);
2302
2303     return file_exists(path);
2304 }
2305
2306 static void delete_pfmsitest_files(void)
2307 {
2308     SHFILEOPSTRUCT shfl;
2309     CHAR path[MAX_PATH+11];
2310
2311     lstrcpyA(path, PROG_FILES_DIR);
2312     lstrcatA(path, "\\msitest\\*");
2313     path[strlen(path) + 1] = '\0';
2314
2315     shfl.hwnd = NULL;
2316     shfl.wFunc = FO_DELETE;
2317     shfl.pFrom = path;
2318     shfl.pTo = NULL;
2319     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2320
2321     SHFileOperation(&shfl);
2322
2323     lstrcpyA(path, PROG_FILES_DIR);
2324     lstrcatA(path, "\\msitest");
2325     RemoveDirectoryA(path);
2326 }
2327
2328 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2329 {
2330     char val[MAX_PATH];
2331     DWORD size, type;
2332     LONG res;
2333
2334     size = MAX_PATH;
2335     val[0] = '\0';
2336     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2337
2338     if (res != ERROR_SUCCESS ||
2339         (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ))
2340     {
2341         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2342         return;
2343     }
2344
2345     if (!expected)
2346         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2347     else
2348     {
2349         if (bcase)
2350             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2351         else
2352             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2353     }
2354 }
2355
2356 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2357 {
2358     DWORD val, size, type;
2359     LONG res;
2360
2361     size = sizeof(DWORD);
2362     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2363
2364     if (res != ERROR_SUCCESS || type != REG_DWORD)
2365     {
2366         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2367         return;
2368     }
2369
2370     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2371 }
2372
2373 #define CHECK_REG_STR(prodkey, name, expected) \
2374     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2375
2376 #define CHECK_DEL_REG_STR(prodkey, name, expected) \
2377     check_reg_str(prodkey, name, expected, TRUE, __LINE__); \
2378     RegDeleteValueA(prodkey, name);
2379
2380 #define CHECK_REG_ISTR(prodkey, name, expected) \
2381     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2382
2383 #define CHECK_DEL_REG_ISTR(prodkey, name, expected) \
2384     check_reg_str(prodkey, name, expected, FALSE, __LINE__); \
2385     RegDeleteValueA(prodkey, name);
2386
2387 #define CHECK_REG_DWORD(prodkey, name, expected) \
2388     check_reg_dword(prodkey, name, expected, __LINE__);
2389
2390 #define CHECK_DEL_REG_DWORD(prodkey, name, expected) \
2391     check_reg_dword(prodkey, name, expected, __LINE__); \
2392     RegDeleteValueA(prodkey, name);
2393
2394 static void get_date_str(LPSTR date)
2395 {
2396     SYSTEMTIME systime;
2397
2398     static const char date_fmt[] = "%d%02d%02d";
2399     GetLocalTime(&systime);
2400     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2401 }
2402
2403 static void test_publish_registerproduct(void)
2404 {
2405     UINT r;
2406     LONG res;
2407     HKEY hkey;
2408     HKEY props, usage;
2409     LPSTR usersid;
2410     char date[MAX_PATH];
2411     char temp[MAX_PATH];
2412     char keypath[MAX_PATH];
2413
2414     static const CHAR uninstall[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2415                                     "\\Uninstall\\{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2416     static const CHAR userdata[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
2417                                    "\\UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2418     static const CHAR ugkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
2419                                 "\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
2420     static const CHAR userugkey[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
2421                                     "\\51AAE0C44620A5E4788506E91F249BD2";
2422
2423     get_user_sid(&usersid);
2424     if (!usersid)
2425     {
2426         skip("ConvertSidToStringSidA is not available\n");
2427         return;
2428     }
2429
2430     get_date_str(date);
2431     GetTempPath(MAX_PATH, temp);
2432
2433     CreateDirectoryA("msitest", NULL);
2434     create_file("msitest\\maximus", 500);
2435
2436     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2437
2438     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2439
2440     /* RegisterProduct */
2441     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2443     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2444     ok(delete_pf("msitest", FALSE), "File not installed\n");
2445
2446     res = RegOpenKeyA(HKEY_CURRENT_USER, userugkey, &hkey);
2447     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2448
2449     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
2450     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2451
2452     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
2453     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
2454     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
2455     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
2456     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2457     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
2458     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2459     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
2460     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
2461     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
2462     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
2463     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
2464     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
2465     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
2466     CHECK_DEL_REG_STR(hkey, "Size", NULL);
2467     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
2468     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
2469     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2470     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2471     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
2472     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
2473     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
2474     todo_wine
2475     {
2476         CHECK_DEL_REG_DWORD(hkey, "EstimatedSize", 12);
2477     }
2478
2479     RegDeleteKeyA(hkey, "");
2480     RegCloseKey(hkey);
2481
2482     sprintf(keypath, userdata, usersid);
2483     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2484     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2485
2486     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2487     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2488
2489     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
2490     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
2491     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
2492     CHECK_DEL_REG_STR(props, "InstallDate", date);
2493     CHECK_DEL_REG_STR(props, "InstallSource", temp);
2494     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2495     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
2496     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2497     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
2498     CHECK_DEL_REG_STR(props, "Comments", NULL);
2499     CHECK_DEL_REG_STR(props, "Contact", NULL);
2500     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
2501     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
2502     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
2503     CHECK_DEL_REG_STR(props, "Readme", NULL);
2504     CHECK_DEL_REG_STR(props, "Size", NULL);
2505     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
2506     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
2507     CHECK_DEL_REG_DWORD(props, "Language", 1033);
2508     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
2509     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
2510     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
2511     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
2512     todo_wine
2513     {
2514         CHECK_DEL_REG_DWORD(props, "EstimatedSize", 12);
2515     }
2516
2517     RegDeleteKeyA(props, "");
2518     RegCloseKey(props);
2519
2520     res = RegOpenKeyA(hkey, "Usage", &usage);
2521     todo_wine
2522     {
2523         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2524     }
2525
2526     RegDeleteKeyA(usage, "");
2527     RegCloseKey(usage);
2528     RegDeleteKeyA(hkey, "");
2529     RegCloseKey(hkey);
2530
2531     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
2532     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2533
2534     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2535
2536     RegDeleteKeyA(hkey, "");
2537     RegCloseKey(hkey);
2538
2539     /* RegisterProduct, machine */
2540     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 ALLUSERS=1");
2541     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2542     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2543     ok(delete_pf("msitest", FALSE), "File not installed\n");
2544
2545     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, userugkey, &hkey);
2546     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2547
2548     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
2549     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2550
2551     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
2552     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
2553     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
2554     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
2555     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2556     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
2557     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2558     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
2559     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
2560     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
2561     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
2562     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
2563     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
2564     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
2565     CHECK_DEL_REG_STR(hkey, "Size", NULL);
2566     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
2567     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
2568     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2569     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2570     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
2571     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
2572     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
2573     todo_wine
2574     {
2575         CHECK_DEL_REG_DWORD(hkey, "EstimatedSize", 12);
2576     }
2577
2578     RegDeleteKeyA(hkey, "");
2579     RegCloseKey(hkey);
2580
2581     sprintf(keypath, userdata, "S-1-5-18");
2582     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2583     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2584
2585     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2586     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2587
2588     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
2589     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
2590     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
2591     CHECK_DEL_REG_STR(props, "InstallDate", date);
2592     CHECK_DEL_REG_STR(props, "InstallSource", temp);
2593     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2594     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
2595     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2596     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
2597     CHECK_DEL_REG_STR(props, "Comments", NULL);
2598     CHECK_DEL_REG_STR(props, "Contact", NULL);
2599     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
2600     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
2601     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
2602     CHECK_DEL_REG_STR(props, "Readme", NULL);
2603     CHECK_DEL_REG_STR(props, "Size", NULL);
2604     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
2605     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
2606     CHECK_DEL_REG_DWORD(props, "Language", 1033);
2607     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
2608     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
2609     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
2610     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
2611     todo_wine
2612     {
2613         CHECK_DEL_REG_DWORD(props, "EstimatedSize", 12);
2614     }
2615
2616     RegDeleteKeyA(props, "");
2617     RegCloseKey(props);
2618
2619     res = RegOpenKeyA(hkey, "Usage", &usage);
2620     todo_wine
2621     {
2622         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2623     }
2624
2625     RegDeleteKeyA(usage, "");
2626     RegCloseKey(usage);
2627     RegDeleteKeyA(hkey, "");
2628     RegCloseKey(hkey);
2629
2630     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
2631     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2632
2633     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2634
2635     RegDeleteKeyA(hkey, "");
2636     RegCloseKey(hkey);
2637
2638     DeleteFile(msifile);
2639     DeleteFile("msitest\\maximus");
2640     RemoveDirectory("msitest");
2641     HeapFree(GetProcessHeap(), 0, usersid);
2642 }
2643
2644 static void test_publish_publishproduct(void)
2645 {
2646     UINT r;
2647     LONG res;
2648     LPSTR usersid;
2649     HKEY sourcelist, net, props;
2650     HKEY hkey, patches, media;
2651     CHAR keypath[MAX_PATH];
2652     CHAR temp[MAX_PATH];
2653     CHAR path[MAX_PATH];
2654
2655     static const CHAR prodpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2656                                    "\\Installer\\UserData\\%s\\Products"
2657                                    "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2658     static const CHAR cuprodpath[] = "Software\\Microsoft\\Installer\\Products"
2659                                      "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2660     static const CHAR cuupgrades[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
2661                                      "\\51AAE0C44620A5E4788506E91F249BD2";
2662     static const CHAR badprod[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2663                                   "\\Installer\\Products"
2664                                   "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2665     static const CHAR machprod[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2666     static const CHAR machup[] = "Installer\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
2667
2668     get_user_sid(&usersid);
2669     if (!usersid)
2670     {
2671         skip("ConvertSidToStringSidA is not available\n");
2672         return;
2673     }
2674
2675     GetTempPath(MAX_PATH, temp);
2676
2677     CreateDirectoryA("msitest", NULL);
2678     create_file("msitest\\maximus", 500);
2679
2680     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2681
2682     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2683
2684     /* PublishProduct, current user */
2685     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2686     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2687     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2688     ok(delete_pf("msitest", FALSE), "File not installed\n");
2689
2690     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
2691     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2692
2693     sprintf(keypath, prodpath, usersid);
2694     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2695     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2696
2697     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2698     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2699
2700     res = RegOpenKeyA(hkey, "Patches", &patches);
2701     todo_wine
2702     {
2703         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2704
2705         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
2706     }
2707
2708     RegDeleteKeyA(patches, "");
2709     RegCloseKey(patches);
2710     RegDeleteKeyA(hkey, "");
2711     RegCloseKey(hkey);
2712
2713     res = RegOpenKeyA(HKEY_CURRENT_USER, cuprodpath, &hkey);
2714     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2715
2716     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
2717     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
2718     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2719     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2720     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
2721     CHECK_DEL_REG_DWORD(hkey, "Assignment", 0);
2722     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
2723     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
2724     CHECK_DEL_REG_STR(hkey, "Clients", ":");
2725
2726     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
2727     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2728
2729     lstrcpyA(path, "n;1;");
2730     lstrcatA(path, temp);
2731     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
2732     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
2733
2734     res = RegOpenKeyA(sourcelist, "Net", &net);
2735     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2736
2737     CHECK_DEL_REG_STR(net, "1", temp);
2738
2739     RegDeleteKeyA(net, "");
2740     RegCloseKey(net);
2741
2742     res = RegOpenKeyA(sourcelist, "Media", &media);
2743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2744
2745     CHECK_DEL_REG_STR(media, "1", "DISK1;");
2746
2747     RegDeleteKeyA(media, "");
2748     RegCloseKey(media);
2749     RegDeleteKeyA(sourcelist, "");
2750     RegCloseKey(sourcelist);
2751     RegDeleteKeyA(hkey, "");
2752     RegCloseKey(hkey);
2753
2754     res = RegOpenKeyA(HKEY_CURRENT_USER, cuupgrades, &hkey);
2755     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2756
2757     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2758
2759     RegDeleteKeyA(hkey, "");
2760     RegCloseKey(hkey);
2761
2762     /* PublishProduct, machine */
2763     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 ALLUSERS=1");
2764     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2765     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2766     ok(delete_pf("msitest", FALSE), "File not installed\n");
2767
2768     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
2769     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2770
2771     sprintf(keypath, prodpath, "S-1-5-18");
2772     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2773     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2774
2775     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2776     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2777
2778     res = RegOpenKeyA(hkey, "Patches", &patches);
2779     todo_wine
2780     {
2781         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2782
2783         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
2784     }
2785
2786     RegDeleteKeyA(patches, "");
2787     RegCloseKey(patches);
2788     RegDeleteKeyA(hkey, "");
2789     RegCloseKey(hkey);
2790
2791     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machprod, &hkey);
2792     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2793
2794     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
2795     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
2796     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2797     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2798     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
2799     todo_wine CHECK_DEL_REG_DWORD(hkey, "Assignment", 1);
2800     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
2801     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
2802     CHECK_DEL_REG_STR(hkey, "Clients", ":");
2803
2804     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
2805     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2806
2807     lstrcpyA(path, "n;1;");
2808     lstrcatA(path, temp);
2809     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
2810     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
2811
2812     res = RegOpenKeyA(sourcelist, "Net", &net);
2813     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2814
2815     CHECK_DEL_REG_STR(net, "1", temp);
2816
2817     RegDeleteKeyA(net, "");
2818     RegCloseKey(net);
2819
2820     res = RegOpenKeyA(sourcelist, "Media", &media);
2821     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2822
2823     CHECK_DEL_REG_STR(media, "1", "DISK1;");
2824
2825     RegDeleteKeyA(media, "");
2826     RegCloseKey(media);
2827     RegDeleteKeyA(sourcelist, "");
2828     RegCloseKey(sourcelist);
2829     RegDeleteKeyA(hkey, "");
2830     RegCloseKey(hkey);
2831
2832     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machup, &hkey);
2833     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2834
2835     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2836
2837     RegDeleteKeyA(hkey, "");
2838     RegCloseKey(hkey);
2839
2840     DeleteFile(msifile);
2841     DeleteFile("msitest\\maximus");
2842     RemoveDirectory("msitest");
2843     HeapFree(GetProcessHeap(), 0, usersid);
2844 }
2845
2846 static void test_publish_publishfeatures(void)
2847 {
2848     UINT r;
2849     LONG res;
2850     HKEY hkey;
2851     LPSTR usersid;
2852     CHAR keypath[MAX_PATH];
2853
2854     static const CHAR cupath[] = "Software\\Microsoft\\Installer\\Features"
2855                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2856     static const CHAR udpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2857                                  "\\Installer\\UserData\\%s\\Products"
2858                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features";
2859     static const CHAR featkey[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2860                                   "\\Installer\\Features";
2861     static const CHAR classfeat[] = "Software\\Classes\\Installer\\Features"
2862                                     "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2863
2864     get_user_sid(&usersid);
2865     if (!usersid)
2866     {
2867         skip("ConvertSidToStringSidA is not available\n");
2868         return;
2869     }
2870
2871     CreateDirectoryA("msitest", NULL);
2872     create_file("msitest\\maximus", 500);
2873
2874     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2875
2876     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2877
2878     /* PublishFeatures, current user */
2879     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2881     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2882     ok(delete_pf("msitest", FALSE), "File not installed\n");
2883
2884     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
2885     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2886
2887     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
2888     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2889
2890     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
2891     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2892
2893     CHECK_REG_STR(hkey, "feature", "");
2894     CHECK_REG_STR(hkey, "montecristo", "");
2895
2896     RegDeleteValueA(hkey, "feature");
2897     RegDeleteValueA(hkey, "montecristo");
2898     RegDeleteKeyA(hkey, "");
2899     RegCloseKey(hkey);
2900
2901     sprintf(keypath, udpath, usersid);
2902     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2903     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2904
2905     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
2906     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
2907
2908     RegDeleteValueA(hkey, "feature");
2909     RegDeleteValueA(hkey, "montecristo");
2910     RegDeleteKeyA(hkey, "");
2911     RegCloseKey(hkey);
2912
2913     /* PublishFeatures, machine */
2914     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1 ALLUSERS=1");
2915     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2916     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2917     ok(delete_pf("msitest", FALSE), "File not installed\n");
2918
2919     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
2920     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2921
2922     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
2923     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2924
2925     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
2926     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2927
2928     CHECK_REG_STR(hkey, "feature", "");
2929     CHECK_REG_STR(hkey, "montecristo", "");
2930
2931     RegDeleteValueA(hkey, "feature");
2932     RegDeleteValueA(hkey, "montecristo");
2933     RegDeleteKeyA(hkey, "");
2934     RegCloseKey(hkey);
2935
2936     sprintf(keypath, udpath, "S-1-5-18");
2937     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2938     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2939
2940     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
2941     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
2942
2943     RegDeleteValueA(hkey, "feature");
2944     RegDeleteValueA(hkey, "montecristo");
2945     RegDeleteKeyA(hkey, "");
2946     RegCloseKey(hkey);
2947
2948     DeleteFile(msifile);
2949     DeleteFile("msitest\\maximus");
2950     RemoveDirectory("msitest");
2951     HeapFree(GetProcessHeap(), 0, usersid);
2952 }
2953
2954 static LPSTR reg_get_val_str(HKEY hkey, LPCSTR name)
2955 {
2956     DWORD len = 0;
2957     LPSTR val;
2958     LONG r;
2959
2960     r = RegQueryValueExA(hkey, name, NULL, NULL, NULL, &len);
2961     if (r != ERROR_SUCCESS)
2962         return NULL;
2963
2964     len += sizeof (WCHAR);
2965     val = HeapAlloc(GetProcessHeap(), 0, len);
2966     if (!val) return NULL;
2967     val[0] = 0;
2968     RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)val, &len);
2969     return val;
2970 }
2971
2972 static void get_owner_company(LPSTR *owner, LPSTR *company)
2973 {
2974     LONG res;
2975     HKEY hkey;
2976
2977     *owner = *company = NULL;
2978
2979     res = RegOpenKeyA(HKEY_CURRENT_USER,
2980                       "Software\\Microsoft\\MS Setup (ACME)\\User Info", &hkey);
2981     if (res == ERROR_SUCCESS)
2982     {
2983         *owner = reg_get_val_str(hkey, "DefName");
2984         *company = reg_get_val_str(hkey, "DefCompany");
2985         RegCloseKey(hkey);
2986     }
2987
2988     if (!*owner || !*company)
2989     {
2990         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
2991                           "Software\\Microsoft\\Windows\\CurrentVersion", &hkey);
2992         if (res == ERROR_SUCCESS)
2993         {
2994             *owner = reg_get_val_str(hkey, "RegisteredOwner");
2995             *company = reg_get_val_str(hkey, "RegisteredOrganization");
2996             RegCloseKey(hkey);
2997         }
2998     }
2999
3000     if (!*owner || !*company)
3001     {
3002         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
3003                           "Software\\Microsoft\\Windows NT\\CurrentVersion", &hkey);
3004         if (res == ERROR_SUCCESS)
3005         {
3006             *owner = reg_get_val_str(hkey, "RegisteredOwner");
3007             *company = reg_get_val_str(hkey, "RegisteredOrganization");
3008             RegCloseKey(hkey);
3009         }
3010     }
3011 }
3012
3013 static void test_publish_registeruser(void)
3014 {
3015     UINT r;
3016     LONG res;
3017     HKEY props;
3018     LPSTR usersid;
3019     LPSTR owner, company;
3020     CHAR keypath[MAX_PATH];
3021
3022     static const CHAR keyfmt[] =
3023         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
3024         "UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
3025
3026     get_user_sid(&usersid);
3027     if (!usersid)
3028     {
3029         skip("ConvertSidToStringSidA is not available\n");
3030         return;
3031     }
3032
3033     get_owner_company(&owner, &company);
3034
3035     CreateDirectoryA("msitest", NULL);
3036     create_file("msitest\\maximus", 500);
3037
3038     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3039
3040     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3041
3042     /* RegisterUser, per-user */
3043     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
3044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3045     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3046     ok(delete_pf("msitest", FALSE), "File not installed\n");
3047
3048     sprintf(keypath, keyfmt, usersid);
3049
3050     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
3051     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3052
3053     CHECK_REG_STR(props, "ProductID", "none");
3054     CHECK_REG_STR(props, "RegCompany", company);
3055     CHECK_REG_STR(props, "RegOwner", owner);
3056
3057     RegDeleteValueA(props, "ProductID");
3058     RegDeleteValueA(props, "RegCompany");
3059     RegDeleteValueA(props, "RegOwner");
3060     RegDeleteKeyA(props, "");
3061     RegCloseKey(props);
3062
3063     /* RegisterUser, machine */
3064     r = MsiInstallProductA(msifile, "REGISTER_USER=1 ALLUSERS=1");
3065     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3066     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3067     ok(delete_pf("msitest", FALSE), "File not installed\n");
3068
3069     sprintf(keypath, keyfmt, "S-1-5-18");
3070
3071     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
3072     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3073
3074     CHECK_REG_STR(props, "ProductID", "none");
3075     CHECK_REG_STR(props, "RegCompany", company);
3076     CHECK_REG_STR(props, "RegOwner", owner);
3077
3078     RegDeleteValueA(props, "ProductID");
3079     RegDeleteValueA(props, "RegCompany");
3080     RegDeleteValueA(props, "RegOwner");
3081     RegDeleteKeyA(props, "");
3082     RegCloseKey(props);
3083
3084     HeapFree(GetProcessHeap(), 0, company);
3085     HeapFree(GetProcessHeap(), 0, owner);
3086
3087     DeleteFile(msifile);
3088     DeleteFile("msitest\\maximus");
3089     RemoveDirectory("msitest");
3090 }
3091
3092 static void test_publish_processcomponents(void)
3093 {
3094     UINT r;
3095     LONG res;
3096     DWORD size;
3097     HKEY comp, hkey;
3098     LPSTR usersid;
3099     CHAR val[MAX_PATH];
3100     CHAR keypath[MAX_PATH];
3101     CHAR program_files_maximus[MAX_PATH];
3102
3103     static const CHAR keyfmt[] =
3104         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
3105         "UserData\\%s\\Components\\%s";
3106     static const CHAR compkey[] =
3107         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Components";
3108
3109     get_user_sid(&usersid);
3110     if (!usersid)
3111     {
3112         skip("ConvertSidToStringSidA is not available\n");
3113         return;
3114     }
3115
3116     CreateDirectoryA("msitest", NULL);
3117     create_file("msitest\\maximus", 500);
3118
3119     create_database(msifile, ppc_tables, sizeof(ppc_tables) / sizeof(msi_table));
3120
3121     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3122
3123     /* ProcessComponents, per-user */
3124     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3125     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3126     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3127     ok(delete_pf("msitest", FALSE), "File not installed\n");
3128
3129     sprintf(keypath, keyfmt, usersid, "CBABC2FDCCB35E749A8944D8C1C098B5");
3130
3131     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3132     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3133
3134     size = MAX_PATH;
3135     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3136                            NULL, NULL, (LPBYTE)val, &size);
3137     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3138
3139     lstrcpyA(program_files_maximus,PROG_FILES_DIR);
3140     lstrcatA(program_files_maximus,"\\msitest\\maximus");
3141
3142     ok(!lstrcmpA(val, program_files_maximus),
3143        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
3144
3145     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3146     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3147
3148     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3149     RegDeleteKeyA(comp, "");
3150     RegCloseKey(comp);
3151
3152     sprintf(keypath, keyfmt, usersid, "241C3DA58FECD0945B9687D408766058");
3153
3154     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3155     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3156
3157     size = MAX_PATH;
3158     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3159                            NULL, NULL, (LPBYTE)val, &size);
3160     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3161     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
3162        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
3163
3164     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3165     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3166
3167     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3168     RegDeleteKeyA(comp, "");
3169     RegCloseKey(comp);
3170
3171     /* ProcessComponents, machine */
3172     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1 ALLUSERS=1");
3173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3174     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3175     ok(delete_pf("msitest", FALSE), "File not installed\n");
3176
3177     sprintf(keypath, keyfmt, "S-1-5-18", "CBABC2FDCCB35E749A8944D8C1C098B5");
3178
3179     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3180     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3181
3182     size = MAX_PATH;
3183     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3184                            NULL, NULL, (LPBYTE)val, &size);
3185     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3186     ok(!lstrcmpA(val, program_files_maximus),
3187        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
3188
3189     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3190     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3191
3192     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3193     RegDeleteKeyA(comp, "");
3194     RegCloseKey(comp);
3195
3196     sprintf(keypath, keyfmt, "S-1-5-18", "241C3DA58FECD0945B9687D408766058");
3197
3198     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3199     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3200
3201     size = MAX_PATH;
3202     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3203                            NULL, NULL, (LPBYTE)val, &size);
3204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3205     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
3206        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
3207
3208     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3209     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3210
3211     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3212     RegDeleteKeyA(comp, "");
3213     RegCloseKey(comp);
3214
3215     DeleteFile(msifile);
3216     DeleteFile("msitest\\maximus");
3217     RemoveDirectory("msitest");
3218 }
3219
3220 static void test_publish(void)
3221 {
3222     UINT r;
3223     LONG res;
3224     HKEY uninstall, prodkey;
3225     INSTALLSTATE state;
3226     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3227     char date[MAX_PATH];
3228     char temp[MAX_PATH];
3229
3230     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
3231
3232     if (!pMsiQueryComponentStateA)
3233     {
3234         skip("MsiQueryComponentStateA is not available\n");
3235         return;
3236     }
3237
3238     get_date_str(date);
3239     GetTempPath(MAX_PATH, temp);
3240
3241     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
3242     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3243
3244     CreateDirectoryA("msitest", NULL);
3245     create_file("msitest\\maximus", 500);
3246
3247     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3248
3249     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3250
3251     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3252     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3253
3254     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3255     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3256
3257     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3258     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3259
3260     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3261                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3262     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3263     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3264
3265     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3266     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3267
3268     /* nothing published */
3269     r = MsiInstallProductA(msifile, NULL);
3270     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3271     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3272     ok(pf_exists("msitest"), "File not installed\n");
3273
3274     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3275     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3276
3277     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3278     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3279
3280     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3281     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3282
3283     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3284                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3285     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3286     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3287
3288     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3289     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3290
3291     /* PublishProduct and RegisterProduct */
3292     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
3293     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3294     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3295     ok(pf_exists("msitest"), "File not installed\n");
3296
3297     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3298     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3299
3300     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3301     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3302
3303     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3304     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3305
3306     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3307                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3308     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3309     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3310
3311     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3312     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3313
3314     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3315     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3316     CHECK_REG_STR(prodkey, "InstallDate", date);
3317     CHECK_REG_STR(prodkey, "InstallSource", temp);
3318     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3319     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3320     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3321     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3322     CHECK_REG_STR(prodkey, "Comments", NULL);
3323     CHECK_REG_STR(prodkey, "Contact", NULL);
3324     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3325     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3326     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3327     CHECK_REG_STR(prodkey, "Readme", NULL);
3328     CHECK_REG_STR(prodkey, "Size", NULL);
3329     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3330     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3331     CHECK_REG_DWORD(prodkey, "Language", 1033);
3332     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3333     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3334     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3335     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3336     todo_wine
3337     {
3338         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3339     }
3340
3341     RegCloseKey(prodkey);
3342
3343     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3345     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3346     ok(pf_exists("msitest"), "File deleted\n");
3347
3348     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3349     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3350
3351     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3352     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3353
3354     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3355     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3356
3357     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3358                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3359     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3360     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3361
3362     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3363     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3364
3365     /* complete install */
3366     r = MsiInstallProductA(msifile, "FULL=1");
3367     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3368     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3369     ok(pf_exists("msitest"), "File not installed\n");
3370
3371     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3372     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3373
3374     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3375     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3376
3377     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3378     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3379
3380     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3381                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3382     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3383     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3384
3385     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3386     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3387
3388     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3389     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3390     CHECK_REG_STR(prodkey, "InstallDate", date);
3391     CHECK_REG_STR(prodkey, "InstallSource", temp);
3392     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3393     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3394     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3395     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3396     CHECK_REG_STR(prodkey, "Comments", NULL);
3397     CHECK_REG_STR(prodkey, "Contact", NULL);
3398     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3399     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3400     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3401     CHECK_REG_STR(prodkey, "Readme", NULL);
3402     CHECK_REG_STR(prodkey, "Size", NULL);
3403     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3404     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3405     CHECK_REG_DWORD(prodkey, "Language", 1033);
3406     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3407     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3408     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3409     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3410     todo_wine
3411     {
3412         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3413     }
3414
3415     RegCloseKey(prodkey);
3416
3417     /* no UnpublishFeatures */
3418     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3419     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3420     ok(!pf_exists("msitest\\maximus"), "File deleted\n");
3421     todo_wine
3422     {
3423         ok(!pf_exists("msitest"), "File deleted\n");
3424     }
3425
3426     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3427     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3428
3429     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3430     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3431
3432     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3433     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3434
3435     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3436                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3437     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3438     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3439
3440     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3441     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3442
3443     /* complete install */
3444     r = MsiInstallProductA(msifile, "FULL=1");
3445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3446     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3447     ok(pf_exists("msitest"), "File not installed\n");
3448
3449     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3450     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3451
3452     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3453     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3454
3455     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3456     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3457
3458     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3459                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3461     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3462
3463     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3464     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3465
3466     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3467     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3468     CHECK_REG_STR(prodkey, "InstallDate", date);
3469     CHECK_REG_STR(prodkey, "InstallSource", temp);
3470     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3471     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3472     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3473     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3474     CHECK_REG_STR(prodkey, "Comments", NULL);
3475     CHECK_REG_STR(prodkey, "Contact", NULL);
3476     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3477     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3478     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3479     CHECK_REG_STR(prodkey, "Readme", NULL);
3480     CHECK_REG_STR(prodkey, "Size", NULL);
3481     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3482     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3483     CHECK_REG_DWORD(prodkey, "Language", 1033);
3484     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3485     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3486     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3487     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3488     todo_wine
3489     {
3490         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3491     }
3492
3493     RegCloseKey(prodkey);
3494
3495     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3496     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3497     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3498     todo_wine ok(pf_exists("msitest\\maximus"), "File deleted\n");
3499     ok(pf_exists("msitest"), "File deleted\n");
3500
3501     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3502     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3503
3504     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3505     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3506
3507     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3508     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3509
3510     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3511                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3512     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3513     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3514
3515     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3516     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3517
3518     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3519     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3520     CHECK_REG_STR(prodkey, "InstallDate", date);
3521     CHECK_REG_STR(prodkey, "InstallSource", temp);
3522     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3523     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3524     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3525     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3526     CHECK_REG_STR(prodkey, "Comments", NULL);
3527     CHECK_REG_STR(prodkey, "Contact", NULL);
3528     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3529     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3530     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3531     CHECK_REG_STR(prodkey, "Readme", NULL);
3532     CHECK_REG_STR(prodkey, "Size", NULL);
3533     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3534     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3535     CHECK_REG_DWORD(prodkey, "Language", 1033);
3536     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3537     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3538     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3539     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3540     todo_wine
3541     {
3542         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3543     }
3544
3545     RegCloseKey(prodkey);
3546
3547     /* complete install */
3548     r = MsiInstallProductA(msifile, "FULL=1");
3549     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3550     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3551     ok(pf_exists("msitest"), "File not installed\n");
3552
3553     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3554     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3555
3556     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3557     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3558
3559     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3560     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3561
3562     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3563                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3565     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3566
3567     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3568     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3569
3570     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3571     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3572     CHECK_REG_STR(prodkey, "InstallDate", date);
3573     CHECK_REG_STR(prodkey, "InstallSource", temp);
3574     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3575     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3576     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3577     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3578     CHECK_REG_STR(prodkey, "Comments", NULL);
3579     CHECK_REG_STR(prodkey, "Contact", NULL);
3580     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3581     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3582     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3583     CHECK_REG_STR(prodkey, "Readme", NULL);
3584     CHECK_REG_STR(prodkey, "Size", NULL);
3585     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3586     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3587     CHECK_REG_DWORD(prodkey, "Language", 1033);
3588     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3589     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3590     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3591     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3592     todo_wine
3593     {
3594         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3595     }
3596
3597     RegCloseKey(prodkey);
3598
3599     /* UnpublishFeatures, both features removed */
3600     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3601     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3602     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3603     todo_wine
3604     {
3605         ok(!pf_exists("msitest"), "File not deleted\n");
3606     }
3607
3608     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3609     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3610
3611     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3612     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3613
3614     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3615     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3616
3617     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3618                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3619     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3620     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3621
3622     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3623     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3624
3625     /* complete install */
3626     r = MsiInstallProductA(msifile, "FULL=1");
3627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3628     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3629     ok(pf_exists("msitest"), "File not installed\n");
3630
3631     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3632     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3633
3634     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3635     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3636
3637     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3638     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3639
3640     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3641                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3643     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3644
3645     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3646     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3647
3648     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3649     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3650     CHECK_REG_STR(prodkey, "InstallDate", date);
3651     CHECK_REG_STR(prodkey, "InstallSource", temp);
3652     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3653     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3654     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3655     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3656     CHECK_REG_STR(prodkey, "Comments", NULL);
3657     CHECK_REG_STR(prodkey, "Contact", NULL);
3658     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3659     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3660     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3661     CHECK_REG_STR(prodkey, "Readme", NULL);
3662     CHECK_REG_STR(prodkey, "Size", NULL);
3663     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3664     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3665     CHECK_REG_DWORD(prodkey, "Language", 1033);
3666     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3667     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3668     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3669     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3670     todo_wine
3671     {
3672         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3673     }
3674
3675     RegCloseKey(prodkey);
3676
3677     /* complete uninstall */
3678     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3680     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3681     todo_wine
3682     {
3683         ok(!pf_exists("msitest"), "File not deleted\n");
3684     }
3685
3686     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3687     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3688
3689     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3690     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3691
3692     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3693     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3694
3695     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3696                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3697     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3698     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3699
3700     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3701     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3702
3703     /* make sure 'Program Files\msitest' is removed */
3704     delete_pfmsitest_files();
3705
3706     RegCloseKey(uninstall);
3707     DeleteFile(msifile);
3708     DeleteFile("msitest\\maximus");
3709     RemoveDirectory("msitest");
3710 }
3711
3712 static void test_publishsourcelist(void)
3713 {
3714     UINT r;
3715     DWORD size;
3716     CHAR value[MAX_PATH];
3717     CHAR path[MAX_PATH];
3718     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3719
3720     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3721     {
3722         skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3723         return;
3724     }
3725
3726     CreateDirectoryA("msitest", NULL);
3727     create_file("msitest\\maximus", 500);
3728
3729     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3730
3731     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3732
3733     r = MsiInstallProductA(msifile, NULL);
3734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3735     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3736     ok(pf_exists("msitest"), "File not installed\n");
3737
3738     /* nothing published */
3739     size = 0xdeadbeef;
3740     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3741                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3742     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3743     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3744
3745     size = 0xdeadbeef;
3746     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3747                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3748     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3749     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3750
3751     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3752     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3753     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3754     ok(pf_exists("msitest"), "File not installed\n");
3755
3756     /* after RegisterProduct */
3757     size = 0xdeadbeef;
3758     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3759                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3760     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3761     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3762
3763     size = 0xdeadbeef;
3764     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3765                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3766     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3767     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3768
3769     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3771     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3772     ok(pf_exists("msitest"), "File not installed\n");
3773
3774     /* after ProcessComponents */
3775     size = 0xdeadbeef;
3776     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3777                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3778     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3779     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3780
3781     size = 0xdeadbeef;
3782     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3783                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3784     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3785     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3786
3787     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3789     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3790     ok(pf_exists("msitest"), "File not installed\n");
3791
3792     /* after PublishFeatures */
3793     size = 0xdeadbeef;
3794     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3795                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3796     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3797     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3798
3799     size = 0xdeadbeef;
3800     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3801                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3802     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3803     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3804
3805     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3806     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3807     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3808     ok(pf_exists("msitest"), "File not installed\n");
3809
3810     /* after PublishProduct */
3811     size = MAX_PATH;
3812     lstrcpyA(value, "aaa");
3813     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3814                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3815     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3816     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3817     ok(size == 11, "Expected 11, got %d\n", size);
3818
3819     size = MAX_PATH;
3820     lstrcpyA(value, "aaa");
3821     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3822                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3823     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3824     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3825     ok(size == 0, "Expected 0, got %d\n", size);
3826
3827     size = MAX_PATH;
3828     lstrcpyA(value, "aaa");
3829     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3830                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3831     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3832     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3833     ok(size == 0, "Expected 0, got %d\n", size);
3834
3835     lstrcpyA(path, CURR_DIR);
3836     lstrcatA(path, "\\");
3837
3838     size = MAX_PATH;
3839     lstrcpyA(value, "aaa");
3840     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3841                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3842     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3843     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3844     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3845
3846     size = MAX_PATH;
3847     lstrcpyA(value, "aaa");
3848     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3849                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3851     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3852     ok(size == 1, "Expected 1, got %d\n", size);
3853
3854     size = MAX_PATH;
3855     lstrcpyA(value, "aaa");
3856     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3857                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3858     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3859     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3860     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3861
3862     size = MAX_PATH;
3863     lstrcpyA(value, "aaa");
3864     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3865                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3867     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3868     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3869
3870     size = MAX_PATH;
3871     lstrcpyA(value, "aaa");
3872     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3873                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3874     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3875     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3876     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3877
3878     /* complete uninstall */
3879     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3880     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3881     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3882     todo_wine
3883     {
3884         ok(!pf_exists("msitest"), "File not deleted\n");
3885     }
3886
3887     /* make sure 'Program Files\msitest' is removed */
3888     delete_pfmsitest_files();
3889
3890     DeleteFile(msifile);
3891     DeleteFile("msitest\\maximus");
3892     RemoveDirectory("msitest");
3893 }
3894
3895 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3896 {
3897     MSIHANDLE hview = 0;
3898     UINT r;
3899
3900     r = MsiDatabaseOpenView(hdb, query, &hview);
3901     if(r != ERROR_SUCCESS)
3902         return r;
3903
3904     r = MsiViewExecute(hview, hrec);
3905     if(r == ERROR_SUCCESS)
3906         r = MsiViewClose(hview);
3907     MsiCloseHandle(hview);
3908     return r;
3909 }
3910
3911 static void set_transform_summary_info(void)
3912 {
3913     UINT r;
3914     MSIHANDLE suminfo = 0;
3915
3916     /* build summary info */
3917     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
3918     todo_wine
3919     {
3920         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
3921     }
3922
3923     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
3924     todo_wine
3925     {
3926         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3927     }
3928
3929     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
3930                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3931                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3932                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
3933     todo_wine
3934     {
3935         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
3936     }
3937
3938     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
3939     todo_wine
3940     {
3941         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3942     }
3943
3944     r = MsiSummaryInfoPersist(suminfo);
3945     todo_wine
3946     {
3947         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
3948     }
3949
3950     r = MsiCloseHandle(suminfo);
3951     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
3952 }
3953
3954 static void generate_transform(void)
3955 {
3956     MSIHANDLE hdb1, hdb2;
3957     LPCSTR query;
3958     UINT r;
3959
3960     /* start with two identical databases */
3961     CopyFile(msifile, msifile2, FALSE);
3962
3963     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
3964     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3965
3966     r = MsiDatabaseCommit(hdb1);
3967     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
3968
3969     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
3970     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3971
3972     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
3973     r = run_query(hdb1, 0, query);
3974     ok(r == ERROR_SUCCESS, "failed to add property\n");
3975
3976     /* database needs to be committed */
3977     MsiDatabaseCommit(hdb1);
3978
3979     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
3980     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
3981
3982 #if 0  /* not implemented in wine yet */
3983     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
3984     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3985 #endif
3986
3987     MsiCloseHandle(hdb1);
3988     MsiCloseHandle(hdb2);
3989 }
3990
3991 /* data for generating a transform */
3992
3993 /* tables transform names - encoded as they would be in an msi database file */
3994 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
3995 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
3996 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
3997
3998 /* data in each table */
3999 static const char data1[] = /* _StringData */
4000     "propval";  /* all the strings squashed together */
4001
4002 static const WCHAR data2[] = { /* _StringPool */
4003 /*  len, refs */
4004     0,   0,    /* string 0 ''     */
4005     4,   1,    /* string 1 'prop' */
4006     3,   1,    /* string 2 'val'  */
4007 };
4008
4009 static const WCHAR data3[] = { /* Property */
4010     0x0201, 0x0001, 0x0002,
4011 };
4012
4013 static const struct {
4014     LPCWSTR name;
4015     const void *data;
4016     DWORD size;
4017 } table_transform_data[] =
4018 {
4019     { name1, data1, sizeof data1 - 1 },
4020     { name2, data2, sizeof data2 },
4021     { name3, data3, sizeof data3 },
4022 };
4023
4024 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
4025
4026 static void generate_transform_manual(void)
4027 {
4028     IStorage *stg = NULL;
4029     IStream *stm;
4030     WCHAR name[0x20];
4031     HRESULT r;
4032     DWORD i, count;
4033     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
4034
4035     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
4036
4037     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
4038
4039     r = StgCreateDocfile(name, mode, 0, &stg);
4040     ok(r == S_OK, "failed to create storage\n");
4041     if (!stg)
4042         return;
4043
4044     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
4045     ok(r == S_OK, "failed to set storage type\n");
4046
4047     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
4048     {
4049         r = IStorage_CreateStream(stg, table_transform_data[i].name,
4050                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4051         if (FAILED(r))
4052         {
4053             ok(0, "failed to create stream %08x\n", r);
4054             continue;
4055         }
4056
4057         r = IStream_Write(stm, table_transform_data[i].data,
4058                           table_transform_data[i].size, &count);
4059         if (FAILED(r) || count != table_transform_data[i].size)
4060             ok(0, "failed to write stream\n");
4061         IStream_Release(stm);
4062     }
4063
4064     IStorage_Release(stg);
4065
4066     set_transform_summary_info();
4067 }
4068
4069 static void test_transformprop(void)
4070 {
4071     UINT r;
4072
4073     CreateDirectoryA("msitest", NULL);
4074     create_file("msitest\\augustus", 500);
4075
4076     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
4077
4078     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4079
4080     r = MsiInstallProductA(msifile, NULL);
4081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4082     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4083     ok(!delete_pf("msitest", FALSE), "File installed\n");
4084
4085     if (0)
4086         generate_transform();
4087     else
4088         generate_transform_manual();
4089
4090     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
4091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4092     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4093     ok(delete_pf("msitest", FALSE), "File not installed\n");
4094
4095     /* Delete the files in the temp (current) folder */
4096     DeleteFile(msifile);
4097     DeleteFile(msifile2);
4098     DeleteFile(mstfile);
4099     DeleteFile("msitest\\augustus");
4100     RemoveDirectory("msitest");
4101 }
4102
4103 static void test_currentworkingdir(void)
4104 {
4105     UINT r;
4106     CHAR path[MAX_PATH];
4107     LPSTR ptr, ptr2;
4108
4109     CreateDirectoryA("msitest", NULL);
4110     create_file("msitest\\augustus", 500);
4111
4112     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
4113
4114     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4115
4116     CreateDirectoryA("diffdir", NULL);
4117     SetCurrentDirectoryA("diffdir");
4118
4119     sprintf(path, "..\\%s", msifile);
4120     r = MsiInstallProductA(path, NULL);
4121     todo_wine
4122     {
4123         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
4124         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4125         ok(!delete_pf("msitest", FALSE), "File installed\n");
4126     }
4127
4128     sprintf(path, "%s\\%s", CURR_DIR, msifile);
4129     r = MsiInstallProductA(path, NULL);
4130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4131     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4132     ok(delete_pf("msitest", FALSE), "File not installed\n");
4133
4134     lstrcpyA(path, CURR_DIR);
4135     if (path[lstrlenA(path) - 1] != '\\')
4136         lstrcatA(path, "\\");
4137     lstrcatA(path, "msitest.msi");
4138
4139     ptr2 = strrchr(path, '\\');
4140     *ptr2 = '\0';
4141     ptr = strrchr(path, '\\');
4142     *ptr2 = '\\';
4143     *(ptr++) = '\0';
4144
4145     SetCurrentDirectoryA(path);
4146
4147     r = MsiInstallProductA(ptr, NULL);
4148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4149     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4150     ok(delete_pf("msitest", FALSE), "File not installed\n");
4151
4152     SetCurrentDirectoryA(CURR_DIR);
4153
4154     DeleteFile(msifile);
4155     DeleteFile("msitest\\augustus");
4156     RemoveDirectory("msitest");
4157     RemoveDirectory("diffdir");
4158 }
4159
4160 static void set_admin_summary_info(const CHAR *name)
4161 {
4162     MSIHANDLE db, summary;
4163     UINT r;
4164
4165     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
4166     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4167
4168     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
4169     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4170
4171     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
4172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4173
4174     /* write the summary changes back to the stream */
4175     r = MsiSummaryInfoPersist(summary);
4176     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4177
4178     MsiCloseHandle(summary);
4179
4180     r = MsiDatabaseCommit(db);
4181     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4182
4183     MsiCloseHandle(db);
4184 }
4185
4186 static void test_admin(void)
4187 {
4188     UINT r;
4189
4190     CreateDirectoryA("msitest", NULL);
4191     create_file("msitest\\augustus", 500);
4192
4193     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
4194     set_admin_summary_info(msifile);
4195
4196     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4197
4198     r = MsiInstallProductA(msifile, NULL);
4199     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4200     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4201     ok(!delete_pf("msitest", FALSE), "File installed\n");
4202     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
4203     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
4204
4205     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
4206     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4207     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4208     ok(!delete_pf("msitest", FALSE), "File installed\n");
4209     todo_wine
4210     {
4211         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
4212         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
4213     }
4214
4215     DeleteFile(msifile);
4216     DeleteFile("msitest\\augustus");
4217     RemoveDirectory("msitest");
4218 }
4219
4220 static void set_admin_property_stream(LPCSTR file)
4221 {
4222     IStorage *stg;
4223     IStream *stm;
4224     WCHAR fileW[MAX_PATH];
4225     HRESULT hr;
4226     DWORD count;
4227     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
4228
4229     /* AdminProperties */
4230     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
4231     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
4232
4233     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
4234
4235     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
4236     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4237     if (!stg)
4238         return;
4239
4240     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4241     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4242
4243     hr = IStream_Write(stm, data, sizeof(data), &count);
4244     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4245
4246     IStream_Release(stm);
4247     IStorage_Release(stg);
4248 }
4249
4250 static void test_adminprops(void)
4251 {
4252     UINT r;
4253
4254     CreateDirectoryA("msitest", NULL);
4255     create_file("msitest\\augustus", 500);
4256
4257     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
4258     set_admin_summary_info(msifile);
4259     set_admin_property_stream(msifile);
4260
4261     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4262
4263     r = MsiInstallProductA(msifile, NULL);
4264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4265     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4266     ok(delete_pf("msitest", FALSE), "File installed\n");
4267
4268     DeleteFile(msifile);
4269     DeleteFile("msitest\\augustus");
4270     RemoveDirectory("msitest");
4271 }
4272
4273 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
4274 {
4275     CHAR path[MAX_PATH];
4276
4277     lstrcpyA(path, PROG_FILES_DIR);
4278     lstrcatA(path, "\\");
4279     lstrcatA(path, file);
4280
4281     if (is_file)
4282         create_file_data(path, data, 500);
4283     else
4284         CreateDirectoryA(path, NULL);
4285 }
4286
4287 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
4288
4289 static void test_removefiles(void)
4290 {
4291     UINT r;
4292
4293     CreateDirectoryA("msitest", NULL);
4294     create_file("msitest\\hydrogen", 500);
4295     create_file("msitest\\helium", 500);
4296     create_file("msitest\\lithium", 500);
4297
4298     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
4299
4300     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4301
4302     r = MsiInstallProductA(msifile, NULL);
4303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4304     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4305     ok(!pf_exists("msitest\\helium"), "File installed\n");
4306     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4307     ok(pf_exists("msitest"), "File not installed\n");
4308
4309     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4310     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4311     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
4312     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
4313     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4314     ok(delete_pf("msitest", FALSE), "File deleted\n");
4315
4316     create_pf("msitest", FALSE);
4317     create_pf("msitest\\hydrogen", TRUE);
4318     create_pf("msitest\\helium", TRUE);
4319     create_pf("msitest\\lithium", TRUE);
4320
4321     r = MsiInstallProductA(msifile, NULL);
4322     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4323     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4324     ok(pf_exists("msitest\\helium"), "File not installed\n");
4325     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4326     ok(pf_exists("msitest"), "File not installed\n");
4327
4328     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4329     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4330     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
4331     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
4332     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4333     ok(delete_pf("msitest", FALSE), "File deleted\n");
4334
4335     create_pf("msitest", FALSE);
4336     create_pf("msitest\\furlong", TRUE);
4337     create_pf("msitest\\firkin", TRUE);
4338     create_pf("msitest\\fortnight", TRUE);
4339     create_pf("msitest\\becquerel", TRUE);
4340     create_pf("msitest\\dioptre", TRUE);
4341     create_pf("msitest\\attoparsec", TRUE);
4342     create_pf("msitest\\storeys", TRUE);
4343     create_pf("msitest\\block", TRUE);
4344     create_pf("msitest\\siriometer", TRUE);
4345     create_pf("msitest\\cabout", FALSE);
4346     create_pf("msitest\\cabout\\blocker", TRUE);
4347
4348     r = MsiInstallProductA(msifile, NULL);
4349     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4350     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4351     ok(!pf_exists("msitest\\helium"), "File installed\n");
4352     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4353     ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
4354     ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
4355     ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
4356     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
4357     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
4358     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
4359     ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
4360     ok(!pf_exists("msitest\\block"), "File not deleted\n");
4361     ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
4362     ok(pf_exists("msitest\\cabout"), "Directory removed\n");
4363     ok(pf_exists("msitest"), "File not installed\n");
4364
4365     create_pf("msitest\\furlong", TRUE);
4366     create_pf("msitest\\firkin", TRUE);
4367     create_pf("msitest\\fortnight", TRUE);
4368     create_pf("msitest\\storeys", TRUE);
4369     create_pf("msitest\\block", TRUE);
4370     create_pf("msitest\\siriometer", TRUE);
4371
4372     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4374     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
4375     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
4376     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4377     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
4378     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
4379     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
4380     ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
4381     ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
4382     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
4383     ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
4384     ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
4385     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
4386     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
4387     ok(pf_exists("msitest"), "Directory deleted\n");
4388
4389     r = MsiInstallProductA(msifile, NULL);
4390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4391     ok(delete_pf("msitest\\hydrogen", TRUE), "File not installed\n");
4392     ok(!delete_pf("msitest\\helium", TRUE), "File installed\n");
4393     ok(delete_pf("msitest\\lithium", TRUE), "File not installed\n");
4394     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
4395     ok(pf_exists("msitest"), "Directory deleted\n");
4396
4397     delete_pf("msitest\\cabout\\blocker", TRUE);
4398
4399     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4400     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4401     ok(!delete_pf("msitest\\cabout", FALSE), "Directory not deleted\n");
4402     ok(delete_pf("msitest", FALSE), "Directory deleted\n");
4403
4404     DeleteFile(msifile);
4405     DeleteFile("msitest\\hydrogen");
4406     DeleteFile("msitest\\helium");
4407     DeleteFile("msitest\\lithium");
4408     RemoveDirectory("msitest");
4409 }
4410
4411 static void test_movefiles(void)
4412 {
4413     UINT r;
4414     char props[MAX_PATH];
4415
4416     CreateDirectoryA("msitest", NULL);
4417     create_file("msitest\\augustus", 100);
4418     create_file("cameroon", 100);
4419     create_file("djibouti", 100);
4420     create_file("egypt", 100);
4421     create_file("finland", 100);
4422     create_file("gambai", 100);
4423     create_file("honduras", 100);
4424     create_file("msitest\\india", 100);
4425     create_file("japan", 100);
4426     create_file("kenya", 100);
4427     CreateDirectoryA("latvia", NULL);
4428     create_file("nauru", 100);
4429     create_file("peru", 100);
4430     create_file("apple", 100);
4431     create_file("application", 100);
4432     create_file("ape", 100);
4433     create_file("foo", 100);
4434     create_file("fao", 100);
4435     create_file("fbod", 100);
4436     create_file("budding", 100);
4437     create_file("buddy", 100);
4438     create_file("bud", 100);
4439     create_file("bar", 100);
4440     create_file("bur", 100);
4441     create_file("bird", 100);
4442
4443     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
4444
4445     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4446
4447     /* if the source or dest property is not a full path,
4448      * windows tries to access it as a network resource
4449      */
4450
4451     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4452             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4453             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4454
4455     r = MsiInstallProductA(msifile, props);
4456     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4457     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4458     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4459     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4460     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4461     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4462     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4463     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4464     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4465     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4466     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4467     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4468     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4469     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4470     ok(delete_pf("msitest\\poland", TRUE), "File not moved\n");
4471     /* either apple or application will be moved depending on directory order */
4472     if (!delete_pf("msitest\\apple", TRUE))
4473         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4474     else
4475         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4476     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4477     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4478     /* either fao or foo will be moved depending on directory order */
4479     if (delete_pf("msitest\\foo", TRUE))
4480         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4481     else
4482         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4483     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4484     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4485     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4486     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4487     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4488     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4489     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4490     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4491     ok(delete_pf("msitest", FALSE), "File not installed\n");
4492     ok(DeleteFileA("cameroon"), "File moved\n");
4493     ok(!DeleteFileA("djibouti"), "File not moved\n");
4494     ok(DeleteFileA("egypt"), "File moved\n");
4495     ok(DeleteFileA("finland"), "File moved\n");
4496     ok(DeleteFileA("gambai"), "File moved\n");
4497     ok(!DeleteFileA("honduras"), "File not moved\n");
4498     ok(DeleteFileA("msitest\\india"), "File moved\n");
4499     ok(DeleteFileA("japan"), "File moved\n");
4500     ok(!DeleteFileA("kenya"), "File not moved\n");
4501     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4502     ok(!DeleteFileA("nauru"), "File not moved\n");
4503     ok(!DeleteFileA("peru"), "File not moved\n");
4504     ok(!DeleteFileA("apple"), "File not moved\n");
4505     ok(!DeleteFileA("application"), "File not moved\n");
4506     ok(DeleteFileA("ape"), "File moved\n");
4507     ok(!DeleteFileA("foo"), "File not moved\n");
4508     ok(!DeleteFileA("fao"), "File not moved\n");
4509     ok(DeleteFileA("fbod"), "File moved\n");
4510     ok(!DeleteFileA("budding"), "File not moved\n");
4511     ok(!DeleteFileA("buddy"), "File not moved\n");
4512     ok(DeleteFileA("bud"), "File moved\n");
4513     ok(!DeleteFileA("bar"), "File not moved\n");
4514     ok(!DeleteFileA("bur"), "File not moved\n");
4515     ok(DeleteFileA("bird"), "File moved\n");
4516
4517     DeleteFile("msitest\\augustus");
4518     RemoveDirectory("msitest");
4519     DeleteFile(msifile);
4520 }
4521
4522 static void test_missingcab(void)
4523 {
4524     UINT r;
4525
4526     CreateDirectoryA("msitest", NULL);
4527     create_file("msitest\\augustus", 500);
4528     create_file("maximus", 500);
4529
4530     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4531
4532     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4533
4534     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4535
4536     create_pf("msitest", FALSE);
4537     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4538
4539     r = MsiInstallProductA(msifile, NULL);
4540     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4541     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4542     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4543     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4544     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4545     ok(delete_pf("msitest", FALSE), "File not installed\n");
4546
4547     create_pf("msitest", FALSE);
4548     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4549     create_pf("msitest\\gaius", TRUE);
4550
4551     r = MsiInstallProductA(msifile, "GAIUS=1");
4552     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4553     todo_wine
4554     {
4555         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4556         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4557     }
4558     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4559     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4560     ok(delete_pf("msitest", FALSE), "File not installed\n");
4561
4562     DeleteFile("msitest\\augustus");
4563     RemoveDirectory("msitest");
4564     DeleteFile("maximus");
4565     DeleteFile("test1.cab");
4566     DeleteFile(msifile);
4567 }
4568
4569 static void test_duplicatefiles(void)
4570 {
4571     UINT r;
4572
4573     CreateDirectoryA("msitest", NULL);
4574     create_file("msitest\\maximus", 500);
4575     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4576
4577     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4578
4579     /* fails if the destination folder is not a valid property */
4580
4581     r = MsiInstallProductA(msifile, NULL);
4582     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4583     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4584     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4585     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4586     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4587     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4588     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4589     ok(delete_pf("msitest", FALSE), "File not installed\n");
4590
4591     DeleteFile("msitest\\maximus");
4592     RemoveDirectory("msitest");
4593     DeleteFile(msifile);
4594 }
4595
4596 static void test_writeregistryvalues(void)
4597 {
4598     UINT r;
4599     LONG res;
4600     HKEY hkey;
4601     DWORD type, size;
4602     CHAR path[MAX_PATH];
4603
4604     CreateDirectoryA("msitest", NULL);
4605     create_file("msitest\\augustus", 500);
4606
4607     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4608
4609     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4610
4611     r = MsiInstallProductA(msifile, NULL);
4612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4613     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4614     ok(delete_pf("msitest", FALSE), "File installed\n");
4615
4616     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4617     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4618
4619     size = MAX_PATH;
4620     type = REG_MULTI_SZ;
4621     memset(path, 'a', MAX_PATH);
4622     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4623     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4624     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4625     ok(size == 15, "Expected 15, got %d\n", size);
4626     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4627
4628     DeleteFile(msifile);
4629     DeleteFile("msitest\\augustus");
4630     RemoveDirectory("msitest");
4631
4632     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
4633     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine");
4634 }
4635
4636 static void test_sourcefolder(void)
4637 {
4638     UINT r;
4639
4640     CreateDirectoryA("msitest", NULL);
4641     create_file("augustus", 500);
4642
4643     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4644
4645     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4646
4647     r = MsiInstallProductA(msifile, NULL);
4648     ok(r == ERROR_INSTALL_FAILURE,
4649        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4650     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4651     todo_wine
4652     {
4653         ok(!delete_pf("msitest", FALSE), "File installed\n");
4654     }
4655
4656     RemoveDirectoryA("msitest");
4657
4658     r = MsiInstallProductA(msifile, NULL);
4659     ok(r == ERROR_INSTALL_FAILURE,
4660        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4661     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4662     todo_wine
4663     {
4664         ok(!delete_pf("msitest", FALSE), "File installed\n");
4665     }
4666
4667     DeleteFile(msifile);
4668     DeleteFile("augustus");
4669 }
4670
4671 static void test_customaction51(void)
4672 {
4673     UINT r;
4674
4675     CreateDirectoryA("msitest", NULL);
4676     create_file("msitest\\augustus", 500);
4677
4678     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
4679
4680     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4681
4682     r = MsiInstallProductA(msifile, NULL);
4683     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4684     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4685     ok(delete_pf("msitest", FALSE), "File installed\n");
4686
4687     DeleteFile(msifile);
4688     DeleteFile("msitest\\augustus");
4689     RemoveDirectory("msitest");
4690 }
4691
4692 static void test_installstate(void)
4693 {
4694     UINT r;
4695
4696     CreateDirectoryA("msitest", NULL);
4697     create_file("msitest\\alpha", 500);
4698     create_file("msitest\\beta", 500);
4699     create_file("msitest\\gamma", 500);
4700     create_file("msitest\\theta", 500);
4701     create_file("msitest\\delta", 500);
4702     create_file("msitest\\epsilon", 500);
4703     create_file("msitest\\zeta", 500);
4704     create_file("msitest\\iota", 500);
4705     create_file("msitest\\eta", 500);
4706     create_file("msitest\\kappa", 500);
4707     create_file("msitest\\lambda", 500);
4708     create_file("msitest\\mu", 500);
4709
4710     create_database(msifile, is_tables, sizeof(is_tables) / sizeof(msi_table));
4711
4712     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4713
4714     r = MsiInstallProductA(msifile, NULL);
4715     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4716     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4717     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4718     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4719     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4720     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4721     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4722     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4723     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4724     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4725     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4726     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4727     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4728     ok(delete_pf("msitest", FALSE), "File not installed\n");
4729
4730     r = MsiInstallProductA(msifile, "ADDLOCAL=\"one,two,three,four\"");
4731     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4732     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4733     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4734     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4735     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4736     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4737     ok(delete_pf("msitest\\epsilon", TRUE), "File not installed\n");
4738     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4739     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4740     ok(delete_pf("msitest\\eta", TRUE), "File not installed\n");
4741     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4742     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4743     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4744     ok(delete_pf("msitest", FALSE), "File not installed\n");
4745
4746     r = MsiInstallProductA(msifile, "ADDSOURCE=\"one,two,three,four\"");
4747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4748     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4749     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4750     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4751     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4752     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4753     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4754     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4755     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4756     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4757     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4758     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4759     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4760     ok(delete_pf("msitest", FALSE), "File not installed\n");
4761
4762     r = MsiInstallProductA(msifile, "REMOVE=\"one,two,three,four\"");
4763     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4764     ok(!delete_pf("msitest\\alpha", TRUE), "File installed\n");
4765     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4766     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4767     ok(!delete_pf("msitest\\theta", TRUE), "File installed\n");
4768     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4769     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4770     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4771     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4772     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4773     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4774     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4775     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4776     ok(!delete_pf("msitest", FALSE), "File installed\n");
4777
4778     DeleteFile(msifile);
4779     DeleteFile("msitest\\alpha");
4780     DeleteFile("msitest\\beta");
4781     DeleteFile("msitest\\gamma");
4782     DeleteFile("msitest\\theta");
4783     DeleteFile("msitest\\delta");
4784     DeleteFile("msitest\\epsilon");
4785     DeleteFile("msitest\\zeta");
4786     DeleteFile("msitest\\iota");
4787     DeleteFile("msitest\\eta");
4788     DeleteFile("msitest\\kappa");
4789     DeleteFile("msitest\\lambda");
4790     DeleteFile("msitest\\mu");
4791     RemoveDirectory("msitest");
4792 }
4793
4794 struct sourcepathmap
4795 {
4796     BOOL sost; /* shortone\shorttwo */
4797     BOOL solt; /* shortone\longtwo */
4798     BOOL lost; /* longone\shorttwo */
4799     BOOL lolt; /* longone\longtwo */
4800     BOOL soste; /* shortone\shorttwo source exists */
4801     BOOL solte; /* shortone\longtwo source exists */
4802     BOOL loste; /* longone\shorttwo source exists */
4803     BOOL lolte; /* longone\longtwo source exists */
4804     UINT err;
4805     DWORD size;
4806 } spmap[256] =
4807 {
4808     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4809     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4810     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4811     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4812     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4813     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4814     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4815     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4816     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4817     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4818     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4819     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4820     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4821     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4822     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4823     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4824     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4825     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4826     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4827     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4828     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4829     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4830     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4831     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4832     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4833     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4834     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4835     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4836     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4837     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4838     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4839     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4840     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4841     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4842     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4843     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4844     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4845     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4846     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4847     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4848     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4849     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4850     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4851     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4852     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4853     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4854     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4855     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4856     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4857     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4858     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4859     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4860     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4861     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4862     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4863     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4864     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4865     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4866     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4867     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4868     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4869     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4870     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4871     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4872     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4873     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4874     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4875     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4876     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4877     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4878     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4879     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4880     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4881     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4882     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4883     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4884     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4885     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4886     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4887     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4888     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4889     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4890     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4891     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4892     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4893     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4894     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4895     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4896     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4897     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4898     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4899     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4900     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4901     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4902     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4903     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4904     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4905     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4906     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4907     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4908     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4909     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4910     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4911     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4912     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4913     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4914     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4915     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4916     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4917     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4918     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4919     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4920     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4921     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4922     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4923     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4924     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4925     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4926     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4927     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4928     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4929     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4930     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4931     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4932     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4933     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4934     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4935     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4936     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4937     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4938     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4939     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4940     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4941     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4942     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4943     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4944     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4945     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4946     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4947     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4948     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4949     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4950     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4951     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4952     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4953     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4954     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4955     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4956     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4957     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4958     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4959     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4960     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4961     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4962     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4963     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4964     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4965     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4966     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4967     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4968     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4969     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4970     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4971     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4972     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4973     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4974     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4975     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4976     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4977     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4978     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4979     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4980     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4981     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4982     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4983     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4984     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4985     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4986     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4987     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4988     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4989     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4990     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4991     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4992     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4993     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4994     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4995     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4996     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4997     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4998     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4999     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5000     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5001     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5002     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5003     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5004     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5005     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5006     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5007     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5008     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5009     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5010     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5011     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5012     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5013     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5014     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5015     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5016     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5017     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5018     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5019     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5020     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5021     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5022     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5023     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5024     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5025     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5026     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5027     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5028     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5029     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5030     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5031     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5032     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5033     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5034     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5035     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5036     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5037     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5038     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5039     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5040     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5041     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5042     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5043     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5044     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5045     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5046     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5047     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5048     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5049     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5050     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5051     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5052     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5053     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5054     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5055     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5056     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5057     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5058     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5059     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5060     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5061     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5062     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5063     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5064 };
5065
5066 static DWORD get_pf_file_size(LPCSTR file)
5067 {
5068     CHAR path[MAX_PATH];
5069     HANDLE hfile;
5070     DWORD size;
5071
5072     lstrcpyA(path, PROG_FILES_DIR);
5073     lstrcatA(path, "\\");
5074     lstrcatA(path, file);
5075
5076     hfile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
5077     if (hfile == INVALID_HANDLE_VALUE)
5078         return 0;
5079
5080     size = GetFileSize(hfile, NULL);
5081     CloseHandle(hfile);
5082     return size;
5083 }
5084
5085 static void test_sourcepath(void)
5086 {
5087     UINT r, i;
5088
5089     create_database(msifile, sp_tables, sizeof(sp_tables) / sizeof(msi_table));
5090
5091     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5092
5093     for (i = 0; i < sizeof(spmap) / sizeof(spmap[0]); i++)
5094     {
5095         if (spmap[i].sost)
5096         {
5097             CreateDirectoryA("shortone", NULL);
5098             CreateDirectoryA("shortone\\shorttwo", NULL);
5099         }
5100
5101         if (spmap[i].solt)
5102         {
5103             CreateDirectoryA("shortone", NULL);
5104             CreateDirectoryA("shortone\\longtwo", NULL);
5105         }
5106
5107         if (spmap[i].lost)
5108         {
5109             CreateDirectoryA("longone", NULL);
5110             CreateDirectoryA("longone\\shorttwo", NULL);
5111         }
5112
5113         if (spmap[i].lolt)
5114         {
5115             CreateDirectoryA("longone", NULL);
5116             CreateDirectoryA("longone\\longtwo", NULL);
5117         }
5118
5119         if (spmap[i].soste)
5120             create_file("shortone\\shorttwo\\augustus", 50);
5121         if (spmap[i].solte)
5122             create_file("shortone\\longtwo\\augustus", 100);
5123         if (spmap[i].loste)
5124             create_file("longone\\shorttwo\\augustus", 150);
5125         if (spmap[i].lolte)
5126             create_file("longone\\longtwo\\augustus", 200);
5127
5128         r = MsiInstallProductA(msifile, NULL);
5129         ok(r == spmap[i].err, "%d: Expected %d, got %d\n", i, spmap[i].err, r);
5130         ok(get_pf_file_size("msitest\\augustus") == spmap[i].size,
5131            "%d: Expected %d, got %d\n", i, spmap[i].size,
5132            get_pf_file_size("msitest\\augustus"));
5133
5134         if (r == ERROR_SUCCESS)
5135         {
5136             ok(delete_pf("msitest\\augustus", TRUE), "%d: File not installed\n", i);
5137             ok(delete_pf("msitest", FALSE), "%d: File not installed\n", i);
5138         }
5139         else
5140         {
5141             ok(!delete_pf("msitest\\augustus", TRUE), "%d: File installed\n", i);
5142             todo_wine ok(!delete_pf("msitest", FALSE), "%d: File installed\n", i);
5143         }
5144
5145         DeleteFileA("shortone\\shorttwo\\augustus");
5146         DeleteFileA("shortone\\longtwo\\augustus");
5147         DeleteFileA("longone\\shorttwo\\augustus");
5148         DeleteFileA("longone\\longtwo\\augustus");
5149         RemoveDirectoryA("shortone\\shorttwo");
5150         RemoveDirectoryA("shortone\\longtwo");
5151         RemoveDirectoryA("longone\\shorttwo");
5152         RemoveDirectoryA("longone\\longtwo");
5153         RemoveDirectoryA("shortone");
5154         RemoveDirectoryA("longone");
5155     }
5156
5157     DeleteFileA(msifile);
5158 }
5159
5160 static void test_MsiConfigureProductEx(void)
5161 {
5162     UINT r;
5163     LONG res;
5164     DWORD type, size;
5165     HKEY props, source;
5166     CHAR keypath[MAX_PATH * 2];
5167     CHAR localpack[MAX_PATH];
5168
5169     CreateDirectoryA("msitest", NULL);
5170     create_file("msitest\\hydrogen", 500);
5171     create_file("msitest\\helium", 500);
5172     create_file("msitest\\lithium", 500);
5173
5174     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5175
5176     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5177
5178     /* NULL szProduct */
5179     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
5180                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5181     ok(r == ERROR_INVALID_PARAMETER,
5182        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5183
5184     /* empty szProduct */
5185     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
5186                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5187     ok(r == ERROR_INVALID_PARAMETER,
5188        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5189
5190     /* garbage szProduct */
5191     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
5192                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5193     ok(r == ERROR_INVALID_PARAMETER,
5194        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5195
5196     /* guid without brackets */
5197     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
5198                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5199                                "PROPVAR=42");
5200     ok(r == ERROR_INVALID_PARAMETER,
5201        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5202
5203     /* guid with brackets */
5204     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
5205                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5206                                "PROPVAR=42");
5207     ok(r == ERROR_UNKNOWN_PRODUCT,
5208        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5209
5210     /* same length as guid, but random */
5211     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
5212                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5213                                "PROPVAR=42");
5214     ok(r == ERROR_UNKNOWN_PRODUCT,
5215        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5216
5217     /* product not installed yet */
5218     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5219                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5220                                "PROPVAR=42");
5221     ok(r == ERROR_UNKNOWN_PRODUCT,
5222        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5223
5224     /* install the product, per-user unmanaged */
5225     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
5226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5227     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5228     ok(pf_exists("msitest\\helium"), "File not installed\n");
5229     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5230     ok(pf_exists("msitest"), "File not installed\n");
5231
5232     /* product is installed per-user managed, remove it */
5233     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5234                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5235                                "PROPVAR=42");
5236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5237     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5238     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5239     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5240     todo_wine
5241     {
5242         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5243     }
5244
5245     /* product has been removed */
5246     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5247                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5248                                "PROPVAR=42");
5249     ok(r == ERROR_UNKNOWN_PRODUCT,
5250        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
5251
5252     /* install the product, machine */
5253     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5255     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5256     ok(pf_exists("msitest\\helium"), "File not installed\n");
5257     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5258     ok(pf_exists("msitest"), "File not installed\n");
5259
5260     /* product is installed machine, remove it */
5261     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5262                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5263                                "PROPVAR=42");
5264     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5265     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5266     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5267     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5268     todo_wine
5269     {
5270         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5271     }
5272
5273     /* product has been removed */
5274     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5275                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5276                                "PROPVAR=42");
5277     ok(r == ERROR_UNKNOWN_PRODUCT,
5278        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
5279
5280     /* install the product, machine */
5281     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5282     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5283     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5284     ok(pf_exists("msitest\\helium"), "File not installed\n");
5285     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5286     ok(pf_exists("msitest"), "File not installed\n");
5287
5288     DeleteFileA(msifile);
5289
5290     /* local msifile is removed */
5291     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5292                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5293                                "PROPVAR=42");
5294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5295     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5296     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5297     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5298     todo_wine
5299     {
5300         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5301     }
5302
5303     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5304
5305     /* install the product, machine */
5306     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5307     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5308     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5309     ok(pf_exists("msitest\\helium"), "File not installed\n");
5310     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5311     ok(pf_exists("msitest"), "File not installed\n");
5312
5313     DeleteFileA(msifile);
5314
5315     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
5316     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
5317     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
5318
5319     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
5320     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5321
5322     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
5323                          (const BYTE *)"C:\\idontexist.msi", 18);
5324     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5325
5326     /* LocalPackage is used to find the cached msi package */
5327     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5328                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5329                                "PROPVAR=42");
5330     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
5331        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
5332     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5333     ok(pf_exists("msitest\\helium"), "File not installed\n");
5334     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5335     ok(pf_exists("msitest"), "File not installed\n");
5336
5337     RegCloseKey(props);
5338     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5339
5340     /* LastUsedSource (local msi package) can be used as a last resort */
5341     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5342                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5343                                "PROPVAR=42");
5344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5345     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5346     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5347     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5348     todo_wine
5349     {
5350         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5351     }
5352
5353     /* install the product, machine */
5354     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5355     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5356     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5357     ok(pf_exists("msitest\\helium"), "File not installed\n");
5358     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5359     ok(pf_exists("msitest"), "File not installed\n");
5360
5361     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
5362     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
5363     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
5364
5365     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
5366     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5367
5368     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
5369                          (const BYTE *)"C:\\idontexist.msi", 18);
5370     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5371
5372     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
5373     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\SourceList");
5374
5375     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &source);
5376     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5377
5378     type = REG_SZ;
5379     size = MAX_PATH;
5380     res = RegQueryValueExA(source, "PackageName", NULL, &type,
5381                            (LPBYTE)localpack, &size);
5382     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5383
5384     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
5385                          (const BYTE *)"idontexist.msi", 15);
5386     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5387
5388     /* SourceList is altered */
5389     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5390                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5391                                "PROPVAR=42");
5392     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
5393        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
5394     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5395     ok(pf_exists("msitest\\helium"), "File not installed\n");
5396     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5397     ok(pf_exists("msitest"), "File not installed\n");
5398
5399     /* restore the SourceList */
5400     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
5401                          (const BYTE *)localpack, lstrlenA(localpack) + 1);
5402     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5403
5404     /* finally remove the product */
5405     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5406                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5407                                "PROPVAR=42");
5408     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5409     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5410     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5411     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5412     todo_wine
5413     {
5414         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5415     }
5416
5417     DeleteFileA(msifile);
5418     RegCloseKey(source);
5419     RegCloseKey(props);
5420     DeleteFileA("msitest\\hydrogen");
5421     DeleteFileA("msitest\\helium");
5422     DeleteFileA("msitest\\lithium");
5423     RemoveDirectoryA("msitest");
5424 }
5425
5426 static void test_missingcomponent(void)
5427 {
5428     UINT r;
5429
5430     CreateDirectoryA("msitest", NULL);
5431     create_file("msitest\\hydrogen", 500);
5432     create_file("msitest\\helium", 500);
5433     create_file("msitest\\lithium", 500);
5434     create_file("beryllium", 500);
5435
5436     create_database(msifile, mcomp_tables, sizeof(mcomp_tables) / sizeof(msi_table));
5437
5438     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5439
5440     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
5441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5442     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5443     ok(pf_exists("msitest\\helium"), "File not installed\n");
5444     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5445     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
5446     ok(pf_exists("msitest"), "File not installed\n");
5447
5448     r = MsiInstallProductA(msifile, "REMOVE=ALL INSTALLLEVEL=10 PROPVAR=42");
5449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5450     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5451     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5452     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5453     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
5454     todo_wine
5455     {
5456         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5457     }
5458
5459     DeleteFileA(msifile);
5460     DeleteFileA("msitest\\hydrogen");
5461     DeleteFileA("msitest\\helium");
5462     DeleteFileA("msitest\\lithium");
5463     DeleteFileA("beryllium");
5464     RemoveDirectoryA("msitest");
5465 }
5466
5467 static void test_sourcedirprop(void)
5468 {
5469     UINT r;
5470     CHAR props[MAX_PATH];
5471
5472     CreateDirectoryA("msitest", NULL);
5473     create_file("msitest\\augustus", 500);
5474
5475     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
5476
5477     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5478
5479     r = MsiInstallProductA(msifile, NULL);
5480     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5481     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5482     ok(delete_pf("msitest", FALSE), "File installed\n");
5483
5484     DeleteFile("msitest\\augustus");
5485     RemoveDirectory("msitest");
5486
5487     CreateDirectoryA("altsource", NULL);
5488     CreateDirectoryA("altsource\\msitest", NULL);
5489     create_file("altsource\\msitest\\augustus", 500);
5490
5491     sprintf(props, "SRCDIR=%s\\altsource\\", CURR_DIR);
5492
5493     r = MsiInstallProductA(msifile, props);
5494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5495     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5496     ok(delete_pf("msitest", FALSE), "File installed\n");
5497
5498     DeleteFile(msifile);
5499     DeleteFile("altsource\\msitest\\augustus");
5500     RemoveDirectory("altsource\\msitest");
5501     RemoveDirectory("altsource");
5502 }
5503
5504 static void test_adminimage(void)
5505 {
5506     UINT r;
5507
5508     CreateDirectoryA("msitest", NULL);
5509     CreateDirectoryA("msitest\\first", NULL);
5510     CreateDirectoryA("msitest\\second", NULL);
5511     CreateDirectoryA("msitest\\cabout", NULL);
5512     CreateDirectoryA("msitest\\cabout\\new", NULL);
5513     create_file("msitest\\one.txt", 100);
5514     create_file("msitest\\first\\two.txt", 100);
5515     create_file("msitest\\second\\three.txt", 100);
5516     create_file("msitest\\cabout\\four.txt", 100);
5517     create_file("msitest\\cabout\\new\\five.txt", 100);
5518     create_file("msitest\\filename", 100);
5519     create_file("msitest\\service.exe", 100);
5520
5521     create_database_wordcount(msifile, ai_tables,
5522                               sizeof(ai_tables) / sizeof(msi_table),
5523                               msidbSumInfoSourceTypeAdminImage);
5524
5525     r = MsiInstallProductA(msifile, NULL);
5526     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5527
5528     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
5529     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
5530     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
5531     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
5532     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
5533     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
5534     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
5535     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
5536     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
5537     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
5538     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
5539     ok(delete_pf("msitest", FALSE), "File not installed\n");
5540
5541     DeleteFileA("msitest.msi");
5542     DeleteFileA("msitest\\cabout\\new\\five.txt");
5543     DeleteFileA("msitest\\cabout\\four.txt");
5544     DeleteFileA("msitest\\second\\three.txt");
5545     DeleteFileA("msitest\\first\\two.txt");
5546     DeleteFileA("msitest\\one.txt");
5547     DeleteFileA("msitest\\service.exe");
5548     DeleteFileA("msitest\\filename");
5549     RemoveDirectoryA("msitest\\cabout\\new");
5550     RemoveDirectoryA("msitest\\cabout");
5551     RemoveDirectoryA("msitest\\second");
5552     RemoveDirectoryA("msitest\\first");
5553     RemoveDirectoryA("msitest");
5554 }
5555
5556 START_TEST(install)
5557 {
5558     DWORD len;
5559     char temp_path[MAX_PATH], prev_path[MAX_PATH];
5560     STATEMGRSTATUS status;
5561     BOOL ret = FALSE;
5562
5563     init_functionpointers();
5564
5565     GetCurrentDirectoryA(MAX_PATH, prev_path);
5566     GetTempPath(MAX_PATH, temp_path);
5567     SetCurrentDirectoryA(temp_path);
5568
5569     lstrcpyA(CURR_DIR, temp_path);
5570     len = lstrlenA(CURR_DIR);
5571
5572     if(len && (CURR_DIR[len - 1] == '\\'))
5573         CURR_DIR[len - 1] = 0;
5574
5575     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
5576
5577     /* Create a restore point ourselves so we circumvent the multitude of restore points
5578      * that would have been created by all the installation and removal tests.
5579      */
5580     if (pSRSetRestorePointA)
5581     {
5582         memset(&status, 0, sizeof(status));
5583         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
5584     }
5585
5586     /* Create only one log file and don't append. We have to pass something
5587      * for the log mode for this to work.
5588      */
5589     MsiEnableLogA(INSTALLLOGMODE_FATALEXIT, "msitest.log", 0);
5590
5591     test_MsiInstallProduct();
5592     test_MsiSetComponentState();
5593     test_packagecoltypes();
5594     test_continuouscabs();
5595     test_caborder();
5596     test_mixedmedia();
5597     test_samesequence();
5598     test_uiLevelFlags();
5599     test_readonlyfile();
5600     test_setdirproperty();
5601     test_cabisextracted();
5602     test_concurrentinstall();
5603     test_setpropertyfolder();
5604     test_publish_registerproduct();
5605     test_publish_publishproduct();
5606     test_publish_publishfeatures();
5607     test_publish_registeruser();
5608     test_publish_processcomponents();
5609     test_publish();
5610     test_publishsourcelist();
5611     test_transformprop();
5612     test_currentworkingdir();
5613     test_admin();
5614     test_adminprops();
5615     test_removefiles();
5616     test_movefiles();
5617     test_missingcab();
5618     test_duplicatefiles();
5619     test_writeregistryvalues();
5620     test_sourcefolder();
5621     test_customaction51();
5622     test_installstate();
5623     test_sourcepath();
5624     test_MsiConfigureProductEx();
5625     test_missingcomponent();
5626     test_sourcedirprop();
5627     test_adminimage();
5628
5629     DeleteFileA("msitest.log");
5630
5631     if (pSRSetRestorePointA && ret)
5632     {
5633         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
5634         if (ret)
5635             remove_restore_point(status.llSequenceNumber);
5636     }
5637     FreeLibrary(hsrclient);
5638
5639     SetCurrentDirectoryA(prev_path);
5640 }