msi: Add tests for the RemoveFiles standard action.
[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     pMsiQueryComponentStateA = (void*)GetProcAddress(hmsi, "MsiQueryComponentStateA");
873     pMsiSourceListGetInfoA = (void*)GetProcAddress(hmsi, "MsiSourceListGetInfoA");
874 }
875
876 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
877 {
878     CHAR buffer[0x20];
879     UINT r;
880     DWORD sz;
881
882     sz = sizeof buffer;
883     r = MsiRecordGetString(rec, field, buffer, &sz);
884     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
885 }
886
887 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
888 {
889     LPSTR tempname;
890
891     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
892     GetTempFileNameA(".", "xx", 0, tempname);
893
894     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
895     {
896         lstrcpyA(pszTempName, tempname);
897         HeapFree(GetProcessHeap(), 0, tempname);
898         return TRUE;
899     }
900
901     HeapFree(GetProcessHeap(), 0, tempname);
902
903     return FALSE;
904 }
905
906 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
907                              USHORT *pattribs, int *err, void *pv)
908 {
909     BY_HANDLE_FILE_INFORMATION finfo;
910     FILETIME filetime;
911     HANDLE handle;
912     DWORD attrs;
913     BOOL res;
914
915     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
916                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
917
918     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
919
920     res = GetFileInformationByHandle(handle, &finfo);
921     ok(res, "Expected GetFileInformationByHandle to succeed\n");
922    
923     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
924     FileTimeToDosDateTime(&filetime, pdate, ptime);
925
926     attrs = GetFileAttributes(pszName);
927     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
928
929     return (INT_PTR)handle;
930 }
931
932 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
933 {
934     char path[MAX_PATH];
935     char filename[MAX_PATH];
936
937     lstrcpyA(path, CURR_DIR);
938     lstrcatA(path, "\\");
939     lstrcatA(path, file);
940
941     lstrcpyA(filename, file);
942
943     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
944                       progress, get_open_info, compress);
945 }
946
947 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
948 {
949     ZeroMemory(pCabParams, sizeof(CCAB));
950
951     pCabParams->cb = max_size;
952     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
953     pCabParams->setID = 0xbeef;
954     pCabParams->iCab = 1;
955     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
956     lstrcatA(pCabParams->szCabPath, "\\");
957     lstrcpyA(pCabParams->szCab, name);
958 }
959
960 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
961 {
962     CCAB cabParams;
963     LPCSTR ptr;
964     HFCI hfci;
965     ERF erf;
966     BOOL res;
967
968     set_cab_parameters(&cabParams, name, max_size);
969
970     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
971                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
972                       get_temp_file, &cabParams, NULL);
973
974     ok(hfci != NULL, "Failed to create an FCI context\n");
975
976     ptr = files;
977     while (*ptr)
978     {
979         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
980         ok(res, "Failed to add file: %s\n", ptr);
981         ptr += lstrlen(ptr) + 1;
982     }
983
984     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
985     ok(res, "Failed to flush the cabinet\n");
986
987     res = FCIDestroy(hfci);
988     ok(res, "Failed to destroy the cabinet\n");
989 }
990
991 static BOOL get_program_files_dir(LPSTR buf)
992 {
993     HKEY hkey;
994     DWORD type = REG_EXPAND_SZ, size;
995
996     if (RegOpenKey(HKEY_LOCAL_MACHINE,
997                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
998         return FALSE;
999
1000     size = MAX_PATH;
1001     if (RegQueryValueEx(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size))
1002         return FALSE;
1003
1004     RegCloseKey(hkey);
1005     return TRUE;
1006 }
1007
1008 static void create_file(const CHAR *name, DWORD size)
1009 {
1010     HANDLE file;
1011     DWORD written, left;
1012
1013     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1014     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1015     WriteFile(file, name, strlen(name), &written, NULL);
1016     WriteFile(file, "\n", strlen("\n"), &written, NULL);
1017
1018     left = size - lstrlen(name) - 1;
1019
1020     SetFilePointer(file, left, NULL, FILE_CURRENT);
1021     SetEndOfFile(file);
1022     
1023     CloseHandle(file);
1024 }
1025
1026 static void create_test_files(void)
1027 {
1028     CreateDirectoryA("msitest", NULL);
1029     create_file("msitest\\one.txt", 100);
1030     CreateDirectoryA("msitest\\first", NULL);
1031     create_file("msitest\\first\\two.txt", 100);
1032     CreateDirectoryA("msitest\\second", NULL);
1033     create_file("msitest\\second\\three.txt", 100);
1034
1035     create_file("four.txt", 100);
1036     create_file("five.txt", 100);
1037     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1038
1039     create_file("msitest\\filename", 100);
1040     create_file("msitest\\service.exe", 100);
1041
1042     DeleteFileA("four.txt");
1043     DeleteFileA("five.txt");
1044 }
1045
1046 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1047 {
1048     CHAR path[MAX_PATH];
1049
1050     lstrcpyA(path, PROG_FILES_DIR);
1051     lstrcatA(path, "\\");
1052     lstrcatA(path, rel_path);
1053
1054     if (is_file)
1055         return DeleteFileA(path);
1056     else
1057         return RemoveDirectoryA(path);
1058 }
1059
1060 static void delete_test_files(void)
1061 {
1062     DeleteFileA("msitest.msi");
1063     DeleteFileA("msitest.cab");
1064     DeleteFileA("msitest\\second\\three.txt");
1065     DeleteFileA("msitest\\first\\two.txt");
1066     DeleteFileA("msitest\\one.txt");
1067     DeleteFileA("msitest\\service.exe");
1068     DeleteFileA("msitest\\filename");
1069     RemoveDirectoryA("msitest\\second");
1070     RemoveDirectoryA("msitest\\first");
1071     RemoveDirectoryA("msitest");
1072 }
1073
1074 static void write_file(const CHAR *filename, const char *data, int data_size)
1075 {
1076     DWORD size;
1077
1078     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1079                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1080
1081     WriteFile(hf, data, data_size, &size, NULL);
1082     CloseHandle(hf);
1083 }
1084
1085 static void write_msi_summary_info(MSIHANDLE db)
1086 {
1087     MSIHANDLE summary;
1088     UINT r;
1089
1090     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1091     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1092
1093     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1094     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1095
1096     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1097                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1098     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1099
1100     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1101     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1102
1103     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
1104     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1105
1106     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1107     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1108
1109     /* write the summary changes back to the stream */
1110     r = MsiSummaryInfoPersist(summary);
1111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1112
1113     MsiCloseHandle(summary);
1114 }
1115
1116 static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
1117 {
1118     MSIHANDLE db;
1119     UINT r;
1120     int j;
1121
1122     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1123     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1124
1125     /* import the tables into the database */
1126     for (j = 0; j < num_tables; j++)
1127     {
1128         const msi_table *table = &tables[j];
1129
1130         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1131
1132         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1133         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1134
1135         DeleteFileA(table->filename);
1136     }
1137
1138     write_msi_summary_info(db);
1139
1140     r = MsiDatabaseCommit(db);
1141     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1142
1143     MsiCloseHandle(db);
1144 }
1145
1146 static void check_service_is_installed(void)
1147 {
1148     SC_HANDLE scm, service;
1149     BOOL res;
1150
1151     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1152     ok(scm != NULL, "Failed to open the SC Manager\n");
1153
1154     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1155     ok(service != NULL, "Failed to open TestService\n");
1156
1157     res = DeleteService(service);
1158     ok(res, "Failed to delete TestService\n");
1159 }
1160
1161 static void test_MsiInstallProduct(void)
1162 {
1163     UINT r;
1164     CHAR path[MAX_PATH];
1165     LONG res;
1166     HKEY hkey;
1167     DWORD num, size, type;
1168
1169     create_test_files();
1170     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1171
1172     r = MsiInstallProductA(msifile, NULL);
1173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1174
1175     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1176     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1177     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1178     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1179     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1180     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1181     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1182     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1183     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1184     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1185     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1186     ok(delete_pf("msitest", FALSE), "File not installed\n");
1187
1188     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1189     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1190
1191     size = MAX_PATH;
1192     type = REG_SZ;
1193     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1194     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1195     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1196
1197     size = MAX_PATH;
1198     type = REG_SZ;
1199     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1200     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1201
1202     size = sizeof(num);
1203     type = REG_DWORD;
1204     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1205     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1206     ok(num == 314, "Expected 314, got %d\n", num);
1207
1208     size = MAX_PATH;
1209     type = REG_SZ;
1210     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1211     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1212     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1213
1214     check_service_is_installed();
1215
1216     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1217
1218     delete_test_files();
1219 }
1220
1221 static void test_MsiSetComponentState(void)
1222 {
1223     INSTALLSTATE installed, action;
1224     MSIHANDLE package;
1225     char path[MAX_PATH];
1226     UINT r;
1227
1228     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1229
1230     CoInitialize(NULL);
1231
1232     lstrcpy(path, CURR_DIR);
1233     lstrcat(path, "\\");
1234     lstrcat(path, msifile);
1235
1236     r = MsiOpenPackage(path, &package);
1237     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1238
1239     r = MsiDoAction(package, "CostInitialize");
1240     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1241
1242     r = MsiDoAction(package, "FileCost");
1243     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1244
1245     r = MsiDoAction(package, "CostFinalize");
1246     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1247
1248     r = MsiGetComponentState(package, "dangler", &installed, &action);
1249     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1250     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1251     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1252
1253     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1254     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1255
1256     MsiCloseHandle(package);
1257     CoUninitialize();
1258
1259     DeleteFileA(msifile);
1260 }
1261
1262 static void test_packagecoltypes(void)
1263 {
1264     MSIHANDLE hdb, view, rec;
1265     char path[MAX_PATH];
1266     LPCSTR query;
1267     UINT r, count;
1268
1269     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1270
1271     CoInitialize(NULL);
1272
1273     lstrcpy(path, CURR_DIR);
1274     lstrcat(path, "\\");
1275     lstrcat(path, msifile);
1276
1277     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1279
1280     query = "SELECT * FROM `Media`";
1281     r = MsiDatabaseOpenView( hdb, query, &view );
1282     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1283
1284     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1285     count = MsiRecordGetFieldCount( rec );
1286     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1287     ok(count == 6, "Expected 6, got %d\n", count);
1288     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1289     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1290     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1291     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1292     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1293     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1294     MsiCloseHandle(rec);
1295
1296     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1297     count = MsiRecordGetFieldCount( rec );
1298     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1299     ok(count == 6, "Expected 6, got %d\n", count);
1300     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1301     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1302     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1303     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1304     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1305     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1306
1307     MsiCloseHandle(rec);
1308     MsiCloseHandle(view);
1309     MsiCloseHandle(hdb);
1310     DeleteFile(msifile);
1311 }
1312
1313 static void create_cc_test_files(void)
1314 {
1315     CCAB cabParams;
1316     HFCI hfci;
1317     ERF erf;
1318     static CHAR cab_context[] = "test%d.cab";
1319     BOOL res;
1320
1321     create_file("maximus", 500);
1322     create_file("augustus", 50000);
1323     create_file("caesar", 500);
1324
1325     set_cab_parameters(&cabParams, "test1.cab", 200);
1326
1327     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1328                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1329                       get_temp_file, &cabParams, cab_context);
1330     ok(hfci != NULL, "Failed to create an FCI context\n");
1331
1332     res = add_file(hfci, "maximus", tcompTYPE_MSZIP);
1333     ok(res, "Failed to add file maximus\n");
1334
1335     res = add_file(hfci, "augustus", tcompTYPE_MSZIP);
1336     ok(res, "Failed to add file augustus\n");
1337
1338     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1339     ok(res, "Failed to flush the cabinet\n");
1340
1341     res = FCIDestroy(hfci);
1342     ok(res, "Failed to destroy the cabinet\n");
1343
1344     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1345
1346     DeleteFile("maximus");
1347     DeleteFile("augustus");
1348     DeleteFile("caesar");
1349 }
1350
1351 static void delete_cab_files(void)
1352 {
1353     SHFILEOPSTRUCT shfl;
1354     CHAR path[MAX_PATH+10];
1355
1356     lstrcpyA(path, CURR_DIR);
1357     lstrcatA(path, "\\*.cab");
1358     path[strlen(path) + 1] = '\0';
1359
1360     shfl.hwnd = NULL;
1361     shfl.wFunc = FO_DELETE;
1362     shfl.pFrom = path;
1363     shfl.pTo = NULL;
1364     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1365
1366     SHFileOperation(&shfl);
1367 }
1368
1369 static void test_continuouscabs(void)
1370 {
1371     UINT r;
1372
1373     create_cc_test_files();
1374     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1375
1376     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1377
1378     r = MsiInstallProductA(msifile, NULL);
1379     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1380     todo_wine
1381     {
1382         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1383         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1384         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1385     }
1386     ok(delete_pf("msitest", FALSE), "File not installed\n");
1387
1388     delete_cab_files();
1389     DeleteFile(msifile);
1390 }
1391
1392 static void test_caborder(void)
1393 {
1394     UINT r;
1395
1396     create_file("imperator", 100);
1397     create_file("maximus", 500);
1398     create_file("augustus", 50000);
1399     create_file("caesar", 500);
1400
1401     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1402
1403     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1404
1405     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1406     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1407     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1408
1409     r = MsiInstallProductA(msifile, NULL);
1410     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1411     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1412     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1413     todo_wine
1414     {
1415         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1416         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1417     }
1418
1419     delete_cab_files();
1420
1421     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1422     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1423     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1424
1425     r = MsiInstallProductA(msifile, NULL);
1426     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1427     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1428     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1429     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1430     todo_wine
1431     {
1432         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1433     }
1434
1435     delete_cab_files();
1436     DeleteFile(msifile);
1437
1438     create_cc_test_files();
1439     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1440
1441     r = MsiInstallProductA(msifile, NULL);
1442     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1443     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1444     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1445     todo_wine
1446     {
1447         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1448         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1449     }
1450
1451     delete_cab_files();
1452     DeleteFile(msifile);
1453
1454     create_cc_test_files();
1455     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
1456
1457     r = MsiInstallProductA(msifile, NULL);
1458     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1459     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1460     todo_wine
1461     {
1462         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1463         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1464         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1465     }
1466
1467     delete_cab_files();
1468     DeleteFile("imperator");
1469     DeleteFile("maximus");
1470     DeleteFile("augustus");
1471     DeleteFile("caesar");
1472     DeleteFile(msifile);
1473 }
1474
1475 static void test_mixedmedia(void)
1476 {
1477     UINT r;
1478
1479     CreateDirectoryA("msitest", NULL);
1480     create_file("msitest\\maximus", 500);
1481     create_file("msitest\\augustus", 500);
1482     create_file("caesar", 500);
1483
1484     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
1485
1486     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1487
1488     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
1489
1490     r = MsiInstallProductA(msifile, NULL);
1491     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1492     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1493     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1494     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1495     ok(delete_pf("msitest", FALSE), "File not installed\n");
1496
1497     /* Delete the files in the temp (current) folder */
1498     DeleteFile("msitest\\maximus");
1499     DeleteFile("msitest\\augustus");
1500     RemoveDirectory("msitest");
1501     DeleteFile("caesar");
1502     DeleteFile("test1.cab");
1503     DeleteFile(msifile);
1504 }
1505
1506 static void test_samesequence(void)
1507 {
1508     UINT r;
1509
1510     create_cc_test_files();
1511     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
1512
1513     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1514
1515     r = MsiInstallProductA(msifile, NULL);
1516     todo_wine
1517     {
1518         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1519         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1520         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1521     }
1522     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1523     ok(delete_pf("msitest", FALSE), "File not installed\n");
1524
1525     delete_cab_files();
1526     DeleteFile(msifile);
1527 }
1528
1529 static void test_uiLevelFlags(void)
1530 {
1531     UINT r;
1532
1533     create_cc_test_files();
1534     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
1535
1536     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
1537
1538     r = MsiInstallProductA(msifile, NULL);
1539     ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
1540     todo_wine
1541     {
1542         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1543         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1544     }
1545     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1546     ok(delete_pf("msitest", FALSE), "File not installed\n");
1547
1548     delete_cab_files();
1549     DeleteFile(msifile);
1550 }
1551
1552 static BOOL file_matches(LPSTR path)
1553 {
1554     CHAR buf[MAX_PATH];
1555     HANDLE file;
1556     DWORD size;
1557
1558     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1559                       NULL, OPEN_EXISTING, 0, NULL);
1560
1561     ZeroMemory(buf, MAX_PATH);
1562     ReadFile(file, buf, 15, &size, NULL);
1563     CloseHandle(file);
1564
1565     return !lstrcmp(buf, "msitest\\maximus");
1566 }
1567
1568 static void test_readonlyfile(void)
1569 {
1570     UINT r;
1571     DWORD size;
1572     HANDLE file;
1573     CHAR path[MAX_PATH];
1574
1575     CreateDirectoryA("msitest", NULL);
1576     create_file("msitest\\maximus", 500);
1577     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
1578
1579     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1580
1581     lstrcpy(path, PROG_FILES_DIR);
1582     lstrcat(path, "\\msitest");
1583     CreateDirectory(path, NULL);
1584
1585     lstrcat(path, "\\maximus");
1586     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1587                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
1588
1589     WriteFile(file, "readonlyfile", 20, &size, NULL);
1590     CloseHandle(file);
1591
1592     r = MsiInstallProductA(msifile, NULL);
1593     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1594     ok(file_matches(path), "Expected file to be overwritten\n");
1595     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1596     ok(delete_pf("msitest", FALSE), "File not installed\n");
1597
1598     /* Delete the files in the temp (current) folder */
1599     DeleteFile("msitest\\maximus");
1600     RemoveDirectory("msitest");
1601     DeleteFile(msifile);
1602 }
1603
1604 static void test_setdirproperty(void)
1605 {
1606     UINT r;
1607
1608     CreateDirectoryA("msitest", NULL);
1609     create_file("msitest\\maximus", 500);
1610     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
1611
1612     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1613
1614     r = MsiInstallProductA(msifile, NULL);
1615     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1616     ok(delete_pf("Common Files\\msitest\\maximus", TRUE), "File not installed\n");
1617     ok(delete_pf("Common Files\\msitest", FALSE), "File not installed\n");
1618
1619     /* Delete the files in the temp (current) folder */
1620     DeleteFile(msifile);
1621     DeleteFile("msitest\\maximus");
1622     RemoveDirectory("msitest");
1623 }
1624
1625 static void test_cabisextracted(void)
1626 {
1627     UINT r;
1628
1629     CreateDirectoryA("msitest", NULL);
1630     create_file("msitest\\gaius", 500);
1631     create_file("maximus", 500);
1632     create_file("augustus", 500);
1633     create_file("caesar", 500);
1634
1635     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1636     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1637     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1638
1639     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
1640
1641     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1642
1643     r = MsiInstallProductA(msifile, NULL);
1644     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1645     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1646     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1647     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1648     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
1649     ok(delete_pf("msitest", FALSE), "File not installed\n");
1650
1651     /* Delete the files in the temp (current) folder */
1652     delete_cab_files();
1653     DeleteFile(msifile);
1654     DeleteFile("maximus");
1655     DeleteFile("augustus");
1656     DeleteFile("caesar");
1657     DeleteFile("msitest\\gaius");
1658     RemoveDirectory("msitest");
1659 }
1660
1661 static void test_concurrentinstall(void)
1662 {
1663     UINT r;
1664     CHAR path[MAX_PATH];
1665
1666     CreateDirectoryA("msitest", NULL);
1667     CreateDirectoryA("msitest\\msitest", NULL);
1668     create_file("msitest\\maximus", 500);
1669     create_file("msitest\\msitest\\augustus", 500);
1670
1671     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
1672
1673     lstrcpyA(path, CURR_DIR);
1674     lstrcatA(path, "\\msitest\\concurrent.msi");
1675     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
1676
1677     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1678
1679     r = MsiInstallProductA(msifile, NULL);
1680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1681     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1682     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1683     ok(delete_pf("msitest", FALSE), "File not installed\n");
1684
1685     /* Delete the files in the temp (current) folder */
1686     DeleteFile(msifile);
1687     DeleteFile(path);
1688     DeleteFile("msitest\\msitest\\augustus");
1689     DeleteFile("msitest\\maximus");
1690     RemoveDirectory("msitest\\msitest");
1691     RemoveDirectory("msitest");
1692 }
1693
1694 static void test_setpropertyfolder(void)
1695 {
1696     UINT r;
1697
1698     CreateDirectoryA("msitest", NULL);
1699     create_file("msitest\\maximus", 500);
1700
1701     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
1702
1703     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1704
1705     r = MsiInstallProductA(msifile, NULL);
1706     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1707     ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
1708     ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
1709     ok(delete_pf("msitest", FALSE), "File not installed\n");
1710
1711     /* Delete the files in the temp (current) folder */
1712     DeleteFile(msifile);
1713     DeleteFile("msitest\\maximus");
1714     RemoveDirectory("msitest");
1715 }
1716
1717 static BOOL file_exists(LPCSTR file)
1718 {
1719     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
1720 }
1721
1722 static BOOL pf_exists(LPCSTR file)
1723 {
1724     CHAR path[MAX_PATH];
1725
1726     lstrcpyA(path, PROG_FILES_DIR);
1727     lstrcatA(path, "\\");
1728     lstrcatA(path, file);
1729
1730     return file_exists(path);
1731 }
1732
1733 static void delete_pfmsitest_files(void)
1734 {
1735     SHFILEOPSTRUCT shfl;
1736     CHAR path[MAX_PATH+10];
1737
1738     lstrcpyA(path, PROG_FILES_DIR);
1739     lstrcatA(path, "\\msitest\\*");
1740     path[strlen(path) + 1] = '\0';
1741
1742     shfl.hwnd = NULL;
1743     shfl.wFunc = FO_DELETE;
1744     shfl.pFrom = path;
1745     shfl.pTo = NULL;
1746     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1747
1748     SHFileOperation(&shfl);
1749
1750     lstrcpyA(path, PROG_FILES_DIR);
1751     lstrcatA(path, "\\msitest");
1752     RemoveDirectoryA(path);
1753 }
1754
1755 static void test_publish(void)
1756 {
1757     UINT r;
1758     INSTALLSTATE state;
1759     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
1760
1761     CreateDirectoryA("msitest", NULL);
1762     create_file("msitest\\maximus", 500);
1763
1764     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
1765
1766     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1767
1768     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1769     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1770
1771     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1772     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1773
1774     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1775     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1776
1777     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1778                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1779     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1780     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1781
1782     /* nothing published */
1783     r = MsiInstallProductA(msifile, NULL);
1784     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1785     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1786     ok(pf_exists("msitest"), "File not installed\n");
1787
1788     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1789     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1790
1791     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1792     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1793
1794     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1795     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1796
1797     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1798                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1799     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1800     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1801
1802     /* install again */
1803     r = MsiInstallProductA(msifile, NULL);
1804     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1805     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1806     ok(pf_exists("msitest"), "File not installed\n");
1807
1808     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1809     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1810
1811     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1812     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1813
1814     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1815     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1816
1817     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1818                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1819     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1820     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1821
1822     /* try to uninstall */
1823     r = MsiInstallProductA(msifile, "REMOVE=ALL");
1824     todo_wine
1825     {
1826         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1827     }
1828     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1829     ok(pf_exists("msitest"), "File deleted\n");
1830
1831     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1832     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1833
1834     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1835     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1836
1837     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1838     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1839
1840     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1841                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1842     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1843     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1844
1845     /* PublishProduct */
1846     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
1847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1848     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1849     ok(pf_exists("msitest"), "File not installed\n");
1850
1851     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1852     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
1853
1854     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1855     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1856
1857     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1858                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1859     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1860     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1861
1862     /* try to uninstall after PublishProduct */
1863     r = MsiInstallProductA(msifile, "REMOVE=ALL");
1864     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1865     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1866     ok(pf_exists("msitest"), "File deleted\n");
1867
1868     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1869     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1870
1871     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1872     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1873
1874     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1875     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1876
1877     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1878                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1879     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1880     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1881
1882     /* PublishProduct and RegisterProduct */
1883     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
1884     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1885     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1886     ok(pf_exists("msitest"), "File not installed\n");
1887
1888     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1889     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1890
1891     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1892     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1893
1894     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1895     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1896
1897     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1898                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1899     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
1900     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1901
1902     /* try it again */
1903     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
1904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1905     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1906     ok(pf_exists("msitest"), "File not installed\n");
1907
1908     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1909     todo_wine
1910     {
1911         ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1912     }
1913
1914     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1915     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1916
1917     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1918     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1919
1920     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1921                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1922     todo_wine
1923     {
1924         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1925     }
1926     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1927
1928     /* uninstall has a problem with this */
1929     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
1930     todo_wine
1931     {
1932         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1933     }
1934     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1935     ok(pf_exists("msitest"), "File deleted\n");
1936
1937     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1938     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1939
1940     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1941     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1942
1943     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1944                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1945     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1946     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1947
1948     /* PublishProduct and RegisterProduct and ProcessComponents */
1949     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
1950     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1951     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1952     ok(pf_exists("msitest"), "File not installed\n");
1953
1954     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1955     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1956
1957     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1958     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1959
1960     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1961     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1962
1963     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1964                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1965     todo_wine
1966     {
1967         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1968         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
1969     }
1970
1971     /* complete uninstall */
1972     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
1973     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1974     ok(pf_exists("msitest\\maximus"), "File deleted\n");
1975     ok(pf_exists("msitest"), "File deleted\n");
1976
1977     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1978     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1979
1980     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
1981     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1982
1983     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
1984     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1985
1986     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
1987                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
1988     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
1989     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
1990
1991     /* PublishProduct, RegisterProduct, ProcessComponents, PublishFeatures */
1992     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1 PUBLISH_FEATURES=1");
1993     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
1994     ok(pf_exists("msitest\\maximus"), "File not installed\n");
1995     ok(pf_exists("msitest"), "File not installed\n");
1996
1997     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
1998     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
1999
2000     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2001     todo_wine
2002     {
2003         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2004     }
2005
2006     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2007     todo_wine
2008     {
2009         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2010     }
2011
2012     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2013                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2014     todo_wine
2015     {
2016         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2017         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2018     }
2019
2020     /* complete uninstall */
2021     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2022     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2023     todo_wine
2024     {
2025         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2026         ok(!pf_exists("msitest"), "File deleted\n");
2027     }
2028
2029     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2030     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2031
2032     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");\
2033     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2034
2035     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2036     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2037
2038     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2039                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2040     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2041     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2042
2043     /* complete install */
2044     r = MsiInstallProductA(msifile, "FULL=1");
2045     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2046     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2047     ok(pf_exists("msitest"), "File not installed\n");
2048
2049     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2050     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2051
2052     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2053     todo_wine
2054     {
2055         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2056     }
2057
2058     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2059     todo_wine
2060     {
2061         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2062     }
2063
2064     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2065                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2066     todo_wine
2067     {
2068         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2069         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2070     }
2071
2072     /* no UnpublishFeatures */
2073     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2074     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2075     todo_wine
2076     {
2077         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
2078         ok(!pf_exists("msitest"), "File deleted\n");
2079     }
2080
2081     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2082     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2083
2084     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2085     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2086
2087     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2088     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2089
2090     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2091                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2092     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2093     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2094
2095     /* complete install */
2096     r = MsiInstallProductA(msifile, "FULL=1");
2097     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2098     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2099     ok(pf_exists("msitest"), "File not installed\n");
2100
2101     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2102     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2103
2104     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2105     todo_wine
2106     {
2107         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2108     }
2109
2110     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2111     todo_wine
2112     {
2113         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2114     }
2115
2116     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2117                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2118     todo_wine
2119     {
2120         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2121         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2122     }
2123
2124     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
2125     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
2126     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2127     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2128     ok(pf_exists("msitest"), "File deleted\n");
2129
2130     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2131     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2132
2133     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2134     todo_wine
2135     {
2136         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2137     }
2138
2139     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2140     todo_wine
2141     {
2142         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2143     }
2144
2145     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2146                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2147     todo_wine
2148     {
2149         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2150         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2151     }
2152
2153     /* complete install */
2154     r = MsiInstallProductA(msifile, "FULL=1");
2155     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2156     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2157     ok(pf_exists("msitest"), "File not installed\n");
2158
2159     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2160     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2161
2162     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2163     todo_wine
2164     {
2165         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2166     }
2167
2168     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2169     todo_wine
2170     {
2171         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2172     }
2173
2174     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2175                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2176     todo_wine
2177     {
2178         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2179         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2180     }
2181
2182     /* UnpublishFeatures, both features removed */
2183     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
2184     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2185     todo_wine
2186     {
2187         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2188         ok(!pf_exists("msitest"), "File not deleted\n");
2189     }
2190
2191     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2192     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2193
2194     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2195     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2196
2197     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2198     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2199
2200     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2201                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2202     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2203     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2204
2205     /* complete install */
2206     r = MsiInstallProductA(msifile, "FULL=1");
2207     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2208     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2209     ok(pf_exists("msitest"), "File not installed\n");
2210
2211     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2212     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2213
2214     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2215     todo_wine
2216     {
2217         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2218     }
2219
2220     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2221     todo_wine
2222     {
2223         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2224     }
2225
2226     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2227                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2228     todo_wine
2229     {
2230         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2231         ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2232     }
2233
2234     /* complete uninstall */
2235     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2236     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2237     todo_wine
2238     {
2239         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2240         ok(!pf_exists("msitest"), "File not deleted\n");
2241     }
2242
2243     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2244     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2245
2246     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2247     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2248
2249     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2250     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2251
2252     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2253                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2254     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2255     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2256
2257     /* make sure 'Program Files\msitest' is removed */
2258     delete_pfmsitest_files();
2259
2260     DeleteFile(msifile);
2261     DeleteFile("msitest\\maximus");
2262     RemoveDirectory("msitest");
2263 }
2264
2265 static void test_publishsourcelist(void)
2266 {
2267     UINT r;
2268     DWORD size;
2269     CHAR value[MAX_PATH];
2270     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2271
2272     CreateDirectoryA("msitest", NULL);
2273     create_file("msitest\\maximus", 500);
2274
2275     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2276
2277     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2278
2279     r = MsiInstallProductA(msifile, NULL);
2280     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2281     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2282     ok(pf_exists("msitest"), "File not installed\n");
2283
2284     /* nothing published */
2285     size = 0xdeadbeef;
2286     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2287                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2288     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2289     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2290
2291     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2292     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2293     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2294     ok(pf_exists("msitest"), "File not installed\n");
2295
2296     /* after RegisterProduct */
2297     size = 0xdeadbeef;
2298     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2299                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2300     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2301     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2302
2303     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2304     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2305     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2306     ok(pf_exists("msitest"), "File not installed\n");
2307
2308     /* after ProcessComponents */
2309     size = 0xdeadbeef;
2310     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2311                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2312     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2313     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2314
2315     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2317     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2318     ok(pf_exists("msitest"), "File not installed\n");
2319
2320     /* after PublishFeatures */
2321     size = 0xdeadbeef;
2322     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2323                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
2324     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2325     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
2326
2327     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2329     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2330     ok(pf_exists("msitest"), "File not installed\n");
2331
2332     /* after PublishProduct */
2333     size = MAX_PATH;
2334     lstrcpyA(value, "aaa");
2335     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2336                               MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
2337     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2338     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
2339     ok(size == 11, "Expected 11, got %d\n", size);
2340
2341     /* complete uninstall */
2342     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2343     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2344     todo_wine
2345     {
2346         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
2347         ok(!pf_exists("msitest"), "File not deleted\n");
2348     }
2349
2350     /* make sure 'Program Files\msitest' is removed */
2351     delete_pfmsitest_files();
2352
2353     DeleteFile(msifile);
2354     DeleteFile("msitest\\maximus");
2355     RemoveDirectory("msitest");
2356 }
2357
2358 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
2359 {
2360     MSIHANDLE hview = 0;
2361     UINT r;
2362
2363     r = MsiDatabaseOpenView(hdb, query, &hview);
2364     if(r != ERROR_SUCCESS)
2365         return r;
2366
2367     r = MsiViewExecute(hview, hrec);
2368     if(r == ERROR_SUCCESS)
2369         r = MsiViewClose(hview);
2370     MsiCloseHandle(hview);
2371     return r;
2372 }
2373
2374 static void set_transform_summary_info(void)
2375 {
2376     UINT r;
2377     MSIHANDLE suminfo;
2378
2379     /* build summmary info */
2380     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
2381     todo_wine
2382     {
2383         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
2384     }
2385
2386     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
2387     todo_wine
2388     {
2389         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
2390     }
2391
2392     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
2393                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
2394                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
2395                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
2396     todo_wine
2397     {
2398         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
2399     }
2400
2401     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
2402     todo_wine
2403     {
2404         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
2405     }
2406
2407     r = MsiSummaryInfoPersist(suminfo);
2408     todo_wine
2409     {
2410         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
2411     }
2412
2413     r = MsiCloseHandle(suminfo);
2414     todo_wine
2415     {
2416         ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
2417     }
2418 }
2419
2420 static void generate_transform(void)
2421 {
2422     MSIHANDLE hdb1, hdb2;
2423     LPCSTR query;
2424     UINT r;
2425
2426     /* start with two identical databases */
2427     CopyFile(msifile, msifile2, FALSE);
2428
2429     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
2430     ok(r == ERROR_SUCCESS , "Failed to create database\n");
2431
2432     r = MsiDatabaseCommit(hdb1);
2433     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
2434
2435     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
2436     ok(r == ERROR_SUCCESS , "Failed to create database\n");
2437
2438     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
2439     r = run_query(hdb1, 0, query);
2440     ok(r == ERROR_SUCCESS, "failed to add property\n");
2441
2442     /* database needs to be committed */
2443     MsiDatabaseCommit(hdb1);
2444
2445     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
2446     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
2447
2448 #if 0  /* not implemented in wine yet */
2449     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
2450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2451 #endif
2452
2453     MsiCloseHandle(hdb1);
2454     MsiCloseHandle(hdb2);
2455 }
2456
2457 /* data for generating a transform */
2458
2459 /* tables transform names - encoded as they would be in an msi database file */
2460 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
2461 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
2462 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
2463
2464 /* data in each table */
2465 static const char data1[] = /* _StringData */
2466     "propval";  /* all the strings squashed together */
2467
2468 static const WCHAR data2[] = { /* _StringPool */
2469 /*  len, refs */
2470     0,   0,    /* string 0 ''     */
2471     4,   1,    /* string 1 'prop' */
2472     3,   1,    /* string 2 'val'  */
2473 };
2474
2475 static const WCHAR data3[] = { /* Property */
2476     0x0201, 0x0001, 0x0002,
2477 };
2478
2479 static const struct {
2480     LPCWSTR name;
2481     const void *data;
2482     DWORD size;
2483 } table_transform_data[] =
2484 {
2485     { name1, data1, sizeof data1 - 1 },
2486     { name2, data2, sizeof data2 },
2487     { name3, data3, sizeof data3 },
2488 };
2489
2490 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
2491
2492 static void generate_transform_manual(void)
2493 {
2494     IStorage *stg = NULL;
2495     IStream *stm;
2496     WCHAR name[0x20];
2497     HRESULT r;
2498     DWORD i, count;
2499     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
2500
2501     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
2502
2503     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
2504
2505     r = StgCreateDocfile(name, mode, 0, &stg);
2506     ok(r == S_OK, "failed to create storage\n");
2507     if (!stg)
2508         return;
2509
2510     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
2511     ok(r == S_OK, "failed to set storage type\n");
2512
2513     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
2514     {
2515         r = IStorage_CreateStream(stg, table_transform_data[i].name,
2516                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2517         if (FAILED(r))
2518         {
2519             ok(0, "failed to create stream %08x\n", r);
2520             continue;
2521         }
2522
2523         r = IStream_Write(stm, table_transform_data[i].data,
2524                           table_transform_data[i].size, &count);
2525         if (FAILED(r) || count != table_transform_data[i].size)
2526             ok(0, "failed to write stream\n");
2527         IStream_Release(stm);
2528     }
2529
2530     IStorage_Release(stg);
2531
2532     set_transform_summary_info();
2533 }
2534
2535 static void test_transformprop(void)
2536 {
2537     UINT r;
2538
2539     CreateDirectoryA("msitest", NULL);
2540     create_file("msitest\\augustus", 500);
2541
2542     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
2543
2544     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2545
2546     r = MsiInstallProductA(msifile, NULL);
2547     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2548     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2549     ok(!delete_pf("msitest", FALSE), "File installed\n");
2550
2551     if (0)
2552         generate_transform();
2553     else
2554         generate_transform_manual();
2555
2556     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
2557     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2558     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2559     ok(delete_pf("msitest", FALSE), "File not installed\n");
2560
2561     /* Delete the files in the temp (current) folder */
2562     DeleteFile(msifile);
2563     DeleteFile(msifile2);
2564     DeleteFile(mstfile);
2565     DeleteFile("msitest\\augustus");
2566     RemoveDirectory("msitest");
2567 }
2568
2569 static void test_currentworkingdir(void)
2570 {
2571     UINT r;
2572     CHAR path[MAX_PATH];
2573     LPSTR ptr, ptr2;
2574
2575     CreateDirectoryA("msitest", NULL);
2576     create_file("msitest\\augustus", 500);
2577
2578     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
2579
2580     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2581
2582     CreateDirectoryA("diffdir", NULL);
2583     SetCurrentDirectoryA("diffdir");
2584
2585     sprintf(path, "..\\%s", msifile);
2586     r = MsiInstallProductA(path, NULL);
2587     todo_wine
2588     {
2589         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
2590         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2591         ok(!delete_pf("msitest", FALSE), "File installed\n");
2592     }
2593
2594     sprintf(path, "%s\\%s", CURR_DIR, msifile);
2595     r = MsiInstallProductA(path, NULL);
2596     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2597     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2598     ok(delete_pf("msitest", FALSE), "File not installed\n");
2599
2600     lstrcpyA(path, CURR_DIR);
2601     if (path[lstrlenA(path) - 1] != '\\')
2602         lstrcatA(path, "\\");
2603     lstrcatA(path, "msitest.msi");
2604
2605     ptr2 = strrchr(path, '\\');
2606     *ptr2 = '\0';
2607     ptr = strrchr(path, '\\');
2608     *ptr2 = '\\';
2609     *(ptr++) = '\0';
2610
2611     SetCurrentDirectoryA(path);
2612
2613     r = MsiInstallProductA(ptr, NULL);
2614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2615     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2616     ok(delete_pf("msitest", FALSE), "File not installed\n");
2617
2618     SetCurrentDirectoryA(CURR_DIR);
2619
2620     DeleteFile(msifile);
2621     DeleteFile("msitest\\augustus");
2622     RemoveDirectory("msitest");
2623     RemoveDirectory("diffdir");
2624 }
2625
2626 static void set_admin_summary_info(const CHAR *name)
2627 {
2628     MSIHANDLE db, summary;
2629     UINT r;
2630
2631     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
2632     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2633
2634     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
2635     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2636
2637     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
2638     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2639
2640     /* write the summary changes back to the stream */
2641     r = MsiSummaryInfoPersist(summary);
2642     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2643
2644     MsiCloseHandle(summary);
2645
2646     r = MsiDatabaseCommit(db);
2647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2648
2649     MsiCloseHandle(db);
2650 }
2651
2652 static void test_admin(void)
2653 {
2654     UINT r;
2655
2656     CreateDirectoryA("msitest", NULL);
2657     create_file("msitest\\augustus", 500);
2658
2659     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
2660     set_admin_summary_info(msifile);
2661
2662     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2663
2664     r = MsiInstallProductA(msifile, NULL);
2665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2666     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2667     ok(!delete_pf("msitest", FALSE), "File installed\n");
2668     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
2669     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
2670
2671     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
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     todo_wine
2676     {
2677         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
2678         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
2679     }
2680
2681     DeleteFile(msifile);
2682     DeleteFile("msitest\\augustus");
2683     RemoveDirectory("msitest");
2684 }
2685
2686 static void set_admin_property_stream(LPCSTR file)
2687 {
2688     IStorage *stg;
2689     IStream *stm;
2690     WCHAR fileW[MAX_PATH];
2691     HRESULT hr;
2692     DWORD count;
2693     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
2694
2695     /* AdminProperties */
2696     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
2697     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
2698
2699     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
2700
2701     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
2702     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2703     if (!stg)
2704         return;
2705
2706     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
2707     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2708
2709     hr = IStream_Write(stm, data, sizeof(data) - 1, &count);
2710     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
2711
2712     IStream_Release(stm);
2713     IStorage_Release(stg);
2714 }
2715
2716 static void test_adminprops(void)
2717 {
2718     UINT r;
2719
2720     CreateDirectoryA("msitest", NULL);
2721     create_file("msitest\\augustus", 500);
2722
2723     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
2724     set_admin_summary_info(msifile);
2725     set_admin_property_stream(msifile);
2726
2727     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2728
2729     r = MsiInstallProductA(msifile, NULL);
2730     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2731     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
2732     ok(delete_pf("msitest", FALSE), "File installed\n");
2733
2734     DeleteFile(msifile);
2735     DeleteFile("msitest\\augustus");
2736     RemoveDirectory("msitest");
2737 }
2738
2739 static void create_pf(LPCSTR file, BOOL is_file)
2740 {
2741     CHAR path[MAX_PATH];
2742
2743     lstrcpyA(path, PROG_FILES_DIR);
2744     lstrcatA(path, "\\");
2745     lstrcatA(path, file);
2746
2747     if (is_file)
2748         create_file(path, 500);
2749     else
2750         CreateDirectoryA(path, NULL);
2751 }
2752
2753 static void test_removefiles(void)
2754 {
2755     UINT r;
2756
2757     CreateDirectoryA("msitest", NULL);
2758     create_file("msitest\\hydrogen", 500);
2759     create_file("msitest\\helium", 500);
2760     create_file("msitest\\lithium", 500);
2761
2762     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
2763
2764     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2765
2766     r = MsiInstallProductA(msifile, NULL);
2767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2768     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2769     ok(!pf_exists("msitest\\helium"), "File installed\n");
2770     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2771     ok(pf_exists("msitest"), "File not installed\n");
2772
2773     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2775     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
2776     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2777     todo_wine
2778     {
2779         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
2780         ok(delete_pf("msitest", FALSE), "File deleted\n");
2781     }
2782
2783     create_pf("msitest", FALSE);
2784     create_pf("msitest\\hydrogen", TRUE);
2785     create_pf("msitest\\helium", TRUE);
2786     create_pf("msitest\\lithium", TRUE);
2787
2788     r = MsiInstallProductA(msifile, NULL);
2789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2790     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2791     ok(pf_exists("msitest\\helium"), "File not installed\n");
2792     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2793     ok(pf_exists("msitest"), "File not installed\n");
2794
2795     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2797     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
2798     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2799     todo_wine
2800     {
2801         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
2802         ok(delete_pf("msitest", FALSE), "File deleted\n");
2803     }
2804
2805     create_pf("msitest", FALSE);
2806     create_pf("msitest\\furlong", TRUE);
2807     create_pf("msitest\\firkin", TRUE);
2808     create_pf("msitest\\fortnight", TRUE);
2809     create_pf("msitest\\becquerel", TRUE);
2810     create_pf("msitest\\dioptre", TRUE);
2811     create_pf("msitest\\attoparsec", TRUE);
2812     create_pf("msitest\\storeys", TRUE);
2813     create_pf("msitest\\block", TRUE);
2814     create_pf("msitest\\siriometer", TRUE);
2815
2816     r = MsiInstallProductA(msifile, NULL);
2817     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2818     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
2819     ok(!pf_exists("msitest\\helium"), "File installed\n");
2820     ok(pf_exists("msitest\\lithium"), "File not installed\n");
2821     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
2822     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
2823     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
2824     ok(pf_exists("msitest"), "File not installed\n");
2825     todo_wine
2826     {
2827         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
2828         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
2829         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
2830         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
2831         ok(!pf_exists("msitest\\block"), "File not deleted\n");
2832         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
2833     }
2834
2835     create_pf("msitest\\furlong", TRUE);
2836     create_pf("msitest\\firkin", TRUE);
2837     create_pf("msitest\\fortnight", TRUE);
2838     create_pf("msitest\\storeys", TRUE);
2839     create_pf("msitest\\block", TRUE);
2840     create_pf("msitest\\siriometer", TRUE);
2841
2842     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2843     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2844     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
2845     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
2846     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
2847     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
2848     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
2849     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
2850     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
2851     todo_wine
2852     {
2853         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
2854         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
2855         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
2856         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
2857         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
2858     }
2859     ok(delete_pf("msitest", FALSE), "File deleted\n");
2860
2861     DeleteFile(msifile);
2862     DeleteFile("msitest\\hydrogen");
2863     DeleteFile("msitest\\helium");
2864     DeleteFile("msitest\\lithium");
2865     RemoveDirectory("msitest");
2866 }
2867
2868 START_TEST(install)
2869 {
2870     DWORD len;
2871     char temp_path[MAX_PATH], prev_path[MAX_PATH];
2872
2873     init_functionpointers();
2874
2875     GetCurrentDirectoryA(MAX_PATH, prev_path);
2876     GetTempPath(MAX_PATH, temp_path);
2877     SetCurrentDirectoryA(temp_path);
2878
2879     lstrcpyA(CURR_DIR, temp_path);
2880     len = lstrlenA(CURR_DIR);
2881
2882     if(len && (CURR_DIR[len - 1] == '\\'))
2883         CURR_DIR[len - 1] = 0;
2884
2885     get_program_files_dir(PROG_FILES_DIR);
2886
2887     test_MsiInstallProduct();
2888     test_MsiSetComponentState();
2889     test_packagecoltypes();
2890     test_continuouscabs();
2891     test_caborder();
2892     test_mixedmedia();
2893     test_samesequence();
2894     test_uiLevelFlags();
2895     test_readonlyfile();
2896     test_setdirproperty();
2897     test_cabisextracted();
2898     test_concurrentinstall();
2899     test_setpropertyfolder();
2900     test_publish();
2901     test_publishsourcelist();
2902     test_transformprop();
2903     test_currentworkingdir();
2904     test_admin();
2905     test_adminprops();
2906     test_removefiles();
2907
2908     SetCurrentDirectoryA(prev_path);
2909 }