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