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