msi: Fix bug in handling of multivolume CAB files.
[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 *pMsiSourceListEnumSourcesA)
38     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
39 static UINT (WINAPI *pMsiSourceListGetInfoA)
40     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
41
42 static const char *msifile = "msitest.msi";
43 static const char *msifile2 = "winetest2.msi";
44 static const char *mstfile = "winetest.mst";
45 static CHAR CURR_DIR[MAX_PATH];
46 static CHAR PROG_FILES_DIR[MAX_PATH];
47 static CHAR COMMON_FILES_DIR[MAX_PATH];
48
49 /* msi database data */
50
51 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
52                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
53                                     "Component\tComponent\n"
54                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
55                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
56                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
57                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
58                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
59                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
60                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
61                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
62
63 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
64                                     "s72\tS72\tl255\n"
65                                     "Directory\tDirectory\n"
66                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
67                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
68                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
69                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
70                                     "NEWDIR\tCABOUTDIR\tnew\n"
71                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
72                                     "TARGETDIR\t\tSourceDir";
73
74 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
75                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
76                                   "Feature\tFeature\n"
77                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
78                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
79                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
80                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
81                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
82                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
83                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
84
85 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
86                                        "s38\ts72\n"
87                                        "FeatureComponents\tFeature_\tComponent_\n"
88                                        "Five\tFive\n"
89                                        "Four\tFour\n"
90                                        "One\tOne\n"
91                                        "Three\tThree\n"
92                                        "Two\tTwo\n"
93                                        "feature\tcomponent\n"
94                                        "service_feature\tservice_comp\n";
95
96 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
97                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
98                                "File\tFile\n"
99                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
100                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
101                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
102                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
103                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
104                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
105                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
106
107 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
108                                            "s72\tS255\tI2\n"
109                                            "InstallExecuteSequence\tAction\n"
110                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
111                                            "CostFinalize\t\t1000\n"
112                                            "CostInitialize\t\t800\n"
113                                            "FileCost\t\t900\n"
114                                            "ResolveSource\t\t950\n"
115                                            "MoveFiles\t\t1700\n"
116                                            "InstallFiles\t\t4000\n"
117                                            "DuplicateFiles\t\t4500\n"
118                                            "InstallServices\t\t5000\n"
119                                            "InstallFinalize\t\t6600\n"
120                                            "InstallInitialize\t\t1500\n"
121                                            "InstallValidate\t\t1400\n"
122                                            "LaunchConditions\t\t100\n"
123                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
124
125 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
126                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
127                                 "Media\tDiskId\n"
128                                 "1\t3\t\t\tDISK1\t\n"
129                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
130
131 static const CHAR property_dat[] = "Property\tValue\n"
132                                    "s72\tl0\n"
133                                    "Property\tProperty\n"
134                                    "DefaultUIFont\tDlgFont8\n"
135                                    "HASUIRUN\t0\n"
136                                    "INSTALLLEVEL\t3\n"
137                                    "InstallMode\tTypical\n"
138                                    "Manufacturer\tWine\n"
139                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
140                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
141                                    "ProductID\tnone\n"
142                                    "ProductLanguage\t1033\n"
143                                    "ProductName\tMSITEST\n"
144                                    "ProductVersion\t1.1.1\n"
145                                    "PROMPTROLLBACKCOST\tP\n"
146                                    "Setup\tSetup\n"
147                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
148                                    "AdminProperties\tPOSTADMIN\n"
149                                    "ROOTDRIVE\tC:\\\n";
150
151 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
152                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
153                                    "Registry\tRegistry\n"
154                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
155                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
156                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
157                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
158
159 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
160                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
161                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
162                                           "ServiceInstall\tServiceInstall\n"
163                                           "TestService\tTestService\tTestService\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
164
165 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
166                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
167                                           "ServiceControl\tServiceControl\n"
168                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
169
170 /* tables for test_continuouscabs */
171 static const CHAR cc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
172                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
173                                        "Component\tComponent\n"
174                                        "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
175                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
176                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
177
178 static const CHAR cc2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
179                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
180                                         "Component\tComponent\n"
181                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
182                                         "augustus\t\tMSITESTDIR\t0\t0\taugustus\n"
183                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
184
185 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
186                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
187                                      "Feature\tFeature\n"
188                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
189
190 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
191                                           "s38\ts72\n"
192                                           "FeatureComponents\tFeature_\tComponent_\n"
193                                           "feature\tmaximus\n"
194                                           "feature\taugustus\n"
195                                           "feature\tcaesar";
196
197 static const CHAR cc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
198                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
199                                   "File\tFile\n"
200                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
201                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
202                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
203
204 static const CHAR cc2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
205                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
206                                    "File\tFile\n"
207                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
208                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
209                                    "tiberius\tmaximus\ttiberius\t500\t\t\t16384\t3\n"
210                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
211
212 static const CHAR cc_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\t2\t\ttest2.cab\tDISK2\t\n"
217                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
218
219 static const CHAR co_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\t16384\t1\n"
223                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
224                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
225
226 static const CHAR co_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
227                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
228                                    "Media\tDiskId\n"
229                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
230                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
231                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
232
233 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
234                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
235                                     "Media\tDiskId\n"
236                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
237                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
238                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
239
240 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
241                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
242                                   "File\tFile\n"
243                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
244                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
245                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
246
247 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
248                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
249                                    "Media\tDiskId\n"
250                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
251
252 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
253                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
254                                    "Media\tDiskId\n"
255                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
256                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
257                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
258
259 /* tables for test_uiLevelFlags */
260 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
261                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
262                                        "Component\tComponent\n"
263                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
264                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
265                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
266
267 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
268                                            "s72\tS255\tI2\n"
269                                            "InstallUISequence\tAction\n"
270                                            "SetUIProperty\t\t5\n"
271                                            "ExecuteAction\t\t1100\n";
272
273 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
274                                            "s72\ti2\tS64\tS0\tS255\n"
275                                            "CustomAction\tAction\n"
276                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
277
278 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
279                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
280                                         "Component\tComponent\n"
281                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
282
283 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
284                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
285                                       "Feature\tFeature\n"
286                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
287                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
288
289 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
290                                            "s38\ts72\n"
291                                            "FeatureComponents\tFeature_\tComponent_\n"
292                                            "feature\tmaximus\n"
293                                            "montecristo\tmaximus";
294
295 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
296                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
297                                    "File\tFile\n"
298                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
299
300 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
301                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
302                                     "Media\tDiskId\n"
303                                     "1\t1\t\t\tDISK1\t\n";
304
305 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
306                                                "s72\tS255\tI2\n"
307                                                "InstallExecuteSequence\tAction\n"
308                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
309                                                "CostFinalize\t\t1000\n"
310                                                "CostInitialize\t\t800\n"
311                                                "FileCost\t\t900\n"
312                                                "InstallFiles\t\t4000\n"
313                                                "InstallFinalize\t\t6600\n"
314                                                "InstallInitialize\t\t1500\n"
315                                                "InstallValidate\t\t1400\n"
316                                                "LaunchConditions\t\t100\n"
317                                                "SetDirProperty\t\t950";
318
319 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
320                                             "s72\ti2\tS64\tS0\tS255\n"
321                                             "CustomAction\tAction\n"
322                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
323
324 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
325                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
326                                         "Component\tComponent\n"
327                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
328                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
329                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
330                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
331
332 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
333                                            "s38\ts72\n"
334                                            "FeatureComponents\tFeature_\tComponent_\n"
335                                            "feature\tmaximus\n"
336                                            "feature\taugustus\n"
337                                            "feature\tcaesar\n"
338                                            "feature\tgaius";
339
340 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
341                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
342                                    "File\tFile\n"
343                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
344                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
345                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
346                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
347
348 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
349                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
350                                     "Media\tDiskId\n"
351                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
352                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
353                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
354
355 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
356                                               "s72\tS255\tI2\n"
357                                               "InstallExecuteSequence\tAction\n"
358                                               "CostFinalize\t\t1000\n"
359                                               "CostInitialize\t\t800\n"
360                                               "FileCost\t\t900\n"
361                                               "InstallFiles\t\t4000\n"
362                                               "InstallServices\t\t5000\n"
363                                               "InstallFinalize\t\t6600\n"
364                                               "InstallInitialize\t\t1500\n"
365                                               "RunInstall\t\t1600\n"
366                                               "InstallValidate\t\t1400\n"
367                                               "LaunchConditions\t\t100";
368
369 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
370                                             "s72\ti2\tS64\tS0\tS255\n"
371                                             "CustomAction\tAction\n"
372                                             "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
373
374 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
375                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
376                                        "Component\tComponent\n"
377                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
378
379 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
380                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
381                                         "Component\tComponent\n"
382                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
383
384 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
385                                            "s38\ts72\n"
386                                            "FeatureComponents\tFeature_\tComponent_\n"
387                                            "feature\taugustus";
388
389 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
390                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
391                                    "File\tFile\n"
392                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
393
394 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
395                                             "s72\ti2\tS64\tS0\tS255\n"
396                                             "CustomAction\tAction\n"
397                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
398
399 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
400                                                "s72\tS255\tI2\n"
401                                                "InstallExecuteSequence\tAction\n"
402                                                "CostFinalize\t\t1000\n"
403                                                "CostInitialize\t\t800\n"
404                                                "FileCost\t\t900\n"
405                                                "SetFolderProp\t\t950\n"
406                                                "InstallFiles\t\t4000\n"
407                                                "InstallServices\t\t5000\n"
408                                                "InstallFinalize\t\t6600\n"
409                                                "InstallInitialize\t\t1500\n"
410                                                "InstallValidate\t\t1400\n"
411                                                "LaunchConditions\t\t100";
412
413 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
414                                              "s72\tS255\tI2\n"
415                                              "InstallUISequence\tAction\n"
416                                              "CostInitialize\t\t800\n"
417                                              "FileCost\t\t900\n"
418                                              "CostFinalize\t\t1000\n"
419                                              "ExecuteAction\t\t1100\n";
420
421 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
422                                               "s72\tS255\tI2\n"
423                                               "InstallExecuteSequence\tAction\n"
424                                               "ValidateProductID\t\t700\n"
425                                               "CostInitialize\t\t800\n"
426                                               "FileCost\t\t900\n"
427                                               "CostFinalize\t\t1000\n"
428                                               "InstallValidate\t\t1400\n"
429                                               "InstallInitialize\t\t1500\n"
430                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
431                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
432                                               "RemoveFiles\t\t3500\n"
433                                               "InstallFiles\t\t4000\n"
434                                               "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
435                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
436                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
437                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
438                                               "InstallFinalize\t\t6600";
439
440 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
441                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
442                                        "Component\tComponent\n"
443                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
444
445 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
446                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
447                                         "Component\tComponent\n"
448                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
449
450 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
451                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
452                                         "Component\tComponent\n"
453                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
454
455 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
456                                             "s72\ti2\tS64\tS0\tS255\n"
457                                             "CustomAction\tAction\n"
458                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
459
460 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
461                                              "s72\tS255\tI2\n"
462                                              "AdminExecuteSequence\tAction\n"
463                                              "CostFinalize\t\t1000\n"
464                                              "CostInitialize\t\t800\n"
465                                              "FileCost\t\t900\n"
466                                              "SetPOSTADMIN\t\t950\n"
467                                              "InstallFiles\t\t4000\n"
468                                              "InstallFinalize\t\t6600\n"
469                                              "InstallInitialize\t\t1500\n"
470                                              "InstallValidate\t\t1400\n"
471                                              "LaunchConditions\t\t100";
472
473 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
474                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
475                                         "Component\tComponent\n"
476                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718\taugustus\n";
477
478 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
479                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
480                                         "Component\tComponent\n"
481                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
482                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
483                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
484
485 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
486                                            "s38\ts72\n"
487                                            "FeatureComponents\tFeature_\tComponent_\n"
488                                            "feature\thydrogen\n"
489                                            "feature\thelium\n"
490                                            "feature\tlithium";
491
492 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
493                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
494                                    "File\tFile\n"
495                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
496                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
497                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
498
499 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
500                                                "s72\tS255\tI2\n"
501                                                "InstallExecuteSequence\tAction\n"
502                                                "ValidateProductID\t\t700\n"
503                                                "CostInitialize\t\t800\n"
504                                                "FileCost\t\t900\n"
505                                                "CostFinalize\t\t1000\n"
506                                                "InstallValidate\t\t1400\n"
507                                                "InstallInitialize\t\t1500\n"
508                                                "ProcessComponents\t\t1600\n"
509                                                "UnpublishFeatures\t\t1800\n"
510                                                "RemoveFiles\t\t3500\n"
511                                                "InstallFiles\t\t4000\n"
512                                                "RegisterProduct\t\t6100\n"
513                                                "PublishFeatures\t\t6300\n"
514                                                "PublishProduct\t\t6400\n"
515                                                "InstallFinalize\t\t6600";
516
517 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
518                                            "s72\ts72\tS255\ts72\tI2\n"
519                                            "RemoveFile\tFileKey\n"
520                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
521                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
522                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
523                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
524                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
525                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
526                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
527                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
528                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n";
529
530 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
531                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
532                                         "MoveFile\tFileKey\n"
533                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
534                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
535                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
536                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
537                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
538                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
539                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
540                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
541                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
542                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
543                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
544                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
545                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
546                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
547                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
548                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
549                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
550
551 static const CHAR mc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
552                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
553                                         "Component\tComponent\n"
554                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
555                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
556                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
557                                         "gaius\t\tMSITESTDIR\t0\tGAIUS=1\tgaius\n";
558
559 static const CHAR mc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
560                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
561                                   "File\tFile\n"
562                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
563                                   "augustus\taugustus\taugustus\t500\t\t\t0\t2\n"
564                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3\n"
565                                   "gaius\tgaius\tgaius\t500\t\t\t16384\t4";
566
567 static const CHAR mc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
568                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
569                                    "Media\tDiskId\n"
570                                    "1\t1\t\ttest1.cab\tDISK1\t\n"
571                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
572                                    "3\t3\t\ttest3.cab\tDISK3\t\n"
573                                    "4\t4\t\ttest3.cab\tDISK3\t\n";
574
575 static const CHAR mc_file_hash_dat[] = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"
576                                        "s72\ti2\ti4\ti4\ti4\ti4\n"
577                                        "MsiFileHash\tFile_\n"
578                                        "caesar\t0\t850433704\t-241429251\t675791761\t-1221108824";
579
580 static const CHAR df_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
581                                        "s72\tS72\tl255\n"
582                                        "Directory\tDirectory\n"
583                                        "THIS\tMSITESTDIR\tthis\n"
584                                        "DOESNOT\tTHIS\tdoesnot\n"
585                                        "NONEXISTENT\tDOESNOT\texist\n"
586                                        "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
587                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
588                                        "TARGETDIR\t\tSourceDir";
589
590 static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestName\tDestFolder\n"
591                                             "s72\ts72\ts72\tS255\tS72\n"
592                                             "DuplicateFile\tFileKey\n"
593                                             "maximus\tmaximus\tmaximus\taugustus\t\n"
594                                             "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n";
595
596 static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
597                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
598                                         "Component\tComponent\n"
599                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
600
601 static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
602                                        "s72\ti2\tl255\tL255\tL0\ts72\n"
603                                        "Registry\tRegistry\n"
604                                        "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus";
605
606 typedef struct _msi_table
607 {
608     const CHAR *filename;
609     const CHAR *data;
610     int size;
611 } msi_table;
612
613 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
614
615 static const msi_table tables[] =
616 {
617     ADD_TABLE(component),
618     ADD_TABLE(directory),
619     ADD_TABLE(feature),
620     ADD_TABLE(feature_comp),
621     ADD_TABLE(file),
622     ADD_TABLE(install_exec_seq),
623     ADD_TABLE(media),
624     ADD_TABLE(property),
625     ADD_TABLE(registry),
626     ADD_TABLE(service_install),
627     ADD_TABLE(service_control)
628 };
629
630 static const msi_table cc_tables[] =
631 {
632     ADD_TABLE(cc_component),
633     ADD_TABLE(directory),
634     ADD_TABLE(cc_feature),
635     ADD_TABLE(cc_feature_comp),
636     ADD_TABLE(cc_file),
637     ADD_TABLE(install_exec_seq),
638     ADD_TABLE(cc_media),
639     ADD_TABLE(property),
640 };
641
642 static const msi_table cc2_tables[] =
643 {
644     ADD_TABLE(cc2_component),
645     ADD_TABLE(directory),
646     ADD_TABLE(cc_feature),
647     ADD_TABLE(cc_feature_comp),
648     ADD_TABLE(cc2_file),
649     ADD_TABLE(install_exec_seq),
650     ADD_TABLE(cc_media),
651     ADD_TABLE(property),
652 };
653
654 static const msi_table co_tables[] =
655 {
656     ADD_TABLE(cc_component),
657     ADD_TABLE(directory),
658     ADD_TABLE(cc_feature),
659     ADD_TABLE(cc_feature_comp),
660     ADD_TABLE(co_file),
661     ADD_TABLE(install_exec_seq),
662     ADD_TABLE(co_media),
663     ADD_TABLE(property),
664 };
665
666 static const msi_table co2_tables[] =
667 {
668     ADD_TABLE(cc_component),
669     ADD_TABLE(directory),
670     ADD_TABLE(cc_feature),
671     ADD_TABLE(cc_feature_comp),
672     ADD_TABLE(cc_file),
673     ADD_TABLE(install_exec_seq),
674     ADD_TABLE(co2_media),
675     ADD_TABLE(property),
676 };
677
678 static const msi_table mm_tables[] =
679 {
680     ADD_TABLE(cc_component),
681     ADD_TABLE(directory),
682     ADD_TABLE(cc_feature),
683     ADD_TABLE(cc_feature_comp),
684     ADD_TABLE(mm_file),
685     ADD_TABLE(install_exec_seq),
686     ADD_TABLE(mm_media),
687     ADD_TABLE(property),
688 };
689
690 static const msi_table ss_tables[] =
691 {
692     ADD_TABLE(cc_component),
693     ADD_TABLE(directory),
694     ADD_TABLE(cc_feature),
695     ADD_TABLE(cc_feature_comp),
696     ADD_TABLE(cc_file),
697     ADD_TABLE(install_exec_seq),
698     ADD_TABLE(ss_media),
699     ADD_TABLE(property),
700 };
701
702 static const msi_table ui_tables[] =
703 {
704     ADD_TABLE(ui_component),
705     ADD_TABLE(directory),
706     ADD_TABLE(cc_feature),
707     ADD_TABLE(cc_feature_comp),
708     ADD_TABLE(cc_file),
709     ADD_TABLE(install_exec_seq),
710     ADD_TABLE(ui_install_ui_seq),
711     ADD_TABLE(ui_custom_action),
712     ADD_TABLE(cc_media),
713     ADD_TABLE(property),
714 };
715
716 static const msi_table rof_tables[] =
717 {
718     ADD_TABLE(rof_component),
719     ADD_TABLE(directory),
720     ADD_TABLE(rof_feature),
721     ADD_TABLE(rof_feature_comp),
722     ADD_TABLE(rof_file),
723     ADD_TABLE(install_exec_seq),
724     ADD_TABLE(rof_media),
725     ADD_TABLE(property),
726 };
727
728 static const msi_table sdp_tables[] =
729 {
730     ADD_TABLE(rof_component),
731     ADD_TABLE(directory),
732     ADD_TABLE(rof_feature),
733     ADD_TABLE(rof_feature_comp),
734     ADD_TABLE(rof_file),
735     ADD_TABLE(sdp_install_exec_seq),
736     ADD_TABLE(sdp_custom_action),
737     ADD_TABLE(rof_media),
738     ADD_TABLE(property),
739 };
740
741 static const msi_table cie_tables[] =
742 {
743     ADD_TABLE(cie_component),
744     ADD_TABLE(directory),
745     ADD_TABLE(cc_feature),
746     ADD_TABLE(cie_feature_comp),
747     ADD_TABLE(cie_file),
748     ADD_TABLE(install_exec_seq),
749     ADD_TABLE(cie_media),
750     ADD_TABLE(property),
751 };
752
753 static const msi_table ci_tables[] =
754 {
755     ADD_TABLE(ci_component),
756     ADD_TABLE(directory),
757     ADD_TABLE(rof_feature),
758     ADD_TABLE(rof_feature_comp),
759     ADD_TABLE(rof_file),
760     ADD_TABLE(ci_install_exec_seq),
761     ADD_TABLE(rof_media),
762     ADD_TABLE(property),
763     ADD_TABLE(ci_custom_action),
764 };
765
766 static const msi_table ci2_tables[] =
767 {
768     ADD_TABLE(ci2_component),
769     ADD_TABLE(directory),
770     ADD_TABLE(rof_feature),
771     ADD_TABLE(ci2_feature_comp),
772     ADD_TABLE(ci2_file),
773     ADD_TABLE(install_exec_seq),
774     ADD_TABLE(rof_media),
775     ADD_TABLE(property),
776 };
777
778 static const msi_table spf_tables[] =
779 {
780     ADD_TABLE(ci_component),
781     ADD_TABLE(directory),
782     ADD_TABLE(rof_feature),
783     ADD_TABLE(rof_feature_comp),
784     ADD_TABLE(rof_file),
785     ADD_TABLE(spf_install_exec_seq),
786     ADD_TABLE(rof_media),
787     ADD_TABLE(property),
788     ADD_TABLE(spf_custom_action),
789     ADD_TABLE(spf_install_ui_seq),
790 };
791
792 static const msi_table pp_tables[] =
793 {
794     ADD_TABLE(ci_component),
795     ADD_TABLE(directory),
796     ADD_TABLE(rof_feature),
797     ADD_TABLE(rof_feature_comp),
798     ADD_TABLE(rof_file),
799     ADD_TABLE(pp_install_exec_seq),
800     ADD_TABLE(rof_media),
801     ADD_TABLE(property),
802 };
803
804 static const msi_table tp_tables[] =
805 {
806     ADD_TABLE(tp_component),
807     ADD_TABLE(directory),
808     ADD_TABLE(rof_feature),
809     ADD_TABLE(ci2_feature_comp),
810     ADD_TABLE(ci2_file),
811     ADD_TABLE(install_exec_seq),
812     ADD_TABLE(rof_media),
813     ADD_TABLE(property),
814 };
815
816 static const msi_table cwd_tables[] =
817 {
818     ADD_TABLE(cwd_component),
819     ADD_TABLE(directory),
820     ADD_TABLE(rof_feature),
821     ADD_TABLE(ci2_feature_comp),
822     ADD_TABLE(ci2_file),
823     ADD_TABLE(install_exec_seq),
824     ADD_TABLE(rof_media),
825     ADD_TABLE(property),
826 };
827
828 static const msi_table adm_tables[] =
829 {
830     ADD_TABLE(adm_component),
831     ADD_TABLE(directory),
832     ADD_TABLE(rof_feature),
833     ADD_TABLE(ci2_feature_comp),
834     ADD_TABLE(ci2_file),
835     ADD_TABLE(install_exec_seq),
836     ADD_TABLE(rof_media),
837     ADD_TABLE(property),
838     ADD_TABLE(adm_custom_action),
839     ADD_TABLE(adm_admin_exec_seq),
840 };
841
842 static const msi_table amp_tables[] =
843 {
844     ADD_TABLE(amp_component),
845     ADD_TABLE(directory),
846     ADD_TABLE(rof_feature),
847     ADD_TABLE(ci2_feature_comp),
848     ADD_TABLE(ci2_file),
849     ADD_TABLE(install_exec_seq),
850     ADD_TABLE(rof_media),
851     ADD_TABLE(property),
852 };
853
854 static const msi_table rem_tables[] =
855 {
856     ADD_TABLE(rem_component),
857     ADD_TABLE(directory),
858     ADD_TABLE(rof_feature),
859     ADD_TABLE(rem_feature_comp),
860     ADD_TABLE(rem_file),
861     ADD_TABLE(rem_install_exec_seq),
862     ADD_TABLE(rof_media),
863     ADD_TABLE(property),
864     ADD_TABLE(rem_remove_files),
865 };
866
867 static const msi_table mov_tables[] =
868 {
869     ADD_TABLE(cwd_component),
870     ADD_TABLE(directory),
871     ADD_TABLE(rof_feature),
872     ADD_TABLE(ci2_feature_comp),
873     ADD_TABLE(ci2_file),
874     ADD_TABLE(install_exec_seq),
875     ADD_TABLE(rof_media),
876     ADD_TABLE(property),
877     ADD_TABLE(mov_move_file),
878 };
879
880 static const msi_table mc_tables[] =
881 {
882     ADD_TABLE(mc_component),
883     ADD_TABLE(directory),
884     ADD_TABLE(cc_feature),
885     ADD_TABLE(cie_feature_comp),
886     ADD_TABLE(mc_file),
887     ADD_TABLE(install_exec_seq),
888     ADD_TABLE(mc_media),
889     ADD_TABLE(property),
890     ADD_TABLE(mc_file_hash),
891 };
892
893 static const msi_table df_tables[] =
894 {
895     ADD_TABLE(rof_component),
896     ADD_TABLE(df_directory),
897     ADD_TABLE(rof_feature),
898     ADD_TABLE(rof_feature_comp),
899     ADD_TABLE(rof_file),
900     ADD_TABLE(install_exec_seq),
901     ADD_TABLE(rof_media),
902     ADD_TABLE(property),
903     ADD_TABLE(df_duplicate_file),
904 };
905
906 static const msi_table wrv_tables[] =
907 {
908     ADD_TABLE(wrv_component),
909     ADD_TABLE(directory),
910     ADD_TABLE(rof_feature),
911     ADD_TABLE(ci2_feature_comp),
912     ADD_TABLE(ci2_file),
913     ADD_TABLE(install_exec_seq),
914     ADD_TABLE(rof_media),
915     ADD_TABLE(property),
916     ADD_TABLE(wrv_registry),
917 };
918
919 static const msi_table sf_tables[] =
920 {
921     ADD_TABLE(wrv_component),
922     ADD_TABLE(directory),
923     ADD_TABLE(rof_feature),
924     ADD_TABLE(ci2_feature_comp),
925     ADD_TABLE(ci2_file),
926     ADD_TABLE(install_exec_seq),
927     ADD_TABLE(rof_media),
928     ADD_TABLE(property),
929 };
930
931 /* cabinet definitions */
932
933 /* make the max size large so there is only one cab file */
934 #define MEDIA_SIZE          0x7FFFFFFF
935 #define FOLDER_THRESHOLD    900000
936
937 /* the FCI callbacks */
938
939 static void *mem_alloc(ULONG cb)
940 {
941     return HeapAlloc(GetProcessHeap(), 0, cb);
942 }
943
944 static void mem_free(void *memory)
945 {
946     HeapFree(GetProcessHeap(), 0, memory);
947 }
948
949 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
950 {
951     sprintf(pccab->szCab, pv, pccab->iCab);
952     return TRUE;
953 }
954
955 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
956 {
957     return 0;
958 }
959
960 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
961                        BOOL fContinuation, void *pv)
962 {
963     return 0;
964 }
965
966 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
967 {
968     HANDLE handle;
969     DWORD dwAccess = 0;
970     DWORD dwShareMode = 0;
971     DWORD dwCreateDisposition = OPEN_EXISTING;
972     
973     dwAccess = GENERIC_READ | GENERIC_WRITE;
974     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
975     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
976
977     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
978         dwCreateDisposition = OPEN_EXISTING;
979     else
980         dwCreateDisposition = CREATE_NEW;
981
982     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
983                          dwCreateDisposition, 0, NULL);
984
985     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
986
987     return (INT_PTR)handle;
988 }
989
990 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
991 {
992     HANDLE handle = (HANDLE)hf;
993     DWORD dwRead;
994     BOOL res;
995     
996     res = ReadFile(handle, memory, cb, &dwRead, NULL);
997     ok(res, "Failed to ReadFile\n");
998
999     return dwRead;
1000 }
1001
1002 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1003 {
1004     HANDLE handle = (HANDLE)hf;
1005     DWORD dwWritten;
1006     BOOL res;
1007
1008     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1009     ok(res, "Failed to WriteFile\n");
1010
1011     return dwWritten;
1012 }
1013
1014 static int fci_close(INT_PTR hf, int *err, void *pv)
1015 {
1016     HANDLE handle = (HANDLE)hf;
1017     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1018
1019     return 0;
1020 }
1021
1022 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
1023 {
1024     HANDLE handle = (HANDLE)hf;
1025     DWORD ret;
1026     
1027     ret = SetFilePointer(handle, dist, NULL, seektype);
1028     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1029
1030     return ret;
1031 }
1032
1033 static int fci_delete(char *pszFile, int *err, void *pv)
1034 {
1035     BOOL ret = DeleteFileA(pszFile);
1036     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1037
1038     return 0;
1039 }
1040
1041 static void init_functionpointers(void)
1042 {
1043     HMODULE hmsi = GetModuleHandleA("msi.dll");
1044
1045 #define GET_PROC(func) \
1046     p ## func = (void*)GetProcAddress(hmsi, #func); \
1047     if(!p ## func) \
1048       trace("GetProcAddress(%s) failed\n", #func);
1049
1050     GET_PROC(MsiQueryComponentStateA);
1051     GET_PROC(MsiSourceListEnumSourcesA);
1052     GET_PROC(MsiSourceListGetInfoA);
1053
1054 #undef GET_PROC
1055 }
1056
1057 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1058 {
1059     CHAR buffer[0x20];
1060     UINT r;
1061     DWORD sz;
1062
1063     sz = sizeof buffer;
1064     r = MsiRecordGetString(rec, field, buffer, &sz);
1065     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1066 }
1067
1068 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1069 {
1070     LPSTR tempname;
1071
1072     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1073     GetTempFileNameA(".", "xx", 0, tempname);
1074
1075     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1076     {
1077         lstrcpyA(pszTempName, tempname);
1078         HeapFree(GetProcessHeap(), 0, tempname);
1079         return TRUE;
1080     }
1081
1082     HeapFree(GetProcessHeap(), 0, tempname);
1083
1084     return FALSE;
1085 }
1086
1087 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1088                              USHORT *pattribs, int *err, void *pv)
1089 {
1090     BY_HANDLE_FILE_INFORMATION finfo;
1091     FILETIME filetime;
1092     HANDLE handle;
1093     DWORD attrs;
1094     BOOL res;
1095
1096     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1097                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1098
1099     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1100
1101     res = GetFileInformationByHandle(handle, &finfo);
1102     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1103    
1104     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1105     FileTimeToDosDateTime(&filetime, pdate, ptime);
1106
1107     attrs = GetFileAttributes(pszName);
1108     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1109
1110     return (INT_PTR)handle;
1111 }
1112
1113 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1114 {
1115     char path[MAX_PATH];
1116     char filename[MAX_PATH];
1117
1118     lstrcpyA(path, CURR_DIR);
1119     lstrcatA(path, "\\");
1120     lstrcatA(path, file);
1121
1122     lstrcpyA(filename, file);
1123
1124     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
1125                       progress, get_open_info, compress);
1126 }
1127
1128 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
1129 {
1130     ZeroMemory(pCabParams, sizeof(CCAB));
1131
1132     pCabParams->cb = max_size;
1133     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
1134     pCabParams->setID = 0xbeef;
1135     pCabParams->iCab = 1;
1136     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1137     lstrcatA(pCabParams->szCabPath, "\\");
1138     lstrcpyA(pCabParams->szCab, name);
1139 }
1140
1141 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1142 {
1143     CCAB cabParams;
1144     LPCSTR ptr;
1145     HFCI hfci;
1146     ERF erf;
1147     BOOL res;
1148
1149     set_cab_parameters(&cabParams, name, max_size);
1150
1151     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1152                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1153                       get_temp_file, &cabParams, NULL);
1154
1155     ok(hfci != NULL, "Failed to create an FCI context\n");
1156
1157     ptr = files;
1158     while (*ptr)
1159     {
1160         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1161         ok(res, "Failed to add file: %s\n", ptr);
1162         ptr += lstrlen(ptr) + 1;
1163     }
1164
1165     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1166     ok(res, "Failed to flush the cabinet\n");
1167
1168     res = FCIDestroy(hfci);
1169     ok(res, "Failed to destroy the cabinet\n");
1170 }
1171
1172 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1173 {
1174     HKEY hkey;
1175     DWORD type, size;
1176
1177     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1178                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1179         return FALSE;
1180
1181     size = MAX_PATH;
1182     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1183         RegCloseKey(hkey);
1184         return FALSE;
1185     }
1186
1187     size = MAX_PATH;
1188     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1189         RegCloseKey(hkey);
1190         return FALSE;
1191     }
1192
1193     RegCloseKey(hkey);
1194     return TRUE;
1195 }
1196
1197 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1198 {
1199     HANDLE file;
1200     DWORD written;
1201
1202     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1203     ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n", name);
1204     WriteFile(file, data, strlen(data), &written, NULL);
1205
1206     if (size)
1207     {
1208         SetFilePointer(file, size, NULL, FILE_BEGIN);
1209         SetEndOfFile(file);
1210     }
1211
1212     CloseHandle(file);
1213 }
1214
1215 #define create_file(name, size) create_file_data(name, name, size)
1216
1217 static void create_test_files(void)
1218 {
1219     CreateDirectoryA("msitest", NULL);
1220     create_file("msitest\\one.txt", 100);
1221     CreateDirectoryA("msitest\\first", NULL);
1222     create_file("msitest\\first\\two.txt", 100);
1223     CreateDirectoryA("msitest\\second", NULL);
1224     create_file("msitest\\second\\three.txt", 100);
1225
1226     create_file("four.txt", 100);
1227     create_file("five.txt", 100);
1228     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1229
1230     create_file("msitest\\filename", 100);
1231     create_file("msitest\\service.exe", 100);
1232
1233     DeleteFileA("four.txt");
1234     DeleteFileA("five.txt");
1235 }
1236
1237 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1238 {
1239     CHAR path[MAX_PATH];
1240
1241     lstrcpyA(path, PROG_FILES_DIR);
1242     lstrcatA(path, "\\");
1243     lstrcatA(path, rel_path);
1244
1245     if (is_file)
1246         return DeleteFileA(path);
1247     else
1248         return RemoveDirectoryA(path);
1249 }
1250
1251 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1252 {
1253     CHAR path[MAX_PATH];
1254
1255     lstrcpyA(path, COMMON_FILES_DIR);
1256     lstrcatA(path, "\\");
1257     lstrcatA(path, rel_path);
1258
1259     if (is_file)
1260         return DeleteFileA(path);
1261     else
1262         return RemoveDirectoryA(path);
1263 }
1264
1265 static void delete_test_files(void)
1266 {
1267     DeleteFileA("msitest.msi");
1268     DeleteFileA("msitest.cab");
1269     DeleteFileA("msitest\\second\\three.txt");
1270     DeleteFileA("msitest\\first\\two.txt");
1271     DeleteFileA("msitest\\one.txt");
1272     DeleteFileA("msitest\\service.exe");
1273     DeleteFileA("msitest\\filename");
1274     RemoveDirectoryA("msitest\\second");
1275     RemoveDirectoryA("msitest\\first");
1276     RemoveDirectoryA("msitest");
1277 }
1278
1279 static void write_file(const CHAR *filename, const char *data, int data_size)
1280 {
1281     DWORD size;
1282
1283     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1284                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1285
1286     WriteFile(hf, data, data_size, &size, NULL);
1287     CloseHandle(hf);
1288 }
1289
1290 static void write_msi_summary_info(MSIHANDLE db)
1291 {
1292     MSIHANDLE summary;
1293     UINT r;
1294
1295     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1296     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1297
1298     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1299     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1300
1301     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1302                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1304
1305     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1306     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1307
1308     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 0, NULL, NULL);
1309     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1310
1311     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1312     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1313
1314     /* write the summary changes back to the stream */
1315     r = MsiSummaryInfoPersist(summary);
1316     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1317
1318     MsiCloseHandle(summary);
1319 }
1320
1321 static void create_database(const CHAR *name, const msi_table *tables, int num_tables)
1322 {
1323     MSIHANDLE db;
1324     UINT r;
1325     int j;
1326
1327     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1329
1330     /* import the tables into the database */
1331     for (j = 0; j < num_tables; j++)
1332     {
1333         const msi_table *table = &tables[j];
1334
1335         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1336
1337         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1338         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1339
1340         DeleteFileA(table->filename);
1341     }
1342
1343     write_msi_summary_info(db);
1344
1345     r = MsiDatabaseCommit(db);
1346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1347
1348     MsiCloseHandle(db);
1349 }
1350
1351 static void check_service_is_installed(void)
1352 {
1353     SC_HANDLE scm, service;
1354     BOOL res;
1355
1356     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1357     ok(scm != NULL, "Failed to open the SC Manager\n");
1358
1359     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1360     ok(service != NULL, "Failed to open TestService\n");
1361
1362     res = DeleteService(service);
1363     ok(res, "Failed to delete TestService\n");
1364
1365     CloseServiceHandle(service);
1366     CloseServiceHandle(scm);
1367 }
1368
1369 static void test_MsiInstallProduct(void)
1370 {
1371     UINT r;
1372     CHAR path[MAX_PATH];
1373     LONG res;
1374     HKEY hkey;
1375     DWORD num, size, type;
1376     SC_HANDLE scm;
1377
1378     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1379     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1380     {
1381         skip("Services are not implemented, we are most likely on win9x\n");
1382         return;
1383     }
1384     CloseServiceHandle(scm);
1385
1386     create_test_files();
1387     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1388
1389     r = MsiInstallProductA(msifile, NULL);
1390     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1391
1392     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1393     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1394     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1395     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1396     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1397     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1398     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1399     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1400     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1401     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1402     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1403     ok(delete_pf("msitest", FALSE), "File not installed\n");
1404
1405     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1406     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1407
1408     size = MAX_PATH;
1409     type = REG_SZ;
1410     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1411     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1412     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1413
1414     size = MAX_PATH;
1415     type = REG_SZ;
1416     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1417     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1418
1419     size = sizeof(num);
1420     type = REG_DWORD;
1421     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1422     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1423     ok(num == 314, "Expected 314, got %d\n", num);
1424
1425     size = MAX_PATH;
1426     type = REG_SZ;
1427     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1428     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1429     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1430
1431     check_service_is_installed();
1432
1433     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1434
1435     delete_test_files();
1436 }
1437
1438 static void test_MsiSetComponentState(void)
1439 {
1440     INSTALLSTATE installed, action;
1441     MSIHANDLE package;
1442     char path[MAX_PATH];
1443     UINT r;
1444
1445     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1446
1447     CoInitialize(NULL);
1448
1449     lstrcpy(path, CURR_DIR);
1450     lstrcat(path, "\\");
1451     lstrcat(path, msifile);
1452
1453     r = MsiOpenPackage(path, &package);
1454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1455
1456     r = MsiDoAction(package, "CostInitialize");
1457     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1458
1459     r = MsiDoAction(package, "FileCost");
1460     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1461
1462     r = MsiDoAction(package, "CostFinalize");
1463     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1464
1465     r = MsiGetComponentState(package, "dangler", &installed, &action);
1466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1467     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1468     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1469
1470     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1471     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1472
1473     MsiCloseHandle(package);
1474     CoUninitialize();
1475
1476     DeleteFileA(msifile);
1477 }
1478
1479 static void test_packagecoltypes(void)
1480 {
1481     MSIHANDLE hdb, view, rec;
1482     char path[MAX_PATH];
1483     LPCSTR query;
1484     UINT r, count;
1485
1486     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1487
1488     CoInitialize(NULL);
1489
1490     lstrcpy(path, CURR_DIR);
1491     lstrcat(path, "\\");
1492     lstrcat(path, msifile);
1493
1494     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1495     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1496
1497     query = "SELECT * FROM `Media`";
1498     r = MsiDatabaseOpenView( hdb, query, &view );
1499     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1500
1501     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1502     count = MsiRecordGetFieldCount( rec );
1503     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1504     ok(count == 6, "Expected 6, got %d\n", count);
1505     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1506     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1507     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1508     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1509     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1510     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1511     MsiCloseHandle(rec);
1512
1513     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1514     count = MsiRecordGetFieldCount( rec );
1515     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1516     ok(count == 6, "Expected 6, got %d\n", count);
1517     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1518     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1519     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1520     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1521     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1522     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1523
1524     MsiCloseHandle(rec);
1525     MsiCloseHandle(view);
1526     MsiCloseHandle(hdb);
1527     DeleteFile(msifile);
1528 }
1529
1530 static void create_cc_test_files(void)
1531 {
1532     CCAB cabParams;
1533     HFCI hfci;
1534     ERF erf;
1535     static CHAR cab_context[] = "test%d.cab";
1536     BOOL res;
1537
1538     create_file("maximus", 500);
1539     create_file("augustus", 50000);
1540     create_file("caesar", 500);
1541
1542     set_cab_parameters(&cabParams, "test1.cab", 200);
1543
1544     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1545                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1546                       get_temp_file, &cabParams, cab_context);
1547     ok(hfci != NULL, "Failed to create an FCI context\n");
1548
1549     res = add_file(hfci, "maximus", tcompTYPE_MSZIP);
1550     ok(res, "Failed to add file maximus\n");
1551
1552     res = add_file(hfci, "augustus", tcompTYPE_MSZIP);
1553     ok(res, "Failed to add file augustus\n");
1554
1555     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1556     ok(res, "Failed to flush the cabinet\n");
1557
1558     res = FCIDestroy(hfci);
1559     ok(res, "Failed to destroy the cabinet\n");
1560
1561     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1562
1563     DeleteFile("maximus");
1564     DeleteFile("augustus");
1565     DeleteFile("caesar");
1566 }
1567
1568 static void create_cc2_test_files(void)
1569 {
1570     CCAB cabParams;
1571     HFCI hfci;
1572     ERF erf;
1573     static CHAR cab_context[] = "test%d.cab";
1574     BOOL res;
1575
1576     create_file("maximus", 500);
1577     create_file("augustus", 50000);
1578     create_file("tiberius", 500);
1579     create_file("caesar", 500);
1580
1581     set_cab_parameters(&cabParams, "test1.cab", 40000);
1582
1583     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1584                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1585                       get_temp_file, &cabParams, cab_context);
1586     ok(hfci != NULL, "Failed to create an FCI context\n");
1587
1588     res = add_file(hfci, "maximus", tcompTYPE_NONE);
1589     ok(res, "Failed to add file maximus\n");
1590
1591     res = add_file(hfci, "augustus", tcompTYPE_NONE);
1592     ok(res, "Failed to add file augustus\n");
1593
1594     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
1595     ok(res, "Failed to add file tiberius\n");
1596
1597     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1598     ok(res, "Failed to flush the cabinet\n");
1599
1600     res = FCIDestroy(hfci);
1601     ok(res, "Failed to destroy the cabinet\n");
1602
1603     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1604
1605     DeleteFile("maximus");
1606     DeleteFile("augustus");
1607     DeleteFile("tiberius");
1608     DeleteFile("caesar");
1609 }
1610
1611 static void delete_cab_files(void)
1612 {
1613     SHFILEOPSTRUCT shfl;
1614     CHAR path[MAX_PATH+10];
1615
1616     lstrcpyA(path, CURR_DIR);
1617     lstrcatA(path, "\\*.cab");
1618     path[strlen(path) + 1] = '\0';
1619
1620     shfl.hwnd = NULL;
1621     shfl.wFunc = FO_DELETE;
1622     shfl.pFrom = path;
1623     shfl.pTo = NULL;
1624     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1625
1626     SHFileOperation(&shfl);
1627 }
1628
1629 static void test_continuouscabs(void)
1630 {
1631     UINT r;
1632
1633     create_cc_test_files();
1634     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1635
1636     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1637
1638     r = MsiInstallProductA(msifile, NULL);
1639     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1640     todo_wine
1641     {
1642         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1643         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1644         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1645     }
1646     ok(delete_pf("msitest", FALSE), "File not installed\n");
1647
1648     delete_cab_files();
1649     DeleteFile(msifile);
1650
1651     create_cc2_test_files();
1652     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
1653
1654     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1655
1656     r = MsiInstallProductA(msifile, NULL);
1657     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1658     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1659     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1660     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
1661     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1662     ok(delete_pf("msitest", FALSE), "File not installed\n");
1663
1664     delete_cab_files();
1665     DeleteFile(msifile);
1666 }
1667
1668 static void test_caborder(void)
1669 {
1670     UINT r;
1671
1672     create_file("imperator", 100);
1673     create_file("maximus", 500);
1674     create_file("augustus", 50000);
1675     create_file("caesar", 500);
1676
1677     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1678
1679     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1680
1681     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1682     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1683     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1684
1685     r = MsiInstallProductA(msifile, NULL);
1686     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1687     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1688     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1689     todo_wine
1690     {
1691         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1692         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1693     }
1694
1695     delete_cab_files();
1696
1697     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1698     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
1699     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1700
1701     r = MsiInstallProductA(msifile, NULL);
1702     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1703     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1704     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1705     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1706     todo_wine
1707     {
1708         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1709     }
1710
1711     delete_cab_files();
1712     DeleteFile(msifile);
1713
1714     create_cc_test_files();
1715     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
1716
1717     r = MsiInstallProductA(msifile, NULL);
1718     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1719     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1720     ok(!delete_pf("msitest", FALSE), "File is installed\n");
1721     todo_wine
1722     {
1723         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1724         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1725     }
1726
1727     delete_cab_files();
1728     DeleteFile(msifile);
1729
1730     create_cc_test_files();
1731     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
1732
1733     r = MsiInstallProductA(msifile, NULL);
1734     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1735     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1736     todo_wine
1737     {
1738         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1739         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1740         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1741     }
1742
1743     delete_cab_files();
1744     DeleteFile("imperator");
1745     DeleteFile("maximus");
1746     DeleteFile("augustus");
1747     DeleteFile("caesar");
1748     DeleteFile(msifile);
1749 }
1750
1751 static void test_mixedmedia(void)
1752 {
1753     UINT r;
1754
1755     CreateDirectoryA("msitest", NULL);
1756     create_file("msitest\\maximus", 500);
1757     create_file("msitest\\augustus", 500);
1758     create_file("caesar", 500);
1759
1760     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
1761
1762     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1763
1764     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
1765
1766     r = MsiInstallProductA(msifile, NULL);
1767     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1768     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1769     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1770     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1771     ok(delete_pf("msitest", FALSE), "File not installed\n");
1772
1773     /* Delete the files in the temp (current) folder */
1774     DeleteFile("msitest\\maximus");
1775     DeleteFile("msitest\\augustus");
1776     RemoveDirectory("msitest");
1777     DeleteFile("caesar");
1778     DeleteFile("test1.cab");
1779     DeleteFile(msifile);
1780 }
1781
1782 static void test_samesequence(void)
1783 {
1784     UINT r;
1785
1786     create_cc_test_files();
1787     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
1788
1789     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1790
1791     r = MsiInstallProductA(msifile, NULL);
1792     todo_wine
1793     {
1794         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1795         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1796         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1797     }
1798     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1799     ok(delete_pf("msitest", FALSE), "File not installed\n");
1800
1801     delete_cab_files();
1802     DeleteFile(msifile);
1803 }
1804
1805 static void test_uiLevelFlags(void)
1806 {
1807     UINT r;
1808
1809     create_cc_test_files();
1810     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
1811
1812     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
1813
1814     r = MsiInstallProductA(msifile, NULL);
1815     ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
1816     todo_wine
1817     {
1818         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1819         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1820     }
1821     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1822     ok(delete_pf("msitest", FALSE), "File not installed\n");
1823
1824     delete_cab_files();
1825     DeleteFile(msifile);
1826 }
1827
1828 static BOOL file_matches(LPSTR path)
1829 {
1830     CHAR buf[MAX_PATH];
1831     HANDLE file;
1832     DWORD size;
1833
1834     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1835                       NULL, OPEN_EXISTING, 0, NULL);
1836
1837     ZeroMemory(buf, MAX_PATH);
1838     ReadFile(file, buf, 15, &size, NULL);
1839     CloseHandle(file);
1840
1841     return !lstrcmp(buf, "msitest\\maximus");
1842 }
1843
1844 static void test_readonlyfile(void)
1845 {
1846     UINT r;
1847     DWORD size;
1848     HANDLE file;
1849     CHAR path[MAX_PATH];
1850
1851     CreateDirectoryA("msitest", NULL);
1852     create_file("msitest\\maximus", 500);
1853     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
1854
1855     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1856
1857     lstrcpy(path, PROG_FILES_DIR);
1858     lstrcat(path, "\\msitest");
1859     CreateDirectory(path, NULL);
1860
1861     lstrcat(path, "\\maximus");
1862     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
1863                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
1864
1865     WriteFile(file, "readonlyfile", 20, &size, NULL);
1866     CloseHandle(file);
1867
1868     r = MsiInstallProductA(msifile, NULL);
1869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1870     ok(file_matches(path), "Expected file to be overwritten\n");
1871     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1872     ok(delete_pf("msitest", FALSE), "File not installed\n");
1873
1874     /* Delete the files in the temp (current) folder */
1875     DeleteFile("msitest\\maximus");
1876     RemoveDirectory("msitest");
1877     DeleteFile(msifile);
1878 }
1879
1880 static void test_setdirproperty(void)
1881 {
1882     UINT r;
1883
1884     CreateDirectoryA("msitest", NULL);
1885     create_file("msitest\\maximus", 500);
1886     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
1887
1888     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1889
1890     r = MsiInstallProductA(msifile, NULL);
1891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1892     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
1893     ok(delete_cf("msitest", FALSE), "File not installed\n");
1894
1895     /* Delete the files in the temp (current) folder */
1896     DeleteFile(msifile);
1897     DeleteFile("msitest\\maximus");
1898     RemoveDirectory("msitest");
1899 }
1900
1901 static void test_cabisextracted(void)
1902 {
1903     UINT r;
1904
1905     CreateDirectoryA("msitest", NULL);
1906     create_file("msitest\\gaius", 500);
1907     create_file("maximus", 500);
1908     create_file("augustus", 500);
1909     create_file("caesar", 500);
1910
1911     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1912     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1913     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1914
1915     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
1916
1917     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1918
1919     r = MsiInstallProductA(msifile, NULL);
1920     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1921     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1922     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1923     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1924     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
1925     ok(delete_pf("msitest", FALSE), "File not installed\n");
1926
1927     /* Delete the files in the temp (current) folder */
1928     delete_cab_files();
1929     DeleteFile(msifile);
1930     DeleteFile("maximus");
1931     DeleteFile("augustus");
1932     DeleteFile("caesar");
1933     DeleteFile("msitest\\gaius");
1934     RemoveDirectory("msitest");
1935 }
1936
1937 static void test_concurrentinstall(void)
1938 {
1939     UINT r;
1940     CHAR path[MAX_PATH];
1941
1942     CreateDirectoryA("msitest", NULL);
1943     CreateDirectoryA("msitest\\msitest", NULL);
1944     create_file("msitest\\maximus", 500);
1945     create_file("msitest\\msitest\\augustus", 500);
1946
1947     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
1948
1949     lstrcpyA(path, CURR_DIR);
1950     lstrcatA(path, "\\msitest\\concurrent.msi");
1951     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
1952
1953     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1954
1955     r = MsiInstallProductA(msifile, NULL);
1956     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1957     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1958     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1959     ok(delete_pf("msitest", FALSE), "File not installed\n");
1960
1961     DeleteFile(path);
1962
1963     r = MsiInstallProductA(msifile, NULL);
1964     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1965     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1966     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1967     ok(delete_pf("msitest", FALSE), "File not installed\n");
1968
1969     DeleteFile(msifile);
1970     DeleteFile("msitest\\msitest\\augustus");
1971     DeleteFile("msitest\\maximus");
1972     RemoveDirectory("msitest\\msitest");
1973     RemoveDirectory("msitest");
1974 }
1975
1976 static void test_setpropertyfolder(void)
1977 {
1978     UINT r;
1979
1980     CreateDirectoryA("msitest", NULL);
1981     create_file("msitest\\maximus", 500);
1982
1983     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
1984
1985     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1986
1987     r = MsiInstallProductA(msifile, NULL);
1988     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1989     ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
1990     ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
1991     ok(delete_pf("msitest", FALSE), "File not installed\n");
1992
1993     /* Delete the files in the temp (current) folder */
1994     DeleteFile(msifile);
1995     DeleteFile("msitest\\maximus");
1996     RemoveDirectory("msitest");
1997 }
1998
1999 static BOOL file_exists(LPCSTR file)
2000 {
2001     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2002 }
2003
2004 static BOOL pf_exists(LPCSTR file)
2005 {
2006     CHAR path[MAX_PATH];
2007
2008     lstrcpyA(path, PROG_FILES_DIR);
2009     lstrcatA(path, "\\");
2010     lstrcatA(path, file);
2011
2012     return file_exists(path);
2013 }
2014
2015 static void delete_pfmsitest_files(void)
2016 {
2017     SHFILEOPSTRUCT shfl;
2018     CHAR path[MAX_PATH+11];
2019
2020     lstrcpyA(path, PROG_FILES_DIR);
2021     lstrcatA(path, "\\msitest\\*");
2022     path[strlen(path) + 1] = '\0';
2023
2024     shfl.hwnd = NULL;
2025     shfl.wFunc = FO_DELETE;
2026     shfl.pFrom = path;
2027     shfl.pTo = NULL;
2028     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2029
2030     SHFileOperation(&shfl);
2031
2032     lstrcpyA(path, PROG_FILES_DIR);
2033     lstrcatA(path, "\\msitest");
2034     RemoveDirectoryA(path);
2035 }
2036
2037 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2038 {
2039     char val[MAX_PATH];
2040     DWORD size, type;
2041     LONG res;
2042
2043     size = MAX_PATH;
2044     val[0] = '\0';
2045     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2046
2047     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
2048     {
2049         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2050         return;
2051     }
2052
2053     if (!expected)
2054         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2055     else
2056     {
2057         if (bcase)
2058             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2059         else
2060             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2061     }
2062 }
2063
2064 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2065 {
2066     DWORD val, size, type;
2067     LONG res;
2068
2069     size = sizeof(DWORD);
2070     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2071
2072     if (res != ERROR_SUCCESS || type != REG_DWORD)
2073     {
2074         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2075         return;
2076     }
2077
2078     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2079 }
2080
2081 #define CHECK_REG_STR(prodkey, name, expected) \
2082     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2083
2084 #define CHECK_REG_ISTR(prodkey, name, expected) \
2085     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2086
2087 #define CHECK_REG_DWORD(prodkey, name, expected) \
2088     check_reg_dword(prodkey, name, expected, __LINE__);
2089
2090 static void get_date_str(LPSTR date)
2091 {
2092     SYSTEMTIME systime;
2093
2094     static const char date_fmt[] = "%d%02d%02d";
2095     GetLocalTime(&systime);
2096     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2097 }
2098
2099 static void test_publish_registerproduct(void)
2100 {
2101     UINT r;
2102     LONG res;
2103     HKEY uninstall, prodkey;
2104     INSTALLSTATE state;
2105     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2106     char date[MAX_PATH];
2107     char temp[MAX_PATH];
2108
2109     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2110
2111     if (!pMsiQueryComponentStateA)
2112     {
2113         skip("MsiQueryComponentStateA is not available\n");
2114         return;
2115     }
2116
2117     get_date_str(date);
2118     GetTempPath(MAX_PATH, temp);
2119
2120     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2121     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2122
2123     CreateDirectoryA("msitest", NULL);
2124     create_file("msitest\\maximus", 500);
2125
2126     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2127
2128     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2129
2130     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2131     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2132
2133     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2134     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2135
2136     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2137     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2138
2139     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2140                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2141     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2142     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2143
2144     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2145     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2146
2147     /* RegisterProduct */
2148     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2150     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2151     ok(pf_exists("msitest"), "File not installed\n");
2152
2153     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2154     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2155
2156     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2157     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2158
2159     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2160     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2161
2162     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2163                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2164     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2165     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2166
2167     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2168     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2169
2170     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2171     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2172     CHECK_REG_STR(prodkey, "InstallDate", date);
2173     CHECK_REG_STR(prodkey, "InstallSource", temp);
2174     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2175     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2176     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2177     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2178     CHECK_REG_STR(prodkey, "Comments", NULL);
2179     CHECK_REG_STR(prodkey, "Contact", NULL);
2180     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2181     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2182     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2183     CHECK_REG_STR(prodkey, "Readme", NULL);
2184     CHECK_REG_STR(prodkey, "Size", NULL);
2185     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2186     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2187     CHECK_REG_DWORD(prodkey, "Language", 1033);
2188     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2189     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2190     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2191     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2192     todo_wine
2193     {
2194         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2195     }
2196
2197     RegCloseKey(prodkey);
2198
2199     /* try to uninstall after RegisterProduct */
2200     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2201     todo_wine
2202     {
2203         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2204     }
2205     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2206     ok(pf_exists("msitest"), "File deleted\n");
2207
2208     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2209     todo_wine
2210     {
2211         ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2212     }
2213
2214     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2215     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2216
2217     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2218     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2219
2220     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2221                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2222     todo_wine
2223     {
2224         ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2225     }
2226     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2227
2228     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2229     todo_wine
2230     {
2231         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2232     }
2233
2234     todo_wine
2235     {
2236         CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2237         CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2238         CHECK_REG_STR(prodkey, "InstallDate", date);
2239         CHECK_REG_STR(prodkey, "InstallSource", temp);
2240         CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2241         CHECK_REG_STR(prodkey, "Publisher", "Wine");
2242         CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2243         CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2244         CHECK_REG_STR(prodkey, "Comments", NULL);
2245         CHECK_REG_STR(prodkey, "Contact", NULL);
2246         CHECK_REG_STR(prodkey, "HelpLink", NULL);
2247         CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2248         CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2249         CHECK_REG_STR(prodkey, "Readme", NULL);
2250         CHECK_REG_STR(prodkey, "Size", NULL);
2251         CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2252         CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2253         CHECK_REG_DWORD(prodkey, "Language", 1033);
2254         CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2255         CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2256         CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2257         CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2258         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2259     }
2260
2261     RegCloseKey(prodkey);
2262
2263     /* full install to remove */
2264     r = MsiInstallProductA(msifile, "FULL=1");
2265     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2266     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2268
2269     RegCloseKey(uninstall);
2270     DeleteFile(msifile);
2271     DeleteFile("msitest\\maximus");
2272     RemoveDirectory("msitest");
2273     delete_pfmsitest_files();
2274 }
2275
2276 static void test_publish_publishproduct(void)
2277 {
2278     UINT r;
2279     LONG res;
2280     HKEY uninstall, prodkey;
2281     INSTALLSTATE state;
2282     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2283
2284     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2285
2286     if (!pMsiQueryComponentStateA)
2287     {
2288         skip("MsiQueryComponentStateA is not available\n");
2289         return;
2290     }
2291
2292     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2293     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2294
2295     CreateDirectoryA("msitest", NULL);
2296     create_file("msitest\\maximus", 500);
2297
2298     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2299
2300     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2301
2302     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2303     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2304
2305     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2306     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2307
2308     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2309     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2310
2311     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2312                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2313     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2314     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2315
2316     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2317     todo_wine
2318     {
2319         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2320     }
2321
2322     /* PublishProduct */
2323     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2324     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2325     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2326     ok(pf_exists("msitest"), "File not installed\n");
2327
2328     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2329     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2330
2331     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2332     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2333
2334     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2335     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2336
2337     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2338                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2339     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2340     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2341
2342     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2343     todo_wine
2344     {
2345         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2346     }
2347
2348     /* try to uninstall after PublishProduct */
2349     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2350     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2351     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2352     ok(pf_exists("msitest"), "File deleted\n");
2353
2354     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2355     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2356
2357     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2358     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2359
2360     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2361     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2362
2363     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2364                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2365     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2366     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2367
2368     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2369     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2370
2371     /* full install to remove */
2372     r = MsiInstallProductA(msifile, "FULL=1");
2373     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2374     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2375     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2376
2377     RegCloseKey(uninstall);
2378     DeleteFile(msifile);
2379     DeleteFile("msitest\\maximus");
2380     RemoveDirectory("msitest");
2381     delete_pfmsitest_files();
2382 }
2383
2384 static void test_publish_publishfeatures(void)
2385 {
2386     UINT r;
2387     LONG res;
2388     HKEY uninstall, prodkey;
2389     INSTALLSTATE state;
2390     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2391
2392     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2393
2394     if (!pMsiQueryComponentStateA)
2395     {
2396         skip("MsiQueryComponentStateA is not available\n");
2397         return;
2398     }
2399
2400     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2401     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2402
2403     CreateDirectoryA("msitest", NULL);
2404     create_file("msitest\\maximus", 500);
2405
2406     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2407
2408     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2409
2410     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2411     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2412
2413     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2414     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2415
2416     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2417     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2418
2419     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2420                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2421     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2422     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2423
2424     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2425     todo_wine
2426     {
2427         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2428     }
2429
2430     /* PublishFeatures */
2431     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2432     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2433     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2434     ok(pf_exists("msitest"), "File not installed\n");
2435
2436     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2437     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2438
2439     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2440     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2441
2442     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2443     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2444
2445     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2446                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2447     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2448     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2449
2450     /* try to uninstall after PublishFeatures */
2451     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2452     todo_wine
2453     {
2454         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2455     }
2456     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2457     ok(pf_exists("msitest"), "File deleted\n");
2458
2459     /* PublishFeatures and PublishProduct */
2460     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 PUBLISH_FEATURES=1");
2461     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2462     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2463     ok(pf_exists("msitest"), "File not installed\n");
2464
2465     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2466     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2467
2468     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2469     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2470
2471     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2472     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2473
2474     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2475                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2476     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2477     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2478
2479     /* PublishFeatures and RegisterProduct */
2480     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_FEATURES=1");
2481     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2482     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2483     ok(pf_exists("msitest"), "File not installed\n");
2484
2485     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2486     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2487
2488     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2489     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2490
2491     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2492     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2493
2494     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2495                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2496     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2497     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2498
2499     /* full install to remove */
2500     r = MsiInstallProductA(msifile, "FULL=1");
2501     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2502     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2503     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2504
2505     RegCloseKey(uninstall);
2506     DeleteFile(msifile);
2507     DeleteFile("msitest\\maximus");
2508     RemoveDirectory("msitest");
2509     delete_pfmsitest_files();
2510 }
2511
2512 static void test_publish_registeruser(void)
2513 {
2514     UINT r;
2515     LONG res;
2516     HKEY uninstall, prodkey;
2517     INSTALLSTATE state;
2518     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2519
2520     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2521
2522     if (!pMsiQueryComponentStateA)
2523     {
2524         skip("MsiQueryComponentStateA is not available\n");
2525         return;
2526     }
2527
2528     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2529     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2530
2531     CreateDirectoryA("msitest", NULL);
2532     create_file("msitest\\maximus", 500);
2533
2534     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2535
2536     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2537
2538     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2539     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2540
2541     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2542     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2543
2544     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2545     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2546
2547     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2548                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2549     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2550     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2551
2552     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2553     todo_wine
2554     {
2555         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2556     }
2557
2558     /* RegisterUser */
2559     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
2560     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2561     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2562     ok(pf_exists("msitest"), "File not installed\n");
2563
2564     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2565     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2566
2567     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2568     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2569
2570     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2571     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2572
2573     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2574                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2575     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2576     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2577
2578     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2579     todo_wine
2580     {
2581         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2582     }
2583
2584     /* try to uninstall after RegisterUser */
2585     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2586     todo_wine
2587     {
2588         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2589     }
2590     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2591     ok(pf_exists("msitest"), "File deleted\n");
2592
2593     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2594     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2595
2596     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2597     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2598
2599     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2600     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2601
2602     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2603                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2604     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2605     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2606
2607     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2608     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2609
2610     /* full install to remove */
2611     r = MsiInstallProductA(msifile, "FULL=1");
2612     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2613     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2615
2616     RegCloseKey(uninstall);
2617     DeleteFile(msifile);
2618     DeleteFile("msitest\\maximus");
2619     RemoveDirectory("msitest");
2620     delete_pfmsitest_files();
2621 }
2622
2623 static void get_user_sid(LPSTR *usersid)
2624 {
2625     HANDLE token;
2626     BYTE buf[1024];
2627     DWORD size;
2628     PTOKEN_USER user;
2629     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
2630     static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
2631
2632     *usersid = NULL;
2633     pConvertSidToStringSidA = (void *)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
2634     if (!pConvertSidToStringSidA)
2635         return;
2636
2637     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
2638     size = sizeof(buf);
2639     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
2640     user = (PTOKEN_USER)buf;
2641     pConvertSidToStringSidA(user->User.Sid, usersid);
2642 }
2643
2644 static void test_publish_processcomponents(void)
2645 {
2646     UINT r;
2647     LONG res;
2648     HKEY uninstall, prodkey, comp;
2649     INSTALLSTATE state;
2650     LPSTR usersid;
2651     CHAR keypath[MAX_PATH];
2652     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2653
2654     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2655
2656     if (!pMsiQueryComponentStateA)
2657     {
2658         skip("MsiQueryComponentStateA is not available\n");
2659         return;
2660     }
2661
2662     get_user_sid(&usersid);
2663     if (!usersid)
2664     {
2665         skip("ConvertSidToStringSidA is not available\n");
2666         return;
2667     }
2668
2669     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2670     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2671
2672     CreateDirectoryA("msitest", NULL);
2673     create_file("msitest\\maximus", 500);
2674
2675     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2676
2677     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2678
2679     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2680     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2681
2682     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2683     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2684
2685     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2686     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2687
2688     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2689                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2690     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2691     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2692
2693     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2694     todo_wine
2695     {
2696         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2697     }
2698
2699     /* ProcessComponent */
2700     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2701     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2702     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2703     ok(pf_exists("msitest"), "File not installed\n");
2704
2705     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2706     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2707
2708     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2709     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2710
2711     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2712                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2713     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2714     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2715
2716     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2717     todo_wine
2718     {
2719         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2720     }
2721
2722     /* try to uninstall after ProcessComponents */
2723     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2724     todo_wine
2725     {
2726         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2727     }
2728     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2729     ok(pf_exists("msitest"), "File deleted\n");
2730
2731     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2732     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2733
2734     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2735     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2736
2737     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2738     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2739
2740     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2741                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2742     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2743     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2744
2745     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2746     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2747
2748     /* ProcessComponent with PublishProduct */
2749     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2750     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2751     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2752     ok(pf_exists("msitest"), "File not installed\n");
2753
2754     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2755     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2756
2757     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2758     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2759
2760     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2761     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2762
2763     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2764                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2765     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2766     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2767
2768     /* uninstall */
2769     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2770     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2771
2772     /* ProcessComponent with RegisterProduct */
2773     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PROCESS_COMPONENTS=1");
2774     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2775     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2776     ok(pf_exists("msitest"), "File not installed\n");
2777
2778     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2779     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2780
2781     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2782     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2783
2784     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2785     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2786
2787     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2788                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2789     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2790     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2791
2792     /* ProcessComponent with RegisterProduct and PublishProduct */
2793     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2795     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2796     ok(pf_exists("msitest"), "File not installed\n");
2797
2798     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2799     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2800
2801     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2802     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2803
2804     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2805     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2806
2807     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2808                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2809     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2810     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2811
2812     /* uninstall */
2813     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2814     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2815
2816     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2817     lstrcatA(keypath, usersid);
2818     lstrcatA(keypath, "\\Components\\CBABC2FDCCB35E749A8944D8C1C098B5");
2819
2820     /* native has trouble removing the comp key unless it's a full install */
2821     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
2822     if (res == ERROR_SUCCESS)
2823     {
2824         RegDeleteKeyA(comp, "");
2825         RegCloseKey(comp);
2826     }
2827
2828     RegCloseKey(uninstall);
2829     DeleteFile(msifile);
2830     DeleteFile("msitest\\maximus");
2831     RemoveDirectory("msitest");
2832     delete_pfmsitest_files();
2833 }
2834
2835 static void test_publish(void)
2836 {
2837     UINT r;
2838     LONG res;
2839     HKEY uninstall, prodkey;
2840     INSTALLSTATE state;
2841     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2842     char date[MAX_PATH];
2843     char temp[MAX_PATH];
2844
2845     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2846
2847     if (!pMsiQueryComponentStateA)
2848     {
2849         skip("MsiQueryComponentStateA is not available\n");
2850         return;
2851     }
2852
2853     get_date_str(date);
2854     GetTempPath(MAX_PATH, temp);
2855
2856     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2858
2859     CreateDirectoryA("msitest", NULL);
2860     create_file("msitest\\maximus", 500);
2861
2862     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2863
2864     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2865
2866     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2867     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2868
2869     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2870     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2871
2872     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2873     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2874
2875     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2876                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2877     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2878     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2879
2880     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2881     todo_wine
2882     {
2883         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2884     }
2885
2886     /* nothing published */
2887     r = MsiInstallProductA(msifile, NULL);
2888     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2889     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2890     ok(pf_exists("msitest"), "File not installed\n");
2891
2892     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2893     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2894
2895     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2896     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2897
2898     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2899     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2900
2901     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2902                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2903     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2904     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2905
2906     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2907     todo_wine
2908     {
2909         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2910     }
2911
2912     /* PublishProduct and RegisterProduct */
2913     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
2914     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2915     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2916     ok(pf_exists("msitest"), "File not installed\n");
2917
2918     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2919     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2920
2921     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2922     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2923
2924     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2925     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2926
2927     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2928                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2929     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2930     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2931
2932     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2933     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2934
2935     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2936     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2937     CHECK_REG_STR(prodkey, "InstallDate", date);
2938     CHECK_REG_STR(prodkey, "InstallSource", temp);
2939     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2940     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2941     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2942     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2943     CHECK_REG_STR(prodkey, "Comments", NULL);
2944     CHECK_REG_STR(prodkey, "Contact", NULL);
2945     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2946     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2947     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2948     CHECK_REG_STR(prodkey, "Readme", NULL);
2949     CHECK_REG_STR(prodkey, "Size", NULL);
2950     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2951     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2952     CHECK_REG_DWORD(prodkey, "Language", 1033);
2953     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2954     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2955     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2956     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2957     todo_wine
2958     {
2959         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2960     }
2961
2962     RegCloseKey(prodkey);
2963
2964     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2965     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2966     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2967     ok(pf_exists("msitest"), "File deleted\n");
2968
2969     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2970     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2971
2972     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2973     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2974
2975     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2976     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2977
2978     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2979                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2980     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2981     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2982
2983     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2984     todo_wine
2985     {
2986         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2987     }
2988
2989     /* complete install */
2990     r = MsiInstallProductA(msifile, "FULL=1");
2991     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2992     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2993     ok(pf_exists("msitest"), "File not installed\n");
2994
2995     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2996     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2997
2998     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2999     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3000
3001     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3002     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3003
3004     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3005                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3007     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3008
3009     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3010     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3011
3012     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3013     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3014     CHECK_REG_STR(prodkey, "InstallDate", date);
3015     CHECK_REG_STR(prodkey, "InstallSource", temp);
3016     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3017     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3018     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3019     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3020     CHECK_REG_STR(prodkey, "Comments", NULL);
3021     CHECK_REG_STR(prodkey, "Contact", NULL);
3022     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3023     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3024     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3025     CHECK_REG_STR(prodkey, "Readme", NULL);
3026     CHECK_REG_STR(prodkey, "Size", NULL);
3027     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3028     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3029     CHECK_REG_DWORD(prodkey, "Language", 1033);
3030     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3031     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3032     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3033     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3034     todo_wine
3035     {
3036         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3037     }
3038
3039     RegCloseKey(prodkey);
3040
3041     /* no UnpublishFeatures */
3042     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3043     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3044     todo_wine
3045     {
3046         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
3047         ok(!pf_exists("msitest"), "File deleted\n");
3048     }
3049
3050     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3051     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3052
3053     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3054     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3055
3056     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3057     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3058
3059     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3060                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3061     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3062     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3063
3064     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3065     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3066
3067     /* complete install */
3068     r = MsiInstallProductA(msifile, "FULL=1");
3069     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3070     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3071     ok(pf_exists("msitest"), "File not installed\n");
3072
3073     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3074     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3075
3076     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3077     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3078
3079     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3080     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3081
3082     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3083                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3084     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3085     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3086
3087     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3088     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3089
3090     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3091     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3092     CHECK_REG_STR(prodkey, "InstallDate", date);
3093     CHECK_REG_STR(prodkey, "InstallSource", temp);
3094     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3095     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3096     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3097     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3098     CHECK_REG_STR(prodkey, "Comments", NULL);
3099     CHECK_REG_STR(prodkey, "Contact", NULL);
3100     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3101     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3102     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3103     CHECK_REG_STR(prodkey, "Readme", NULL);
3104     CHECK_REG_STR(prodkey, "Size", NULL);
3105     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3106     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3107     CHECK_REG_DWORD(prodkey, "Language", 1033);
3108     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3109     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3110     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3111     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3112     todo_wine
3113     {
3114         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3115     }
3116
3117     RegCloseKey(prodkey);
3118
3119     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3120     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3121     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3122     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3123     ok(pf_exists("msitest"), "File deleted\n");
3124
3125     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3126     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3127
3128     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3129     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3130
3131     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3132     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3133
3134     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3135                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3136     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3137     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3138
3139     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3140     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3141
3142     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3143     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3144     CHECK_REG_STR(prodkey, "InstallDate", date);
3145     CHECK_REG_STR(prodkey, "InstallSource", temp);
3146     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3147     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3148     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3149     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3150     CHECK_REG_STR(prodkey, "Comments", NULL);
3151     CHECK_REG_STR(prodkey, "Contact", NULL);
3152     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3153     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3154     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3155     CHECK_REG_STR(prodkey, "Readme", NULL);
3156     CHECK_REG_STR(prodkey, "Size", NULL);
3157     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3158     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3159     CHECK_REG_DWORD(prodkey, "Language", 1033);
3160     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3161     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3162     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3163     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3164     todo_wine
3165     {
3166         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3167     }
3168
3169     RegCloseKey(prodkey);
3170
3171     /* complete install */
3172     r = MsiInstallProductA(msifile, "FULL=1");
3173     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3174     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3175     ok(pf_exists("msitest"), "File not installed\n");
3176
3177     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3178     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3179
3180     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3181     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3182
3183     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3184     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3185
3186     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3187                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3188     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3189     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3190
3191     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3192     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3193
3194     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3195     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3196     CHECK_REG_STR(prodkey, "InstallDate", date);
3197     CHECK_REG_STR(prodkey, "InstallSource", temp);
3198     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3199     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3200     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3201     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3202     CHECK_REG_STR(prodkey, "Comments", NULL);
3203     CHECK_REG_STR(prodkey, "Contact", NULL);
3204     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3205     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3206     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3207     CHECK_REG_STR(prodkey, "Readme", NULL);
3208     CHECK_REG_STR(prodkey, "Size", NULL);
3209     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3210     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3211     CHECK_REG_DWORD(prodkey, "Language", 1033);
3212     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3213     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3214     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3215     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3216     todo_wine
3217     {
3218         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3219     }
3220
3221     RegCloseKey(prodkey);
3222
3223     /* UnpublishFeatures, both features removed */
3224     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3225     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3226     todo_wine
3227     {
3228         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3229         ok(!pf_exists("msitest"), "File not deleted\n");
3230     }
3231
3232     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3233     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3234
3235     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3236     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3237
3238     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3239     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3240
3241     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3242                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3243     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3244     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3245
3246     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3247     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3248
3249     /* complete install */
3250     r = MsiInstallProductA(msifile, "FULL=1");
3251     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3252     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3253     ok(pf_exists("msitest"), "File not installed\n");
3254
3255     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3256     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3257
3258     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3259     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3260
3261     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3262     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3263
3264     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3265                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3267     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3268
3269     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3270     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3271
3272     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3273     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3274     CHECK_REG_STR(prodkey, "InstallDate", date);
3275     CHECK_REG_STR(prodkey, "InstallSource", temp);
3276     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3277     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3278     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3279     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3280     CHECK_REG_STR(prodkey, "Comments", NULL);
3281     CHECK_REG_STR(prodkey, "Contact", NULL);
3282     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3283     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3284     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3285     CHECK_REG_STR(prodkey, "Readme", NULL);
3286     CHECK_REG_STR(prodkey, "Size", NULL);
3287     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3288     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3289     CHECK_REG_DWORD(prodkey, "Language", 1033);
3290     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3291     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3292     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3293     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3294     todo_wine
3295     {
3296         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3297     }
3298
3299     RegCloseKey(prodkey);
3300
3301     /* complete uninstall */
3302     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3303     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3304     todo_wine
3305     {
3306         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3307         ok(!pf_exists("msitest"), "File not deleted\n");
3308     }
3309
3310     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3311     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3312
3313     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3314     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3315
3316     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3317     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3318
3319     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3320                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3321     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3322     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3323
3324     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3325     todo_wine
3326     {
3327         ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3328     }
3329
3330     /* make sure 'Program Files\msitest' is removed */
3331     delete_pfmsitest_files();
3332
3333     RegCloseKey(uninstall);
3334     DeleteFile(msifile);
3335     DeleteFile("msitest\\maximus");
3336     RemoveDirectory("msitest");
3337 }
3338
3339 static void test_publishsourcelist(void)
3340 {
3341     UINT r;
3342     DWORD size;
3343     CHAR value[MAX_PATH];
3344     CHAR path[MAX_PATH];
3345     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3346
3347     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3348     {
3349         skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3350         return;
3351     }
3352
3353     CreateDirectoryA("msitest", NULL);
3354     create_file("msitest\\maximus", 500);
3355
3356     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3357
3358     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3359
3360     r = MsiInstallProductA(msifile, NULL);
3361     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3362     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3363     ok(pf_exists("msitest"), "File not installed\n");
3364
3365     /* nothing published */
3366     size = 0xdeadbeef;
3367     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3368                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3369     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3370     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3371
3372     size = 0xdeadbeef;
3373     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3374                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3375     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3376     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3377
3378     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3379     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3380     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3381     ok(pf_exists("msitest"), "File not installed\n");
3382
3383     /* after RegisterProduct */
3384     size = 0xdeadbeef;
3385     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3386                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3387     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3388     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3389
3390     size = 0xdeadbeef;
3391     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3392                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3393     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3394     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3395
3396     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3397     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3398     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3399     ok(pf_exists("msitest"), "File not installed\n");
3400
3401     /* after ProcessComponents */
3402     size = 0xdeadbeef;
3403     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3404                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3405     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3406     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3407
3408     size = 0xdeadbeef;
3409     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3410                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3411     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3412     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3413
3414     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3416     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3417     ok(pf_exists("msitest"), "File not installed\n");
3418
3419     /* after PublishFeatures */
3420     size = 0xdeadbeef;
3421     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3422                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3423     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3424     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3425
3426     size = 0xdeadbeef;
3427     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3428                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3429     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3430     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3431
3432     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3433     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3434     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3435     ok(pf_exists("msitest"), "File not installed\n");
3436
3437     /* after PublishProduct */
3438     size = MAX_PATH;
3439     lstrcpyA(value, "aaa");
3440     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3441                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3442     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3443     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3444     ok(size == 11, "Expected 11, got %d\n", size);
3445
3446     size = MAX_PATH;
3447     lstrcpyA(value, "aaa");
3448     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3449                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3450     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3451     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3452     ok(size == 0, "Expected 0, got %d\n", size);
3453
3454     size = MAX_PATH;
3455     lstrcpyA(value, "aaa");
3456     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3457                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3458     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3459     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3460     ok(size == 0, "Expected 0, got %d\n", size);
3461
3462     lstrcpyA(path, CURR_DIR);
3463     lstrcatA(path, "\\");
3464
3465     size = MAX_PATH;
3466     lstrcpyA(value, "aaa");
3467     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3468                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3470     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3471     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3472
3473     size = MAX_PATH;
3474     lstrcpyA(value, "aaa");
3475     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3476                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3477     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3478     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3479     ok(size == 1, "Expected 1, got %d\n", size);
3480
3481     size = MAX_PATH;
3482     lstrcpyA(value, "aaa");
3483     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3484                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3485     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3486     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3487     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3488
3489     size = MAX_PATH;
3490     lstrcpyA(value, "aaa");
3491     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3492                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3493     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3494     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3495     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3496
3497     size = MAX_PATH;
3498     lstrcpyA(value, "aaa");
3499     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3500                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3501     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3502     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3503     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3504
3505     /* complete uninstall */
3506     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3507     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3508     todo_wine
3509     {
3510         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3511         ok(!pf_exists("msitest"), "File not deleted\n");
3512     }
3513
3514     /* make sure 'Program Files\msitest' is removed */
3515     delete_pfmsitest_files();
3516
3517     DeleteFile(msifile);
3518     DeleteFile("msitest\\maximus");
3519     RemoveDirectory("msitest");
3520 }
3521
3522 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3523 {
3524     MSIHANDLE hview = 0;
3525     UINT r;
3526
3527     r = MsiDatabaseOpenView(hdb, query, &hview);
3528     if(r != ERROR_SUCCESS)
3529         return r;
3530
3531     r = MsiViewExecute(hview, hrec);
3532     if(r == ERROR_SUCCESS)
3533         r = MsiViewClose(hview);
3534     MsiCloseHandle(hview);
3535     return r;
3536 }
3537
3538 static void set_transform_summary_info(void)
3539 {
3540     UINT r;
3541     MSIHANDLE suminfo = 0;
3542
3543     /* build summmary info */
3544     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
3545     todo_wine
3546     {
3547         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
3548     }
3549
3550     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
3551     todo_wine
3552     {
3553         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3554     }
3555
3556     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
3557                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3558                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3559                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
3560     todo_wine
3561     {
3562         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
3563     }
3564
3565     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
3566     todo_wine
3567     {
3568         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3569     }
3570
3571     r = MsiSummaryInfoPersist(suminfo);
3572     todo_wine
3573     {
3574         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
3575     }
3576
3577     r = MsiCloseHandle(suminfo);
3578     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
3579 }
3580
3581 static void generate_transform(void)
3582 {
3583     MSIHANDLE hdb1, hdb2;
3584     LPCSTR query;
3585     UINT r;
3586
3587     /* start with two identical databases */
3588     CopyFile(msifile, msifile2, FALSE);
3589
3590     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
3591     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3592
3593     r = MsiDatabaseCommit(hdb1);
3594     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
3595
3596     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
3597     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3598
3599     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
3600     r = run_query(hdb1, 0, query);
3601     ok(r == ERROR_SUCCESS, "failed to add property\n");
3602
3603     /* database needs to be committed */
3604     MsiDatabaseCommit(hdb1);
3605
3606     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
3607     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
3608
3609 #if 0  /* not implemented in wine yet */
3610     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
3611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3612 #endif
3613
3614     MsiCloseHandle(hdb1);
3615     MsiCloseHandle(hdb2);
3616 }
3617
3618 /* data for generating a transform */
3619
3620 /* tables transform names - encoded as they would be in an msi database file */
3621 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
3622 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
3623 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
3624
3625 /* data in each table */
3626 static const char data1[] = /* _StringData */
3627     "propval";  /* all the strings squashed together */
3628
3629 static const WCHAR data2[] = { /* _StringPool */
3630 /*  len, refs */
3631     0,   0,    /* string 0 ''     */
3632     4,   1,    /* string 1 'prop' */
3633     3,   1,    /* string 2 'val'  */
3634 };
3635
3636 static const WCHAR data3[] = { /* Property */
3637     0x0201, 0x0001, 0x0002,
3638 };
3639
3640 static const struct {
3641     LPCWSTR name;
3642     const void *data;
3643     DWORD size;
3644 } table_transform_data[] =
3645 {
3646     { name1, data1, sizeof data1 - 1 },
3647     { name2, data2, sizeof data2 },
3648     { name3, data3, sizeof data3 },
3649 };
3650
3651 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
3652
3653 static void generate_transform_manual(void)
3654 {
3655     IStorage *stg = NULL;
3656     IStream *stm;
3657     WCHAR name[0x20];
3658     HRESULT r;
3659     DWORD i, count;
3660     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
3661
3662     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
3663
3664     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
3665
3666     r = StgCreateDocfile(name, mode, 0, &stg);
3667     ok(r == S_OK, "failed to create storage\n");
3668     if (!stg)
3669         return;
3670
3671     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
3672     ok(r == S_OK, "failed to set storage type\n");
3673
3674     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
3675     {
3676         r = IStorage_CreateStream(stg, table_transform_data[i].name,
3677                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3678         if (FAILED(r))
3679         {
3680             ok(0, "failed to create stream %08x\n", r);
3681             continue;
3682         }
3683
3684         r = IStream_Write(stm, table_transform_data[i].data,
3685                           table_transform_data[i].size, &count);
3686         if (FAILED(r) || count != table_transform_data[i].size)
3687             ok(0, "failed to write stream\n");
3688         IStream_Release(stm);
3689     }
3690
3691     IStorage_Release(stg);
3692
3693     set_transform_summary_info();
3694 }
3695
3696 static void test_transformprop(void)
3697 {
3698     UINT r;
3699
3700     CreateDirectoryA("msitest", NULL);
3701     create_file("msitest\\augustus", 500);
3702
3703     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
3704
3705     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3706
3707     r = MsiInstallProductA(msifile, NULL);
3708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3709     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3710     ok(!delete_pf("msitest", FALSE), "File installed\n");
3711
3712     if (0)
3713         generate_transform();
3714     else
3715         generate_transform_manual();
3716
3717     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
3718     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3719     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3720     ok(delete_pf("msitest", FALSE), "File not installed\n");
3721
3722     /* Delete the files in the temp (current) folder */
3723     DeleteFile(msifile);
3724     DeleteFile(msifile2);
3725     DeleteFile(mstfile);
3726     DeleteFile("msitest\\augustus");
3727     RemoveDirectory("msitest");
3728 }
3729
3730 static void test_currentworkingdir(void)
3731 {
3732     UINT r;
3733     CHAR path[MAX_PATH];
3734     LPSTR ptr, ptr2;
3735
3736     CreateDirectoryA("msitest", NULL);
3737     create_file("msitest\\augustus", 500);
3738
3739     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
3740
3741     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3742
3743     CreateDirectoryA("diffdir", NULL);
3744     SetCurrentDirectoryA("diffdir");
3745
3746     sprintf(path, "..\\%s", msifile);
3747     r = MsiInstallProductA(path, NULL);
3748     todo_wine
3749     {
3750         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
3751         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3752         ok(!delete_pf("msitest", FALSE), "File installed\n");
3753     }
3754
3755     sprintf(path, "%s\\%s", CURR_DIR, msifile);
3756     r = MsiInstallProductA(path, NULL);
3757     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3758     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3759     ok(delete_pf("msitest", FALSE), "File not installed\n");
3760
3761     lstrcpyA(path, CURR_DIR);
3762     if (path[lstrlenA(path) - 1] != '\\')
3763         lstrcatA(path, "\\");
3764     lstrcatA(path, "msitest.msi");
3765
3766     ptr2 = strrchr(path, '\\');
3767     *ptr2 = '\0';
3768     ptr = strrchr(path, '\\');
3769     *ptr2 = '\\';
3770     *(ptr++) = '\0';
3771
3772     SetCurrentDirectoryA(path);
3773
3774     r = MsiInstallProductA(ptr, NULL);
3775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3776     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3777     ok(delete_pf("msitest", FALSE), "File not installed\n");
3778
3779     SetCurrentDirectoryA(CURR_DIR);
3780
3781     DeleteFile(msifile);
3782     DeleteFile("msitest\\augustus");
3783     RemoveDirectory("msitest");
3784     RemoveDirectory("diffdir");
3785 }
3786
3787 static void set_admin_summary_info(const CHAR *name)
3788 {
3789     MSIHANDLE db, summary;
3790     UINT r;
3791
3792     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
3793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3794
3795     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
3796     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3797
3798     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
3799     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3800
3801     /* write the summary changes back to the stream */
3802     r = MsiSummaryInfoPersist(summary);
3803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3804
3805     MsiCloseHandle(summary);
3806
3807     r = MsiDatabaseCommit(db);
3808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3809
3810     MsiCloseHandle(db);
3811 }
3812
3813 static void test_admin(void)
3814 {
3815     UINT r;
3816
3817     CreateDirectoryA("msitest", NULL);
3818     create_file("msitest\\augustus", 500);
3819
3820     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
3821     set_admin_summary_info(msifile);
3822
3823     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3824
3825     r = MsiInstallProductA(msifile, NULL);
3826     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3827     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3828     ok(!delete_pf("msitest", FALSE), "File installed\n");
3829     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
3830     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
3831
3832     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
3833     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3834     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3835     ok(!delete_pf("msitest", FALSE), "File installed\n");
3836     todo_wine
3837     {
3838         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
3839         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
3840     }
3841
3842     DeleteFile(msifile);
3843     DeleteFile("msitest\\augustus");
3844     RemoveDirectory("msitest");
3845 }
3846
3847 static void set_admin_property_stream(LPCSTR file)
3848 {
3849     IStorage *stg;
3850     IStream *stm;
3851     WCHAR fileW[MAX_PATH];
3852     HRESULT hr;
3853     DWORD count;
3854     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
3855
3856     /* AdminProperties */
3857     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
3858     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
3859
3860     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
3861
3862     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
3863     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3864     if (!stg)
3865         return;
3866
3867     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3868     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3869
3870     hr = IStream_Write(stm, data, sizeof(data), &count);
3871     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3872
3873     IStream_Release(stm);
3874     IStorage_Release(stg);
3875 }
3876
3877 static void test_adminprops(void)
3878 {
3879     UINT r;
3880
3881     CreateDirectoryA("msitest", NULL);
3882     create_file("msitest\\augustus", 500);
3883
3884     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
3885     set_admin_summary_info(msifile);
3886     set_admin_property_stream(msifile);
3887
3888     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3889
3890     r = MsiInstallProductA(msifile, NULL);
3891     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3892     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
3893     ok(delete_pf("msitest", FALSE), "File installed\n");
3894
3895     DeleteFile(msifile);
3896     DeleteFile("msitest\\augustus");
3897     RemoveDirectory("msitest");
3898 }
3899
3900 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
3901 {
3902     CHAR path[MAX_PATH];
3903
3904     lstrcpyA(path, PROG_FILES_DIR);
3905     lstrcatA(path, "\\");
3906     lstrcatA(path, file);
3907
3908     if (is_file)
3909         create_file_data(path, data, 500);
3910     else
3911         CreateDirectoryA(path, NULL);
3912 }
3913
3914 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
3915
3916 static void test_removefiles(void)
3917 {
3918     UINT r;
3919
3920     CreateDirectoryA("msitest", NULL);
3921     create_file("msitest\\hydrogen", 500);
3922     create_file("msitest\\helium", 500);
3923     create_file("msitest\\lithium", 500);
3924
3925     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
3926
3927     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3928
3929     r = MsiInstallProductA(msifile, NULL);
3930     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3931     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3932     ok(!pf_exists("msitest\\helium"), "File installed\n");
3933     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3934     ok(pf_exists("msitest"), "File not installed\n");
3935
3936     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3937     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3938     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
3939     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3940     todo_wine
3941     {
3942         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3943         ok(delete_pf("msitest", FALSE), "File deleted\n");
3944     }
3945
3946     create_pf("msitest", FALSE);
3947     create_pf("msitest\\hydrogen", TRUE);
3948     create_pf("msitest\\helium", TRUE);
3949     create_pf("msitest\\lithium", TRUE);
3950
3951     r = MsiInstallProductA(msifile, NULL);
3952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3953     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3954     ok(pf_exists("msitest\\helium"), "File not installed\n");
3955     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3956     ok(pf_exists("msitest"), "File not installed\n");
3957
3958     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3959     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3960     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
3961     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3962     todo_wine
3963     {
3964         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3965         ok(delete_pf("msitest", FALSE), "File deleted\n");
3966     }
3967
3968     create_pf("msitest", FALSE);
3969     create_pf("msitest\\furlong", TRUE);
3970     create_pf("msitest\\firkin", TRUE);
3971     create_pf("msitest\\fortnight", TRUE);
3972     create_pf("msitest\\becquerel", TRUE);
3973     create_pf("msitest\\dioptre", TRUE);
3974     create_pf("msitest\\attoparsec", TRUE);
3975     create_pf("msitest\\storeys", TRUE);
3976     create_pf("msitest\\block", TRUE);
3977     create_pf("msitest\\siriometer", TRUE);
3978
3979     r = MsiInstallProductA(msifile, NULL);
3980     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3981     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3982     ok(!pf_exists("msitest\\helium"), "File installed\n");
3983     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3984     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
3985     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
3986     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
3987     ok(pf_exists("msitest"), "File not installed\n");
3988     todo_wine
3989     {
3990         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
3991         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
3992         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
3993         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
3994         ok(!pf_exists("msitest\\block"), "File not deleted\n");
3995         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
3996     }
3997
3998     create_pf("msitest\\furlong", TRUE);
3999     create_pf("msitest\\firkin", TRUE);
4000     create_pf("msitest\\fortnight", TRUE);
4001     create_pf("msitest\\storeys", TRUE);
4002     create_pf("msitest\\block", TRUE);
4003     create_pf("msitest\\siriometer", TRUE);
4004
4005     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4006     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4007     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
4008     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4009     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
4010     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
4011     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
4012     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
4013     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
4014     todo_wine
4015     {
4016         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
4017         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
4018         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
4019         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
4020         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
4021     }
4022     ok(delete_pf("msitest", FALSE), "File deleted\n");
4023
4024     DeleteFile(msifile);
4025     DeleteFile("msitest\\hydrogen");
4026     DeleteFile("msitest\\helium");
4027     DeleteFile("msitest\\lithium");
4028     RemoveDirectory("msitest");
4029 }
4030
4031 static void test_movefiles(void)
4032 {
4033     UINT r;
4034     char props[MAX_PATH];
4035
4036     CreateDirectoryA("msitest", NULL);
4037     create_file("msitest\\augustus", 100);
4038     create_file("cameroon", 100);
4039     create_file("djibouti", 100);
4040     create_file("egypt", 100);
4041     create_file("finland", 100);
4042     create_file("gambai", 100);
4043     create_file("honduras", 100);
4044     create_file("msitest\\india", 100);
4045     create_file("japan", 100);
4046     create_file("kenya", 100);
4047     CreateDirectoryA("latvia", NULL);
4048     create_file("nauru", 100);
4049     create_file("apple", 100);
4050     create_file("application", 100);
4051     create_file("ape", 100);
4052     create_file("foo", 100);
4053     create_file("fao", 100);
4054     create_file("fbod", 100);
4055     create_file("budding", 100);
4056     create_file("buddy", 100);
4057     create_file("bud", 100);
4058     create_file("bar", 100);
4059     create_file("bur", 100);
4060     create_file("bird", 100);
4061
4062     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
4063
4064     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4065     MsiEnableLog(INSTALLLOGMODE_VERBOSE | INSTALLLOGMODE_EXTRADEBUG, "log.txt", 0);
4066
4067     /* if the source or dest property is not a full path,
4068      * windows tries to access it as a network resource
4069      */
4070
4071     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4072             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4073             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4074
4075     r = MsiInstallProductA(msifile, props);
4076     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4077     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4078     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4079     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4080     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4081     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4082     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4083     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4084     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4085     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4086     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4087     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4088     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4089     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4090     /* either apple or application will be moved depending on directory order */
4091     if (!delete_pf("msitest\\apple", TRUE))
4092         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4093     else
4094         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4095     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4096     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4097     /* either fao or foo will be moved depending on directory order */
4098     if (delete_pf("msitest\\foo", TRUE))
4099         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4100     else
4101         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4102     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4103     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4104     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4105     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4106     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4107     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4108     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4109     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4110     ok(delete_pf("msitest", FALSE), "File not installed\n");
4111     ok(DeleteFileA("cameroon"), "File moved\n");
4112     ok(!DeleteFileA("djibouti"), "File not moved\n");
4113     ok(DeleteFileA("egypt"), "File moved\n");
4114     ok(DeleteFileA("finland"), "File moved\n");
4115     ok(DeleteFileA("gambai"), "File moved\n");
4116     ok(!DeleteFileA("honduras"), "File not moved\n");
4117     ok(DeleteFileA("msitest\\india"), "File moved\n");
4118     ok(DeleteFileA("japan"), "File moved\n");
4119     ok(!DeleteFileA("kenya"), "File not moved\n");
4120     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4121     ok(!DeleteFileA("nauru"), "File not moved\n");
4122     ok(!DeleteFileA("apple"), "File not moved\n");
4123     ok(!DeleteFileA("application"), "File not moved\n");
4124     ok(DeleteFileA("ape"), "File moved\n");
4125     ok(!DeleteFileA("foo"), "File not moved\n");
4126     ok(!DeleteFileA("fao"), "File not moved\n");
4127     ok(DeleteFileA("fbod"), "File moved\n");
4128     ok(!DeleteFileA("budding"), "File not moved\n");
4129     ok(!DeleteFileA("buddy"), "File not moved\n");
4130     ok(DeleteFileA("bud"), "File moved\n");
4131     ok(!DeleteFileA("bar"), "File not moved\n");
4132     ok(!DeleteFileA("bur"), "File not moved\n");
4133     ok(DeleteFileA("bird"), "File moved\n");
4134
4135     DeleteFile("msitest\\augustus");
4136     RemoveDirectory("msitest");
4137     DeleteFile(msifile);
4138 }
4139
4140 static void test_missingcab(void)
4141 {
4142     UINT r;
4143
4144     CreateDirectoryA("msitest", NULL);
4145     create_file("msitest\\augustus", 500);
4146     create_file("maximus", 500);
4147
4148     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4149
4150     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4151
4152     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4153
4154     create_pf("msitest", FALSE);
4155     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4156
4157     r = MsiInstallProductA(msifile, NULL);
4158     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4159     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4160     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4161     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4162     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4163     ok(delete_pf("msitest", FALSE), "File not installed\n");
4164
4165     create_pf("msitest", FALSE);
4166     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4167     create_pf("msitest\\gaius", TRUE);
4168
4169     r = MsiInstallProductA(msifile, "GAIUS=1");
4170     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4171     todo_wine
4172     {
4173         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4174         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4175     }
4176     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4177     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4178     ok(delete_pf("msitest", FALSE), "File not installed\n");
4179
4180     DeleteFile("msitest\\augustus");
4181     RemoveDirectory("msitest");
4182     DeleteFile("maximus");
4183     DeleteFile("test1.cab");
4184     DeleteFile(msifile);
4185 }
4186
4187 static void test_duplicatefiles(void)
4188 {
4189     UINT r;
4190
4191     CreateDirectoryA("msitest", NULL);
4192     create_file("msitest\\maximus", 500);
4193     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4194
4195     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4196
4197     /* fails if the destination folder is not a valid property */
4198
4199     r = MsiInstallProductA(msifile, NULL);
4200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4201     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4202     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4203     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4204     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4205     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4206     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4207     ok(delete_pf("msitest", FALSE), "File not installed\n");
4208
4209     DeleteFile("msitest\\maximus");
4210     RemoveDirectory("msitest");
4211     DeleteFile(msifile);
4212 }
4213
4214 static void test_writeregistryvalues(void)
4215 {
4216     UINT r;
4217     LONG res;
4218     HKEY hkey;
4219     DWORD type, size;
4220     CHAR path[MAX_PATH];
4221
4222     CreateDirectoryA("msitest", NULL);
4223     create_file("msitest\\augustus", 500);
4224
4225     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4226
4227     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4228
4229     r = MsiInstallProductA(msifile, NULL);
4230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4231     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4232     ok(delete_pf("msitest", FALSE), "File installed\n");
4233
4234     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4235     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4236
4237     size = MAX_PATH;
4238     type = REG_MULTI_SZ;
4239     memset(path, 'a', MAX_PATH);
4240     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4241     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4242     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4243     ok(size == 15, "Expected 15, got %d\n", size);
4244     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4245
4246     DeleteFile(msifile);
4247     DeleteFile("msitest\\augustus");
4248     RemoveDirectory("msitest");
4249 }
4250
4251 static void test_sourcefolder(void)
4252 {
4253     UINT r;
4254
4255     CreateDirectoryA("msitest", NULL);
4256     create_file("augustus", 500);
4257
4258     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4259
4260     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4261
4262     r = MsiInstallProductA(msifile, NULL);
4263     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4264     todo_wine
4265     {
4266         ok(r == ERROR_INSTALL_FAILURE,
4267            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4268         ok(!delete_pf("msitest", FALSE), "File installed\n");
4269     }
4270
4271     RemoveDirectoryA("msitest");
4272
4273     r = MsiInstallProductA(msifile, NULL);
4274     todo_wine
4275     {
4276         ok(r == ERROR_INSTALL_FAILURE,
4277            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4278         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4279         ok(!delete_pf("msitest", FALSE), "File installed\n");
4280     }
4281
4282     DeleteFile(msifile);
4283     DeleteFile("augustus");
4284 }
4285
4286 START_TEST(install)
4287 {
4288     DWORD len;
4289     char temp_path[MAX_PATH], prev_path[MAX_PATH];
4290
4291     init_functionpointers();
4292
4293     GetCurrentDirectoryA(MAX_PATH, prev_path);
4294     GetTempPath(MAX_PATH, temp_path);
4295     SetCurrentDirectoryA(temp_path);
4296
4297     lstrcpyA(CURR_DIR, temp_path);
4298     len = lstrlenA(CURR_DIR);
4299
4300     if(len && (CURR_DIR[len - 1] == '\\'))
4301         CURR_DIR[len - 1] = 0;
4302
4303     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
4304
4305     test_MsiInstallProduct();
4306     test_MsiSetComponentState();
4307     test_packagecoltypes();
4308     test_continuouscabs();
4309     test_caborder();
4310     test_mixedmedia();
4311     test_samesequence();
4312     test_uiLevelFlags();
4313     test_readonlyfile();
4314     test_setdirproperty();
4315     test_cabisextracted();
4316     test_concurrentinstall();
4317     test_setpropertyfolder();
4318     test_publish_registerproduct();
4319     test_publish_publishproduct();
4320     test_publish_publishfeatures();
4321     test_publish_registeruser();
4322     test_publish_processcomponents();
4323     test_publish();
4324     test_publishsourcelist();
4325     test_transformprop();
4326     test_currentworkingdir();
4327     test_admin();
4328     test_adminprops();
4329     test_removefiles();
4330     test_movefiles();
4331     test_missingcab();
4332     test_duplicatefiles();
4333     test_writeregistryvalues();
4334     test_sourcefolder();
4335
4336     SetCurrentDirectoryA(prev_path);
4337 }