quartz: Fix discontinuities in wave parser.
[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     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1960     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1961     ok(delete_pf("msitest", FALSE), "File not installed\n");
1962
1963     DeleteFile(path);
1964
1965     r = MsiInstallProductA(msifile, NULL);
1966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1967     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1968     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
1969     ok(delete_pf("msitest", FALSE), "File not installed\n");
1970
1971     DeleteFile(msifile);
1972     DeleteFile("msitest\\msitest\\augustus");
1973     DeleteFile("msitest\\maximus");
1974     RemoveDirectory("msitest\\msitest");
1975     RemoveDirectory("msitest");
1976 }
1977
1978 static void test_setpropertyfolder(void)
1979 {
1980     UINT r;
1981
1982     CreateDirectoryA("msitest", NULL);
1983     create_file("msitest\\maximus", 500);
1984
1985     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
1986
1987     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
1988
1989     r = MsiInstallProductA(msifile, NULL);
1990     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1991     ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
1992     ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
1993     ok(delete_pf("msitest", FALSE), "File not installed\n");
1994
1995     /* Delete the files in the temp (current) folder */
1996     DeleteFile(msifile);
1997     DeleteFile("msitest\\maximus");
1998     RemoveDirectory("msitest");
1999 }
2000
2001 static BOOL file_exists(LPCSTR file)
2002 {
2003     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2004 }
2005
2006 static BOOL pf_exists(LPCSTR file)
2007 {
2008     CHAR path[MAX_PATH];
2009
2010     lstrcpyA(path, PROG_FILES_DIR);
2011     lstrcatA(path, "\\");
2012     lstrcatA(path, file);
2013
2014     return file_exists(path);
2015 }
2016
2017 static void delete_pfmsitest_files(void)
2018 {
2019     SHFILEOPSTRUCT shfl;
2020     CHAR path[MAX_PATH+11];
2021
2022     lstrcpyA(path, PROG_FILES_DIR);
2023     lstrcatA(path, "\\msitest\\*");
2024     path[strlen(path) + 1] = '\0';
2025
2026     shfl.hwnd = NULL;
2027     shfl.wFunc = FO_DELETE;
2028     shfl.pFrom = path;
2029     shfl.pTo = NULL;
2030     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2031
2032     SHFileOperation(&shfl);
2033
2034     lstrcpyA(path, PROG_FILES_DIR);
2035     lstrcatA(path, "\\msitest");
2036     RemoveDirectoryA(path);
2037 }
2038
2039 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2040 {
2041     char val[MAX_PATH];
2042     DWORD size, type;
2043     LONG res;
2044
2045     size = MAX_PATH;
2046     val[0] = '\0';
2047     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2048
2049     if (res != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ))
2050     {
2051         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2052         return;
2053     }
2054
2055     if (!expected)
2056         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2057     else
2058     {
2059         if (bcase)
2060             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2061         else
2062             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2063     }
2064 }
2065
2066 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2067 {
2068     DWORD val, size, type;
2069     LONG res;
2070
2071     size = sizeof(DWORD);
2072     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2073
2074     if (res != ERROR_SUCCESS || type != REG_DWORD)
2075     {
2076         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2077         return;
2078     }
2079
2080     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2081 }
2082
2083 #define CHECK_REG_STR(prodkey, name, expected) \
2084     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2085
2086 #define CHECK_REG_ISTR(prodkey, name, expected) \
2087     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2088
2089 #define CHECK_REG_DWORD(prodkey, name, expected) \
2090     check_reg_dword(prodkey, name, expected, __LINE__);
2091
2092 static void get_date_str(LPSTR date)
2093 {
2094     SYSTEMTIME systime;
2095
2096     static const char date_fmt[] = "%d%02d%02d";
2097     GetLocalTime(&systime);
2098     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2099 }
2100
2101 static void test_publish_registerproduct(void)
2102 {
2103     UINT r;
2104     LONG res;
2105     HKEY uninstall, prodkey;
2106     INSTALLSTATE state;
2107     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2108     char date[MAX_PATH];
2109     char temp[MAX_PATH];
2110
2111     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2112
2113     if (!pMsiQueryComponentStateA)
2114     {
2115         skip("MsiQueryComponentStateA is not available\n");
2116         return;
2117     }
2118
2119     get_date_str(date);
2120     GetTempPath(MAX_PATH, temp);
2121
2122     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2123     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2124
2125     CreateDirectoryA("msitest", NULL);
2126     create_file("msitest\\maximus", 500);
2127
2128     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2129
2130     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2131
2132     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2133     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2134
2135     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2136     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2137
2138     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2139     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2140
2141     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2142                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2143     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2144     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2145
2146     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2147     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2148
2149     /* RegisterProduct */
2150     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2151     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2152     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2153     ok(pf_exists("msitest"), "File not installed\n");
2154
2155     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2156     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2157
2158     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2159     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2160
2161     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2162     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2163
2164     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2165                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2166     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2167     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2168
2169     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2170     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2171
2172     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2173     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2174     CHECK_REG_STR(prodkey, "InstallDate", date);
2175     CHECK_REG_STR(prodkey, "InstallSource", temp);
2176     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2177     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2178     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2179     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2180     CHECK_REG_STR(prodkey, "Comments", NULL);
2181     CHECK_REG_STR(prodkey, "Contact", NULL);
2182     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2183     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2184     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2185     CHECK_REG_STR(prodkey, "Readme", NULL);
2186     CHECK_REG_STR(prodkey, "Size", NULL);
2187     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2188     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2189     CHECK_REG_DWORD(prodkey, "Language", 1033);
2190     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2191     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2192     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2193     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2194     todo_wine
2195     {
2196         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2197     }
2198
2199     RegCloseKey(prodkey);
2200
2201     /* try to uninstall after RegisterProduct */
2202     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2203     todo_wine
2204     {
2205         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2206     }
2207     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2208     ok(pf_exists("msitest"), "File deleted\n");
2209
2210     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2211     todo_wine
2212     {
2213         ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2214     }
2215
2216     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2217     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2218
2219     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2220     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2221
2222     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2223                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2224     todo_wine
2225     {
2226         ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2227     }
2228     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2229
2230     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2231     todo_wine
2232     {
2233         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2234     }
2235
2236     todo_wine
2237     {
2238         CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2239         CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2240         CHECK_REG_STR(prodkey, "InstallDate", date);
2241         CHECK_REG_STR(prodkey, "InstallSource", temp);
2242         CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2243         CHECK_REG_STR(prodkey, "Publisher", "Wine");
2244         CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2245         CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2246         CHECK_REG_STR(prodkey, "Comments", NULL);
2247         CHECK_REG_STR(prodkey, "Contact", NULL);
2248         CHECK_REG_STR(prodkey, "HelpLink", NULL);
2249         CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2250         CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2251         CHECK_REG_STR(prodkey, "Readme", NULL);
2252         CHECK_REG_STR(prodkey, "Size", NULL);
2253         CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2254         CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2255         CHECK_REG_DWORD(prodkey, "Language", 1033);
2256         CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2257         CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2258         CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2259         CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2260         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2261     }
2262
2263     RegCloseKey(prodkey);
2264
2265     /* full install to remove */
2266     r = MsiInstallProductA(msifile, "FULL=1");
2267     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2268     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2269     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2270
2271     RegCloseKey(uninstall);
2272     DeleteFile(msifile);
2273     DeleteFile("msitest\\maximus");
2274     RemoveDirectory("msitest");
2275     delete_pfmsitest_files();
2276 }
2277
2278 static void test_publish_publishproduct(void)
2279 {
2280     UINT r;
2281     LONG res;
2282     HKEY uninstall, prodkey;
2283     INSTALLSTATE state;
2284     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2285
2286     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2287
2288     if (!pMsiQueryComponentStateA)
2289     {
2290         skip("MsiQueryComponentStateA is not available\n");
2291         return;
2292     }
2293
2294     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2295     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2296
2297     CreateDirectoryA("msitest", NULL);
2298     create_file("msitest\\maximus", 500);
2299
2300     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2301
2302     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2303
2304     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2305     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2306
2307     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2308     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2309
2310     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2311     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2312
2313     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2314                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2315     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2316     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2317
2318     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2319     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2320
2321     /* PublishProduct */
2322     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2323     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2324     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2325     ok(pf_exists("msitest"), "File not installed\n");
2326
2327     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2328     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2329
2330     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2331     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2332
2333     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2334     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2335
2336     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2337                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2338     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2339     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2340
2341     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2342     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2343
2344     /* try to uninstall after PublishProduct */
2345     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2346     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2347     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2348     ok(pf_exists("msitest"), "File deleted\n");
2349
2350     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2351     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2352
2353     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2354     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2355
2356     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2357     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2358
2359     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2360                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2361     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2362     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2363
2364     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2365     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2366
2367     /* full install to remove */
2368     r = MsiInstallProductA(msifile, "FULL=1");
2369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2370     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2371     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2372
2373     RegCloseKey(uninstall);
2374     DeleteFile(msifile);
2375     DeleteFile("msitest\\maximus");
2376     RemoveDirectory("msitest");
2377     delete_pfmsitest_files();
2378 }
2379
2380 static void test_publish_publishfeatures(void)
2381 {
2382     UINT r;
2383     LONG res;
2384     HKEY uninstall, prodkey;
2385     INSTALLSTATE state;
2386     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2387
2388     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2389
2390     if (!pMsiQueryComponentStateA)
2391     {
2392         skip("MsiQueryComponentStateA is not available\n");
2393         return;
2394     }
2395
2396     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2397     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2398
2399     CreateDirectoryA("msitest", NULL);
2400     create_file("msitest\\maximus", 500);
2401
2402     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2403
2404     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2405
2406     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2407     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2408
2409     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2410     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2411
2412     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2413     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2414
2415     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2416                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2417     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2418     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2419
2420     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2421     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2422
2423     /* PublishFeatures */
2424     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2426     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2427     ok(pf_exists("msitest"), "File not installed\n");
2428
2429     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2430     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2431
2432     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2433     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2434
2435     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2436     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2437
2438     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2439                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2440     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2441     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2442
2443     /* try to uninstall after PublishFeatures */
2444     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2445     todo_wine
2446     {
2447         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2448     }
2449     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2450     ok(pf_exists("msitest"), "File deleted\n");
2451
2452     /* PublishFeatures and PublishProduct */
2453     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 PUBLISH_FEATURES=1");
2454     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2455     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2456     ok(pf_exists("msitest"), "File not installed\n");
2457
2458     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2459     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2460
2461     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2462     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2463
2464     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2465     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2466
2467     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2468                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2469     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2470     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2471
2472     /* PublishFeatures and RegisterProduct */
2473     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_FEATURES=1");
2474     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2475     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2476     ok(pf_exists("msitest"), "File not installed\n");
2477
2478     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2479     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2480
2481     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2482     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2483
2484     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2485     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2486
2487     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2488                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2489     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2490     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2491
2492     /* full install to remove */
2493     r = MsiInstallProductA(msifile, "FULL=1");
2494     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2495     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2496     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2497
2498     RegCloseKey(uninstall);
2499     DeleteFile(msifile);
2500     DeleteFile("msitest\\maximus");
2501     RemoveDirectory("msitest");
2502     delete_pfmsitest_files();
2503 }
2504
2505 static void test_publish_registeruser(void)
2506 {
2507     UINT r;
2508     LONG res;
2509     HKEY uninstall, prodkey;
2510     INSTALLSTATE state;
2511     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2512
2513     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2514
2515     if (!pMsiQueryComponentStateA)
2516     {
2517         skip("MsiQueryComponentStateA is not available\n");
2518         return;
2519     }
2520
2521     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2522     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2523
2524     CreateDirectoryA("msitest", NULL);
2525     create_file("msitest\\maximus", 500);
2526
2527     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2528
2529     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2530
2531     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2532     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2533
2534     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2535     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2536
2537     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2538     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2539
2540     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2541                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2542     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2543     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2544
2545     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2546     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2547
2548     /* RegisterUser */
2549     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
2550     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2551     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2552     ok(pf_exists("msitest"), "File not installed\n");
2553
2554     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2555     todo_wine
2556     {
2557         ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2558     }
2559
2560     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2561     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2562
2563     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2564     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2565
2566     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2567                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2568     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2569     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2570
2571     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2572     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2573
2574     /* try to uninstall after RegisterUser */
2575     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2576     todo_wine
2577     {
2578         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2579     }
2580     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2581     ok(pf_exists("msitest"), "File deleted\n");
2582
2583     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2584     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2585
2586     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2587     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2588
2589     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2590     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2591
2592     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2593                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2594     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2595     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2596
2597     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2598     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2599
2600     /* full install to remove */
2601     r = MsiInstallProductA(msifile, "FULL=1");
2602     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2603     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2604     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2605
2606     RegCloseKey(uninstall);
2607     DeleteFile(msifile);
2608     DeleteFile("msitest\\maximus");
2609     RemoveDirectory("msitest");
2610     delete_pfmsitest_files();
2611 }
2612
2613 static void get_user_sid(LPSTR *usersid)
2614 {
2615     HANDLE token;
2616     BYTE buf[1024];
2617     DWORD size;
2618     PTOKEN_USER user;
2619     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
2620     static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
2621
2622     *usersid = NULL;
2623     pConvertSidToStringSidA = (void *)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
2624     if (!pConvertSidToStringSidA)
2625         return;
2626
2627     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
2628     size = sizeof(buf);
2629     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
2630     user = (PTOKEN_USER)buf;
2631     pConvertSidToStringSidA(user->User.Sid, usersid);
2632 }
2633
2634 static void test_publish_processcomponents(void)
2635 {
2636     UINT r;
2637     LONG res;
2638     HKEY uninstall, prodkey, comp;
2639     INSTALLSTATE state;
2640     LPSTR usersid;
2641     CHAR keypath[MAX_PATH];
2642     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2643
2644     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2645
2646     if (!pMsiQueryComponentStateA)
2647     {
2648         skip("MsiQueryComponentStateA is not available\n");
2649         return;
2650     }
2651
2652     get_user_sid(&usersid);
2653     if (!usersid)
2654     {
2655         skip("ConvertSidToStringSidA is not available\n");
2656         return;
2657     }
2658
2659     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2660     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2661
2662     CreateDirectoryA("msitest", NULL);
2663     create_file("msitest\\maximus", 500);
2664
2665     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2666
2667     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2668
2669     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2670     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2671
2672     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2673     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2674
2675     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2676     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2677
2678     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2679                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2680     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2681     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2682
2683     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2684     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2685
2686     /* ProcessComponent */
2687     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
2688     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2689     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2690     ok(pf_exists("msitest"), "File not installed\n");
2691
2692     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2693     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2694
2695     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2696     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2697
2698     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2699                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2700     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2701     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2702
2703     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2704     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2705
2706     /* try to uninstall after ProcessComponents */
2707     r = MsiInstallProductA(msifile, "REMOVE=ALL");
2708     todo_wine
2709     {
2710         ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2711     }
2712     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2713     ok(pf_exists("msitest"), "File deleted\n");
2714
2715     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2716     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2717
2718     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2719     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2720
2721     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2722     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2723
2724     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2725                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2726     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2727     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2728
2729     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2730     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2731
2732     /* ProcessComponent with PublishProduct */
2733     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2734     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2735     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2736     ok(pf_exists("msitest"), "File not installed\n");
2737
2738     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2739     ok(state == INSTALLSTATE_ADVERTISED, "Expected INSTALLSTATE_ADVERTISED, got %d\n", state);
2740
2741     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2742     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2743
2744     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2745     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2746
2747     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2748                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2749     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2750     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2751
2752     /* uninstall */
2753     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2754     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2755
2756     /* ProcessComponent with RegisterProduct */
2757     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PROCESS_COMPONENTS=1");
2758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2759     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2760     ok(pf_exists("msitest"), "File not installed\n");
2761
2762     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2763     ok(state == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", state);
2764
2765     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2766     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2767
2768     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2769     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2770
2771     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2772                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2773     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2774     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2775
2776     /* ProcessComponent with RegisterProduct and PublishProduct */
2777     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1 PROCESS_COMPONENTS=1");
2778     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2779     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2780     ok(pf_exists("msitest"), "File not installed\n");
2781
2782     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2783     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2784
2785     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2786     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2787
2788     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2789     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2790
2791     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2792                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2793     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2794     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2795
2796     /* uninstall */
2797     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2799
2800     lstrcpyA(keypath, "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\");
2801     lstrcatA(keypath, usersid);
2802     lstrcatA(keypath, "\\Components\\CBABC2FDCCB35E749A8944D8C1C098B5");
2803
2804     /* native has trouble removing the comp key unless it's a full install */
2805     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
2806     if (res == ERROR_SUCCESS)
2807     {
2808         RegDeleteKeyA(comp, "");
2809         RegCloseKey(comp);
2810     }
2811
2812     RegCloseKey(uninstall);
2813     DeleteFile(msifile);
2814     DeleteFile("msitest\\maximus");
2815     RemoveDirectory("msitest");
2816     delete_pfmsitest_files();
2817 }
2818
2819 static void test_publish(void)
2820 {
2821     UINT r;
2822     LONG res;
2823     HKEY uninstall, prodkey;
2824     INSTALLSTATE state;
2825     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2826     char date[MAX_PATH];
2827     char temp[MAX_PATH];
2828
2829     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
2830
2831     if (!pMsiQueryComponentStateA)
2832     {
2833         skip("MsiQueryComponentStateA is not available\n");
2834         return;
2835     }
2836
2837     get_date_str(date);
2838     GetTempPath(MAX_PATH, temp);
2839
2840     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
2841     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2842
2843     CreateDirectoryA("msitest", NULL);
2844     create_file("msitest\\maximus", 500);
2845
2846     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2847
2848     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2849
2850     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2851     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2852
2853     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2854     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2855
2856     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2857     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2858
2859     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2860                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2861     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2862     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2863
2864     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2865     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2866
2867     /* nothing published */
2868     r = MsiInstallProductA(msifile, NULL);
2869     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2870     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2871     ok(pf_exists("msitest"), "File not installed\n");
2872
2873     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2874     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2875
2876     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2877     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2878
2879     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2880     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2881
2882     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2883                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2884     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2885     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2886
2887     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2888     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2889
2890     /* PublishProduct and RegisterProduct */
2891     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
2892     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2893     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2894     ok(pf_exists("msitest"), "File not installed\n");
2895
2896     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2897     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2898
2899     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2900     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2901
2902     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2903     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2904
2905     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2906                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2907     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
2908     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2909
2910     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2911     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2912
2913     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2914     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2915     CHECK_REG_STR(prodkey, "InstallDate", date);
2916     CHECK_REG_STR(prodkey, "InstallSource", temp);
2917     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2918     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2919     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2920     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2921     CHECK_REG_STR(prodkey, "Comments", NULL);
2922     CHECK_REG_STR(prodkey, "Contact", NULL);
2923     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2924     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2925     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
2926     CHECK_REG_STR(prodkey, "Readme", NULL);
2927     CHECK_REG_STR(prodkey, "Size", NULL);
2928     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
2929     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
2930     CHECK_REG_DWORD(prodkey, "Language", 1033);
2931     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
2932     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
2933     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
2934     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
2935     todo_wine
2936     {
2937         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
2938     }
2939
2940     RegCloseKey(prodkey);
2941
2942     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
2943     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2944     ok(pf_exists("msitest\\maximus"), "File deleted\n");
2945     ok(pf_exists("msitest"), "File deleted\n");
2946
2947     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2948     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2949
2950     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2951     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2952
2953     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2954     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2955
2956     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2957                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2958     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
2959     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
2960
2961     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2962     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2963
2964     /* complete install */
2965     r = MsiInstallProductA(msifile, "FULL=1");
2966     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2967     ok(pf_exists("msitest\\maximus"), "File not installed\n");
2968     ok(pf_exists("msitest"), "File not installed\n");
2969
2970     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2971     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
2972
2973     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
2974     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2975
2976     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
2977     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2978
2979     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
2980                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
2981     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2982     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
2983
2984     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
2985     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2986
2987     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
2988     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
2989     CHECK_REG_STR(prodkey, "InstallDate", date);
2990     CHECK_REG_STR(prodkey, "InstallSource", temp);
2991     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2992     CHECK_REG_STR(prodkey, "Publisher", "Wine");
2993     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2994     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
2995     CHECK_REG_STR(prodkey, "Comments", NULL);
2996     CHECK_REG_STR(prodkey, "Contact", NULL);
2997     CHECK_REG_STR(prodkey, "HelpLink", NULL);
2998     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
2999     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3000     CHECK_REG_STR(prodkey, "Readme", NULL);
3001     CHECK_REG_STR(prodkey, "Size", NULL);
3002     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3003     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3004     CHECK_REG_DWORD(prodkey, "Language", 1033);
3005     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3006     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3007     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3008     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3009     todo_wine
3010     {
3011         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3012     }
3013
3014     RegCloseKey(prodkey);
3015
3016     /* no UnpublishFeatures */
3017     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3018     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3019     todo_wine
3020     {
3021         ok(!pf_exists("msitest\\maximus"), "File deleted\n");
3022         ok(!pf_exists("msitest"), "File deleted\n");
3023     }
3024
3025     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3026     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3027
3028     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3029     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3030
3031     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3032     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3033
3034     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3035                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3036     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3037     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3038
3039     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3040     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3041
3042     /* complete install */
3043     r = MsiInstallProductA(msifile, "FULL=1");
3044     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3045     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3046     ok(pf_exists("msitest"), "File not installed\n");
3047
3048     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3049     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3050
3051     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3052     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3053
3054     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3055     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3056
3057     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3058                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3059     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3060     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3061
3062     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3063     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3064
3065     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3066     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3067     CHECK_REG_STR(prodkey, "InstallDate", date);
3068     CHECK_REG_STR(prodkey, "InstallSource", temp);
3069     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3070     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3071     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3072     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3073     CHECK_REG_STR(prodkey, "Comments", NULL);
3074     CHECK_REG_STR(prodkey, "Contact", NULL);
3075     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3076     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3077     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3078     CHECK_REG_STR(prodkey, "Readme", NULL);
3079     CHECK_REG_STR(prodkey, "Size", NULL);
3080     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3081     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3082     CHECK_REG_DWORD(prodkey, "Language", 1033);
3083     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3084     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3085     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3086     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3087     todo_wine
3088     {
3089         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3090     }
3091
3092     RegCloseKey(prodkey);
3093
3094     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3095     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3096     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3097     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3098     ok(pf_exists("msitest"), "File deleted\n");
3099
3100     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3101     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3102
3103     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3104     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3105
3106     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3107     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3108
3109     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3110                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3111     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3112     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3113
3114     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3115     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3116
3117     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3118     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3119     CHECK_REG_STR(prodkey, "InstallDate", date);
3120     CHECK_REG_STR(prodkey, "InstallSource", temp);
3121     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3122     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3123     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3124     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3125     CHECK_REG_STR(prodkey, "Comments", NULL);
3126     CHECK_REG_STR(prodkey, "Contact", NULL);
3127     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3128     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3129     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3130     CHECK_REG_STR(prodkey, "Readme", NULL);
3131     CHECK_REG_STR(prodkey, "Size", NULL);
3132     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3133     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3134     CHECK_REG_DWORD(prodkey, "Language", 1033);
3135     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3136     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3137     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3138     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3139     todo_wine
3140     {
3141         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3142     }
3143
3144     RegCloseKey(prodkey);
3145
3146     /* complete install */
3147     r = MsiInstallProductA(msifile, "FULL=1");
3148     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3149     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3150     ok(pf_exists("msitest"), "File not installed\n");
3151
3152     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3153     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3154
3155     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3156     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3157
3158     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3159     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3160
3161     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3162                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3163     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3164     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3165
3166     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3167     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3168
3169     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3170     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3171     CHECK_REG_STR(prodkey, "InstallDate", date);
3172     CHECK_REG_STR(prodkey, "InstallSource", temp);
3173     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3174     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3175     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3176     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3177     CHECK_REG_STR(prodkey, "Comments", NULL);
3178     CHECK_REG_STR(prodkey, "Contact", NULL);
3179     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3180     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3181     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3182     CHECK_REG_STR(prodkey, "Readme", NULL);
3183     CHECK_REG_STR(prodkey, "Size", NULL);
3184     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3185     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3186     CHECK_REG_DWORD(prodkey, "Language", 1033);
3187     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3188     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3189     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3190     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3191     todo_wine
3192     {
3193         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3194     }
3195
3196     RegCloseKey(prodkey);
3197
3198     /* UnpublishFeatures, both features removed */
3199     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3201     todo_wine
3202     {
3203         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3204         ok(!pf_exists("msitest"), "File not deleted\n");
3205     }
3206
3207     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3208     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3209
3210     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3211     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3212
3213     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3214     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3215
3216     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3217                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3218     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3219     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3220
3221     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3222     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3223
3224     /* complete install */
3225     r = MsiInstallProductA(msifile, "FULL=1");
3226     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3227     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3228     ok(pf_exists("msitest"), "File not installed\n");
3229
3230     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3231     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3232
3233     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3234     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3235
3236     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3237     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3238
3239     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3240                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3241     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3242     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3243
3244     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3245     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3246
3247     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3248     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3249     CHECK_REG_STR(prodkey, "InstallDate", date);
3250     CHECK_REG_STR(prodkey, "InstallSource", temp);
3251     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3252     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3253     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3254     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3255     CHECK_REG_STR(prodkey, "Comments", NULL);
3256     CHECK_REG_STR(prodkey, "Contact", NULL);
3257     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3258     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3259     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3260     CHECK_REG_STR(prodkey, "Readme", NULL);
3261     CHECK_REG_STR(prodkey, "Size", NULL);
3262     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3263     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3264     CHECK_REG_DWORD(prodkey, "Language", 1033);
3265     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3266     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3267     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3268     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3269     todo_wine
3270     {
3271         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3272     }
3273
3274     RegCloseKey(prodkey);
3275
3276     /* complete uninstall */
3277     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3278     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3279     todo_wine
3280     {
3281         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3282         ok(!pf_exists("msitest"), "File not deleted\n");
3283     }
3284
3285     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3286     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3287
3288     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3289     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3290
3291     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3292     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3293
3294     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3295                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3296     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3297     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3298
3299     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3300     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3301
3302     /* make sure 'Program Files\msitest' is removed */
3303     delete_pfmsitest_files();
3304
3305     RegCloseKey(uninstall);
3306     DeleteFile(msifile);
3307     DeleteFile("msitest\\maximus");
3308     RemoveDirectory("msitest");
3309 }
3310
3311 static void test_publishsourcelist(void)
3312 {
3313     UINT r;
3314     DWORD size;
3315     CHAR value[MAX_PATH];
3316     CHAR path[MAX_PATH];
3317     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3318
3319     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3320     {
3321         skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3322         return;
3323     }
3324
3325     CreateDirectoryA("msitest", NULL);
3326     create_file("msitest\\maximus", 500);
3327
3328     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3329
3330     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3331
3332     r = MsiInstallProductA(msifile, NULL);
3333     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3334     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3335     ok(pf_exists("msitest"), "File not installed\n");
3336
3337     /* nothing published */
3338     size = 0xdeadbeef;
3339     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3340                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3341     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3342     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3343
3344     size = 0xdeadbeef;
3345     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3346                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3347     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3348     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3349
3350     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3351     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3352     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3353     ok(pf_exists("msitest"), "File not installed\n");
3354
3355     /* after RegisterProduct */
3356     size = 0xdeadbeef;
3357     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3358                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3359     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3360     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3361
3362     size = 0xdeadbeef;
3363     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3364                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3365     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3366     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3367
3368     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3369     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3370     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3371     ok(pf_exists("msitest"), "File not installed\n");
3372
3373     /* after ProcessComponents */
3374     size = 0xdeadbeef;
3375     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3376                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3377     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3378     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3379
3380     size = 0xdeadbeef;
3381     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3382                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3383     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3384     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3385
3386     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3387     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3388     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3389     ok(pf_exists("msitest"), "File not installed\n");
3390
3391     /* after PublishFeatures */
3392     size = 0xdeadbeef;
3393     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3394                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3395     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3396     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3397
3398     size = 0xdeadbeef;
3399     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3400                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3401     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3402     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3403
3404     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3405     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3406     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3407     ok(pf_exists("msitest"), "File not installed\n");
3408
3409     /* after PublishProduct */
3410     size = MAX_PATH;
3411     lstrcpyA(value, "aaa");
3412     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3413                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3414     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3415     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3416     ok(size == 11, "Expected 11, got %d\n", size);
3417
3418     size = MAX_PATH;
3419     lstrcpyA(value, "aaa");
3420     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3421                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3422     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3423     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3424     ok(size == 0, "Expected 0, got %d\n", size);
3425
3426     size = MAX_PATH;
3427     lstrcpyA(value, "aaa");
3428     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3429                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3430     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3431     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3432     ok(size == 0, "Expected 0, got %d\n", size);
3433
3434     lstrcpyA(path, CURR_DIR);
3435     lstrcatA(path, "\\");
3436
3437     size = MAX_PATH;
3438     lstrcpyA(value, "aaa");
3439     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3440                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3441     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3442     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3443     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3444
3445     size = MAX_PATH;
3446     lstrcpyA(value, "aaa");
3447     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3448                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3449     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3450     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3451     ok(size == 1, "Expected 1, got %d\n", size);
3452
3453     size = MAX_PATH;
3454     lstrcpyA(value, "aaa");
3455     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3456                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3457     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3458     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3459     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3460
3461     size = MAX_PATH;
3462     lstrcpyA(value, "aaa");
3463     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3464                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3465     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3466     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3467     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3468
3469     size = MAX_PATH;
3470     lstrcpyA(value, "aaa");
3471     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3472                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3473     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3474     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3475     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3476
3477     /* complete uninstall */
3478     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3479     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3480     todo_wine
3481     {
3482         ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3483         ok(!pf_exists("msitest"), "File not deleted\n");
3484     }
3485
3486     /* make sure 'Program Files\msitest' is removed */
3487     delete_pfmsitest_files();
3488
3489     DeleteFile(msifile);
3490     DeleteFile("msitest\\maximus");
3491     RemoveDirectory("msitest");
3492 }
3493
3494 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3495 {
3496     MSIHANDLE hview = 0;
3497     UINT r;
3498
3499     r = MsiDatabaseOpenView(hdb, query, &hview);
3500     if(r != ERROR_SUCCESS)
3501         return r;
3502
3503     r = MsiViewExecute(hview, hrec);
3504     if(r == ERROR_SUCCESS)
3505         r = MsiViewClose(hview);
3506     MsiCloseHandle(hview);
3507     return r;
3508 }
3509
3510 static void set_transform_summary_info(void)
3511 {
3512     UINT r;
3513     MSIHANDLE suminfo = 0;
3514
3515     /* build summary info */
3516     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
3517     todo_wine
3518     {
3519         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
3520     }
3521
3522     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
3523     todo_wine
3524     {
3525         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3526     }
3527
3528     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
3529                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3530                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3531                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
3532     todo_wine
3533     {
3534         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
3535     }
3536
3537     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
3538     todo_wine
3539     {
3540         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3541     }
3542
3543     r = MsiSummaryInfoPersist(suminfo);
3544     todo_wine
3545     {
3546         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
3547     }
3548
3549     r = MsiCloseHandle(suminfo);
3550     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
3551 }
3552
3553 static void generate_transform(void)
3554 {
3555     MSIHANDLE hdb1, hdb2;
3556     LPCSTR query;
3557     UINT r;
3558
3559     /* start with two identical databases */
3560     CopyFile(msifile, msifile2, FALSE);
3561
3562     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
3563     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3564
3565     r = MsiDatabaseCommit(hdb1);
3566     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
3567
3568     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
3569     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3570
3571     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
3572     r = run_query(hdb1, 0, query);
3573     ok(r == ERROR_SUCCESS, "failed to add property\n");
3574
3575     /* database needs to be committed */
3576     MsiDatabaseCommit(hdb1);
3577
3578     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
3579     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
3580
3581 #if 0  /* not implemented in wine yet */
3582     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
3583     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3584 #endif
3585
3586     MsiCloseHandle(hdb1);
3587     MsiCloseHandle(hdb2);
3588 }
3589
3590 /* data for generating a transform */
3591
3592 /* tables transform names - encoded as they would be in an msi database file */
3593 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
3594 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
3595 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
3596
3597 /* data in each table */
3598 static const char data1[] = /* _StringData */
3599     "propval";  /* all the strings squashed together */
3600
3601 static const WCHAR data2[] = { /* _StringPool */
3602 /*  len, refs */
3603     0,   0,    /* string 0 ''     */
3604     4,   1,    /* string 1 'prop' */
3605     3,   1,    /* string 2 'val'  */
3606 };
3607
3608 static const WCHAR data3[] = { /* Property */
3609     0x0201, 0x0001, 0x0002,
3610 };
3611
3612 static const struct {
3613     LPCWSTR name;
3614     const void *data;
3615     DWORD size;
3616 } table_transform_data[] =
3617 {
3618     { name1, data1, sizeof data1 - 1 },
3619     { name2, data2, sizeof data2 },
3620     { name3, data3, sizeof data3 },
3621 };
3622
3623 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
3624
3625 static void generate_transform_manual(void)
3626 {
3627     IStorage *stg = NULL;
3628     IStream *stm;
3629     WCHAR name[0x20];
3630     HRESULT r;
3631     DWORD i, count;
3632     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
3633
3634     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
3635
3636     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
3637
3638     r = StgCreateDocfile(name, mode, 0, &stg);
3639     ok(r == S_OK, "failed to create storage\n");
3640     if (!stg)
3641         return;
3642
3643     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
3644     ok(r == S_OK, "failed to set storage type\n");
3645
3646     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
3647     {
3648         r = IStorage_CreateStream(stg, table_transform_data[i].name,
3649                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3650         if (FAILED(r))
3651         {
3652             ok(0, "failed to create stream %08x\n", r);
3653             continue;
3654         }
3655
3656         r = IStream_Write(stm, table_transform_data[i].data,
3657                           table_transform_data[i].size, &count);
3658         if (FAILED(r) || count != table_transform_data[i].size)
3659             ok(0, "failed to write stream\n");
3660         IStream_Release(stm);
3661     }
3662
3663     IStorage_Release(stg);
3664
3665     set_transform_summary_info();
3666 }
3667
3668 static void test_transformprop(void)
3669 {
3670     UINT r;
3671
3672     CreateDirectoryA("msitest", NULL);
3673     create_file("msitest\\augustus", 500);
3674
3675     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
3676
3677     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3678
3679     r = MsiInstallProductA(msifile, NULL);
3680     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3681     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3682     ok(!delete_pf("msitest", FALSE), "File installed\n");
3683
3684     if (0)
3685         generate_transform();
3686     else
3687         generate_transform_manual();
3688
3689     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
3690     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3691     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3692     ok(delete_pf("msitest", FALSE), "File not installed\n");
3693
3694     /* Delete the files in the temp (current) folder */
3695     DeleteFile(msifile);
3696     DeleteFile(msifile2);
3697     DeleteFile(mstfile);
3698     DeleteFile("msitest\\augustus");
3699     RemoveDirectory("msitest");
3700 }
3701
3702 static void test_currentworkingdir(void)
3703 {
3704     UINT r;
3705     CHAR path[MAX_PATH];
3706     LPSTR ptr, ptr2;
3707
3708     CreateDirectoryA("msitest", NULL);
3709     create_file("msitest\\augustus", 500);
3710
3711     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
3712
3713     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3714
3715     CreateDirectoryA("diffdir", NULL);
3716     SetCurrentDirectoryA("diffdir");
3717
3718     sprintf(path, "..\\%s", msifile);
3719     r = MsiInstallProductA(path, NULL);
3720     todo_wine
3721     {
3722         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
3723         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3724         ok(!delete_pf("msitest", FALSE), "File installed\n");
3725     }
3726
3727     sprintf(path, "%s\\%s", CURR_DIR, msifile);
3728     r = MsiInstallProductA(path, NULL);
3729     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3730     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3731     ok(delete_pf("msitest", FALSE), "File not installed\n");
3732
3733     lstrcpyA(path, CURR_DIR);
3734     if (path[lstrlenA(path) - 1] != '\\')
3735         lstrcatA(path, "\\");
3736     lstrcatA(path, "msitest.msi");
3737
3738     ptr2 = strrchr(path, '\\');
3739     *ptr2 = '\0';
3740     ptr = strrchr(path, '\\');
3741     *ptr2 = '\\';
3742     *(ptr++) = '\0';
3743
3744     SetCurrentDirectoryA(path);
3745
3746     r = MsiInstallProductA(ptr, NULL);
3747     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3748     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
3749     ok(delete_pf("msitest", FALSE), "File not installed\n");
3750
3751     SetCurrentDirectoryA(CURR_DIR);
3752
3753     DeleteFile(msifile);
3754     DeleteFile("msitest\\augustus");
3755     RemoveDirectory("msitest");
3756     RemoveDirectory("diffdir");
3757 }
3758
3759 static void set_admin_summary_info(const CHAR *name)
3760 {
3761     MSIHANDLE db, summary;
3762     UINT r;
3763
3764     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
3765     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3766
3767     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
3768     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3769
3770     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
3771     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3772
3773     /* write the summary changes back to the stream */
3774     r = MsiSummaryInfoPersist(summary);
3775     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3776
3777     MsiCloseHandle(summary);
3778
3779     r = MsiDatabaseCommit(db);
3780     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3781
3782     MsiCloseHandle(db);
3783 }
3784
3785 static void test_admin(void)
3786 {
3787     UINT r;
3788
3789     CreateDirectoryA("msitest", NULL);
3790     create_file("msitest\\augustus", 500);
3791
3792     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
3793     set_admin_summary_info(msifile);
3794
3795     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3796
3797     r = MsiInstallProductA(msifile, NULL);
3798     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3799     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3800     ok(!delete_pf("msitest", FALSE), "File installed\n");
3801     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
3802     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
3803
3804     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
3805     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3806     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
3807     ok(!delete_pf("msitest", FALSE), "File installed\n");
3808     todo_wine
3809     {
3810         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
3811         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
3812     }
3813
3814     DeleteFile(msifile);
3815     DeleteFile("msitest\\augustus");
3816     RemoveDirectory("msitest");
3817 }
3818
3819 static void set_admin_property_stream(LPCSTR file)
3820 {
3821     IStorage *stg;
3822     IStream *stm;
3823     WCHAR fileW[MAX_PATH];
3824     HRESULT hr;
3825     DWORD count;
3826     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
3827
3828     /* AdminProperties */
3829     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
3830     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',0};
3831
3832     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
3833
3834     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
3835     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3836     if (!stg)
3837         return;
3838
3839     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
3840     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3841
3842     hr = IStream_Write(stm, data, sizeof(data), &count);
3843     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
3844
3845     IStream_Release(stm);
3846     IStorage_Release(stg);
3847 }
3848
3849 static void test_adminprops(void)
3850 {
3851     UINT r;
3852
3853     CreateDirectoryA("msitest", NULL);
3854     create_file("msitest\\augustus", 500);
3855
3856     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
3857     set_admin_summary_info(msifile);
3858     set_admin_property_stream(msifile);
3859
3860     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
3861
3862     r = MsiInstallProductA(msifile, NULL);
3863     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3864     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
3865     ok(delete_pf("msitest", FALSE), "File installed\n");
3866
3867     DeleteFile(msifile);
3868     DeleteFile("msitest\\augustus");
3869     RemoveDirectory("msitest");
3870 }
3871
3872 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
3873 {
3874     CHAR path[MAX_PATH];
3875
3876     lstrcpyA(path, PROG_FILES_DIR);
3877     lstrcatA(path, "\\");
3878     lstrcatA(path, file);
3879
3880     if (is_file)
3881         create_file_data(path, data, 500);
3882     else
3883         CreateDirectoryA(path, NULL);
3884 }
3885
3886 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
3887
3888 static void test_removefiles(void)
3889 {
3890     UINT r;
3891
3892     CreateDirectoryA("msitest", NULL);
3893     create_file("msitest\\hydrogen", 500);
3894     create_file("msitest\\helium", 500);
3895     create_file("msitest\\lithium", 500);
3896
3897     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
3898
3899     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3900
3901     r = MsiInstallProductA(msifile, NULL);
3902     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3903     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3904     ok(!pf_exists("msitest\\helium"), "File installed\n");
3905     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3906     ok(pf_exists("msitest"), "File not installed\n");
3907
3908     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3909     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3910     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
3911     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3912     todo_wine
3913     {
3914         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3915         ok(delete_pf("msitest", FALSE), "File deleted\n");
3916     }
3917
3918     create_pf("msitest", FALSE);
3919     create_pf("msitest\\hydrogen", TRUE);
3920     create_pf("msitest\\helium", TRUE);
3921     create_pf("msitest\\lithium", TRUE);
3922
3923     r = MsiInstallProductA(msifile, NULL);
3924     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3925     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3926     ok(pf_exists("msitest\\helium"), "File not installed\n");
3927     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3928     ok(pf_exists("msitest"), "File not installed\n");
3929
3930     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3931     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3932     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
3933     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3934     todo_wine
3935     {
3936         ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
3937         ok(delete_pf("msitest", FALSE), "File deleted\n");
3938     }
3939
3940     create_pf("msitest", FALSE);
3941     create_pf("msitest\\furlong", TRUE);
3942     create_pf("msitest\\firkin", TRUE);
3943     create_pf("msitest\\fortnight", TRUE);
3944     create_pf("msitest\\becquerel", TRUE);
3945     create_pf("msitest\\dioptre", TRUE);
3946     create_pf("msitest\\attoparsec", TRUE);
3947     create_pf("msitest\\storeys", TRUE);
3948     create_pf("msitest\\block", TRUE);
3949     create_pf("msitest\\siriometer", TRUE);
3950
3951     r = MsiInstallProductA(msifile, NULL);
3952     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3953     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
3954     ok(!pf_exists("msitest\\helium"), "File installed\n");
3955     ok(pf_exists("msitest\\lithium"), "File not installed\n");
3956     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
3957     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
3958     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
3959     ok(pf_exists("msitest"), "File not installed\n");
3960     todo_wine
3961     {
3962         ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
3963         ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
3964         ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
3965         ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
3966         ok(!pf_exists("msitest\\block"), "File not deleted\n");
3967         ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
3968     }
3969
3970     create_pf("msitest\\furlong", TRUE);
3971     create_pf("msitest\\firkin", TRUE);
3972     create_pf("msitest\\fortnight", TRUE);
3973     create_pf("msitest\\storeys", TRUE);
3974     create_pf("msitest\\block", TRUE);
3975     create_pf("msitest\\siriometer", TRUE);
3976
3977     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3978     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3979     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
3980     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
3981     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
3982     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
3983     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
3984     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
3985     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
3986     todo_wine
3987     {
3988         ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
3989         ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
3990         ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
3991         ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
3992         ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
3993     }
3994     ok(delete_pf("msitest", FALSE), "File deleted\n");
3995
3996     DeleteFile(msifile);
3997     DeleteFile("msitest\\hydrogen");
3998     DeleteFile("msitest\\helium");
3999     DeleteFile("msitest\\lithium");
4000     RemoveDirectory("msitest");
4001 }
4002
4003 static void test_movefiles(void)
4004 {
4005     UINT r;
4006     char props[MAX_PATH];
4007
4008     CreateDirectoryA("msitest", NULL);
4009     create_file("msitest\\augustus", 100);
4010     create_file("cameroon", 100);
4011     create_file("djibouti", 100);
4012     create_file("egypt", 100);
4013     create_file("finland", 100);
4014     create_file("gambai", 100);
4015     create_file("honduras", 100);
4016     create_file("msitest\\india", 100);
4017     create_file("japan", 100);
4018     create_file("kenya", 100);
4019     CreateDirectoryA("latvia", NULL);
4020     create_file("nauru", 100);
4021     create_file("apple", 100);
4022     create_file("application", 100);
4023     create_file("ape", 100);
4024     create_file("foo", 100);
4025     create_file("fao", 100);
4026     create_file("fbod", 100);
4027     create_file("budding", 100);
4028     create_file("buddy", 100);
4029     create_file("bud", 100);
4030     create_file("bar", 100);
4031     create_file("bur", 100);
4032     create_file("bird", 100);
4033
4034     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
4035
4036     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4037     MsiEnableLog(INSTALLLOGMODE_VERBOSE | INSTALLLOGMODE_EXTRADEBUG, "log.txt", 0);
4038
4039     /* if the source or dest property is not a full path,
4040      * windows tries to access it as a network resource
4041      */
4042
4043     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4044             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4045             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4046
4047     r = MsiInstallProductA(msifile, props);
4048     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4049     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4050     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4051     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4052     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4053     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4054     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4055     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4056     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4057     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4058     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4059     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4060     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4061     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4062     /* either apple or application will be moved depending on directory order */
4063     if (!delete_pf("msitest\\apple", TRUE))
4064         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4065     else
4066         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4067     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4068     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4069     /* either fao or foo will be moved depending on directory order */
4070     if (delete_pf("msitest\\foo", TRUE))
4071         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4072     else
4073         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4074     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4075     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4076     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4077     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4078     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4079     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4080     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4081     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4082     ok(delete_pf("msitest", FALSE), "File not installed\n");
4083     ok(DeleteFileA("cameroon"), "File moved\n");
4084     ok(!DeleteFileA("djibouti"), "File not moved\n");
4085     ok(DeleteFileA("egypt"), "File moved\n");
4086     ok(DeleteFileA("finland"), "File moved\n");
4087     ok(DeleteFileA("gambai"), "File moved\n");
4088     ok(!DeleteFileA("honduras"), "File not moved\n");
4089     ok(DeleteFileA("msitest\\india"), "File moved\n");
4090     ok(DeleteFileA("japan"), "File moved\n");
4091     ok(!DeleteFileA("kenya"), "File not moved\n");
4092     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4093     ok(!DeleteFileA("nauru"), "File not moved\n");
4094     ok(!DeleteFileA("apple"), "File not moved\n");
4095     ok(!DeleteFileA("application"), "File not moved\n");
4096     ok(DeleteFileA("ape"), "File moved\n");
4097     ok(!DeleteFileA("foo"), "File not moved\n");
4098     ok(!DeleteFileA("fao"), "File not moved\n");
4099     ok(DeleteFileA("fbod"), "File moved\n");
4100     ok(!DeleteFileA("budding"), "File not moved\n");
4101     ok(!DeleteFileA("buddy"), "File not moved\n");
4102     ok(DeleteFileA("bud"), "File moved\n");
4103     ok(!DeleteFileA("bar"), "File not moved\n");
4104     ok(!DeleteFileA("bur"), "File not moved\n");
4105     ok(DeleteFileA("bird"), "File moved\n");
4106
4107     DeleteFile("msitest\\augustus");
4108     RemoveDirectory("msitest");
4109     DeleteFile(msifile);
4110 }
4111
4112 static void test_missingcab(void)
4113 {
4114     UINT r;
4115
4116     CreateDirectoryA("msitest", NULL);
4117     create_file("msitest\\augustus", 500);
4118     create_file("maximus", 500);
4119
4120     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4121
4122     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4123
4124     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4125
4126     create_pf("msitest", FALSE);
4127     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4128
4129     r = MsiInstallProductA(msifile, NULL);
4130     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4131     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4132     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4133     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4134     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4135     ok(delete_pf("msitest", FALSE), "File not installed\n");
4136
4137     create_pf("msitest", FALSE);
4138     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4139     create_pf("msitest\\gaius", TRUE);
4140
4141     r = MsiInstallProductA(msifile, "GAIUS=1");
4142     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4143     todo_wine
4144     {
4145         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4146         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4147     }
4148     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4149     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4150     ok(delete_pf("msitest", FALSE), "File not installed\n");
4151
4152     DeleteFile("msitest\\augustus");
4153     RemoveDirectory("msitest");
4154     DeleteFile("maximus");
4155     DeleteFile("test1.cab");
4156     DeleteFile(msifile);
4157 }
4158
4159 static void test_duplicatefiles(void)
4160 {
4161     UINT r;
4162
4163     CreateDirectoryA("msitest", NULL);
4164     create_file("msitest\\maximus", 500);
4165     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4166
4167     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4168
4169     /* fails if the destination folder is not a valid property */
4170
4171     r = MsiInstallProductA(msifile, NULL);
4172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4173     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4174     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4175     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4176     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4177     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4178     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4179     ok(delete_pf("msitest", FALSE), "File not installed\n");
4180
4181     DeleteFile("msitest\\maximus");
4182     RemoveDirectory("msitest");
4183     DeleteFile(msifile);
4184 }
4185
4186 static void test_writeregistryvalues(void)
4187 {
4188     UINT r;
4189     LONG res;
4190     HKEY hkey;
4191     DWORD type, size;
4192     CHAR path[MAX_PATH];
4193
4194     CreateDirectoryA("msitest", NULL);
4195     create_file("msitest\\augustus", 500);
4196
4197     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4198
4199     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4200
4201     r = MsiInstallProductA(msifile, NULL);
4202     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4203     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4204     ok(delete_pf("msitest", FALSE), "File installed\n");
4205
4206     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4207     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4208
4209     size = MAX_PATH;
4210     type = REG_MULTI_SZ;
4211     memset(path, 'a', MAX_PATH);
4212     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4213     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4214     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4215     ok(size == 15, "Expected 15, got %d\n", size);
4216     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4217
4218     DeleteFile(msifile);
4219     DeleteFile("msitest\\augustus");
4220     RemoveDirectory("msitest");
4221 }
4222
4223 static void test_sourcefolder(void)
4224 {
4225     UINT r;
4226
4227     CreateDirectoryA("msitest", NULL);
4228     create_file("augustus", 500);
4229
4230     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4231
4232     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4233
4234     r = MsiInstallProductA(msifile, NULL);
4235     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4236     todo_wine
4237     {
4238         ok(r == ERROR_INSTALL_FAILURE,
4239            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4240         ok(!delete_pf("msitest", FALSE), "File installed\n");
4241     }
4242
4243     RemoveDirectoryA("msitest");
4244
4245     r = MsiInstallProductA(msifile, NULL);
4246     todo_wine
4247     {
4248         ok(r == ERROR_INSTALL_FAILURE,
4249            "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4250         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4251         ok(!delete_pf("msitest", FALSE), "File installed\n");
4252     }
4253
4254     DeleteFile(msifile);
4255     DeleteFile("augustus");
4256 }
4257
4258 static void test_customaction51(void)
4259 {
4260     UINT r;
4261
4262     CreateDirectoryA("msitest", NULL);
4263     create_file("msitest\\augustus", 500);
4264
4265     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
4266
4267     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4268
4269     r = MsiInstallProductA(msifile, NULL);
4270     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4271     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4272     ok(delete_pf("msitest", FALSE), "File installed\n");
4273
4274     DeleteFile(msifile);
4275     DeleteFile("msitest\\augustus");
4276     RemoveDirectory("msitest");
4277 }
4278
4279 START_TEST(install)
4280 {
4281     DWORD len;
4282     char temp_path[MAX_PATH], prev_path[MAX_PATH];
4283
4284     init_functionpointers();
4285
4286     GetCurrentDirectoryA(MAX_PATH, prev_path);
4287     GetTempPath(MAX_PATH, temp_path);
4288     SetCurrentDirectoryA(temp_path);
4289
4290     lstrcpyA(CURR_DIR, temp_path);
4291     len = lstrlenA(CURR_DIR);
4292
4293     if(len && (CURR_DIR[len - 1] == '\\'))
4294         CURR_DIR[len - 1] = 0;
4295
4296     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
4297
4298     test_MsiInstallProduct();
4299     test_MsiSetComponentState();
4300     test_packagecoltypes();
4301     test_continuouscabs();
4302     test_caborder();
4303     test_mixedmedia();
4304     test_samesequence();
4305     test_uiLevelFlags();
4306     test_readonlyfile();
4307     test_setdirproperty();
4308     test_cabisextracted();
4309     test_concurrentinstall();
4310     test_setpropertyfolder();
4311     test_publish_registerproduct();
4312     test_publish_publishproduct();
4313     test_publish_publishfeatures();
4314     test_publish_registeruser();
4315     test_publish_processcomponents();
4316     test_publish();
4317     test_publishsourcelist();
4318     test_transformprop();
4319     test_currentworkingdir();
4320     test_admin();
4321     test_adminprops();
4322     test_removefiles();
4323     test_movefiles();
4324     test_missingcab();
4325     test_duplicatefiles();
4326     test_writeregistryvalues();
4327     test_sourcefolder();
4328     test_customaction51();
4329
4330     SetCurrentDirectoryA(prev_path);
4331 }