wintrust: Add a helper function to initialize chain creation parameters.
[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
33 #include "wine/test.h"
34
35 static UINT (WINAPI *pMsiQueryComponentStateA)
36     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
37 static UINT (WINAPI *pMsiSourceListGetInfoA)
38     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
39
40 static const char *msifile = "msitest.msi";
41 static const char *msifile2 = "winetest2.msi";
42 static const char *mstfile = "winetest.mst";
43 CHAR CURR_DIR[MAX_PATH];
44 CHAR PROG_FILES_DIR[MAX_PATH];
45
46 /* msi database data */
47
48 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
49                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
50                                     "Component\tComponent\n"
51                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
52                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
53                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
54                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
55                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
56                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
57                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
58                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
59
60 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
61                                     "s72\tS72\tl255\n"
62                                     "Directory\tDirectory\n"
63                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
64                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
65                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
66                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
67                                     "NEWDIR\tCABOUTDIR\tnew\n"
68                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
69                                     "TARGETDIR\t\tSourceDir";
70
71 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
72                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
73                                   "Feature\tFeature\n"
74                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
75                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
76                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
77                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
78                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
79                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
80                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
81
82 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
83                                        "s38\ts72\n"
84                                        "FeatureComponents\tFeature_\tComponent_\n"
85                                        "Five\tFive\n"
86                                        "Four\tFour\n"
87                                        "One\tOne\n"
88                                        "Three\tThree\n"
89                                        "Two\tTwo\n"
90                                        "feature\tcomponent\n"
91                                        "service_feature\tservice_comp\n";
92
93 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
94                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
95                                "File\tFile\n"
96                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
97                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
98                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
99                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
100                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
101                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
102                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
103
104 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
105                                            "s72\tS255\tI2\n"
106                                            "InstallExecuteSequence\tAction\n"
107                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
108                                            "CostFinalize\t\t1000\n"
109                                            "CostInitialize\t\t800\n"
110                                            "FileCost\t\t900\n"
111                                            "InstallFiles\t\t4000\n"
112                                            "InstallServices\t\t5000\n"
113                                            "InstallFinalize\t\t6600\n"
114                                            "InstallInitialize\t\t1500\n"
115                                            "InstallValidate\t\t1400\n"
116                                            "LaunchConditions\t\t100\n"
117                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
118
119 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
120                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
121                                 "Media\tDiskId\n"
122                                 "1\t3\t\t\tDISK1\t\n"
123                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
124
125 static const CHAR property_dat[] = "Property\tValue\n"
126                                    "s72\tl0\n"
127                                    "Property\tProperty\n"
128                                    "DefaultUIFont\tDlgFont8\n"
129                                    "HASUIRUN\t0\n"
130                                    "INSTALLLEVEL\t3\n"
131                                    "InstallMode\tTypical\n"
132                                    "Manufacturer\tWine\n"
133                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
134                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
135                                    "ProductID\tnone\n"
136                                    "ProductLanguage\t1033\n"
137                                    "ProductName\tMSITEST\n"
138                                    "ProductVersion\t1.1.1\n"
139                                    "PROMPTROLLBACKCOST\tP\n"
140                                    "Setup\tSetup\n"
141                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
142                                    "AdminProperties\tPOSTADMIN\n";
143
144 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
145                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
146                                    "Registry\tRegistry\n"
147                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
148                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
149                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
150                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
151
152 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
153                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
154                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
155                                           "ServiceInstall\tServiceInstall\n"
156                                           "TestService\tTestService\tTestService\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
157
158 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
159                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
160                                           "ServiceControl\tServiceControl\n"
161                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
162
163 /* tables for test_continuouscabs */
164 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
165                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
166                                        "Component\tComponent\n"
167                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
168                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
169                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
170
171 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
172                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
173                                      "Feature\tFeature\n"
174                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
175
176 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
177                                           "s38\ts72\n"
178                                           "FeatureComponents\tFeature_\tComponent_\n"
179                                           "feature\tmaximus\n"
180                                           "feature\taugustus\n"
181                                           "feature\tcaesar";
182
183 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
184                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
185                                   "File\tFile\n"
186                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
187                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
188                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
189
190 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
191                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
192                                    "Media\tDiskId\n"
193                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
194                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
195                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
196
197 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
198                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
199                                   "File\tFile\n"
200                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
201                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
202                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
203
204 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
205                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
206                                    "Media\tDiskId\n"
207                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
208                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
209                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
210
211 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
212                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
213                                     "Media\tDiskId\n"
214                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
215                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
216                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
217
218 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
219                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
220                                   "File\tFile\n"
221                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
222                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
223                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
224
225 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
226                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
227                                    "Media\tDiskId\n"
228                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
229
230 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
231                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
232                                    "Media\tDiskId\n"
233                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
234                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
235                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
236
237 /* tables for test_uiLevelFlags */
238 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
239                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
240                                        "Component\tComponent\n"
241                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
242                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
243                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
244
245 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
246                                            "s72\tS255\tI2\n"
247                                            "InstallUISequence\tAction\n"
248                                            "SetUIProperty\t\t5\n"
249                                            "ExecuteAction\t\t1100\n";
250
251 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
252                                            "s72\ti2\tS64\tS0\tS255\n"
253                                            "CustomAction\tAction\n"
254                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
255
256 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
257                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
258                                         "Component\tComponent\n"
259                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
260
261 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
262                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
263                                       "Feature\tFeature\n"
264                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
265                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
266
267 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
268                                            "s38\ts72\n"
269                                            "FeatureComponents\tFeature_\tComponent_\n"
270                                            "feature\tmaximus\n"
271                                            "montecristo\tmaximus";
272
273 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
274                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
275                                    "File\tFile\n"
276                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
277
278 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
279                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
280                                     "Media\tDiskId\n"
281                                     "1\t1\t\t\tDISK1\t\n";
282
283 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
284                                                "s72\tS255\tI2\n"
285                                                "InstallExecuteSequence\tAction\n"
286                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
287                                                "CostFinalize\t\t1000\n"
288                                                "CostInitialize\t\t800\n"
289                                                "FileCost\t\t900\n"
290                                                "InstallFiles\t\t4000\n"
291                                                "InstallFinalize\t\t6600\n"
292                                                "InstallInitialize\t\t1500\n"
293                                                "InstallValidate\t\t1400\n"
294                                                "LaunchConditions\t\t100\n"
295                                                "SetDirProperty\t\t950";
296
297 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
298                                             "s72\ti2\tS64\tS0\tS255\n"
299                                             "CustomAction\tAction\n"
300                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
301
302 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
303                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
304                                         "Component\tComponent\n"
305                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
306                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
307                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
308                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
309
310 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
311                                            "s38\ts72\n"
312                                            "FeatureComponents\tFeature_\tComponent_\n"
313                                            "feature\tmaximus\n"
314                                            "feature\taugustus\n"
315                                            "feature\tcaesar\n"
316                                            "feature\tgaius";
317
318 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
319                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
320                                    "File\tFile\n"
321                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
322                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
323                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
324                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
325
326 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
327                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
328                                     "Media\tDiskId\n"
329                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
330                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
331                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
332
333 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
334                                               "s72\tS255\tI2\n"
335                                               "InstallExecuteSequence\tAction\n"
336                                               "CostFinalize\t\t1000\n"
337                                               "CostInitialize\t\t800\n"
338                                               "FileCost\t\t900\n"
339                                               "InstallFiles\t\t4000\n"
340                                               "InstallServices\t\t5000\n"
341                                               "InstallFinalize\t\t6600\n"
342                                               "InstallInitialize\t\t1500\n"
343                                               "RunInstall\t\t1600\n"
344                                               "InstallValidate\t\t1400\n"
345                                               "LaunchConditions\t\t100";
346
347 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
348                                             "s72\ti2\tS64\tS0\tS255\n"
349                                             "CustomAction\tAction\n"
350                                             "RunInstall\t23\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
351
352 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
353                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
354                                        "Component\tComponent\n"
355                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
356
357 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
358                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
359                                         "Component\tComponent\n"
360                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
361
362 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
363                                            "s38\ts72\n"
364                                            "FeatureComponents\tFeature_\tComponent_\n"
365                                            "feature\taugustus";
366
367 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
368                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
369                                    "File\tFile\n"
370                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
371
372 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
373                                             "s72\ti2\tS64\tS0\tS255\n"
374                                             "CustomAction\tAction\n"
375                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
376
377 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
378                                                "s72\tS255\tI2\n"
379                                                "InstallExecuteSequence\tAction\n"
380                                                "CostFinalize\t\t1000\n"
381                                                "CostInitialize\t\t800\n"
382                                                "FileCost\t\t900\n"
383                                                "SetFolderProp\t\t950\n"
384                                                "InstallFiles\t\t4000\n"
385                                                "InstallServices\t\t5000\n"
386                                                "InstallFinalize\t\t6600\n"
387                                                "InstallInitialize\t\t1500\n"
388                                                "InstallValidate\t\t1400\n"
389                                                "LaunchConditions\t\t100";
390
391 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
392                                              "s72\tS255\tI2\n"
393                                              "InstallUISequence\tAction\n"
394                                              "CostInitialize\t\t800\n"
395                                              "FileCost\t\t900\n"
396                                              "CostFinalize\t\t1000\n"
397                                              "ExecuteAction\t\t1100\n";
398
399 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
400                                               "s72\tS255\tI2\n"
401                                               "InstallExecuteSequence\tAction\n"
402                                               "ValidateProductID\t\t700\n"
403                                               "CostInitialize\t\t800\n"
404                                               "FileCost\t\t900\n"
405                                               "CostFinalize\t\t1000\n"
406                                               "InstallValidate\t\t1400\n"
407                                               "InstallInitialize\t\t1500\n"
408                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
409                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
410                                               "RemoveFiles\t\t3500\n"
411                                               "InstallFiles\t\t4000\n"
412                                               "RegisterUser\t\t6000\n"
413                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
414                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
415                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
416                                               "InstallFinalize\t\t6600";
417
418 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
419                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
420                                        "Component\tComponent\n"
421                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
422
423 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
424                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
425                                         "Component\tComponent\n"
426                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
427
428 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
429                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
430                                         "Component\tComponent\n"
431                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
432
433 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
434                                             "s72\ti2\tS64\tS0\tS255\n"
435                                             "CustomAction\tAction\n"
436                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t";
437
438 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
439                                              "s72\tS255\tI2\n"
440                                              "AdminExecuteSequence\tAction\n"
441                                              "CostFinalize\t\t1000\n"
442                                              "CostInitialize\t\t800\n"
443                                              "FileCost\t\t900\n"
444                                              "SetPOSTADMIN\t\t950\n"
445                                              "InstallFiles\t\t4000\n"
446                                              "InstallFinalize\t\t6600\n"
447                                              "InstallInitialize\t\t1500\n"
448                                              "InstallValidate\t\t1400\n"
449                                              "LaunchConditions\t\t100";
450
451 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
452                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
453                                         "Component\tComponent\n"
454                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718\taugustus\n";
455
456 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
457                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
458                                         "Component\tComponent\n"
459                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
460                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
461                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
462
463 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
464                                            "s38\ts72\n"
465                                            "FeatureComponents\tFeature_\tComponent_\n"
466                                            "feature\thydrogen\n"
467                                            "feature\thelium\n"
468                                            "feature\tlithium";
469
470 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
471                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
472                                    "File\tFile\n"
473                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
474                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
475                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
476
477 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
478                                                "s72\tS255\tI2\n"
479                                                "InstallExecuteSequence\tAction\n"
480                                                "ValidateProductID\t\t700\n"
481                                                "CostInitialize\t\t800\n"
482                                                "FileCost\t\t900\n"
483                                                "CostFinalize\t\t1000\n"
484                                                "InstallValidate\t\t1400\n"
485                                                "InstallInitialize\t\t1500\n"
486                                                "ProcessComponents\t\t1600\n"
487                                                "UnpublishFeatures\t\t1800\n"
488                                                "RemoveFiles\t\t3500\n"
489                                                "InstallFiles\t\t4000\n"
490                                                "RegisterUser\t\t6000\n"
491                                                "RegisterProduct\t\t6100\n"
492                                                "PublishFeatures\t\t6300\n"
493                                                "PublishProduct\t\t6400\n"
494                                                "InstallFinalize\t\t6600";
495
496 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
497                                            "s72\ts72\tS255\ts72\tI2\n"
498                                            "RemoveFile\tFileKey\n"
499                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
500                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
501                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
502                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
503                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
504                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
505                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
506                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
507                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n";
508
509 typedef struct _msi_table
510 {
511     const CHAR *filename;
512     const CHAR *data;
513     int size;
514 } msi_table;
515
516 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
517
518 static const msi_table tables[] =
519 {
520     ADD_TABLE(component),
521     ADD_TABLE(directory),
522     ADD_TABLE(feature),
523     ADD_TABLE(feature_comp),
524     ADD_TABLE(file),
525     ADD_TABLE(install_exec_seq),
526     ADD_TABLE(media),
527     ADD_TABLE(property),
528     ADD_TABLE(registry),
529     ADD_TABLE(service_install),
530     ADD_TABLE(service_control)
531 };
532
533 static const msi_table cc_tables[] =
534 {
535     ADD_TABLE(cc_component),
536     ADD_TABLE(directory),
537     ADD_TABLE(cc_feature),
538     ADD_TABLE(cc_feature_comp),
539     ADD_TABLE(cc_file),
540     ADD_TABLE(install_exec_seq),
541     ADD_TABLE(cc_media),
542     ADD_TABLE(property),
543 };
544
545 static const msi_table co_tables[] =
546 {
547     ADD_TABLE(cc_component),
548     ADD_TABLE(directory),
549     ADD_TABLE(cc_feature),
550     ADD_TABLE(cc_feature_comp),
551     ADD_TABLE(co_file),
552     ADD_TABLE(install_exec_seq),
553     ADD_TABLE(co_media),
554     ADD_TABLE(property),
555 };
556
557 static const msi_table co2_tables[] =
558 {
559     ADD_TABLE(cc_component),
560     ADD_TABLE(directory),
561     ADD_TABLE(cc_feature),
562     ADD_TABLE(cc_feature_comp),
563     ADD_TABLE(cc_file),
564     ADD_TABLE(install_exec_seq),
565     ADD_TABLE(co2_media),
566     ADD_TABLE(property),
567 };
568
569 static const msi_table mm_tables[] =
570 {
571     ADD_TABLE(cc_component),
572     ADD_TABLE(directory),
573     ADD_TABLE(cc_feature),
574     ADD_TABLE(cc_feature_comp),
575     ADD_TABLE(mm_file),
576     ADD_TABLE(install_exec_seq),
577     ADD_TABLE(mm_media),
578     ADD_TABLE(property),
579 };
580
581 static const msi_table ss_tables[] =
582 {
583     ADD_TABLE(cc_component),
584     ADD_TABLE(directory),
585     ADD_TABLE(cc_feature),
586     ADD_TABLE(cc_feature_comp),
587     ADD_TABLE(cc_file),
588     ADD_TABLE(install_exec_seq),
589     ADD_TABLE(ss_media),
590     ADD_TABLE(property),
591 };
592
593 static const msi_table ui_tables[] =
594 {
595     ADD_TABLE(ui_component),
596     ADD_TABLE(directory),
597     ADD_TABLE(cc_feature),
598     ADD_TABLE(cc_feature_comp),
599     ADD_TABLE(cc_file),
600     ADD_TABLE(install_exec_seq),
601     ADD_TABLE(ui_install_ui_seq),
602     ADD_TABLE(ui_custom_action),
603     ADD_TABLE(cc_media),
604     ADD_TABLE(property),
605 };
606
607 static const msi_table rof_tables[] =
608 {
609     ADD_TABLE(rof_component),
610     ADD_TABLE(directory),
611     ADD_TABLE(rof_feature),
612     ADD_TABLE(rof_feature_comp),
613     ADD_TABLE(rof_file),
614     ADD_TABLE(install_exec_seq),
615     ADD_TABLE(rof_media),
616     ADD_TABLE(property),
617 };
618
619 static const msi_table sdp_tables[] =
620 {
621     ADD_TABLE(rof_component),
622     ADD_TABLE(directory),
623     ADD_TABLE(rof_feature),
624     ADD_TABLE(rof_feature_comp),
625     ADD_TABLE(rof_file),
626     ADD_TABLE(sdp_install_exec_seq),
627     ADD_TABLE(sdp_custom_action),
628     ADD_TABLE(rof_media),
629     ADD_TABLE(property),
630 };
631
632 static const msi_table cie_tables[] =
633 {
634     ADD_TABLE(cie_component),
635     ADD_TABLE(directory),
636     ADD_TABLE(cc_feature),
637     ADD_TABLE(cie_feature_comp),
638     ADD_TABLE(cie_file),
639     ADD_TABLE(install_exec_seq),
640     ADD_TABLE(cie_media),
641     ADD_TABLE(property),
642 };
643
644 static const msi_table ci_tables[] =
645 {
646     ADD_TABLE(ci_component),
647     ADD_TABLE(directory),
648     ADD_TABLE(rof_feature),
649     ADD_TABLE(rof_feature_comp),
650     ADD_TABLE(rof_file),
651     ADD_TABLE(ci_install_exec_seq),
652     ADD_TABLE(rof_media),
653     ADD_TABLE(property),
654     ADD_TABLE(ci_custom_action),
655 };
656
657 static const msi_table ci2_tables[] =
658 {
659     ADD_TABLE(ci2_component),
660     ADD_TABLE(directory),
661     ADD_TABLE(rof_feature),
662     ADD_TABLE(ci2_feature_comp),
663     ADD_TABLE(ci2_file),
664     ADD_TABLE(install_exec_seq),
665     ADD_TABLE(rof_media),
666     ADD_TABLE(property),
667 };
668
669 static const msi_table spf_tables[] =
670 {
671     ADD_TABLE(ci_component),
672     ADD_TABLE(directory),
673     ADD_TABLE(rof_feature),
674     ADD_TABLE(rof_feature_comp),
675     ADD_TABLE(rof_file),
676     ADD_TABLE(spf_install_exec_seq),
677     ADD_TABLE(rof_media),
678     ADD_TABLE(property),
679     ADD_TABLE(spf_custom_action),
680     ADD_TABLE(spf_install_ui_seq),
681 };
682
683 static const msi_table pp_tables[] =
684 {
685     ADD_TABLE(ci_component),
686     ADD_TABLE(directory),
687     ADD_TABLE(rof_feature),
688     ADD_TABLE(rof_feature_comp),
689     ADD_TABLE(rof_file),
690     ADD_TABLE(pp_install_exec_seq),
691     ADD_TABLE(rof_media),
692     ADD_TABLE(property),
693 };
694
695 static const msi_table tp_tables[] =
696 {
697     ADD_TABLE(tp_component),
698     ADD_TABLE(directory),
699     ADD_TABLE(rof_feature),
700     ADD_TABLE(ci2_feature_comp),
701     ADD_TABLE(ci2_file),
702     ADD_TABLE(install_exec_seq),
703     ADD_TABLE(rof_media),
704     ADD_TABLE(property),
705 };
706
707 static const msi_table cwd_tables[] =
708 {
709     ADD_TABLE(cwd_component),
710     ADD_TABLE(directory),
711     ADD_TABLE(rof_feature),
712     ADD_TABLE(ci2_feature_comp),
713     ADD_TABLE(ci2_file),
714     ADD_TABLE(install_exec_seq),
715     ADD_TABLE(rof_media),
716     ADD_TABLE(property),
717 };
718
719 static const msi_table adm_tables[] =
720 {
721     ADD_TABLE(adm_component),
722     ADD_TABLE(directory),
723     ADD_TABLE(rof_feature),
724     ADD_TABLE(ci2_feature_comp),
725     ADD_TABLE(ci2_file),
726     ADD_TABLE(install_exec_seq),
727     ADD_TABLE(rof_media),
728     ADD_TABLE(property),
729     ADD_TABLE(adm_custom_action),
730     ADD_TABLE(adm_admin_exec_seq),
731 };
732
733 static const msi_table amp_tables[] =
734 {
735     ADD_TABLE(amp_component),
736     ADD_TABLE(directory),
737     ADD_TABLE(rof_feature),
738     ADD_TABLE(ci2_feature_comp),
739     ADD_TABLE(ci2_file),
740     ADD_TABLE(install_exec_seq),
741     ADD_TABLE(rof_media),
742     ADD_TABLE(property),
743 };
744
745 static const msi_table rem_tables[] =
746 {
747     ADD_TABLE(rem_component),
748     ADD_TABLE(directory),
749     ADD_TABLE(rof_feature),
750     ADD_TABLE(rem_feature_comp),
751     ADD_TABLE(rem_file),
752     ADD_TABLE(rem_install_exec_seq),
753     ADD_TABLE(rof_media),
754     ADD_TABLE(property),
755     ADD_TABLE(rem_remove_files),
756 };
757
758 /* cabinet definitions */
759
760 /* make the max size large so there is only one cab file */
761 #define MEDIA_SIZE          0x7FFFFFFF
762 #define FOLDER_THRESHOLD    900000
763
764 /* the FCI callbacks */
765
766 static void *mem_alloc(ULONG cb)
767 {
768     return HeapAlloc(GetProcessHeap(), 0, cb);
769 }
770
771 static void mem_free(void *memory)
772 {
773     HeapFree(GetProcessHeap(), 0, memory);
774 }
775
776 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
777 {
778     sprintf(pccab->szCab, pv, pccab->iCab);
779     return TRUE;
780 }
781
782 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
783 {
784     return 0;
785 }
786
787 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
788                        BOOL fContinuation, void *pv)
789 {
790     return 0;
791 }
792
793 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
794 {
795     HANDLE handle;
796     DWORD dwAccess = 0;
797     DWORD dwShareMode = 0;
798     DWORD dwCreateDisposition = OPEN_EXISTING;
799     
800     dwAccess = GENERIC_READ | GENERIC_WRITE;
801     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
802     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
803
804     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
805         dwCreateDisposition = OPEN_EXISTING;
806     else
807         dwCreateDisposition = CREATE_NEW;
808
809     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
810                          dwCreateDisposition, 0, NULL);
811
812     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
813
814     return (INT_PTR)handle;
815 }
816
817 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
818 {
819     HANDLE handle = (HANDLE)hf;
820     DWORD dwRead;
821     BOOL res;
822     
823     res = ReadFile(handle, memory, cb, &dwRead, NULL);
824     ok(res, "Failed to ReadFile\n");
825
826     return dwRead;
827 }
828
829 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
830 {
831     HANDLE handle = (HANDLE)hf;
832     DWORD dwWritten;
833     BOOL res;
834
835     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
836     ok(res, "Failed to WriteFile\n");
837
838     return dwWritten;
839 }
840
841 static int fci_close(INT_PTR hf, int *err, void *pv)
842 {
843     HANDLE handle = (HANDLE)hf;
844     ok(CloseHandle(handle), "Failed to CloseHandle\n");
845
846     return 0;
847 }
848
849 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
850 {
851     HANDLE handle = (HANDLE)hf;
852     DWORD ret;
853     
854     ret = SetFilePointer(handle, dist, NULL, seektype);
855     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
856
857     return ret;
858 }
859
860 static int fci_delete(char *pszFile, int *err, void *pv)
861 {
862     BOOL ret = DeleteFileA(pszFile);
863     ok(ret, "Failed to DeleteFile %s\n", pszFile);
864
865     return 0;
866 }
867
868 static void init_functionpointers(void)
869 {
870     HMODULE hmsi = GetModuleHandleA("msi.dll");
871
872 #define GET_PROC(func) \
873     p ## func = (void*)GetProcAddress(hmsi, #func); \
874     if(!p ## func) \
875       trace("GetProcAddress(%s) failed\n", #func);
876
877     GET_PROC(MsiQueryComponentStateA);
878     GET_PROC(MsiSourceListGetInfoA);
879
880 #undef GET_PROC
881 }
882
883 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
884 {
885     CHAR buffer[0x20];
886     UINT r;
887     DWORD sz;
888
889     sz = sizeof buffer;
890     r = MsiRecordGetString(rec, field, buffer, &sz);
891     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
892 }
893
894 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
895 {
896     LPSTR tempname;
897
898     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
899     GetTempFileNameA(".", "xx", 0, tempname);
900
901     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
902     {
903         lstrcpyA(pszTempName, tempname);
904         HeapFree(GetProcessHeap(), 0, tempname);
905         return TRUE;
906     }
907
908     HeapFree(GetProcessHeap(), 0, tempname);
909
910     return FALSE;
911 }
912
913 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
914                              USHORT *pattribs, int *err, void *pv)
915 {
916     BY_HANDLE_FILE_INFORMATION finfo;
917     FILETIME filetime;
918     HANDLE handle;
919     DWORD attrs;
920     BOOL res;
921
922     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
923                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
924
925     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
926
927     res = GetFileInformationByHandle(handle, &finfo);
928     ok(res, "Expected GetFileInformationByHandle to succeed\n");
929    
930     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
931     FileTimeToDosDateTime(&filetime, pdate, ptime);
932
933     attrs = GetFileAttributes(pszName);
934     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
935
936     return (INT_PTR)handle;
937 }
938
939 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
940 {
941     char path[MAX_PATH];
942     char filename[MAX_PATH];
943
944     lstrcpyA(path, CURR_DIR);
945     lstrcatA(path, "\\");
946     lstrcatA(path, file);
947
948     lstrcpyA(filename, file);
949
950     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
951                       progress, get_open_info, compress);
952 }
953
954 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
955 {
956     ZeroMemory(pCabParams, sizeof(CCAB));
957
958     pCabParams->cb = max_size;
959     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
960     pCabParams->setID = 0xbeef;
961     pCabParams->iCab = 1;
962     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
963     lstrcatA(pCabParams->szCabPath, "\\");
964     lstrcpyA(pCabParams->szCab, name);
965 }
966
967 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
968 {
969     CCAB cabParams;
970     LPCSTR ptr;
971     HFCI hfci;
972     ERF erf;
973     BOOL res;
974
975     set_cab_parameters(&cabParams, name, max_size);
976
977     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
978                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
979                       get_temp_file, &cabParams, NULL);
980
981     ok(hfci != NULL, "Failed to create an FCI context\n");
982
983     ptr = files;
984     while (*ptr)
985     {
986         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
987         ok(res, "Failed to add file: %s\n", ptr);
988         ptr += lstrlen(ptr) + 1;
989     }
990
991     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
992     ok(res, "Failed to flush the cabinet\n");
993
994     res = FCIDestroy(hfci);
995     ok(res, "Failed to destroy the cabinet\n");
996 }
997
998 static BOOL get_program_files_dir(LPSTR buf)
999 {
1000     HKEY hkey;
1001     DWORD type = REG_EXPAND_SZ, size;
1002
1003     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1004                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1005         return FALSE;
1006
1007     size = MAX_PATH;
1008     if (RegQueryValueEx(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size))
1009         return FALSE;
1010
1011     RegCloseKey(hkey);
1012     return TRUE;
1013 }
1014
1015 static void create_file(const CHAR *name, DWORD size)
1016 {
1017     HANDLE file;
1018     DWORD written, left;
1019
1020     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1021     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1022     WriteFile(file, name, strlen(name), &written, NULL);
1023     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1024
1025     left = size - lstrlen(name) - 1;
1026
1027     SetFilePointer(file, left, NULL, FILE_CURRENT);
1028     SetEndOfFile(file);
1029     
1030     CloseHandle(file);
1031 }
1032
1033 static void create_test_files(void)
1034 {
1035     CreateDirectoryA("msitest", NULL);
1036     create_file("msitest\\one.txt", 100);
1037     CreateDirectoryA("msitest\\first", NULL);
1038     create_file("msitest\\first\\two.txt", 100);
1039     CreateDirectoryA("msitest\\second", NULL);
1040     create_file("msitest\\second\\three.txt", 100);
1041
1042     create_file("four.txt", 100);
1043     create_file("five.txt", 100);
1044     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1045
1046     create_file("msitest\\filename", 100);
1047     create_file("msitest\\service.exe", 100);
1048
1049     DeleteFileA("four.txt");
1050     DeleteFileA("five.txt");
1051 }
1052
1053 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1054 {
1055     CHAR path[MAX_PATH];
1056
1057     lstrcpyA(path, PROG_FILES_DIR);
1058     lstrcatA(path, "\\");
1059     lstrcatA(path, rel_path);
1060
1061     if (is_file)
1062         return DeleteFileA(path);
1063     else
1064         return RemoveDirectoryA(path);
1065 }
1066
1067 static void delete_test_files(void)
1068 {
1069     DeleteFileA("msitest.msi");
1070     DeleteFileA("msitest.cab");
1071     DeleteFileA("msitest\\second\\three.txt");
1072     DeleteFileA("msitest\\first\\two.txt");
1073     DeleteFileA("msitest\\one.txt");
1074     DeleteFileA("msitest\\service.exe");
1075     DeleteFileA("msitest\\filename");
1076     RemoveDirectoryA("msitest\\second");
1077     RemoveDirectoryA("msitest\\first");
1078     RemoveDirectoryA("msitest");
1079 }
1080
1081 static void write_file(const CHAR *filename, const char *data, int data_size)
1082 {
1083     DWORD size;
1084
1085     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1086                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1087
1088     WriteFile(hf, data, data_size, &size, NULL);
1089     CloseHandle(hf);
1090 }
1091
1092 static void write_msi_summary_info(MSIHANDLE db)
1093 {
1094     MSIHANDLE summary;
1095     UINT r;
1096
1097     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1099
1100     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1102
1103     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1104                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1106
1107     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1108     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1109
1110     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
1111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1112
1113     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1114     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1115
1116     /* write the summary changes back to the stream */
1117     r = MsiSummaryInfoPersist(summary);
1118     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1119
1120     MsiCloseHandle(summary);
1121 }
1122
1123 static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
1124 {
1125     MSIHANDLE db;
1126     UINT r;
1127     int j;
1128
1129     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1131
1132     /* import the tables into the database */
1133     for (j = 0; j < num_tables; j++)
1134     {
1135         const msi_table *table = &tables[j];
1136
1137         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1138
1139         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1140         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1141
1142         DeleteFileA(table->filename);
1143     }
1144
1145     write_msi_summary_info(db);
1146
1147     r = MsiDatabaseCommit(db);
1148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1149
1150     MsiCloseHandle(db);
1151 }
1152
1153 static void check_service_is_installed(void)
1154 {
1155     SC_HANDLE scm, service;
1156     BOOL res;
1157
1158     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1159     ok(scm != NULL, "Failed to open the SC Manager\n");
1160
1161     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1162     ok(service != NULL, "Failed to open TestService\n");
1163
1164     res = DeleteService(service);
1165     ok(res, "Failed to delete TestService\n");
1166 }
1167
1168 static void test_MsiInstallProduct(void)
1169 {
1170     UINT r;
1171     CHAR path[MAX_PATH];
1172     LONG res;
1173     HKEY hkey;
1174     DWORD num, size, type;
1175
1176     create_test_files();
1177     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1178
1179     r = MsiInstallProductA(msifile, NULL);
1180     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1181
1182     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1183     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1184     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1185     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1186     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1187     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1188     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1189     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1190     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1191     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1192     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1193     ok(delete_pf("msitest", FALSE), "File not installed\n");
1194
1195     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1196     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1197
1198     size = MAX_PATH;
1199     type = REG_SZ;
1200     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1201     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1202     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1203
1204     size = MAX_PATH;
1205     type = REG_SZ;
1206     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1207     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1208
1209     size = sizeof(num);
1210     type = REG_DWORD;
1211     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1212     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1213     ok(num == 314, "Expected 314, got %d\n", num);
1214
1215     size = MAX_PATH;
1216     type = REG_SZ;
1217     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1218     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1219     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1220
1221     check_service_is_installed();
1222
1223     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1224
1225     delete_test_files();
1226 }
1227
1228 static void test_MsiSetComponentState(void)
1229 {
1230     INSTALLSTATE installed, action;
1231     MSIHANDLE package;
1232     char path[MAX_PATH];
1233     UINT r;
1234
1235     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1236
1237     CoInitialize(NULL);
1238
1239     lstrcpy(path, CURR_DIR);
1240     lstrcat(path, "\\");
1241     lstrcat(path, msifile);
1242
1243     r = MsiOpenPackage(path, &package);
1244     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1245
1246     r = MsiDoAction(package, "CostInitialize");
1247     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1248
1249     r = MsiDoAction(package, "FileCost");
1250     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1251
1252     r = MsiDoAction(package, "CostFinalize");
1253     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1254
1255     r = MsiGetComponentState(package, "dangler", &installed, &action);
1256     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1257     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1258     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1259
1260     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1261     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1262
1263     MsiCloseHandle(package);
1264     CoUninitialize();
1265
1266     DeleteFileA(msifile);
1267 }
1268
1269 static void test_packagecoltypes(void)
1270 {
1271     MSIHANDLE hdb, view, rec;
1272     char path[MAX_PATH];
1273     LPCSTR query;
1274     UINT r, count;
1275
1276     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1277
1278     CoInitialize(NULL);
1279
1280     lstrcpy(path, CURR_DIR);
1281     lstrcat(path, "\\");
1282     lstrcat(path, msifile);
1283
1284     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1285     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1286
1287     query = "SELECT * FROM `Media`";
1288     r = MsiDatabaseOpenView( hdb, query, &view );
1289     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1290
1291     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1292     count = MsiRecordGetFieldCount( rec );
1293     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1294     ok(count == 6, "Expected 6, got %d\n", count);
1295     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1296     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1297     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1298     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1299     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1300     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1301     MsiCloseHandle(rec);
1302
1303     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1304     count = MsiRecordGetFieldCount( rec );
1305     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1306     ok(count == 6, "Expected 6, got %d\n", count);
1307     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1308     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1309     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1310     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1311     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1312     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1313
1314     MsiCloseHandle(rec);
1315     MsiCloseHandle(view);
1316     MsiCloseHandle(hdb);
1317     DeleteFile(msifile);
1318 }
1319
1320 static void create_cc_test_files(void)
1321 {
1322     CCAB cabParams;
1323     HFCI hfci;
1324     ERF erf;
1325     static CHAR cab_context[] = "test%d.cab";
1326     BOOL res;
1327
1328     create_file("maximus", 500);
1329     create_file("augustus", 50000);
1330     create_file("caesar", 500);
1331
1332     set_cab_parameters(&cabParams, "test1.cab", 200);
1333
1334     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1335                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1336                       get_temp_file, &cabParams, cab_context);
1337     ok(hfci != NULL, "Failed to create an FCI context\n");
1338
1339     res = add_file(hfci, "maximus", tcompTYPE_MSZIP);
1340     ok(res, "Failed to add file maximus\n");
1341
1342     res = add_file(hfci, "augustus", tcompTYPE_MSZIP);
1343     ok(res, "Failed to add file augustus\n");
1344
1345     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1346     ok(res, "Failed to flush the cabinet\n");
1347
1348     res = FCIDestroy(hfci);
1349     ok(res, "Failed to destroy the cabinet\n");
1350
1351     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1352
1353     DeleteFile("maximus");
1354     DeleteFile("augustus");
1355     DeleteFile("caesar");
1356 }
1357
1358 static void delete_cab_files(void)
1359 {
1360     SHFILEOPSTRUCT shfl;
1361     CHAR path[MAX_PATH+10];
1362
1363     lstrcpyA(path, CURR_DIR);
1364     lstrcatA(path, "\\*.cab");
1365     path[strlen(path) + 1] = '\0';
1366
1367     shfl.hwnd = NULL;
1368     shfl.wFunc = FO_DELETE;
1369     shfl.pFrom = path;
1370     shfl.pTo = NULL;
1371     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1372
1373     SHFileOperation(&shfl);
1374 }
1375
1376 static void test_continuouscabs(void)
1377 {
1378     UINT r;
1379
1380     create_cc_test_files();
1381     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1382
1383     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1384
1385     r = MsiInstallProductA(msifile, NULL);
1386     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1387     todo_wine
1388     {
1389         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1390         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1391         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1392     }
1393     ok(delete_pf("msitest", FALSE), "File not installed\n");
1394
1395     delete_cab_files();
1396     DeleteFile(msifile);
1397 }
1398
1399 static void test_caborder(void)
1400 {
1401     UINT r;
1402
1403     create_file("imperator", 100);
1404     create_file("maximus", 500);
1405     create_file("augustus", 50000);
1406     create_file("caesar", 500);
1407
1408     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1409
1410     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1411
1412     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1413     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1414     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1415
1416     r = MsiInstallProductA(msifile, NULL);
1417     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1418     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1419     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1420     todo_wine
1421     {
1422         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1423         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1424     }
1425
1426     delete_cab_files();
1427
1428     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1429     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1430     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1431
1432     r = MsiInstallProductA(msifile, NULL);
1433     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1434     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1435     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1436     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1437     todo_wine
1438     {
1439         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1440     }
1441
1442     delete_cab_files();
1443     DeleteFile(msifile);
1444
1445     create_cc_test_files();
1446     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1447
1448     r = MsiInstallProductA(msifile, NULL);
1449     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1450     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1451     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1452     todo_wine
1453     {
1454         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1455         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1456     }
1457
1458     delete_cab_files();
1459     DeleteFile(msifile);
1460
1461     create_cc_test_files();
1462     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
1463
1464     r = MsiInstallProductA(msifile, NULL);
1465     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1466     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1467     todo_wine
1468     {
1469         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1470         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1471         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1472     }
1473
1474     delete_cab_files();
1475     DeleteFile("imperator");
1476     DeleteFile("maximus");
1477     DeleteFile("augustus");
1478     DeleteFile("caesar");
1479     DeleteFile(msifile);
1480 }
1481
1482 static void test_mixedmedia(void)
1483 {
1484     UINT r;
1485
1486     CreateDirectoryA("msitest", NULL);
1487     create_file("msitest\\maximus", 500);
1488     create_file("msitest\\augustus", 500);
1489     create_file("caesar", 500);
1490
1491     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
1492
1493     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1494
1495     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
1496
1497     r = MsiInstallProductA(msifile, NULL);
1498     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1499     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1500     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1501     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1502     ok(delete_pf("msitest", FALSE), "File not installed\n");
1503
1504     /* Delete the files in the temp (current) folder */
1505     DeleteFile("msitest\\maximus");
1506     DeleteFile("msitest\\augustus");
1507     RemoveDirectory("msitest");
1508     DeleteFile("caesar");
1509     DeleteFile("test1.cab");
1510     DeleteFile(msifile);
1511 }
1512
1513 static void test_samesequence(void)
1514 {
1515     UINT r;
1516
1517     create_cc_test_files();
1518     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
1519
1520     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1521
1522     r = MsiInstallProductA(msifile, NULL);
1523     todo_wine
1524     {
1525         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1526         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1527         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1528     }
1529     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1530     ok(delete_pf("msitest", FALSE), "File not installed\n");
1531
1532     delete_cab_files();
1533     DeleteFile(msifile);
1534 }
1535
1536 static void test_uiLevelFlags(void)
1537 {
1538     UINT r;
1539
1540     create_cc_test_files();
1541     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
1542
1543     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
1544
1545     r = MsiInstallProductA(msifile, NULL);
1546     ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
1547     todo_wine
1548     {
1549         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1550         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1551     }
1552     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1553     ok(delete_pf("msitest", FALSE), "File not installed\n");
1554
1555     delete_cab_files();
1556     DeleteFile(msifile);
1557 }
1558
1559 static BOOL file_matches(LPSTR path)
1560 {
1561     CHAR buf[MAX_PATH];
1562     HANDLE file;
1563     DWORD size;
1564
1565     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1566                       NULL, OPEN_EXISTING, 0, NULL);
1567
1568     ZeroMemory(buf, MAX_PATH);
1569     ReadFile(file, buf, 15, &size, NULL);
1570     CloseHandle(file);
1571
1572     return !lstrcmp(buf, "msitest\\maximus");
1573 }
1574
1575 static void test_readonlyfile(void)
1576 {
1577     UINT r;
1578     DWORD size;
1579     HANDLE file;
1580     CHAR path[MAX_PATH];
1581
1582     CreateDirectoryA("msitest", NULL);
1583     create_file("msitest\\maximus", 500);
1584     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
1585
1586     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1587
1588     lstrcpy(path, PROG_FILES_DIR);
1589     lstrcat(path, "\\msitest");
1590     CreateDirectory(path, NULL);
1591
1592     lstrcat(path, "\\maximus");
1593     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1594                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
1595
1596     WriteFile(file, "readonlyfile", 20, &size, NULL);
1597     CloseHandle(file);
1598
1599     r = MsiInstallProductA(msifile, NULL);
1600     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1601     ok(file_matches(path), "Expected file to be overwritten\n");
1602     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1603     ok(delete_pf("msitest", FALSE), "File not installed\n");
1604
1605     /* Delete the files in the temp (current) folder */
1606     DeleteFile("msitest\\maximus");
1607     RemoveDirectory("msitest");
1608     DeleteFile(msifile);
1609 }
1610
1611 static void test_setdirproperty(void)
1612 {
1613     UINT r;
1614
1615     CreateDirectoryA("msitest", NULL);
1616     create_file("msitest\\maximus", 500);
1617     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
1618
1619     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1620
1621     r = MsiInstallProductA(msifile, NULL);
1622     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1623     ok(delete_pf("Common Files\\msitest\\maximus", TRUE), "File not installed\n");
1624     ok(delete_pf("Common Files\\msitest", FALSE), "File not installed\n");
1625
1626     /* Delete the files in the temp (current) folder */
1627     DeleteFile(msifile);
1628     DeleteFile("msitest\\maximus");
1629     RemoveDirectory("msitest");
1630 }
1631
1632 static void test_cabisextracted(void)
1633 {
1634     UINT r;
1635
1636     CreateDirectoryA("msitest", NULL);
1637     create_file("msitest\\gaius", 500);
1638     create_file("maximus", 500);
1639     create_file("augustus", 500);
1640     create_file("caesar", 500);
1641
1642     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1643     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1644     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1645
1646     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
1647
1648     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1649
1650     r = MsiInstallProductA(msifile, NULL);
1651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1652     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1653     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1654     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1655     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
1656     ok(delete_pf("msitest", FALSE), "File not installed\n");
1657
1658     /* Delete the files in the temp (current) folder */
1659     delete_cab_files();
1660     DeleteFile(msifile);
1661     DeleteFile("maximus");
1662     DeleteFile("augustus");
1663     DeleteFile("caesar");
1664     DeleteFile("msitest\\gaius");
1665     RemoveDirectory("msitest");
1666 }
1667
1668 static void test_concurrentinstall(void)
1669 {
1670     UINT r;
1671     CHAR path[MAX_PATH];
1672
1673     CreateDirectoryA("msitest", NULL);
1674     CreateDirectoryA("msitest\\msitest", NULL);
1675     create_file("msitest\\maximus", 500);
1676     create_file("msitest\\msitest\\augustus", 500);
1677
1678     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
1679
1680     lstrcpyA(path, CURR_DIR);
1681     lstrcatA(path, "\\msitest\\concurrent.msi");
1682     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
1683
1684     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1685
1686     r = MsiInstallProductA(msifile, NULL);
1687     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1688     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1689     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1690     ok(delete_pf("msitest", FALSE), "File not installed\n");
1691
1692     /* Delete the files in the temp (current) folder */
1693     DeleteFile(msifile);
1694     DeleteFile(path);
1695     DeleteFile("msitest\\msitest\\augustus");
1696     DeleteFile("msitest\\maximus");
1697     RemoveDirectory("msitest\\msitest");
1698     RemoveDirectory("msitest");
1699 }
1700
1701 static void test_setpropertyfolder(void)
1702 {
1703     UINT r;
1704
1705     CreateDirectoryA("msitest", NULL);
1706     create_file("msitest\\maximus", 500);
1707
1708     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
1709
1710     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1711
1712     r = MsiInstallProductA(msifile, NULL);
1713     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1714     ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
1715     ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
1716     ok(delete_pf("msitest", FALSE), "File not installed\n");
1717
1718     /* Delete the files in the temp (current) folder */
1719     DeleteFile(msifile);
1720     DeleteFile("msitest\\maximus");
1721     RemoveDirectory("msitest");
1722 }
1723
1724 static BOOL file_exists(LPCSTR file)
1725 {
1726     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
1727 }
1728
1729 static BOOL pf_exists(LPCSTR file)
1730 {
1731     CHAR path[MAX_PATH];
1732
1733     lstrcpyA(path, PROG_FILES_DIR);
1734     lstrcatA(path, "\\");
1735     lstrcatA(path, file);
1736
1737     return file_exists(path);
1738 }
1739
1740 static void delete_pfmsitest_files(void)
1741 {
1742     SHFILEOPSTRUCT shfl;
1743     CHAR path[MAX_PATH+11];
1744
1745     lstrcpyA(path, PROG_FILES_DIR);
1746     lstrcatA(path, "\\msitest\\*");
1747     path[strlen(path) + 1] = '\0';
1748
1749     shfl.hwnd = NULL;
1750     shfl.wFunc = FO_DELETE;
1751     shfl.pFrom = path;
1752     shfl.pTo = NULL;
1753     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1754
1755     SHFileOperation(&shfl);
1756
1757     lstrcpyA(path, PROG_FILES_DIR);
1758     lstrcatA(path, "\\msitest");
1759     RemoveDirectoryA(path);
1760 }
1761
1762 static void test_publish(void)
1763 {
1764     UINT r;
1765     INSTALLSTATE state;
1766     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
1767
1768     CreateDirectoryA("msitest", NULL);
1769     create_file("msitest\\maximus", 500);
1770
1771     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
1772
1773     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1774
1775     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1776     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1777
1778     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1779     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1780
1781     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1782     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1783
1784     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1785                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1786     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1787     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1788
1789     /* nothing published */
1790     r = MsiInstallProductA(msifile, NULL);
1791     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1792     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1793     ok(pf_exists("msitest"), "File not installed\n");
1794
1795     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1796     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1797
1798     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1799     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1800
1801     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1802     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1803
1804     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1805                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1806     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1807     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1808
1809     /* install again */
1810     r = MsiInstallProductA(msifile, NULL);
1811     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1812     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1813     ok(pf_exists("msitest"), "File not installed\n");
1814
1815     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1816     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1817
1818     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1819     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1820
1821     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1822     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1823
1824     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1825                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1826     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1827     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1828
1829     /* try to uninstall */
1830     r = MsiInstallProductA(msifile, "REMOVE=ALL");
1831     todo_wine
1832     {
1833         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1834     }
1835     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1836     ok(pf_exists("msitest"), "File deleted\n");
1837
1838     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1839     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1840
1841     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1842     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1843
1844     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1845     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1846
1847     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1848                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1849     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1850     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1851
1852     /* PublishProduct */
1853     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
1854     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1855     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1856     ok(pf_exists("msitest"), "File not installed\n");
1857
1858     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1859     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1860
1861     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1862     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1863
1864     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1865                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1866     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1867     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1868
1869     /* try to uninstall after PublishProduct */
1870     r = MsiInstallProductA(msifile, "REMOVE=ALL");
1871     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1872     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1873     ok(pf_exists("msitest"), "File deleted\n");
1874
1875     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1876     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1877
1878     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1879     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1880
1881     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1882     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1883
1884     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1885                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1886     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1887     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1888
1889     /* PublishProduct and RegisterProduct */
1890     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
1891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1892     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1893     ok(pf_exists("msitest"), "File not installed\n");
1894
1895     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1896     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1897
1898     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1899     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1900
1901     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1902     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1903
1904     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1905                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1906     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1907     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1908
1909     /* try it again */
1910     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
1911     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1912     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1913     ok(pf_exists("msitest"), "File not installed\n");
1914
1915     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1916     todo_wine
1917     {
1918         ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1919     }
1920
1921     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1922     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1923
1924     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1925     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1926
1927     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1928                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1929     todo_wine
1930     {
1931         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1932     }
1933     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1934
1935     /* uninstall has a problem with this */
1936     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
1937     todo_wine
1938     {
1939         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1940     }
1941     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1942     ok(pf_exists("msitest"), "File deleted\n");
1943
1944     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1945     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1946
1947     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1948     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1949
1950     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1951                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1952     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1953     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1954
1955     /* PublishProduct and RegisterProduct and ProcessComponents */
1956     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
1957     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1958     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1959     ok(pf_exists("msitest"), "File not installed\n");
1960
1961     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1962     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1963
1964     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1965     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1966
1967     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1968     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1969
1970     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1971                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1972     todo_wine
1973     {
1974         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1975         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1976     }
1977
1978     /* complete uninstall */
1979     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
1980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1981     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1982     ok(pf_exists("msitest"), "File deleted\n");
1983
1984     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1985     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1986
1987     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1988     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1989
1990     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1991     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1992
1993     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1994                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1995     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1996     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1997
1998     /* PublishProduct, RegisterProduct, ProcessComponents, PublishFeatures */
1999     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1 PUBLISH_FEATURES=1");
2000     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2001     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2002     ok(pf_exists("msitest"), "File not installed\n");
2003
2004     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2005     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2006
2007     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2008     todo_wine
2009     {
2010         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2011     }
2012
2013     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2014     todo_wine
2015     {
2016         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2017     }
2018
2019     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2020                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2021     todo_wine
2022     {
2023         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2024         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2025     }
2026
2027     /* complete uninstall */
2028     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2029     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2030     todo_wine
2031     {
2032         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2033         ok(!pf_exists("msitest"), "File deleted\n");
2034     }
2035
2036     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2037     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2038
2039     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");\
2040     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2041
2042     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2043     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2044
2045     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2046                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2047     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2048     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2049
2050     /* complete install */
2051     r = MsiInstallProductA(msifile, "FULL=1");
2052     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2053     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2054     ok(pf_exists("msitest"), "File not installed\n");
2055
2056     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2057     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2058
2059     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2060     todo_wine
2061     {
2062         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2063     }
2064
2065     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2066     todo_wine
2067     {
2068         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2069     }
2070
2071     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2072                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2073     todo_wine
2074     {
2075         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2076         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2077     }
2078
2079     /* no UnpublishFeatures */
2080     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2081     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2082     todo_wine
2083     {
2084         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2085         ok(!pf_exists("msitest"), "File deleted\n");
2086     }
2087
2088     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2089     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2090
2091     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2092     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2093
2094     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2095     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2096
2097     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2098                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2099     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2100     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2101
2102     /* complete install */
2103     r = MsiInstallProductA(msifile, "FULL=1");
2104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2105     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2106     ok(pf_exists("msitest"), "File not installed\n");
2107
2108     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2109     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2110
2111     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2112     todo_wine
2113     {
2114         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2115     }
2116
2117     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2118     todo_wine
2119     {
2120         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2121     }
2122
2123     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2124                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2125     todo_wine
2126     {
2127         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2128         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2129     }
2130
2131     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
2132     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
2133     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2134     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2135     ok(pf_exists("msitest"), "File deleted\n");
2136
2137     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2138     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2139
2140     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2141     todo_wine
2142     {
2143         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2144     }
2145
2146     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2147     todo_wine
2148     {
2149         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2150     }
2151
2152     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2153                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2154     todo_wine
2155     {
2156         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2157         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2158     }
2159
2160     /* complete install */
2161     r = MsiInstallProductA(msifile, "FULL=1");
2162     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2163     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2164     ok(pf_exists("msitest"), "File not installed\n");
2165
2166     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2167     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2168
2169     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2170     todo_wine
2171     {
2172         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2173     }
2174
2175     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2176     todo_wine
2177     {
2178         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2179     }
2180
2181     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2182                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2183     todo_wine
2184     {
2185         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2186         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2187     }
2188
2189     /* UnpublishFeatures, both features removed */
2190     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
2191     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2192     todo_wine
2193     {
2194         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2195         ok(!pf_exists("msitest"), "File not deleted\n");
2196     }
2197
2198     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2199     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2200
2201     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2202     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2203
2204     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2205     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2206
2207     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2208                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2209     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2210     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2211
2212     /* complete install */
2213     r = MsiInstallProductA(msifile, "FULL=1");
2214     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2215     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2216     ok(pf_exists("msitest"), "File not installed\n");
2217
2218     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2219     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2220
2221     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2222     todo_wine
2223     {
2224         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2225     }
2226
2227     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2228     todo_wine
2229     {
2230         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2231     }
2232
2233     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2234                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2235     todo_wine
2236     {
2237         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2238         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2239     }
2240
2241     /* complete uninstall */
2242     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2244     todo_wine
2245     {
2246         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2247         ok(!pf_exists("msitest"), "File not deleted\n");
2248     }
2249
2250     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2251     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2252
2253     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2254     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2255
2256     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2257     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2258
2259     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2260                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2261     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2262     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2263
2264     /* make sure 'Program Files\msitest' is removed */
2265     delete_pfmsitest_files();
2266
2267     DeleteFile(msifile);
2268     DeleteFile("msitest\\maximus");
2269     RemoveDirectory("msitest");
2270 }
2271
2272 static void test_publishsourcelist(void)
2273 {
2274     UINT r;
2275     DWORD size;
2276     CHAR value[MAX_PATH];
2277     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2278
2279     CreateDirectoryA("msitest", NULL);
2280     create_file("msitest\\maximus", 500);
2281
2282     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2283
2284     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2285
2286     r = MsiInstallProductA(msifile, NULL);
2287     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2288     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2289     ok(pf_exists("msitest"), "File not installed\n");
2290
2291     /* nothing published */
2292     size = 0xdeadbeef;
2293     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2294                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2295     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2296     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2297
2298     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2300     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2301     ok(pf_exists("msitest"), "File not installed\n");
2302
2303     /* after RegisterProduct */
2304     size = 0xdeadbeef;
2305     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2306                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2307     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2308     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2309
2310     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2311     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2312     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2313     ok(pf_exists("msitest"), "File not installed\n");
2314
2315     /* after ProcessComponents */
2316     size = 0xdeadbeef;
2317     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2318                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2319     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2320     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2321
2322     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2324     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2325     ok(pf_exists("msitest"), "File not installed\n");
2326
2327     /* after PublishFeatures */
2328     size = 0xdeadbeef;
2329     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2330                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2331     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2332     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2333
2334     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2336     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2337     ok(pf_exists("msitest"), "File not installed\n");
2338
2339     /* after PublishProduct */
2340     size = MAX_PATH;
2341     lstrcpyA(value, "aaa");
2342     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2343                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
2344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2345     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
2346     ok(size == 11, "Expected 11, got %d\n", size);
2347
2348     /* complete uninstall */
2349     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2351     todo_wine
2352     {
2353         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2354         ok(!pf_exists("msitest"), "File not deleted\n");
2355     }
2356
2357     /* make sure 'Program Files\msitest' is removed */
2358     delete_pfmsitest_files();
2359
2360     DeleteFile(msifile);
2361     DeleteFile("msitest\\maximus");
2362     RemoveDirectory("msitest");
2363 }
2364
2365 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
2366 {
2367     MSIHANDLE hview = 0;
2368     UINT r;
2369
2370     r = MsiDatabaseOpenView(hdb, query, &hview);
2371     if(r != ERROR_SUCCESS)
2372         return r;
2373
2374     r = MsiViewExecute(hview, hrec);
2375     if(r == ERROR_SUCCESS)
2376         r = MsiViewClose(hview);
2377     MsiCloseHandle(hview);
2378     return r;
2379 }
2380
2381 static void set_transform_summary_info(void)
2382 {
2383     UINT r;
2384     MSIHANDLE suminfo;
2385
2386     /* build summmary info */
2387     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
2388     todo_wine
2389     {
2390         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
2391     }
2392
2393     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
2394     todo_wine
2395     {
2396         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
2397     }
2398
2399     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
2400                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
2401                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
2402                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
2403     todo_wine
2404     {
2405         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
2406     }
2407
2408     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
2409     todo_wine
2410     {
2411         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
2412     }
2413
2414     r = MsiSummaryInfoPersist(suminfo);
2415     todo_wine
2416     {
2417         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
2418     }
2419
2420     r = MsiCloseHandle(suminfo);
2421     todo_wine
2422     {
2423         ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
2424     }
2425 }
2426
2427 static void generate_transform(void)
2428 {
2429     MSIHANDLE hdb1, hdb2;
2430     LPCSTR query;
2431     UINT r;
2432
2433     /* start with two identical databases */
2434     CopyFile(msifile, msifile2, FALSE);
2435
2436     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
2437     ok(r == ERROR_SUCCESS , "Failed to create database\n");
2438
2439     r = MsiDatabaseCommit(hdb1);
2440     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
2441
2442     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
2443     ok(r == ERROR_SUCCESS , "Failed to create database\n");
2444
2445     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2446     r = run_query(hdb1, 0, query);
2447     ok(r == ERROR_SUCCESS, "failed to add property\n");
2448
2449     /* database needs to be committed */
2450     MsiDatabaseCommit(hdb1);
2451
2452     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2453     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
2454
2455 #if 0  /* not implemented in wine yet */
2456     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
2457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2458 #endif
2459
2460     MsiCloseHandle(hdb1);
2461     MsiCloseHandle(hdb2);
2462 }
2463
2464 /* data for generating a transform */
2465
2466 /* tables transform names - encoded as they would be in an msi database file */
2467 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2468 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2469 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2470
2471 /* data in each table */
2472 static const char data1[] = /* _StringData */
2473     "propval";  /* all the strings squashed together */
2474
2475 static const WCHAR data2[] = { /* _StringPool */
2476 /*  len, refs */
2477     0,   0,    /* string 0 ''     */
2478     4,   1,    /* string 1 'prop' */
2479     3,   1,    /* string 2 'val'  */
2480 };
2481
2482 static const WCHAR data3[] = { /* Property */
2483     0x0201, 0x0001, 0x0002,
2484 };
2485
2486 static const struct {
2487     LPCWSTR name;
2488     const void *data;
2489     DWORD size;
2490 } table_transform_data[] =
2491 {
2492     { name1, data1, sizeof data1 - 1 },
2493     { name2, data2, sizeof data2 },
2494     { name3, data3, sizeof data3 },
2495 };
2496
2497 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2498
2499 static void generate_transform_manual(void)
2500 {
2501     IStorage *stg = NULL;
2502     IStream *stm;
2503     WCHAR name[0x20];
2504     HRESULT r;
2505     DWORD i, count;
2506     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2507
2508     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2509
2510     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2511
2512     r = StgCreateDocfile(name, mode, 0, &stg);
2513     ok(r == S_OK, "failed to create storage\n");
2514     if (!stg)
2515         return;
2516
2517     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
2518     ok(r == S_OK, "failed to set storage type\n");
2519
2520     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2521     {
2522         r = IStorage_CreateStream(stg, table_transform_data[i].name,
2523                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2524         if (FAILED(r))
2525         {
2526             ok(0, "failed to create stream %08x\n", r);
2527             continue;
2528         }
2529
2530         r = IStream_Write(stm, table_transform_data[i].data,
2531                           table_transform_data[i].size, &count);
2532         if (FAILED(r) || count != table_transform_data[i].size)
2533             ok(0, "failed to write stream\n");
2534         IStream_Release(stm);
2535     }
2536
2537     IStorage_Release(stg);
2538
2539     set_transform_summary_info();
2540 }
2541
2542 static void test_transformprop(void)
2543 {
2544     UINT r;
2545
2546     CreateDirectoryA("msitest", NULL);
2547     create_file("msitest\\augustus", 500);
2548
2549     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
2550
2551     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2552
2553     r = MsiInstallProductA(msifile, NULL);
2554     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2555     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2556     ok(!delete_pf("msitest", FALSE), "File installed\n");
2557
2558     if (0)
2559         generate_transform();
2560     else
2561         generate_transform_manual();
2562
2563     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
2564     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2565     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2566     ok(delete_pf("msitest", FALSE), "File not installed\n");
2567
2568     /* Delete the files in the temp (current) folder */
2569     DeleteFile(msifile);
2570     DeleteFile(msifile2);
2571     DeleteFile(mstfile);
2572     DeleteFile("msitest\\augustus");
2573     RemoveDirectory("msitest");
2574 }
2575
2576 static void test_currentworkingdir(void)
2577 {
2578     UINT r;
2579     CHAR path[MAX_PATH];
2580     LPSTR ptr, ptr2;
2581
2582     CreateDirectoryA("msitest", NULL);
2583     create_file("msitest\\augustus", 500);
2584
2585     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
2586
2587     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2588
2589     CreateDirectoryA("diffdir", NULL);
2590     SetCurrentDirectoryA("diffdir");
2591
2592     sprintf(path, "..\\%s", msifile);
2593     r = MsiInstallProductA(path, NULL);
2594     todo_wine
2595     {
2596         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
2597         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2598         ok(!delete_pf("msitest", FALSE), "File installed\n");
2599     }
2600
2601     sprintf(path, "%s\\%s", CURR_DIR, msifile);
2602     r = MsiInstallProductA(path, NULL);
2603     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2604     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2605     ok(delete_pf("msitest", FALSE), "File not installed\n");
2606
2607     lstrcpyA(path, CURR_DIR);
2608     if (path[lstrlenA(path) - 1] != '\\')
2609         lstrcatA(path, "\\");
2610     lstrcatA(path, "msitest.msi");
2611
2612     ptr2 = strrchr(path, '\\');
2613     *ptr2 = '\0';
2614     ptr = strrchr(path, '\\');
2615     *ptr2 = '\\';
2616     *(ptr++) = '\0';
2617
2618     SetCurrentDirectoryA(path);
2619
2620     r = MsiInstallProductA(ptr, NULL);
2621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2622     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2623     ok(delete_pf("msitest", FALSE), "File not installed\n");
2624
2625     SetCurrentDirectoryA(CURR_DIR);
2626
2627     DeleteFile(msifile);
2628     DeleteFile("msitest\\augustus");
2629     RemoveDirectory("msitest");
2630     RemoveDirectory("diffdir");
2631 }
2632
2633 static void set_admin_summary_info(const CHAR *name)
2634 {
2635     MSIHANDLE db, summary;
2636     UINT r;
2637
2638     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
2639     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2640
2641     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
2642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2643
2644     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
2645     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2646
2647     /* write the summary changes back to the stream */
2648     r = MsiSummaryInfoPersist(summary);
2649     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2650
2651     MsiCloseHandle(summary);
2652
2653     r = MsiDatabaseCommit(db);
2654     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2655
2656     MsiCloseHandle(db);
2657 }
2658
2659 static void test_admin(void)
2660 {
2661     UINT r;
2662
2663     CreateDirectoryA("msitest", NULL);
2664     create_file("msitest\\augustus", 500);
2665
2666     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
2667     set_admin_summary_info(msifile);
2668
2669     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2670
2671     r = MsiInstallProductA(msifile, NULL);
2672     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2673     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2674     ok(!delete_pf("msitest", FALSE), "File installed\n");
2675     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
2676     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
2677
2678     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
2679     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2680     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2681     ok(!delete_pf("msitest", FALSE), "File installed\n");
2682     todo_wine
2683     {
2684         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
2685         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
2686     }
2687
2688     DeleteFile(msifile);
2689     DeleteFile("msitest\\augustus");
2690     RemoveDirectory("msitest");
2691 }
2692
2693 static void set_admin_property_stream(LPCSTR file)
2694 {
2695     IStorage *stg;
2696     IStream *stm;
2697     WCHAR fileW[MAX_PATH];
2698     HRESULT hr;
2699     DWORD count;
2700     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
2701
2702     /* AdminProperties */
2703     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
2704     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
2705
2706     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
2707
2708     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
2709     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2710     if (!stg)
2711         return;
2712
2713     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2714     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2715
2716     hr = IStream_Write(stm, data, sizeof(data) - 1, &count);
2717     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2718
2719     IStream_Release(stm);
2720     IStorage_Release(stg);
2721 }
2722
2723 static void test_adminprops(void)
2724 {
2725     UINT r;
2726
2727     CreateDirectoryA("msitest", NULL);
2728     create_file("msitest\\augustus", 500);
2729
2730     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
2731     set_admin_summary_info(msifile);
2732     set_admin_property_stream(msifile);
2733
2734     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2735
2736     r = MsiInstallProductA(msifile, NULL);
2737     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2738     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
2739     ok(delete_pf("msitest", FALSE), "File installed\n");
2740
2741     DeleteFile(msifile);
2742     DeleteFile("msitest\\augustus");
2743     RemoveDirectory("msitest");
2744 }
2745
2746 static void create_pf(LPCSTR file, BOOL is_file)
2747 {
2748     CHAR path[MAX_PATH];
2749
2750     lstrcpyA(path, PROG_FILES_DIR);
2751     lstrcatA(path, "\\");
2752     lstrcatA(path, file);
2753
2754     if (is_file)
2755         create_file(path, 500);
2756     else
2757         CreateDirectoryA(path, NULL);
2758 }
2759
2760 static void test_removefiles(void)
2761 {
2762     UINT r;
2763
2764     CreateDirectoryA("msitest", NULL);
2765     create_file("msitest\\hydrogen", 500);
2766     create_file("msitest\\helium", 500);
2767     create_file("msitest\\lithium", 500);
2768
2769     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
2770
2771     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2772
2773     r = MsiInstallProductA(msifile, NULL);
2774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2775     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2776     ok(!pf_exists("msitest\\helium"), "File installed\n");
2777     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2778     ok(pf_exists("msitest"), "File not installed\n");
2779
2780     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2781     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2782     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
2783     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2784     todo_wine
2785     {
2786         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
2787         ok(delete_pf("msitest", FALSE), "File deleted\n");
2788     }
2789
2790     create_pf("msitest", FALSE);
2791     create_pf("msitest\\hydrogen", TRUE);
2792     create_pf("msitest\\helium", TRUE);
2793     create_pf("msitest\\lithium", TRUE);
2794
2795     r = MsiInstallProductA(msifile, NULL);
2796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2797     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2798     ok(pf_exists("msitest\\helium"), "File not installed\n");
2799     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2800     ok(pf_exists("msitest"), "File not installed\n");
2801
2802     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2804     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
2805     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2806     todo_wine
2807     {
2808         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
2809         ok(delete_pf("msitest", FALSE), "File deleted\n");
2810     }
2811
2812     create_pf("msitest", FALSE);
2813     create_pf("msitest\\furlong", TRUE);
2814     create_pf("msitest\\firkin", TRUE);
2815     create_pf("msitest\\fortnight", TRUE);
2816     create_pf("msitest\\becquerel", TRUE);
2817     create_pf("msitest\\dioptre", TRUE);
2818     create_pf("msitest\\attoparsec", TRUE);
2819     create_pf("msitest\\storeys", TRUE);
2820     create_pf("msitest\\block", TRUE);
2821     create_pf("msitest\\siriometer", TRUE);
2822
2823     r = MsiInstallProductA(msifile, NULL);
2824     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2825     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2826     ok(!pf_exists("msitest\\helium"), "File installed\n");
2827     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2828     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
2829     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
2830     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
2831     ok(pf_exists("msitest"), "File not installed\n");
2832     todo_wine
2833     {
2834         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
2835         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
2836         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
2837         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
2838         ok(!pf_exists("msitest\\block"), "File not deleted\n");
2839         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
2840     }
2841
2842     create_pf("msitest\\furlong", TRUE);
2843     create_pf("msitest\\firkin", TRUE);
2844     create_pf("msitest\\fortnight", TRUE);
2845     create_pf("msitest\\storeys", TRUE);
2846     create_pf("msitest\\block", TRUE);
2847     create_pf("msitest\\siriometer", TRUE);
2848
2849     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2850     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2851     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
2852     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2853     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
2854     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
2855     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
2856     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
2857     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
2858     todo_wine
2859     {
2860         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
2861         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
2862         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
2863         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
2864         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
2865     }
2866     ok(delete_pf("msitest", FALSE), "File deleted\n");
2867
2868     DeleteFile(msifile);
2869     DeleteFile("msitest\\hydrogen");
2870     DeleteFile("msitest\\helium");
2871     DeleteFile("msitest\\lithium");
2872     RemoveDirectory("msitest");
2873 }
2874
2875 START_TEST(install)
2876 {
2877     DWORD len;
2878     char temp_path[MAX_PATH], prev_path[MAX_PATH];
2879
2880     init_functionpointers();
2881
2882     GetCurrentDirectoryA(MAX_PATH, prev_path);
2883     GetTempPath(MAX_PATH, temp_path);
2884     SetCurrentDirectoryA(temp_path);
2885
2886     lstrcpyA(CURR_DIR, temp_path);
2887     len = lstrlenA(CURR_DIR);
2888
2889     if(len && (CURR_DIR[len - 1] == '\\'))
2890         CURR_DIR[len - 1] = 0;
2891
2892     get_program_files_dir(PROG_FILES_DIR);
2893
2894     test_MsiInstallProduct();
2895     test_MsiSetComponentState();
2896     test_packagecoltypes();
2897     test_continuouscabs();
2898     test_caborder();
2899     test_mixedmedia();
2900     test_samesequence();
2901     test_uiLevelFlags();
2902     test_readonlyfile();
2903     test_setdirproperty();
2904     test_cabisextracted();
2905     test_concurrentinstall();
2906     test_setpropertyfolder();
2907     test_publish();
2908     test_publishsourcelist();
2909     test_transformprop();
2910     test_currentworkingdir();
2911     test_admin();
2912     test_adminprops();
2913     test_removefiles();
2914
2915     SetCurrentDirectoryA(prev_path);
2916 }