comctl32/tests: Destroy the window after the tests.
[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 #include <srrestoreptapi.h>
33
34 #include "wine/test.h"
35
36 static UINT (WINAPI *pMsiQueryComponentStateA)
37     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, LPCSTR, INSTALLSTATE*);
38 static UINT (WINAPI *pMsiSourceListEnumSourcesA)
39     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, DWORD, LPSTR, LPDWORD);
40 static UINT (WINAPI *pMsiSourceListGetInfoA)
41     (LPCSTR, LPCSTR, MSIINSTALLCONTEXT, DWORD, LPCSTR, LPSTR, LPDWORD);
42
43 static HMODULE hsrclient = 0;
44 static BOOL (WINAPI *pSRRemoveRestorePoint)(DWORD);
45 static BOOL (WINAPI *pSRSetRestorePointA)(RESTOREPOINTINFOA*, STATEMGRSTATUS*);
46
47 static BOOL on_win9x = FALSE;
48
49 static const char *msifile = "msitest.msi";
50 static const char *msifile2 = "winetest2.msi";
51 static const char *mstfile = "winetest.mst";
52 static CHAR CURR_DIR[MAX_PATH];
53 static CHAR PROG_FILES_DIR[MAX_PATH];
54 static CHAR COMMON_FILES_DIR[MAX_PATH];
55
56 /* msi database data */
57
58 static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
59                                     "s72\tS38\ts72\ti2\tS255\tS72\n"
60                                     "Component\tComponent\n"
61                                     "Five\t{8CC92E9D-14B2-4CA4-B2AA-B11D02078087}\tNEWDIR\t2\t\tfive.txt\n"
62                                     "Four\t{FD37B4EA-7209-45C0-8917-535F35A2F080}\tCABOUTDIR\t2\t\tfour.txt\n"
63                                     "One\t{783B242E-E185-4A56-AF86-C09815EC053C}\tMSITESTDIR\t2\t\tone.txt\n"
64                                     "Three\t{010B6ADD-B27D-4EDD-9B3D-34C4F7D61684}\tCHANGEDDIR\t2\t\tthree.txt\n"
65                                     "Two\t{BF03D1A6-20DA-4A65-82F3-6CAC995915CE}\tFIRSTDIR\t2\t\ttwo.txt\n"
66                                     "dangler\t{6091DF25-EF96-45F1-B8E9-A9B1420C7A3C}\tTARGETDIR\t4\t\tregdata\n"
67                                     "component\t\tMSITESTDIR\t0\t1\tfile\n"
68                                     "service_comp\t\tMSITESTDIR\t0\t1\tservice_file";
69
70 static const CHAR directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
71                                     "s72\tS72\tl255\n"
72                                     "Directory\tDirectory\n"
73                                     "CABOUTDIR\tMSITESTDIR\tcabout\n"
74                                     "CHANGEDDIR\tMSITESTDIR\tchanged:second\n"
75                                     "FIRSTDIR\tMSITESTDIR\tfirst\n"
76                                     "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
77                                     "NEWDIR\tCABOUTDIR\tnew\n"
78                                     "ProgramFilesFolder\tTARGETDIR\t.\n"
79                                     "TARGETDIR\t\tSourceDir";
80
81 static const CHAR feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
82                                   "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
83                                   "Feature\tFeature\n"
84                                   "Five\t\tFive\tThe Five Feature\t5\t3\tNEWDIR\t0\n"
85                                   "Four\t\tFour\tThe Four Feature\t4\t3\tCABOUTDIR\t0\n"
86                                   "One\t\tOne\tThe One Feature\t1\t3\tMSITESTDIR\t0\n"
87                                   "Three\t\tThree\tThe Three Feature\t3\t3\tCHANGEDDIR\t0\n"
88                                   "Two\t\tTwo\tThe Two Feature\t2\t3\tFIRSTDIR\t0\n"
89                                   "feature\t\t\t\t2\t1\tTARGETDIR\t0\n"
90                                   "service_feature\t\t\t\t2\t1\tTARGETDIR\t0";
91
92 static const CHAR feature_comp_dat[] = "Feature_\tComponent_\n"
93                                        "s38\ts72\n"
94                                        "FeatureComponents\tFeature_\tComponent_\n"
95                                        "Five\tFive\n"
96                                        "Four\tFour\n"
97                                        "One\tOne\n"
98                                        "Three\tThree\n"
99                                        "Two\tTwo\n"
100                                        "feature\tcomponent\n"
101                                        "service_feature\tservice_comp\n";
102
103 static const CHAR file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
104                                "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
105                                "File\tFile\n"
106                                "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
107                                "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
108                                "one.txt\tOne\tone.txt\t1000\t\t\t0\t1\n"
109                                "three.txt\tThree\tthree.txt\t1000\t\t\t0\t3\n"
110                                "two.txt\tTwo\ttwo.txt\t1000\t\t\t0\t2\n"
111                                "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
112                                "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
113
114 static const CHAR install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
115                                            "s72\tS255\tI2\n"
116                                            "InstallExecuteSequence\tAction\n"
117                                            "AllocateRegistrySpace\tNOT Installed\t1550\n"
118                                            "CostFinalize\t\t1000\n"
119                                            "CostInitialize\t\t800\n"
120                                            "FileCost\t\t900\n"
121                                            "ResolveSource\t\t950\n"
122                                            "MoveFiles\t\t1700\n"
123                                            "InstallFiles\t\t4000\n"
124                                            "DuplicateFiles\t\t4500\n"
125                                            "InstallServices\t\t5000\n"
126                                            "InstallFinalize\t\t6600\n"
127                                            "InstallInitialize\t\t1500\n"
128                                            "InstallValidate\t\t1400\n"
129                                            "LaunchConditions\t\t100\n"
130                                            "WriteRegistryValues\tSourceDir And SOURCEDIR\t5000";
131
132 static const CHAR media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
133                                 "i2\ti4\tL64\tS255\tS32\tS72\n"
134                                 "Media\tDiskId\n"
135                                 "1\t3\t\t\tDISK1\t\n"
136                                 "2\t5\t\tmsitest.cab\tDISK2\t\n";
137
138 static const CHAR property_dat[] = "Property\tValue\n"
139                                    "s72\tl0\n"
140                                    "Property\tProperty\n"
141                                    "DefaultUIFont\tDlgFont8\n"
142                                    "HASUIRUN\t0\n"
143                                    "INSTALLLEVEL\t3\n"
144                                    "InstallMode\tTypical\n"
145                                    "Manufacturer\tWine\n"
146                                    "PIDTemplate\t12345<###-%%%%%%%>@@@@@\n"
147                                    "ProductCode\t{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}\n"
148                                    "ProductID\tnone\n"
149                                    "ProductLanguage\t1033\n"
150                                    "ProductName\tMSITEST\n"
151                                    "ProductVersion\t1.1.1\n"
152                                    "PROMPTROLLBACKCOST\tP\n"
153                                    "Setup\tSetup\n"
154                                    "UpgradeCode\t{4C0EAA15-0264-4E5A-8758-609EF142B92D}\n"
155                                    "AdminProperties\tPOSTADMIN\n"
156                                    "ROOTDRIVE\tC:\\\n"
157                                    "SERVNAME\tTestService\n"
158                                    "SERVDISP\tTestServiceDisp\n";
159
160 static const CHAR registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
161                                    "s72\ti2\tl255\tL255\tL0\ts72\n"
162                                    "Registry\tRegistry\n"
163                                    "Apples\t2\tSOFTWARE\\Wine\\msitest\tName\timaname\tOne\n"
164                                    "Oranges\t2\tSOFTWARE\\Wine\\msitest\tnumber\t#314\tTwo\n"
165                                    "regdata\t2\tSOFTWARE\\Wine\\msitest\tblah\tbad\tdangler\n"
166                                    "OrderTest\t2\tSOFTWARE\\Wine\\msitest\tOrderTestName\tOrderTestValue\tcomponent";
167
168 static const CHAR service_install_dat[] = "ServiceInstall\tName\tDisplayName\tServiceType\tStartType\tErrorControl\t"
169                                           "LoadOrderGroup\tDependencies\tStartName\tPassword\tArguments\tComponent_\tDescription\n"
170                                           "s72\ts255\tL255\ti4\ti4\ti4\tS255\tS255\tS255\tS255\tS255\ts72\tL255\n"
171                                           "ServiceInstall\tServiceInstall\n"
172                                           "TestService\t[SERVNAME]\t[SERVDISP]\t2\t3\t0\t\t\tTestService\t\t\tservice_comp\t\t";
173
174 static const CHAR service_control_dat[] = "ServiceControl\tName\tEvent\tArguments\tWait\tComponent_\n"
175                                           "s72\tl255\ti2\tL255\tI2\ts72\n"
176                                           "ServiceControl\tServiceControl\n"
177                                           "ServiceControl\tTestService\t8\t\t0\tservice_comp";
178
179 /* tables for test_continuouscabs */
180 static const CHAR cc_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\t1\taugustus\n"
185                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
186
187 static const CHAR cc2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
188                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
189                                         "Component\tComponent\n"
190                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
191                                         "augustus\t\tMSITESTDIR\t0\t0\taugustus\n"
192                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
193
194 static const CHAR cc_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
195                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
196                                      "Feature\tFeature\n"
197                                      "feature\t\t\t\t2\t1\tTARGETDIR\t0";
198
199 static const CHAR cc_feature_comp_dat[] = "Feature_\tComponent_\n"
200                                           "s38\ts72\n"
201                                           "FeatureComponents\tFeature_\tComponent_\n"
202                                           "feature\tmaximus\n"
203                                           "feature\taugustus\n"
204                                           "feature\tcaesar";
205
206 static const CHAR cc_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                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
212
213 static const CHAR cc2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
214                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
215                                    "File\tFile\n"
216                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
217                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
218                                    "tiberius\tmaximus\ttiberius\t500\t\t\t16384\t3\n"
219                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12";
220
221 static const CHAR cc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
222                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
223                                    "Media\tDiskId\n"
224                                    "1\t10\t\ttest1.cab\tDISK1\t\n"
225                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
226                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
227
228 static const CHAR co_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
229                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
230                                   "File\tFile\n"
231                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
232                                   "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
233                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
234
235 static const CHAR co_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\t2\t\ttest2.cab\tDISK2\t\n"
240                                    "3\t3\t\ttest3.cab\tDISK3\t\n";
241
242 static const CHAR co2_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
243                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
244                                     "Media\tDiskId\n"
245                                     "1\t10\t\ttest1.cab\tDISK1\t\n"
246                                     "2\t12\t\ttest3.cab\tDISK3\t\n"
247                                     "3\t2\t\ttest2.cab\tDISK2\t\n";
248
249 static const CHAR mm_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
250                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
251                                   "File\tFile\n"
252                                   "maximus\tmaximus\tmaximus\t500\t\t\t512\t1\n"
253                                   "augustus\taugustus\taugustus\t500\t\t\t512\t2\n"
254                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3";
255
256 static const CHAR mm_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
257                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
258                                    "Media\tDiskId\n"
259                                    "1\t3\t\ttest1.cab\tDISK1\t\n";
260
261 static const CHAR ss_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
262                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
263                                    "Media\tDiskId\n"
264                                    "1\t2\t\ttest1.cab\tDISK1\t\n"
265                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
266                                    "3\t12\t\ttest3.cab\tDISK3\t\n";
267
268 /* tables for test_uiLevelFlags */
269 static const CHAR ui_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
270                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
271                                        "Component\tComponent\n"
272                                        "maximus\t\tMSITESTDIR\t0\tHASUIRUN=1\tmaximus\n"
273                                        "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
274                                        "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n";
275
276 static const CHAR ui_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
277                                            "s72\tS255\tI2\n"
278                                            "InstallUISequence\tAction\n"
279                                            "SetUIProperty\t\t5\n"
280                                            "ExecuteAction\t\t1100\n";
281
282 static const CHAR ui_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
283                                            "s72\ti2\tS64\tS0\tS255\n"
284                                            "CustomAction\tAction\n"
285                                            "SetUIProperty\t51\tHASUIRUN\t1\t\n";
286
287 static const CHAR rof_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
288                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
289                                         "Component\tComponent\n"
290                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n";
291
292 static const CHAR rof_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
293                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
294                                       "Feature\tFeature\n"
295                                       "feature\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0\n"
296                                       "montecristo\t\tFeature\tFeature\t2\t1\tTARGETDIR\t0";
297
298 static const CHAR rof_feature_comp_dat[] = "Feature_\tComponent_\n"
299                                            "s38\ts72\n"
300                                            "FeatureComponents\tFeature_\tComponent_\n"
301                                            "feature\tmaximus\n"
302                                            "montecristo\tmaximus";
303
304 static const CHAR rof_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
305                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
306                                    "File\tFile\n"
307                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1";
308
309 static const CHAR rof_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
310                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
311                                     "Media\tDiskId\n"
312                                     "1\t1\t\t\tDISK1\t\n";
313
314 static const CHAR sdp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
315                                                "s72\tS255\tI2\n"
316                                                "InstallExecuteSequence\tAction\n"
317                                                "AllocateRegistrySpace\tNOT Installed\t1550\n"
318                                                "CostFinalize\t\t1000\n"
319                                                "CostInitialize\t\t800\n"
320                                                "FileCost\t\t900\n"
321                                                "InstallFiles\t\t4000\n"
322                                                "InstallFinalize\t\t6600\n"
323                                                "InstallInitialize\t\t1500\n"
324                                                "InstallValidate\t\t1400\n"
325                                                "LaunchConditions\t\t100\n"
326                                                "SetDirProperty\t\t950";
327
328 static const CHAR sdp_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
329                                             "s72\ti2\tS64\tS0\tS255\n"
330                                             "CustomAction\tAction\n"
331                                             "SetDirProperty\t51\tMSITESTDIR\t[CommonFilesFolder]msitest\\\t\n";
332
333 static const CHAR cie_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
334                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
335                                         "Component\tComponent\n"
336                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
337                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
338                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
339                                         "gaius\t\tMSITESTDIR\t0\t1\tgaius\n";
340
341 static const CHAR cie_feature_comp_dat[] = "Feature_\tComponent_\n"
342                                            "s38\ts72\n"
343                                            "FeatureComponents\tFeature_\tComponent_\n"
344                                            "feature\tmaximus\n"
345                                            "feature\taugustus\n"
346                                            "feature\tcaesar\n"
347                                            "feature\tgaius";
348
349 static const CHAR cie_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
350                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
351                                    "File\tFile\n"
352                                    "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
353                                    "augustus\taugustus\taugustus\t50000\t\t\t16384\t2\n"
354                                    "caesar\tcaesar\tcaesar\t500\t\t\t16384\t12\n"
355                                    "gaius\tgaius\tgaius\t500\t\t\t8192\t11";
356
357 static const CHAR cie_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
358                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
359                                     "Media\tDiskId\n"
360                                     "1\t1\t\ttest1.cab\tDISK1\t\n"
361                                     "2\t2\t\ttest2.cab\tDISK2\t\n"
362                                     "3\t12\t\ttest3.cab\tDISK3\t\n";
363
364 static const CHAR ci_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
365                                               "s72\tS255\tI2\n"
366                                               "InstallExecuteSequence\tAction\n"
367                                               "CostFinalize\t\t1000\n"
368                                               "CostInitialize\t\t800\n"
369                                               "FileCost\t\t900\n"
370                                               "InstallFiles\t\t4000\n"
371                                               "InstallServices\t\t5000\n"
372                                               "InstallFinalize\t\t6600\n"
373                                               "InstallInitialize\t\t1500\n"
374                                               "RunInstall\t\t1600\n"
375                                               "InstallValidate\t\t1400\n"
376                                               "LaunchConditions\t\t100";
377
378 static const CHAR ci_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
379                                             "s72\ti2\tS64\tS0\tS255\n"
380                                             "CustomAction\tAction\n"
381                                             "RunInstall\t87\tmsitest\\concurrent.msi\tMYPROP=[UILevel]\t\n";
382
383 static const CHAR ci_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
384                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
385                                        "Component\tComponent\n"
386                                        "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n";
387
388 static const CHAR ci2_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
389                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
390                                         "Component\tComponent\n"
391                                         "augustus\t\tMSITESTDIR\t0\tUILevel=3 AND MYPROP=5\taugustus\n";
392
393 static const CHAR ci2_feature_comp_dat[] = "Feature_\tComponent_\n"
394                                            "s38\ts72\n"
395                                            "FeatureComponents\tFeature_\tComponent_\n"
396                                            "feature\taugustus";
397
398 static const CHAR ci2_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
399                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
400                                    "File\tFile\n"
401                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t1";
402
403 static const CHAR spf_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
404                                             "s72\ti2\tS64\tS0\tS255\n"
405                                             "CustomAction\tAction\n"
406                                             "SetFolderProp\t51\tMSITESTDIR\t[ProgramFilesFolder]\\msitest\\added\t\n";
407
408 static const CHAR spf_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
409                                                "s72\tS255\tI2\n"
410                                                "InstallExecuteSequence\tAction\n"
411                                                "CostFinalize\t\t1000\n"
412                                                "CostInitialize\t\t800\n"
413                                                "FileCost\t\t900\n"
414                                                "SetFolderProp\t\t950\n"
415                                                "InstallFiles\t\t4000\n"
416                                                "InstallServices\t\t5000\n"
417                                                "InstallFinalize\t\t6600\n"
418                                                "InstallInitialize\t\t1500\n"
419                                                "InstallValidate\t\t1400\n"
420                                                "LaunchConditions\t\t100";
421
422 static const CHAR spf_install_ui_seq_dat[] = "Action\tCondition\tSequence\n"
423                                              "s72\tS255\tI2\n"
424                                              "InstallUISequence\tAction\n"
425                                              "CostInitialize\t\t800\n"
426                                              "FileCost\t\t900\n"
427                                              "CostFinalize\t\t1000\n"
428                                              "ExecuteAction\t\t1100\n";
429
430 static const CHAR pp_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
431                                               "s72\tS255\tI2\n"
432                                               "InstallExecuteSequence\tAction\n"
433                                               "ValidateProductID\t\t700\n"
434                                               "CostInitialize\t\t800\n"
435                                               "FileCost\t\t900\n"
436                                               "CostFinalize\t\t1000\n"
437                                               "InstallValidate\t\t1400\n"
438                                               "InstallInitialize\t\t1500\n"
439                                               "ProcessComponents\tPROCESS_COMPONENTS=1 Or FULL=1\t1600\n"
440                                               "UnpublishFeatures\tUNPUBLISH_FEATURES=1 Or FULL=1\t1800\n"
441                                               "RemoveFiles\t\t3500\n"
442                                               "InstallFiles\t\t4000\n"
443                                               "RegisterUser\tREGISTER_USER=1 Or FULL=1\t6000\n"
444                                               "RegisterProduct\tREGISTER_PRODUCT=1 Or FULL=1\t6100\n"
445                                               "PublishFeatures\tPUBLISH_FEATURES=1 Or FULL=1\t6300\n"
446                                               "PublishProduct\tPUBLISH_PRODUCT=1 Or FULL=1\t6400\n"
447                                               "InstallFinalize\t\t6600";
448
449 static const CHAR ppc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
450                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
451                                         "Component\tComponent\n"
452                                         "maximus\t{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}\tMSITESTDIR\t0\tUILevel=5\tmaximus\n"
453                                         "augustus\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\taugustus\n";
454
455 static const CHAR ppc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
456                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
457                                    "File\tFile\n"
458                                    "maximus\tmaximus\tmaximus\t500\t\t\t8192\t1\n"
459                                    "augustus\taugustus\taugustus\t500\t\t\t8192\t2";
460
461 static const CHAR ppc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
462                                     "i2\ti4\tL64\tS255\tS32\tS72\n"
463                                     "Media\tDiskId\n"
464                                     "1\t2\t\t\tDISK1\t\n";
465
466 static const CHAR ppc_feature_comp_dat[] = "Feature_\tComponent_\n"
467                                            "s38\ts72\n"
468                                            "FeatureComponents\tFeature_\tComponent_\n"
469                                            "feature\tmaximus\n"
470                                            "feature\taugustus\n"
471                                            "montecristo\tmaximus";
472
473 static const CHAR tp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
474                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
475                                        "Component\tComponent\n"
476                                        "augustus\t\tMSITESTDIR\t0\tprop=\"val\"\taugustus\n";
477
478 static const CHAR cwd_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
479                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
480                                         "Component\tComponent\n"
481                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
482
483 static const CHAR adm_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
484                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
485                                         "Component\tComponent\n"
486                                         "augustus\t\tMSITESTDIR\t0\tPOSTADMIN=1\taugustus";
487
488 static const CHAR adm_custom_action_dat[] = "Action\tType\tSource\tTarget\tISComments\n"
489                                             "s72\ti2\tS64\tS0\tS255\n"
490                                             "CustomAction\tAction\n"
491                                             "SetPOSTADMIN\t51\tPOSTADMIN\t1\t\n";
492
493 static const CHAR adm_admin_exec_seq_dat[] = "Action\tCondition\tSequence\n"
494                                              "s72\tS255\tI2\n"
495                                              "AdminExecuteSequence\tAction\n"
496                                              "CostFinalize\t\t1000\n"
497                                              "CostInitialize\t\t800\n"
498                                              "FileCost\t\t900\n"
499                                              "SetPOSTADMIN\t\t950\n"
500                                              "InstallFiles\t\t4000\n"
501                                              "InstallFinalize\t\t6600\n"
502                                              "InstallInitialize\t\t1500\n"
503                                              "InstallValidate\t\t1400\n"
504                                              "LaunchConditions\t\t100";
505
506 static const CHAR amp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
507                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
508                                         "Component\tComponent\n"
509                                         "augustus\t\tMSITESTDIR\t0\tMYPROP=2718 and MyProp=42\taugustus\n";
510
511 static const CHAR rem_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
512                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
513                                         "Component\tComponent\n"
514                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t0\t\thydrogen\n"
515                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t1\t\thelium\n"
516                                         "lithium\t\tMSITESTDIR\t2\t\tlithium\n";
517
518 static const CHAR rem_feature_comp_dat[] = "Feature_\tComponent_\n"
519                                            "s38\ts72\n"
520                                            "FeatureComponents\tFeature_\tComponent_\n"
521                                            "feature\thydrogen\n"
522                                            "feature\thelium\n"
523                                            "feature\tlithium";
524
525 static const CHAR rem_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
526                                    "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
527                                    "File\tFile\n"
528                                    "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
529                                    "helium\thelium\thelium\t0\t\t\t8192\t1\n"
530                                    "lithium\tlithium\tlithium\t0\t\t\t8192\t1";
531
532 static const CHAR rem_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
533                                                "s72\tS255\tI2\n"
534                                                "InstallExecuteSequence\tAction\n"
535                                                "ValidateProductID\t\t700\n"
536                                                "CostInitialize\t\t800\n"
537                                                "FileCost\t\t900\n"
538                                                "CostFinalize\t\t1000\n"
539                                                "InstallValidate\t\t1400\n"
540                                                "InstallInitialize\t\t1500\n"
541                                                "ProcessComponents\t\t1600\n"
542                                                "UnpublishFeatures\t\t1800\n"
543                                                "RemoveFiles\t\t3500\n"
544                                                "InstallFiles\t\t4000\n"
545                                                "RegisterProduct\t\t6100\n"
546                                                "PublishFeatures\t\t6300\n"
547                                                "PublishProduct\t\t6400\n"
548                                                "InstallFinalize\t\t6600";
549
550 static const CHAR rem_remove_files_dat[] = "FileKey\tComponent_\tFileName\tDirProperty\tInstallMode\n"
551                                            "s72\ts72\tS255\ts72\tI2\n"
552                                            "RemoveFile\tFileKey\n"
553                                            "furlong\thydrogen\tfurlong\tMSITESTDIR\t1\n"
554                                            "firkin\thelium\tfirkin\tMSITESTDIR\t1\n"
555                                            "fortnight\tlithium\tfortnight\tMSITESTDIR\t1\n"
556                                            "becquerel\thydrogen\tbecquerel\tMSITESTDIR\t2\n"
557                                            "dioptre\thelium\tdioptre\tMSITESTDIR\t2\n"
558                                            "attoparsec\tlithium\tattoparsec\tMSITESTDIR\t2\n"
559                                            "storeys\thydrogen\tstoreys\tMSITESTDIR\t3\n"
560                                            "block\thelium\tblock\tMSITESTDIR\t3\n"
561                                            "siriometer\tlithium\tsiriometer\tMSITESTDIR\t3\n"
562                                            "nanoacre\thydrogen\t\tCABOUTDIR\t3\n";
563
564 static const CHAR mov_move_file_dat[] = "FileKey\tComponent_\tSourceName\tDestName\tSourceFolder\tDestFolder\tOptions\n"
565                                         "s72\ts72\tS255\tS255\tS72\ts72\ti2\n"
566                                         "MoveFile\tFileKey\n"
567                                         "abkhazia\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t0\n"
568                                         "bahamas\taugustus\tnonexistent\tdest\tSourceDir\tMSITESTDIR\t1\n"
569                                         "cambodia\taugustus\tcameroon\tcanada\tSourceDir\tMSITESTDIR\t0\n"
570                                         "denmark\taugustus\tdjibouti\tdominica\tSourceDir\tMSITESTDIR\t1\n"
571                                         "ecuador\taugustus\tegypt\telsalvador\tNotAProp\tMSITESTDIR\t1\n"
572                                         "fiji\taugustus\tfinland\tfrance\tSourceDir\tNotAProp\t1\n"
573                                         "gabon\taugustus\tgambia\tgeorgia\tSOURCEFULL\tMSITESTDIR\t1\n"
574                                         "haiti\taugustus\thonduras\thungary\tSourceDir\tDESTFULL\t1\n"
575                                         "iceland\taugustus\tindia\tindonesia\tMSITESTDIR\tMSITESTDIR\t1\n"
576                                         "jamaica\taugustus\tjapan\tjordan\tFILEPATHBAD\tMSITESTDIR\t1\n"
577                                         "kazakhstan\taugustus\t\tkiribati\tFILEPATHGOOD\tMSITESTDIR\t1\n"
578                                         "laos\taugustus\tlatvia\tlebanon\tSourceDir\tMSITESTDIR\t1\n"
579                                         "namibia\taugustus\tnauru\tkiribati\tSourceDir\tMSITESTDIR\t1\n"
580                                         "pakistan\taugustus\tperu\tsfn|poland\tSourceDir\tMSITESTDIR\t1\n"
581                                         "wildcard\taugustus\tapp*\twildcard\tSourceDir\tMSITESTDIR\t1\n"
582                                         "single\taugustus\tf?o\tsingle\tSourceDir\tMSITESTDIR\t1\n"
583                                         "wildcardnodest\taugustus\tbudd*\t\tSourceDir\tMSITESTDIR\t1\n"
584                                         "singlenodest\taugustus\tb?r\t\tSourceDir\tMSITESTDIR\t1\n";
585
586 static const CHAR mc_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
587                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
588                                         "Component\tComponent\n"
589                                         "maximus\t\tMSITESTDIR\t0\t1\tmaximus\n"
590                                         "augustus\t\tMSITESTDIR\t0\t1\taugustus\n"
591                                         "caesar\t\tMSITESTDIR\t0\t1\tcaesar\n"
592                                         "gaius\t\tMSITESTDIR\t0\tGAIUS=1\tgaius\n";
593
594 static const CHAR mc_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
595                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
596                                   "File\tFile\n"
597                                   "maximus\tmaximus\tmaximus\t500\t\t\t16384\t1\n"
598                                   "augustus\taugustus\taugustus\t500\t\t\t0\t2\n"
599                                   "caesar\tcaesar\tcaesar\t500\t\t\t16384\t3\n"
600                                   "gaius\tgaius\tgaius\t500\t\t\t16384\t4";
601
602 static const CHAR mc_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
603                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
604                                    "Media\tDiskId\n"
605                                    "1\t1\t\ttest1.cab\tDISK1\t\n"
606                                    "2\t2\t\ttest2.cab\tDISK2\t\n"
607                                    "3\t3\t\ttest3.cab\tDISK3\t\n"
608                                    "4\t4\t\ttest3.cab\tDISK3\t\n";
609
610 static const CHAR mc_file_hash_dat[] = "File_\tOptions\tHashPart1\tHashPart2\tHashPart3\tHashPart4\n"
611                                        "s72\ti2\ti4\ti4\ti4\ti4\n"
612                                        "MsiFileHash\tFile_\n"
613                                        "caesar\t0\t850433704\t-241429251\t675791761\t-1221108824";
614
615 static const CHAR df_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
616                                        "s72\tS72\tl255\n"
617                                        "Directory\tDirectory\n"
618                                        "THIS\tMSITESTDIR\tthis\n"
619                                        "DOESNOT\tTHIS\tdoesnot\n"
620                                        "NONEXISTENT\tDOESNOT\texist\n"
621                                        "MSITESTDIR\tProgramFilesFolder\tmsitest\n"
622                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
623                                        "TARGETDIR\t\tSourceDir";
624
625 static const CHAR df_duplicate_file_dat[] = "FileKey\tComponent_\tFile_\tDestName\tDestFolder\n"
626                                             "s72\ts72\ts72\tS255\tS72\n"
627                                             "DuplicateFile\tFileKey\n"
628                                             "maximus\tmaximus\tmaximus\taugustus\t\n"
629                                             "caesar\tmaximus\tmaximus\t\tNONEXISTENT\n";
630
631 static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
632                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
633                                         "Component\tComponent\n"
634                                         "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
635
636 static const CHAR wrv_registry_dat[] = "Registry\tRoot\tKey\tName\tValue\tComponent_\n"
637                                        "s72\ti2\tl255\tL255\tL0\ts72\n"
638                                        "Registry\tRegistry\n"
639                                        "regdata\t2\tSOFTWARE\\Wine\\msitest\tValue\t[~]one[~]two[~]three\taugustus";
640
641 static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
642                                          "s72\tS38\ts72\ti2\tS255\tS72\n"
643                                          "Component\tComponent\n"
644                                          "augustus\t\tMSITESTDIR\t0\tMYPROP=42\taugustus\n";
645
646 static const CHAR ca51_install_exec_seq_dat[] = "Action\tCondition\tSequence\n"
647                                                 "s72\tS255\tI2\n"
648                                                 "InstallExecuteSequence\tAction\n"
649                                                 "ValidateProductID\t\t700\n"
650                                                 "GoodSetProperty\t\t725\n"
651                                                 "BadSetProperty\t\t750\n"
652                                                 "CostInitialize\t\t800\n"
653                                                 "ResolveSource\t\t810\n"
654                                                 "FileCost\t\t900\n"
655                                                 "SetSourceDir\tSRCDIR\t910\n"
656                                                 "CostFinalize\t\t1000\n"
657                                                 "InstallValidate\t\t1400\n"
658                                                 "InstallInitialize\t\t1500\n"
659                                                 "InstallFiles\t\t4000\n"
660                                                 "InstallFinalize\t\t6600";
661
662 static const CHAR ca51_custom_action_dat[] = "Action\tType\tSource\tTarget\n"
663                                              "s72\ti2\tS64\tS0\n"
664                                              "CustomAction\tAction\n"
665                                              "GoodSetProperty\t51\tMYPROP\t42\n"
666                                              "BadSetProperty\t51\t\tMYPROP\n"
667                                              "SetSourceDir\t51\tSourceDir\t[SRCDIR]\n";
668
669 static const CHAR is_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
670                                      "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
671                                      "Feature\tFeature\n"
672                                      "one\t\t\t\t2\t1\t\t0\n" /* favorLocal */
673                                      "two\t\t\t\t2\t1\t\t1\n" /* favorSource */
674                                      "three\t\t\t\t2\t1\t\t4\n" /* favorAdvertise */
675                                      "four\t\t\t\t2\t0\t\t0"; /* disabled */
676
677 static const CHAR is_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
678                                        "s72\tS38\ts72\ti2\tS255\tS72\n"
679                                        "Component\tComponent\n"
680                                        "alpha\t\tMSITESTDIR\t0\t\talpha_file\n" /* favorLocal:Local */
681                                        "beta\t\tMSITESTDIR\t1\t\tbeta_file\n" /* favorLocal:Source */
682                                        "gamma\t\tMSITESTDIR\t2\t\tgamma_file\n" /* favorLocal:Optional */
683                                        "theta\t\tMSITESTDIR\t0\t\ttheta_file\n" /* favorSource:Local */
684                                        "delta\t\tMSITESTDIR\t1\t\tdelta_file\n" /* favorSource:Source */
685                                        "epsilon\t\tMSITESTDIR\t2\t\tepsilon_file\n" /* favorSource:Optional */
686                                        "zeta\t\tMSITESTDIR\t0\t\tzeta_file\n" /* favorAdvertise:Local */
687                                        "iota\t\tMSITESTDIR\t1\t\tiota_file\n" /* favorAdvertise:Source */
688                                        "eta\t\tMSITESTDIR\t2\t\teta_file\n" /* favorAdvertise:Optional */
689                                        "kappa\t\tMSITESTDIR\t0\t\tkappa_file\n" /* disabled:Local */
690                                        "lambda\t\tMSITESTDIR\t1\t\tlambda_file\n" /* disabled:Source */
691                                        "mu\t\tMSITESTDIR\t2\t\tmu_file\n"; /* disabled:Optional */
692
693 static const CHAR is_feature_comp_dat[] = "Feature_\tComponent_\n"
694                                           "s38\ts72\n"
695                                           "FeatureComponents\tFeature_\tComponent_\n"
696                                           "one\talpha\n"
697                                           "one\tbeta\n"
698                                           "one\tgamma\n"
699                                           "two\ttheta\n"
700                                           "two\tdelta\n"
701                                           "two\tepsilon\n"
702                                           "three\tzeta\n"
703                                           "three\tiota\n"
704                                           "three\teta\n"
705                                           "four\tkappa\n"
706                                           "four\tlambda\n"
707                                           "four\tmu";
708
709 static const CHAR is_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
710                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
711                                   "File\tFile\n"
712                                   "alpha_file\talpha\talpha\t500\t\t\t8192\t1\n"
713                                   "beta_file\tbeta\tbeta\t500\t\t\t8291\t2\n"
714                                   "gamma_file\tgamma\tgamma\t500\t\t\t8192\t3\n"
715                                   "theta_file\ttheta\ttheta\t500\t\t\t8192\t4\n"
716                                   "delta_file\tdelta\tdelta\t500\t\t\t8192\t5\n"
717                                   "epsilon_file\tepsilon\tepsilon\t500\t\t\t8192\t6\n"
718                                   "zeta_file\tzeta\tzeta\t500\t\t\t8192\t7\n"
719                                   "iota_file\tiota\tiota\t500\t\t\t8192\t8\n"
720                                   "eta_file\teta\teta\t500\t\t\t8192\t9\n"
721                                   "kappa_file\tkappa\tkappa\t500\t\t\t8192\t10\n"
722                                   "lambda_file\tlambda\tlambda\t500\t\t\t8192\t11\n"
723                                   "mu_file\tmu\tmu\t500\t\t\t8192\t12";
724
725 static const CHAR is_media_dat[] = "DiskId\tLastSequence\tDiskPrompt\tCabinet\tVolumeLabel\tSource\n"
726                                    "i2\ti4\tL64\tS255\tS32\tS72\n"
727                                    "Media\tDiskId\n"
728                                    "1\t12\t\t\tDISK1\t\n";
729
730 static const CHAR sp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
731                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
732                                         "Component\tComponent\n"
733                                         "augustus\t\tTWODIR\t0\t\taugustus\n";
734
735 static const CHAR sp_directory_dat[] = "Directory\tDirectory_Parent\tDefaultDir\n"
736                                        "s72\tS72\tl255\n"
737                                        "Directory\tDirectory\n"
738                                        "TARGETDIR\t\tSourceDir\n"
739                                        "ProgramFilesFolder\tTARGETDIR\t.\n"
740                                        "MSITESTDIR\tProgramFilesFolder\tmsitest:.\n"
741                                        "ONEDIR\tMSITESTDIR\t.:shortone|longone\n"
742                                        "TWODIR\tONEDIR\t.:shorttwo|longtwo";
743
744 static const CHAR mcp_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n"
745                                         "s72\tS38\ts72\ti2\tS255\tS72\n"
746                                         "Component\tComponent\n"
747                                         "hydrogen\t{C844BD1E-1907-4C00-8BC9-150BD70DF0A1}\tMSITESTDIR\t2\t\thydrogen\n"
748                                         "helium\t{5AD3C142-CEF8-490D-B569-784D80670685}\tMSITESTDIR\t2\t\thelium\n"
749                                         "lithium\t{4AF28FFC-71C7-4307-BDE4-B77C5338F56F}\tMSITESTDIR\t2\tPROPVAR=42\tlithium\n";
750
751 static const CHAR mcp_feature_dat[] = "Feature\tFeature_Parent\tTitle\tDescription\tDisplay\tLevel\tDirectory_\tAttributes\n"
752                                       "s38\tS38\tL64\tL255\tI2\ti2\tS72\ti2\n"
753                                       "Feature\tFeature\n"
754                                       "hydroxyl\t\thydroxyl\thydroxyl\t2\t1\tTARGETDIR\t0\n"
755                                       "heliox\t\theliox\theliox\t2\t5\tTARGETDIR\t0\n"
756                                       "lithia\t\tlithia\tlithia\t2\t10\tTARGETDIR\t0";
757
758 static const CHAR mcp_feature_comp_dat[] = "Feature_\tComponent_\n"
759                                            "s38\ts72\n"
760                                            "FeatureComponents\tFeature_\tComponent_\n"
761                                            "hydroxyl\thydrogen\n"
762                                            "heliox\thelium\n"
763                                            "lithia\tlithium";
764
765 static const CHAR mcomp_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
766                                      "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
767                                      "File\tFile\n"
768                                      "hydrogen\thydrogen\thydrogen\t0\t\t\t8192\t1\n"
769                                      "helium\thelium\thelium\t0\t\t\t8192\t1\n"
770                                      "lithium\tlithium\tlithium\t0\t\t\t8192\t1\n"
771                                      "beryllium\tmissingcomp\tberyllium\t0\t\t\t8192\t1";
772
773 static const CHAR ai_file_dat[] = "File\tComponent_\tFileName\tFileSize\tVersion\tLanguage\tAttributes\tSequence\n"
774                                   "s72\ts72\tl255\ti4\tS72\tS20\tI2\ti2\n"
775                                   "File\tFile\n"
776                                   "five.txt\tFive\tfive.txt\t1000\t\t\t16384\t5\n"
777                                   "four.txt\tFour\tfour.txt\t1000\t\t\t16384\t4\n"
778                                   "one.txt\tOne\tone.txt\t1000\t\t\t16384\t1\n"
779                                   "three.txt\tThree\tthree.txt\t1000\t\t\t16384\t3\n"
780                                   "two.txt\tTwo\ttwo.txt\t1000\t\t\t16384\t2\n"
781                                   "file\tcomponent\tfilename\t100\t\t\t8192\t1\n"
782                                   "service_file\tservice_comp\tservice.exe\t100\t\t\t8192\t1";
783
784 typedef struct _msi_table
785 {
786     const CHAR *filename;
787     const CHAR *data;
788     int size;
789 } msi_table;
790
791 #define ADD_TABLE(x) {#x".idt", x##_dat, sizeof(x##_dat)}
792
793 static const msi_table tables[] =
794 {
795     ADD_TABLE(component),
796     ADD_TABLE(directory),
797     ADD_TABLE(feature),
798     ADD_TABLE(feature_comp),
799     ADD_TABLE(file),
800     ADD_TABLE(install_exec_seq),
801     ADD_TABLE(media),
802     ADD_TABLE(property),
803     ADD_TABLE(registry),
804     ADD_TABLE(service_install),
805     ADD_TABLE(service_control)
806 };
807
808 static const msi_table cc_tables[] =
809 {
810     ADD_TABLE(cc_component),
811     ADD_TABLE(directory),
812     ADD_TABLE(cc_feature),
813     ADD_TABLE(cc_feature_comp),
814     ADD_TABLE(cc_file),
815     ADD_TABLE(install_exec_seq),
816     ADD_TABLE(cc_media),
817     ADD_TABLE(property),
818 };
819
820 static const msi_table cc2_tables[] =
821 {
822     ADD_TABLE(cc2_component),
823     ADD_TABLE(directory),
824     ADD_TABLE(cc_feature),
825     ADD_TABLE(cc_feature_comp),
826     ADD_TABLE(cc2_file),
827     ADD_TABLE(install_exec_seq),
828     ADD_TABLE(cc_media),
829     ADD_TABLE(property),
830 };
831
832 static const msi_table co_tables[] =
833 {
834     ADD_TABLE(cc_component),
835     ADD_TABLE(directory),
836     ADD_TABLE(cc_feature),
837     ADD_TABLE(cc_feature_comp),
838     ADD_TABLE(co_file),
839     ADD_TABLE(install_exec_seq),
840     ADD_TABLE(co_media),
841     ADD_TABLE(property),
842 };
843
844 static const msi_table co2_tables[] =
845 {
846     ADD_TABLE(cc_component),
847     ADD_TABLE(directory),
848     ADD_TABLE(cc_feature),
849     ADD_TABLE(cc_feature_comp),
850     ADD_TABLE(cc_file),
851     ADD_TABLE(install_exec_seq),
852     ADD_TABLE(co2_media),
853     ADD_TABLE(property),
854 };
855
856 static const msi_table mm_tables[] =
857 {
858     ADD_TABLE(cc_component),
859     ADD_TABLE(directory),
860     ADD_TABLE(cc_feature),
861     ADD_TABLE(cc_feature_comp),
862     ADD_TABLE(mm_file),
863     ADD_TABLE(install_exec_seq),
864     ADD_TABLE(mm_media),
865     ADD_TABLE(property),
866 };
867
868 static const msi_table ss_tables[] =
869 {
870     ADD_TABLE(cc_component),
871     ADD_TABLE(directory),
872     ADD_TABLE(cc_feature),
873     ADD_TABLE(cc_feature_comp),
874     ADD_TABLE(cc_file),
875     ADD_TABLE(install_exec_seq),
876     ADD_TABLE(ss_media),
877     ADD_TABLE(property),
878 };
879
880 static const msi_table ui_tables[] =
881 {
882     ADD_TABLE(ui_component),
883     ADD_TABLE(directory),
884     ADD_TABLE(cc_feature),
885     ADD_TABLE(cc_feature_comp),
886     ADD_TABLE(cc_file),
887     ADD_TABLE(install_exec_seq),
888     ADD_TABLE(ui_install_ui_seq),
889     ADD_TABLE(ui_custom_action),
890     ADD_TABLE(cc_media),
891     ADD_TABLE(property),
892 };
893
894 static const msi_table rof_tables[] =
895 {
896     ADD_TABLE(rof_component),
897     ADD_TABLE(directory),
898     ADD_TABLE(rof_feature),
899     ADD_TABLE(rof_feature_comp),
900     ADD_TABLE(rof_file),
901     ADD_TABLE(install_exec_seq),
902     ADD_TABLE(rof_media),
903     ADD_TABLE(property),
904 };
905
906 static const msi_table sdp_tables[] =
907 {
908     ADD_TABLE(rof_component),
909     ADD_TABLE(directory),
910     ADD_TABLE(rof_feature),
911     ADD_TABLE(rof_feature_comp),
912     ADD_TABLE(rof_file),
913     ADD_TABLE(sdp_install_exec_seq),
914     ADD_TABLE(sdp_custom_action),
915     ADD_TABLE(rof_media),
916     ADD_TABLE(property),
917 };
918
919 static const msi_table cie_tables[] =
920 {
921     ADD_TABLE(cie_component),
922     ADD_TABLE(directory),
923     ADD_TABLE(cc_feature),
924     ADD_TABLE(cie_feature_comp),
925     ADD_TABLE(cie_file),
926     ADD_TABLE(install_exec_seq),
927     ADD_TABLE(cie_media),
928     ADD_TABLE(property),
929 };
930
931 static const msi_table ci_tables[] =
932 {
933     ADD_TABLE(ci_component),
934     ADD_TABLE(directory),
935     ADD_TABLE(rof_feature),
936     ADD_TABLE(rof_feature_comp),
937     ADD_TABLE(rof_file),
938     ADD_TABLE(ci_install_exec_seq),
939     ADD_TABLE(rof_media),
940     ADD_TABLE(property),
941     ADD_TABLE(ci_custom_action),
942 };
943
944 static const msi_table ci2_tables[] =
945 {
946     ADD_TABLE(ci2_component),
947     ADD_TABLE(directory),
948     ADD_TABLE(rof_feature),
949     ADD_TABLE(ci2_feature_comp),
950     ADD_TABLE(ci2_file),
951     ADD_TABLE(install_exec_seq),
952     ADD_TABLE(rof_media),
953     ADD_TABLE(property),
954 };
955
956 static const msi_table spf_tables[] =
957 {
958     ADD_TABLE(ci_component),
959     ADD_TABLE(directory),
960     ADD_TABLE(rof_feature),
961     ADD_TABLE(rof_feature_comp),
962     ADD_TABLE(rof_file),
963     ADD_TABLE(spf_install_exec_seq),
964     ADD_TABLE(rof_media),
965     ADD_TABLE(property),
966     ADD_TABLE(spf_custom_action),
967     ADD_TABLE(spf_install_ui_seq),
968 };
969
970 static const msi_table pp_tables[] =
971 {
972     ADD_TABLE(ci_component),
973     ADD_TABLE(directory),
974     ADD_TABLE(rof_feature),
975     ADD_TABLE(rof_feature_comp),
976     ADD_TABLE(rof_file),
977     ADD_TABLE(pp_install_exec_seq),
978     ADD_TABLE(rof_media),
979     ADD_TABLE(property),
980 };
981
982 static const msi_table ppc_tables[] =
983 {
984     ADD_TABLE(ppc_component),
985     ADD_TABLE(directory),
986     ADD_TABLE(rof_feature),
987     ADD_TABLE(ppc_feature_comp),
988     ADD_TABLE(ppc_file),
989     ADD_TABLE(pp_install_exec_seq),
990     ADD_TABLE(ppc_media),
991     ADD_TABLE(property),
992 };
993
994 static const msi_table tp_tables[] =
995 {
996     ADD_TABLE(tp_component),
997     ADD_TABLE(directory),
998     ADD_TABLE(rof_feature),
999     ADD_TABLE(ci2_feature_comp),
1000     ADD_TABLE(ci2_file),
1001     ADD_TABLE(install_exec_seq),
1002     ADD_TABLE(rof_media),
1003     ADD_TABLE(property),
1004 };
1005
1006 static const msi_table cwd_tables[] =
1007 {
1008     ADD_TABLE(cwd_component),
1009     ADD_TABLE(directory),
1010     ADD_TABLE(rof_feature),
1011     ADD_TABLE(ci2_feature_comp),
1012     ADD_TABLE(ci2_file),
1013     ADD_TABLE(install_exec_seq),
1014     ADD_TABLE(rof_media),
1015     ADD_TABLE(property),
1016 };
1017
1018 static const msi_table adm_tables[] =
1019 {
1020     ADD_TABLE(adm_component),
1021     ADD_TABLE(directory),
1022     ADD_TABLE(rof_feature),
1023     ADD_TABLE(ci2_feature_comp),
1024     ADD_TABLE(ci2_file),
1025     ADD_TABLE(install_exec_seq),
1026     ADD_TABLE(rof_media),
1027     ADD_TABLE(property),
1028     ADD_TABLE(adm_custom_action),
1029     ADD_TABLE(adm_admin_exec_seq),
1030 };
1031
1032 static const msi_table amp_tables[] =
1033 {
1034     ADD_TABLE(amp_component),
1035     ADD_TABLE(directory),
1036     ADD_TABLE(rof_feature),
1037     ADD_TABLE(ci2_feature_comp),
1038     ADD_TABLE(ci2_file),
1039     ADD_TABLE(install_exec_seq),
1040     ADD_TABLE(rof_media),
1041     ADD_TABLE(property),
1042 };
1043
1044 static const msi_table rem_tables[] =
1045 {
1046     ADD_TABLE(rem_component),
1047     ADD_TABLE(directory),
1048     ADD_TABLE(rof_feature),
1049     ADD_TABLE(rem_feature_comp),
1050     ADD_TABLE(rem_file),
1051     ADD_TABLE(rem_install_exec_seq),
1052     ADD_TABLE(rof_media),
1053     ADD_TABLE(property),
1054     ADD_TABLE(rem_remove_files),
1055 };
1056
1057 static const msi_table mov_tables[] =
1058 {
1059     ADD_TABLE(cwd_component),
1060     ADD_TABLE(directory),
1061     ADD_TABLE(rof_feature),
1062     ADD_TABLE(ci2_feature_comp),
1063     ADD_TABLE(ci2_file),
1064     ADD_TABLE(install_exec_seq),
1065     ADD_TABLE(rof_media),
1066     ADD_TABLE(property),
1067     ADD_TABLE(mov_move_file),
1068 };
1069
1070 static const msi_table mc_tables[] =
1071 {
1072     ADD_TABLE(mc_component),
1073     ADD_TABLE(directory),
1074     ADD_TABLE(cc_feature),
1075     ADD_TABLE(cie_feature_comp),
1076     ADD_TABLE(mc_file),
1077     ADD_TABLE(install_exec_seq),
1078     ADD_TABLE(mc_media),
1079     ADD_TABLE(property),
1080     ADD_TABLE(mc_file_hash),
1081 };
1082
1083 static const msi_table df_tables[] =
1084 {
1085     ADD_TABLE(rof_component),
1086     ADD_TABLE(df_directory),
1087     ADD_TABLE(rof_feature),
1088     ADD_TABLE(rof_feature_comp),
1089     ADD_TABLE(rof_file),
1090     ADD_TABLE(install_exec_seq),
1091     ADD_TABLE(rof_media),
1092     ADD_TABLE(property),
1093     ADD_TABLE(df_duplicate_file),
1094 };
1095
1096 static const msi_table wrv_tables[] =
1097 {
1098     ADD_TABLE(wrv_component),
1099     ADD_TABLE(directory),
1100     ADD_TABLE(rof_feature),
1101     ADD_TABLE(ci2_feature_comp),
1102     ADD_TABLE(ci2_file),
1103     ADD_TABLE(install_exec_seq),
1104     ADD_TABLE(rof_media),
1105     ADD_TABLE(property),
1106     ADD_TABLE(wrv_registry),
1107 };
1108
1109 static const msi_table sf_tables[] =
1110 {
1111     ADD_TABLE(wrv_component),
1112     ADD_TABLE(directory),
1113     ADD_TABLE(rof_feature),
1114     ADD_TABLE(ci2_feature_comp),
1115     ADD_TABLE(ci2_file),
1116     ADD_TABLE(install_exec_seq),
1117     ADD_TABLE(rof_media),
1118     ADD_TABLE(property),
1119 };
1120
1121 static const msi_table ca51_tables[] =
1122 {
1123     ADD_TABLE(ca51_component),
1124     ADD_TABLE(directory),
1125     ADD_TABLE(rof_feature),
1126     ADD_TABLE(ci2_feature_comp),
1127     ADD_TABLE(ci2_file),
1128     ADD_TABLE(ca51_install_exec_seq),
1129     ADD_TABLE(rof_media),
1130     ADD_TABLE(property),
1131     ADD_TABLE(ca51_custom_action),
1132 };
1133
1134 static const msi_table is_tables[] =
1135 {
1136     ADD_TABLE(is_component),
1137     ADD_TABLE(directory),
1138     ADD_TABLE(is_feature),
1139     ADD_TABLE(is_feature_comp),
1140     ADD_TABLE(is_file),
1141     ADD_TABLE(install_exec_seq),
1142     ADD_TABLE(is_media),
1143     ADD_TABLE(property),
1144 };
1145
1146 static const msi_table sp_tables[] =
1147 {
1148     ADD_TABLE(sp_component),
1149     ADD_TABLE(sp_directory),
1150     ADD_TABLE(rof_feature),
1151     ADD_TABLE(ci2_feature_comp),
1152     ADD_TABLE(ci2_file),
1153     ADD_TABLE(install_exec_seq),
1154     ADD_TABLE(rof_media),
1155     ADD_TABLE(property),
1156 };
1157
1158 static const msi_table mcp_tables[] =
1159 {
1160     ADD_TABLE(mcp_component),
1161     ADD_TABLE(directory),
1162     ADD_TABLE(mcp_feature),
1163     ADD_TABLE(mcp_feature_comp),
1164     ADD_TABLE(rem_file),
1165     ADD_TABLE(rem_install_exec_seq),
1166     ADD_TABLE(rof_media),
1167     ADD_TABLE(property),
1168 };
1169
1170 static const msi_table mcomp_tables[] =
1171 {
1172     ADD_TABLE(mcp_component),
1173     ADD_TABLE(directory),
1174     ADD_TABLE(mcp_feature),
1175     ADD_TABLE(mcp_feature_comp),
1176     ADD_TABLE(mcomp_file),
1177     ADD_TABLE(rem_install_exec_seq),
1178     ADD_TABLE(rof_media),
1179     ADD_TABLE(property),
1180 };
1181
1182 static const msi_table ai_tables[] =
1183 {
1184     ADD_TABLE(component),
1185     ADD_TABLE(directory),
1186     ADD_TABLE(feature),
1187     ADD_TABLE(feature_comp),
1188     ADD_TABLE(ai_file),
1189     ADD_TABLE(install_exec_seq),
1190     ADD_TABLE(media),
1191     ADD_TABLE(property)
1192 };
1193
1194 static const msi_table pc_tables[] =
1195 {
1196     ADD_TABLE(ca51_component),
1197     ADD_TABLE(directory),
1198     ADD_TABLE(rof_feature),
1199     ADD_TABLE(ci2_feature_comp),
1200     ADD_TABLE(ci2_file),
1201     ADD_TABLE(install_exec_seq),
1202     ADD_TABLE(rof_media),
1203     ADD_TABLE(property)
1204 };
1205
1206 /* cabinet definitions */
1207
1208 /* make the max size large so there is only one cab file */
1209 #define MEDIA_SIZE          0x7FFFFFFF
1210 #define FOLDER_THRESHOLD    900000
1211
1212 /* the FCI callbacks */
1213
1214 static void *mem_alloc(ULONG cb)
1215 {
1216     return HeapAlloc(GetProcessHeap(), 0, cb);
1217 }
1218
1219 static void mem_free(void *memory)
1220 {
1221     HeapFree(GetProcessHeap(), 0, memory);
1222 }
1223
1224 static BOOL get_next_cabinet(PCCAB pccab, ULONG  cbPrevCab, void *pv)
1225 {
1226     sprintf(pccab->szCab, pv, pccab->iCab);
1227     return TRUE;
1228 }
1229
1230 static long progress(UINT typeStatus, ULONG cb1, ULONG cb2, void *pv)
1231 {
1232     return 0;
1233 }
1234
1235 static int file_placed(PCCAB pccab, char *pszFile, long cbFile,
1236                        BOOL fContinuation, void *pv)
1237 {
1238     return 0;
1239 }
1240
1241 static INT_PTR fci_open(char *pszFile, int oflag, int pmode, int *err, void *pv)
1242 {
1243     HANDLE handle;
1244     DWORD dwAccess = 0;
1245     DWORD dwShareMode = 0;
1246     DWORD dwCreateDisposition = OPEN_EXISTING;
1247     
1248     dwAccess = GENERIC_READ | GENERIC_WRITE;
1249     /* FILE_SHARE_DELETE is not supported by Windows Me/98/95 */
1250     dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
1251
1252     if (GetFileAttributesA(pszFile) != INVALID_FILE_ATTRIBUTES)
1253         dwCreateDisposition = OPEN_EXISTING;
1254     else
1255         dwCreateDisposition = CREATE_NEW;
1256
1257     handle = CreateFileA(pszFile, dwAccess, dwShareMode, NULL,
1258                          dwCreateDisposition, 0, NULL);
1259
1260     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszFile);
1261
1262     return (INT_PTR)handle;
1263 }
1264
1265 static UINT fci_read(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1266 {
1267     HANDLE handle = (HANDLE)hf;
1268     DWORD dwRead;
1269     BOOL res;
1270     
1271     res = ReadFile(handle, memory, cb, &dwRead, NULL);
1272     ok(res, "Failed to ReadFile\n");
1273
1274     return dwRead;
1275 }
1276
1277 static UINT fci_write(INT_PTR hf, void *memory, UINT cb, int *err, void *pv)
1278 {
1279     HANDLE handle = (HANDLE)hf;
1280     DWORD dwWritten;
1281     BOOL res;
1282
1283     res = WriteFile(handle, memory, cb, &dwWritten, NULL);
1284     ok(res, "Failed to WriteFile\n");
1285
1286     return dwWritten;
1287 }
1288
1289 static int fci_close(INT_PTR hf, int *err, void *pv)
1290 {
1291     HANDLE handle = (HANDLE)hf;
1292     ok(CloseHandle(handle), "Failed to CloseHandle\n");
1293
1294     return 0;
1295 }
1296
1297 static long fci_seek(INT_PTR hf, long dist, int seektype, int *err, void *pv)
1298 {
1299     HANDLE handle = (HANDLE)hf;
1300     DWORD ret;
1301     
1302     ret = SetFilePointer(handle, dist, NULL, seektype);
1303     ok(ret != INVALID_SET_FILE_POINTER, "Failed to SetFilePointer\n");
1304
1305     return ret;
1306 }
1307
1308 static int fci_delete(char *pszFile, int *err, void *pv)
1309 {
1310     BOOL ret = DeleteFileA(pszFile);
1311     ok(ret, "Failed to DeleteFile %s\n", pszFile);
1312
1313     return 0;
1314 }
1315
1316 static void init_functionpointers(void)
1317 {
1318     HMODULE hmsi = GetModuleHandleA("msi.dll");
1319
1320 #define GET_PROC(mod, func) \
1321     p ## func = (void*)GetProcAddress(mod, #func); \
1322     if(!p ## func) \
1323       trace("GetProcAddress(%s) failed\n", #func);
1324
1325     GET_PROC(hmsi, MsiQueryComponentStateA);
1326     GET_PROC(hmsi, MsiSourceListEnumSourcesA);
1327     GET_PROC(hmsi, MsiSourceListGetInfoA);
1328
1329     hsrclient = LoadLibraryA("srclient.dll");
1330     GET_PROC(hsrclient, SRRemoveRestorePoint);
1331     GET_PROC(hsrclient, SRSetRestorePointA);
1332
1333 #undef GET_PROC
1334 }
1335
1336 static BOOL check_win9x(void)
1337 {
1338     SC_HANDLE scm;
1339
1340     scm = OpenSCManager(NULL, NULL, GENERIC_ALL);
1341     if (!scm && (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED))
1342         return TRUE;
1343
1344     CloseServiceHandle(scm);
1345
1346     return FALSE;
1347 }
1348
1349 static void get_user_sid(LPSTR *usersid)
1350 {
1351     HANDLE token;
1352     BYTE buf[1024];
1353     DWORD size;
1354     PTOKEN_USER user;
1355     HMODULE hadvapi32 = GetModuleHandleA("advapi32.dll");
1356     static BOOL (WINAPI *pConvertSidToStringSidA)(PSID, LPSTR*);
1357
1358     *usersid = NULL;
1359     pConvertSidToStringSidA = (void *)GetProcAddress(hadvapi32, "ConvertSidToStringSidA");
1360     if (!pConvertSidToStringSidA)
1361         return;
1362
1363     OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token);
1364     size = sizeof(buf);
1365     GetTokenInformation(token, TokenUser, (void *)buf, size, &size);
1366     user = (PTOKEN_USER)buf;
1367     pConvertSidToStringSidA(user->User.Sid, usersid);
1368 }
1369
1370 static BOOL check_record(MSIHANDLE rec, UINT field, LPCSTR val)
1371 {
1372     CHAR buffer[0x20];
1373     UINT r;
1374     DWORD sz;
1375
1376     sz = sizeof buffer;
1377     r = MsiRecordGetString(rec, field, buffer, &sz);
1378     return (r == ERROR_SUCCESS ) && !strcmp(val, buffer);
1379 }
1380
1381 static BOOL get_temp_file(char *pszTempName, int cbTempName, void *pv)
1382 {
1383     LPSTR tempname;
1384
1385     tempname = HeapAlloc(GetProcessHeap(), 0, MAX_PATH);
1386     GetTempFileNameA(".", "xx", 0, tempname);
1387
1388     if (tempname && (strlen(tempname) < (unsigned)cbTempName))
1389     {
1390         lstrcpyA(pszTempName, tempname);
1391         HeapFree(GetProcessHeap(), 0, tempname);
1392         return TRUE;
1393     }
1394
1395     HeapFree(GetProcessHeap(), 0, tempname);
1396
1397     return FALSE;
1398 }
1399
1400 static INT_PTR get_open_info(char *pszName, USHORT *pdate, USHORT *ptime,
1401                              USHORT *pattribs, int *err, void *pv)
1402 {
1403     BY_HANDLE_FILE_INFORMATION finfo;
1404     FILETIME filetime;
1405     HANDLE handle;
1406     DWORD attrs;
1407     BOOL res;
1408
1409     handle = CreateFile(pszName, GENERIC_READ, FILE_SHARE_READ, NULL,
1410                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1411
1412     ok(handle != INVALID_HANDLE_VALUE, "Failed to CreateFile %s\n", pszName);
1413
1414     res = GetFileInformationByHandle(handle, &finfo);
1415     ok(res, "Expected GetFileInformationByHandle to succeed\n");
1416    
1417     FileTimeToLocalFileTime(&finfo.ftLastWriteTime, &filetime);
1418     FileTimeToDosDateTime(&filetime, pdate, ptime);
1419
1420     attrs = GetFileAttributes(pszName);
1421     ok(attrs != INVALID_FILE_ATTRIBUTES, "Failed to GetFileAttributes\n");
1422
1423     return (INT_PTR)handle;
1424 }
1425
1426 static BOOL add_file(HFCI hfci, const char *file, TCOMP compress)
1427 {
1428     char path[MAX_PATH];
1429     char filename[MAX_PATH];
1430
1431     lstrcpyA(path, CURR_DIR);
1432     lstrcatA(path, "\\");
1433     lstrcatA(path, file);
1434
1435     lstrcpyA(filename, file);
1436
1437     return FCIAddFile(hfci, path, filename, FALSE, get_next_cabinet,
1438                       progress, get_open_info, compress);
1439 }
1440
1441 static void set_cab_parameters(PCCAB pCabParams, const CHAR *name, DWORD max_size)
1442 {
1443     ZeroMemory(pCabParams, sizeof(CCAB));
1444
1445     pCabParams->cb = max_size;
1446     pCabParams->cbFolderThresh = FOLDER_THRESHOLD;
1447     pCabParams->setID = 0xbeef;
1448     pCabParams->iCab = 1;
1449     lstrcpyA(pCabParams->szCabPath, CURR_DIR);
1450     lstrcatA(pCabParams->szCabPath, "\\");
1451     lstrcpyA(pCabParams->szCab, name);
1452 }
1453
1454 static void create_cab_file(const CHAR *name, DWORD max_size, const CHAR *files)
1455 {
1456     CCAB cabParams;
1457     LPCSTR ptr;
1458     HFCI hfci;
1459     ERF erf;
1460     BOOL res;
1461
1462     set_cab_parameters(&cabParams, name, max_size);
1463
1464     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1465                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1466                       get_temp_file, &cabParams, NULL);
1467
1468     ok(hfci != NULL, "Failed to create an FCI context\n");
1469
1470     ptr = files;
1471     while (*ptr)
1472     {
1473         res = add_file(hfci, ptr, tcompTYPE_MSZIP);
1474         ok(res, "Failed to add file: %s\n", ptr);
1475         ptr += lstrlen(ptr) + 1;
1476     }
1477
1478     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1479     ok(res, "Failed to flush the cabinet\n");
1480
1481     res = FCIDestroy(hfci);
1482     ok(res, "Failed to destroy the cabinet\n");
1483 }
1484
1485 static BOOL get_program_files_dir(LPSTR buf, LPSTR buf2)
1486 {
1487     HKEY hkey;
1488     DWORD type, size;
1489
1490     if (RegOpenKey(HKEY_LOCAL_MACHINE,
1491                    "Software\\Microsoft\\Windows\\CurrentVersion", &hkey))
1492         return FALSE;
1493
1494     size = MAX_PATH;
1495     if (RegQueryValueExA(hkey, "ProgramFilesDir", 0, &type, (LPBYTE)buf, &size)) {
1496         RegCloseKey(hkey);
1497         return FALSE;
1498     }
1499
1500     size = MAX_PATH;
1501     if (RegQueryValueExA(hkey, "CommonFilesDir", 0, &type, (LPBYTE)buf2, &size)) {
1502         RegCloseKey(hkey);
1503         return FALSE;
1504     }
1505
1506     RegCloseKey(hkey);
1507     return TRUE;
1508 }
1509
1510 static void create_file_data(LPCSTR name, LPCSTR data, DWORD size)
1511 {
1512     HANDLE file;
1513     DWORD written;
1514
1515     file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
1516     if (file == INVALID_HANDLE_VALUE)
1517         return;
1518
1519     WriteFile(file, data, strlen(data), &written, NULL);
1520
1521     if (size)
1522     {
1523         SetFilePointer(file, size, NULL, FILE_BEGIN);
1524         SetEndOfFile(file);
1525     }
1526
1527     CloseHandle(file);
1528 }
1529
1530 #define create_file(name, size) create_file_data(name, name, size)
1531
1532 static void create_test_files(void)
1533 {
1534     CreateDirectoryA("msitest", NULL);
1535     create_file("msitest\\one.txt", 100);
1536     CreateDirectoryA("msitest\\first", NULL);
1537     create_file("msitest\\first\\two.txt", 100);
1538     CreateDirectoryA("msitest\\second", NULL);
1539     create_file("msitest\\second\\three.txt", 100);
1540
1541     create_file("four.txt", 100);
1542     create_file("five.txt", 100);
1543     create_cab_file("msitest.cab", MEDIA_SIZE, "four.txt\0five.txt\0");
1544
1545     create_file("msitest\\filename", 100);
1546     create_file("msitest\\service.exe", 100);
1547
1548     DeleteFileA("four.txt");
1549     DeleteFileA("five.txt");
1550 }
1551
1552 static BOOL delete_pf(const CHAR *rel_path, BOOL is_file)
1553 {
1554     CHAR path[MAX_PATH];
1555
1556     lstrcpyA(path, PROG_FILES_DIR);
1557     lstrcatA(path, "\\");
1558     lstrcatA(path, rel_path);
1559
1560     if (is_file)
1561         return DeleteFileA(path);
1562     else
1563         return RemoveDirectoryA(path);
1564 }
1565
1566 static BOOL delete_cf(const CHAR *rel_path, BOOL is_file)
1567 {
1568     CHAR path[MAX_PATH];
1569
1570     lstrcpyA(path, COMMON_FILES_DIR);
1571     lstrcatA(path, "\\");
1572     lstrcatA(path, rel_path);
1573
1574     if (is_file)
1575         return DeleteFileA(path);
1576     else
1577         return RemoveDirectoryA(path);
1578 }
1579
1580 static void delete_test_files(void)
1581 {
1582     DeleteFileA("msitest.msi");
1583     DeleteFileA("msitest.cab");
1584     DeleteFileA("msitest\\second\\three.txt");
1585     DeleteFileA("msitest\\first\\two.txt");
1586     DeleteFileA("msitest\\one.txt");
1587     DeleteFileA("msitest\\service.exe");
1588     DeleteFileA("msitest\\filename");
1589     RemoveDirectoryA("msitest\\second");
1590     RemoveDirectoryA("msitest\\first");
1591     RemoveDirectoryA("msitest");
1592 }
1593
1594 static void write_file(const CHAR *filename, const char *data, int data_size)
1595 {
1596     DWORD size;
1597
1598     HANDLE hf = CreateFile(filename, GENERIC_WRITE, 0, NULL,
1599                            CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1600
1601     WriteFile(hf, data, data_size, &size, NULL);
1602     CloseHandle(hf);
1603 }
1604
1605 static void write_msi_summary_info(MSIHANDLE db, INT wordcount)
1606 {
1607     MSIHANDLE summary;
1608     UINT r;
1609
1610     r = MsiGetSummaryInformationA(db, NULL, 5, &summary);
1611     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1612
1613     r = MsiSummaryInfoSetPropertyA(summary, PID_TEMPLATE, VT_LPSTR, 0, NULL, ";1033");
1614     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1615
1616     r = MsiSummaryInfoSetPropertyA(summary, PID_REVNUMBER, VT_LPSTR, 0, NULL,
1617                                    "{004757CA-5092-49c2-AD20-28E1CE0DF5F2}");
1618     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1619
1620     r = MsiSummaryInfoSetPropertyA(summary, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
1621     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1622
1623     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, wordcount, NULL, NULL);
1624     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1625
1626     r = MsiSummaryInfoSetPropertyA(summary, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
1627     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1628
1629     /* write the summary changes back to the stream */
1630     r = MsiSummaryInfoPersist(summary);
1631     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1632
1633     MsiCloseHandle(summary);
1634 }
1635
1636 #define create_database(name, tables, num_tables) \
1637     create_database_wordcount(name, tables, num_tables, 0);
1638
1639 static void create_database_wordcount(const CHAR *name, const msi_table *tables,
1640                                       int num_tables, INT wordcount)
1641 {
1642     MSIHANDLE db;
1643     UINT r;
1644     int j;
1645
1646     r = MsiOpenDatabaseA(name, MSIDBOPEN_CREATE, &db);
1647     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1648
1649     /* import the tables into the database */
1650     for (j = 0; j < num_tables; j++)
1651     {
1652         const msi_table *table = &tables[j];
1653
1654         write_file(table->filename, table->data, (table->size - 1) * sizeof(char));
1655
1656         r = MsiDatabaseImportA(db, CURR_DIR, table->filename);
1657         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1658
1659         DeleteFileA(table->filename);
1660     }
1661
1662     write_msi_summary_info(db, wordcount);
1663
1664     r = MsiDatabaseCommit(db);
1665     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1666
1667     MsiCloseHandle(db);
1668 }
1669
1670 static void check_service_is_installed(void)
1671 {
1672     SC_HANDLE scm, service;
1673     BOOL res;
1674
1675     scm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
1676     ok(scm != NULL, "Failed to open the SC Manager\n");
1677
1678     service = OpenService(scm, "TestService", SC_MANAGER_ALL_ACCESS);
1679     ok(service != NULL, "Failed to open TestService\n");
1680
1681     res = DeleteService(service);
1682     ok(res, "Failed to delete TestService\n");
1683
1684     CloseServiceHandle(service);
1685     CloseServiceHandle(scm);
1686 }
1687
1688 static BOOL notify_system_change(DWORD event_type, STATEMGRSTATUS *status)
1689 {
1690     RESTOREPOINTINFOA spec;
1691
1692     spec.dwEventType = event_type;
1693     spec.dwRestorePtType = APPLICATION_INSTALL;
1694     spec.llSequenceNumber = status->llSequenceNumber;
1695     lstrcpyA(spec.szDescription, "msitest restore point");
1696
1697     return pSRSetRestorePointA(&spec, status);
1698 }
1699
1700 static void remove_restore_point(DWORD seq_number)
1701 {
1702     DWORD res;
1703
1704     res = pSRRemoveRestorePoint(seq_number);
1705     if (res != ERROR_SUCCESS)
1706         trace("Failed to remove the restore point : %08x\n", res);
1707 }
1708
1709 static void test_MsiInstallProduct(void)
1710 {
1711     UINT r;
1712     CHAR path[MAX_PATH];
1713     LONG res;
1714     HKEY hkey;
1715     DWORD num, size, type;
1716
1717     if (on_win9x)
1718     {
1719         win_skip("Services are not implemented on Win9x and WinMe\n");
1720         return;
1721     }
1722
1723     create_test_files();
1724     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1725
1726     r = MsiInstallProductA(msifile, NULL);
1727     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1728
1729     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
1730     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
1731     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
1732     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
1733     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
1734     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
1735     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
1736     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
1737     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
1738     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
1739     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
1740     ok(delete_pf("msitest", FALSE), "File not installed\n");
1741
1742     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
1743     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1744
1745     size = MAX_PATH;
1746     type = REG_SZ;
1747     res = RegQueryValueExA(hkey, "Name", NULL, &type, (LPBYTE)path, &size);
1748     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1749     ok(!lstrcmpA(path, "imaname"), "Expected imaname, got %s\n", path);
1750
1751     size = MAX_PATH;
1752     type = REG_SZ;
1753     res = RegQueryValueExA(hkey, "blah", NULL, &type, (LPBYTE)path, &size);
1754     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
1755
1756     size = sizeof(num);
1757     type = REG_DWORD;
1758     res = RegQueryValueExA(hkey, "number", NULL, &type, (LPBYTE)&num, &size);
1759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1760     ok(num == 314, "Expected 314, got %d\n", num);
1761
1762     size = MAX_PATH;
1763     type = REG_SZ;
1764     res = RegQueryValueExA(hkey, "OrderTestName", NULL, &type, (LPBYTE)path, &size);
1765     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
1766     ok(!lstrcmpA(path, "OrderTestValue"), "Expected imaname, got %s\n", path);
1767
1768     check_service_is_installed();
1769
1770     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
1771
1772     delete_test_files();
1773 }
1774
1775 static void test_MsiSetComponentState(void)
1776 {
1777     INSTALLSTATE installed, action;
1778     MSIHANDLE package;
1779     char path[MAX_PATH];
1780     UINT r;
1781
1782     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1783
1784     CoInitialize(NULL);
1785
1786     lstrcpy(path, CURR_DIR);
1787     lstrcat(path, "\\");
1788     lstrcat(path, msifile);
1789
1790     r = MsiOpenPackage(path, &package);
1791     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1792
1793     r = MsiDoAction(package, "CostInitialize");
1794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1795
1796     r = MsiDoAction(package, "FileCost");
1797     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1798
1799     r = MsiDoAction(package, "CostFinalize");
1800     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1801
1802     r = MsiGetComponentState(package, "dangler", &installed, &action);
1803     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1804     ok(installed == INSTALLSTATE_ABSENT, "Expected INSTALLSTATE_ABSENT, got %d\n", installed);
1805     ok(action == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", action);
1806
1807     r = MsiSetComponentState(package, "dangler", INSTALLSTATE_SOURCE);
1808     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1809
1810     MsiCloseHandle(package);
1811     CoUninitialize();
1812
1813     DeleteFileA(msifile);
1814 }
1815
1816 static void test_packagecoltypes(void)
1817 {
1818     MSIHANDLE hdb, view, rec;
1819     char path[MAX_PATH];
1820     LPCSTR query;
1821     UINT r, count;
1822
1823     create_database(msifile, tables, sizeof(tables) / sizeof(msi_table));
1824
1825     CoInitialize(NULL);
1826
1827     lstrcpy(path, CURR_DIR);
1828     lstrcat(path, "\\");
1829     lstrcat(path, msifile);
1830
1831     r = MsiOpenDatabase(path, MSIDBOPEN_READONLY, &hdb);
1832     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1833
1834     query = "SELECT * FROM `Media`";
1835     r = MsiDatabaseOpenView( hdb, query, &view );
1836     ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n");
1837
1838     r = MsiViewGetColumnInfo( view, MSICOLINFO_NAMES, &rec );
1839     count = MsiRecordGetFieldCount( rec );
1840     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1841     ok(count == 6, "Expected 6, got %d\n", count);
1842     ok(check_record(rec, 1, "DiskId"), "wrong column label\n");
1843     ok(check_record(rec, 2, "LastSequence"), "wrong column label\n");
1844     ok(check_record(rec, 3, "DiskPrompt"), "wrong column label\n");
1845     ok(check_record(rec, 4, "Cabinet"), "wrong column label\n");
1846     ok(check_record(rec, 5, "VolumeLabel"), "wrong column label\n");
1847     ok(check_record(rec, 6, "Source"), "wrong column label\n");
1848     MsiCloseHandle(rec);
1849
1850     r = MsiViewGetColumnInfo( view, MSICOLINFO_TYPES, &rec );
1851     count = MsiRecordGetFieldCount( rec );
1852     ok(r == ERROR_SUCCESS, "MsiViewGetColumnInfo failed\n");
1853     ok(count == 6, "Expected 6, got %d\n", count);
1854     ok(check_record(rec, 1, "i2"), "wrong column label\n");
1855     ok(check_record(rec, 2, "i4"), "wrong column label\n");
1856     ok(check_record(rec, 3, "L64"), "wrong column label\n");
1857     ok(check_record(rec, 4, "S255"), "wrong column label\n");
1858     ok(check_record(rec, 5, "S32"), "wrong column label\n");
1859     ok(check_record(rec, 6, "S72"), "wrong column label\n");
1860
1861     MsiCloseHandle(rec);
1862     MsiCloseHandle(view);
1863     MsiCloseHandle(hdb);
1864     CoUninitialize();
1865
1866     DeleteFile(msifile);
1867 }
1868
1869 static void create_cc_test_files(void)
1870 {
1871     CCAB cabParams;
1872     HFCI hfci;
1873     ERF erf;
1874     static CHAR cab_context[] = "test%d.cab";
1875     BOOL res;
1876
1877     create_file("maximus", 500);
1878     create_file("augustus", 50000);
1879     create_file("tiberius", 500);
1880     create_file("caesar", 500);
1881
1882     set_cab_parameters(&cabParams, "test1.cab", 40000);
1883
1884     hfci = FCICreate(&erf, file_placed, mem_alloc, mem_free, fci_open,
1885                       fci_read, fci_write, fci_close, fci_seek, fci_delete,
1886                       get_temp_file, &cabParams, cab_context);
1887     ok(hfci != NULL, "Failed to create an FCI context\n");
1888
1889     res = add_file(hfci, "maximus", tcompTYPE_NONE);
1890     ok(res, "Failed to add file maximus\n");
1891
1892     res = add_file(hfci, "augustus", tcompTYPE_NONE);
1893     ok(res, "Failed to add file augustus\n");
1894
1895     res = add_file(hfci, "tiberius", tcompTYPE_NONE);
1896     ok(res, "Failed to add file tiberius\n");
1897
1898     res = FCIFlushCabinet(hfci, FALSE, get_next_cabinet, progress);
1899     ok(res, "Failed to flush the cabinet\n");
1900
1901     res = FCIDestroy(hfci);
1902     ok(res, "Failed to destroy the cabinet\n");
1903
1904     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1905
1906     DeleteFile("maximus");
1907     DeleteFile("augustus");
1908     DeleteFile("tiberius");
1909     DeleteFile("caesar");
1910 }
1911
1912 static void delete_cab_files(void)
1913 {
1914     SHFILEOPSTRUCT shfl;
1915     CHAR path[MAX_PATH+10];
1916
1917     lstrcpyA(path, CURR_DIR);
1918     lstrcatA(path, "\\*.cab");
1919     path[strlen(path) + 1] = '\0';
1920
1921     shfl.hwnd = NULL;
1922     shfl.wFunc = FO_DELETE;
1923     shfl.pFrom = path;
1924     shfl.pTo = NULL;
1925     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
1926
1927     SHFileOperation(&shfl);
1928 }
1929
1930 static void test_continuouscabs(void)
1931 {
1932     UINT r;
1933
1934     create_cc_test_files();
1935     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1936
1937     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1938
1939     r = MsiInstallProductA(msifile, NULL);
1940     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
1941     {
1942         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
1943         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
1944         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1945         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
1946         ok(delete_pf("msitest", FALSE), "File not installed\n");
1947     }
1948
1949     delete_cab_files();
1950     DeleteFile(msifile);
1951
1952     create_cc_test_files();
1953     create_database(msifile, cc2_tables, sizeof(cc2_tables) / sizeof(msi_table));
1954
1955     MsiSetInternalUI(INSTALLUILEVEL_NONE, 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 installed\n");
1961     ok(delete_pf("msitest\\tiberius", TRUE), "File not installed\n");
1962     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
1963     ok(delete_pf("msitest", FALSE), "File not installed\n");
1964
1965     delete_cab_files();
1966     DeleteFile(msifile);
1967 }
1968
1969 static void test_caborder(void)
1970 {
1971     UINT r;
1972
1973     create_file("imperator", 100);
1974     create_file("maximus", 500);
1975     create_file("augustus", 50000);
1976     create_file("caesar", 500);
1977
1978     create_database(msifile, cc_tables, sizeof(cc_tables) / sizeof(msi_table));
1979
1980     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
1981
1982     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
1983     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
1984     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
1985
1986     r = MsiInstallProductA(msifile, NULL);
1987     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
1988     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
1989     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
1990     todo_wine
1991     {
1992         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
1993         ok(!delete_pf("msitest", FALSE), "File is installed\n");
1994     }
1995
1996     delete_cab_files();
1997
1998     create_cab_file("test1.cab", MEDIA_SIZE, "imperator\0");
1999     create_cab_file("test2.cab", MEDIA_SIZE, "maximus\0augustus\0");
2000     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2001
2002     r = MsiInstallProductA(msifile, NULL);
2003     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2004     ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2005     ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2006     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2007     todo_wine
2008     {
2009         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2010     }
2011
2012     delete_cab_files();
2013     DeleteFile(msifile);
2014
2015     create_cc_test_files();
2016     create_database(msifile, co_tables, sizeof(co_tables) / sizeof(msi_table));
2017
2018     r = MsiInstallProductA(msifile, NULL);
2019     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2020     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2021     ok(!delete_pf("msitest", FALSE), "File is installed\n");
2022     todo_wine
2023     {
2024         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2025         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2026     }
2027
2028     delete_cab_files();
2029     DeleteFile(msifile);
2030
2031     create_cc_test_files();
2032     create_database(msifile, co2_tables, sizeof(co2_tables) / sizeof(msi_table));
2033
2034     r = MsiInstallProductA(msifile, NULL);
2035     ok(!delete_pf("msitest\\caesar", TRUE), "File is installed\n");
2036     todo_wine
2037     {
2038         ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
2039         ok(!delete_pf("msitest\\augustus", TRUE), "File is installed\n");
2040         ok(!delete_pf("msitest\\maximus", TRUE), "File is installed\n");
2041         ok(!delete_pf("msitest", FALSE), "File is installed\n");
2042     }
2043
2044     delete_cab_files();
2045     DeleteFile("imperator");
2046     DeleteFile("maximus");
2047     DeleteFile("augustus");
2048     DeleteFile("caesar");
2049     DeleteFile(msifile);
2050 }
2051
2052 static void test_mixedmedia(void)
2053 {
2054     UINT r;
2055
2056     CreateDirectoryA("msitest", NULL);
2057     create_file("msitest\\maximus", 500);
2058     create_file("msitest\\augustus", 500);
2059     create_file("caesar", 500);
2060
2061     create_database(msifile, mm_tables, sizeof(mm_tables) / sizeof(msi_table));
2062
2063     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2064
2065     create_cab_file("test1.cab", MEDIA_SIZE, "caesar\0");
2066
2067     r = MsiInstallProductA(msifile, NULL);
2068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2069     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2070     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2071     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2072     ok(delete_pf("msitest", FALSE), "File not installed\n");
2073
2074     /* Delete the files in the temp (current) folder */
2075     DeleteFile("msitest\\maximus");
2076     DeleteFile("msitest\\augustus");
2077     RemoveDirectory("msitest");
2078     DeleteFile("caesar");
2079     DeleteFile("test1.cab");
2080     DeleteFile(msifile);
2081 }
2082
2083 static void test_samesequence(void)
2084 {
2085     UINT r;
2086
2087     create_cc_test_files();
2088     create_database(msifile, ss_tables, sizeof(ss_tables) / sizeof(msi_table));
2089
2090     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2091
2092     r = MsiInstallProductA(msifile, NULL);
2093     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2094     {
2095         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2096         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2097         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2098         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2099         ok(delete_pf("msitest", FALSE), "File not installed\n");
2100     }
2101
2102     delete_cab_files();
2103     DeleteFile(msifile);
2104 }
2105
2106 static void test_uiLevelFlags(void)
2107 {
2108     UINT r;
2109
2110     create_cc_test_files();
2111     create_database(msifile, ui_tables, sizeof(ui_tables) / sizeof(msi_table));
2112
2113     MsiSetInternalUI(INSTALLUILEVEL_NONE | INSTALLUILEVEL_SOURCERESONLY, NULL);
2114
2115     r = MsiInstallProductA(msifile, NULL);
2116     if (r == ERROR_SUCCESS) /* win9x has a problem with this */
2117     {
2118         ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2119         ok(!delete_pf("msitest\\maximus", TRUE), "UI install occurred, but execute-only was requested.\n");
2120         ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2121         ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2122         ok(delete_pf("msitest", FALSE), "File not installed\n");
2123     }
2124
2125     delete_cab_files();
2126     DeleteFile(msifile);
2127 }
2128
2129 static BOOL file_matches(LPSTR path)
2130 {
2131     CHAR buf[MAX_PATH];
2132     HANDLE file;
2133     DWORD size;
2134
2135     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2136                       NULL, OPEN_EXISTING, 0, NULL);
2137
2138     ZeroMemory(buf, MAX_PATH);
2139     ReadFile(file, buf, 15, &size, NULL);
2140     CloseHandle(file);
2141
2142     return !lstrcmp(buf, "msitest\\maximus");
2143 }
2144
2145 static void test_readonlyfile(void)
2146 {
2147     UINT r;
2148     DWORD size;
2149     HANDLE file;
2150     CHAR path[MAX_PATH];
2151
2152     CreateDirectoryA("msitest", NULL);
2153     create_file("msitest\\maximus", 500);
2154     create_database(msifile, rof_tables, sizeof(rof_tables) / sizeof(msi_table));
2155
2156     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2157
2158     lstrcpy(path, PROG_FILES_DIR);
2159     lstrcat(path, "\\msitest");
2160     CreateDirectory(path, NULL);
2161
2162     lstrcat(path, "\\maximus");
2163     file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
2164                       NULL, CREATE_NEW, FILE_ATTRIBUTE_READONLY, NULL);
2165
2166     WriteFile(file, "readonlyfile", strlen("readonlyfile"), &size, NULL);
2167     CloseHandle(file);
2168
2169     r = MsiInstallProductA(msifile, NULL);
2170     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2171     ok(file_matches(path), "Expected file to be overwritten\n");
2172     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2173     ok(delete_pf("msitest", FALSE), "File not installed\n");
2174
2175     /* Delete the files in the temp (current) folder */
2176     DeleteFile("msitest\\maximus");
2177     RemoveDirectory("msitest");
2178     DeleteFile(msifile);
2179 }
2180
2181 static void test_setdirproperty(void)
2182 {
2183     UINT r;
2184
2185     CreateDirectoryA("msitest", NULL);
2186     create_file("msitest\\maximus", 500);
2187     create_database(msifile, sdp_tables, sizeof(sdp_tables) / sizeof(msi_table));
2188
2189     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2190
2191     r = MsiInstallProductA(msifile, NULL);
2192     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2193     ok(delete_cf("msitest\\maximus", TRUE), "File not installed\n");
2194     ok(delete_cf("msitest", FALSE), "File not installed\n");
2195
2196     /* Delete the files in the temp (current) folder */
2197     DeleteFile(msifile);
2198     DeleteFile("msitest\\maximus");
2199     RemoveDirectory("msitest");
2200 }
2201
2202 static void test_cabisextracted(void)
2203 {
2204     UINT r;
2205
2206     CreateDirectoryA("msitest", NULL);
2207     create_file("msitest\\gaius", 500);
2208     create_file("maximus", 500);
2209     create_file("augustus", 500);
2210     create_file("caesar", 500);
2211
2212     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
2213     create_cab_file("test2.cab", MEDIA_SIZE, "augustus\0");
2214     create_cab_file("test3.cab", MEDIA_SIZE, "caesar\0");
2215
2216     create_database(msifile, cie_tables, sizeof(cie_tables) / sizeof(msi_table));
2217
2218     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
2219
2220     r = MsiInstallProductA(msifile, NULL);
2221     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2222     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2223     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
2224     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
2225     ok(delete_pf("msitest\\gaius", TRUE), "File not installed\n");
2226     ok(delete_pf("msitest", FALSE), "File not installed\n");
2227
2228     /* Delete the files in the temp (current) folder */
2229     delete_cab_files();
2230     DeleteFile(msifile);
2231     DeleteFile("maximus");
2232     DeleteFile("augustus");
2233     DeleteFile("caesar");
2234     DeleteFile("msitest\\gaius");
2235     RemoveDirectory("msitest");
2236 }
2237
2238 static void test_concurrentinstall(void)
2239 {
2240     UINT r;
2241     CHAR path[MAX_PATH];
2242
2243     CreateDirectoryA("msitest", NULL);
2244     CreateDirectoryA("msitest\\msitest", NULL);
2245     create_file("msitest\\maximus", 500);
2246     create_file("msitest\\msitest\\augustus", 500);
2247
2248     create_database(msifile, ci_tables, sizeof(ci_tables) / sizeof(msi_table));
2249
2250     lstrcpyA(path, CURR_DIR);
2251     lstrcatA(path, "\\msitest\\concurrent.msi");
2252     create_database(path, ci2_tables, sizeof(ci2_tables) / sizeof(msi_table));
2253
2254     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2255
2256     r = MsiInstallProductA(msifile, NULL);
2257     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2258     if (!delete_pf("msitest\\augustus", TRUE))
2259         trace("concurrent installs not supported\n");
2260     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2261     ok(delete_pf("msitest", FALSE), "File not installed\n");
2262
2263     DeleteFile(path);
2264
2265     r = MsiInstallProductA(msifile, NULL);
2266     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2267     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2268     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
2269     ok(delete_pf("msitest", FALSE), "File not installed\n");
2270
2271     DeleteFile(msifile);
2272     DeleteFile("msitest\\msitest\\augustus");
2273     DeleteFile("msitest\\maximus");
2274     RemoveDirectory("msitest\\msitest");
2275     RemoveDirectory("msitest");
2276 }
2277
2278 static void test_setpropertyfolder(void)
2279 {
2280     UINT r;
2281     CHAR path[MAX_PATH];
2282
2283     lstrcpyA(path, PROG_FILES_DIR);
2284     lstrcatA(path, "\\msitest\\added");
2285
2286     CreateDirectoryA("msitest", NULL);
2287     create_file("msitest\\maximus", 500);
2288
2289     create_database(msifile, spf_tables, sizeof(spf_tables) / sizeof(msi_table));
2290
2291     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2292
2293     r = MsiInstallProductA(msifile, NULL);
2294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
2295     if (GetFileAttributesA(path) == FILE_ATTRIBUTE_DIRECTORY)
2296     {
2297         ok(delete_pf("msitest\\added\\maximus", TRUE), "File not installed\n");
2298         ok(delete_pf("msitest\\added", FALSE), "File not installed\n");
2299         ok(delete_pf("msitest", FALSE), "File not installed\n");
2300     }
2301     else
2302     {
2303         trace("changing folder property not supported\n");
2304         ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2305         ok(delete_pf("msitest", FALSE), "File not installed\n");
2306     }
2307
2308     /* Delete the files in the temp (current) folder */
2309     DeleteFile(msifile);
2310     DeleteFile("msitest\\maximus");
2311     RemoveDirectory("msitest");
2312 }
2313
2314 static BOOL file_exists(LPCSTR file)
2315 {
2316     return GetFileAttributes(file) != INVALID_FILE_ATTRIBUTES;
2317 }
2318
2319 static BOOL pf_exists(LPCSTR file)
2320 {
2321     CHAR path[MAX_PATH];
2322
2323     lstrcpyA(path, PROG_FILES_DIR);
2324     lstrcatA(path, "\\");
2325     lstrcatA(path, file);
2326
2327     return file_exists(path);
2328 }
2329
2330 static void delete_pfmsitest_files(void)
2331 {
2332     SHFILEOPSTRUCT shfl;
2333     CHAR path[MAX_PATH+11];
2334
2335     lstrcpyA(path, PROG_FILES_DIR);
2336     lstrcatA(path, "\\msitest\\*");
2337     path[strlen(path) + 1] = '\0';
2338
2339     shfl.hwnd = NULL;
2340     shfl.wFunc = FO_DELETE;
2341     shfl.pFrom = path;
2342     shfl.pTo = NULL;
2343     shfl.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_NORECURSION | FOF_SILENT;
2344
2345     SHFileOperation(&shfl);
2346
2347     lstrcpyA(path, PROG_FILES_DIR);
2348     lstrcatA(path, "\\msitest");
2349     RemoveDirectoryA(path);
2350 }
2351
2352 static void check_reg_str(HKEY prodkey, LPCSTR name, LPCSTR expected, BOOL bcase, DWORD line)
2353 {
2354     char val[MAX_PATH];
2355     DWORD size, type;
2356     LONG res;
2357
2358     size = MAX_PATH;
2359     val[0] = '\0';
2360     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)val, &size);
2361
2362     if (res != ERROR_SUCCESS ||
2363         (type != REG_SZ && type != REG_EXPAND_SZ && type != REG_MULTI_SZ))
2364     {
2365         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2366         return;
2367     }
2368
2369     if (!expected)
2370         ok_(__FILE__, line)(lstrlenA(val) == 0, "Expected empty string, got %s\n", val);
2371     else
2372     {
2373         if (bcase)
2374             ok_(__FILE__, line)(!lstrcmpA(val, expected), "Expected %s, got %s\n", expected, val);
2375         else
2376             ok_(__FILE__, line)(!lstrcmpiA(val, expected), "Expected %s, got %s\n", expected, val);
2377     }
2378 }
2379
2380 static void check_reg_dword(HKEY prodkey, LPCSTR name, DWORD expected, DWORD line)
2381 {
2382     DWORD val, size, type;
2383     LONG res;
2384
2385     size = sizeof(DWORD);
2386     res = RegQueryValueExA(prodkey, name, NULL, &type, (LPBYTE)&val, &size);
2387
2388     if (res != ERROR_SUCCESS || type != REG_DWORD)
2389     {
2390         ok_(__FILE__, line)(FALSE, "Key doesn't exist or wrong type\n");
2391         return;
2392     }
2393
2394     ok_(__FILE__, line)(val == expected, "Expected %d, got %d\n", expected, val);
2395 }
2396
2397 #define CHECK_REG_STR(prodkey, name, expected) \
2398     check_reg_str(prodkey, name, expected, TRUE, __LINE__);
2399
2400 #define CHECK_DEL_REG_STR(prodkey, name, expected) \
2401     check_reg_str(prodkey, name, expected, TRUE, __LINE__); \
2402     RegDeleteValueA(prodkey, name);
2403
2404 #define CHECK_REG_ISTR(prodkey, name, expected) \
2405     check_reg_str(prodkey, name, expected, FALSE, __LINE__);
2406
2407 #define CHECK_DEL_REG_ISTR(prodkey, name, expected) \
2408     check_reg_str(prodkey, name, expected, FALSE, __LINE__); \
2409     RegDeleteValueA(prodkey, name);
2410
2411 #define CHECK_REG_DWORD(prodkey, name, expected) \
2412     check_reg_dword(prodkey, name, expected, __LINE__);
2413
2414 #define CHECK_DEL_REG_DWORD(prodkey, name, expected) \
2415     check_reg_dword(prodkey, name, expected, __LINE__); \
2416     RegDeleteValueA(prodkey, name);
2417
2418 static void get_date_str(LPSTR date)
2419 {
2420     SYSTEMTIME systime;
2421
2422     static const char date_fmt[] = "%d%02d%02d";
2423     GetLocalTime(&systime);
2424     sprintf(date, date_fmt, systime.wYear, systime.wMonth, systime.wDay);
2425 }
2426
2427 static void test_publish_registerproduct(void)
2428 {
2429     UINT r;
2430     LONG res;
2431     HKEY hkey;
2432     HKEY props, usage;
2433     LPSTR usersid;
2434     char date[MAX_PATH];
2435     char temp[MAX_PATH];
2436     char keypath[MAX_PATH];
2437
2438     static const CHAR uninstall[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2439                                     "\\Uninstall\\{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
2440     static const CHAR userdata[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
2441                                    "\\UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2442     static const CHAR ugkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Installer"
2443                                 "\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
2444     static const CHAR userugkey[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
2445                                     "\\51AAE0C44620A5E4788506E91F249BD2";
2446
2447     get_user_sid(&usersid);
2448     if (!usersid)
2449     {
2450         skip("ConvertSidToStringSidA is not available\n");
2451         return;
2452     }
2453
2454     get_date_str(date);
2455     GetTempPath(MAX_PATH, temp);
2456
2457     CreateDirectoryA("msitest", NULL);
2458     create_file("msitest\\maximus", 500);
2459
2460     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2461
2462     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2463
2464     /* RegisterProduct */
2465     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
2466     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2467     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2468     ok(delete_pf("msitest", FALSE), "File not installed\n");
2469
2470     res = RegOpenKeyA(HKEY_CURRENT_USER, userugkey, &hkey);
2471     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2472
2473     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
2474     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2475
2476     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
2477     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
2478     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
2479     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
2480     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2481     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
2482     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2483     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
2484     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
2485     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
2486     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
2487     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
2488     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
2489     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
2490     CHECK_DEL_REG_STR(hkey, "Size", NULL);
2491     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
2492     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
2493     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2494     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2495     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
2496     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
2497     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
2498     todo_wine
2499     {
2500         CHECK_DEL_REG_DWORD(hkey, "EstimatedSize", 12);
2501     }
2502
2503     RegDeleteKeyA(hkey, "");
2504     RegCloseKey(hkey);
2505
2506     sprintf(keypath, userdata, usersid);
2507     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2508     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2509
2510     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2511     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2512
2513     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
2514     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
2515     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
2516     CHECK_DEL_REG_STR(props, "InstallDate", date);
2517     CHECK_DEL_REG_STR(props, "InstallSource", temp);
2518     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2519     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
2520     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2521     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
2522     CHECK_DEL_REG_STR(props, "Comments", NULL);
2523     CHECK_DEL_REG_STR(props, "Contact", NULL);
2524     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
2525     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
2526     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
2527     CHECK_DEL_REG_STR(props, "Readme", NULL);
2528     CHECK_DEL_REG_STR(props, "Size", NULL);
2529     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
2530     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
2531     CHECK_DEL_REG_DWORD(props, "Language", 1033);
2532     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
2533     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
2534     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
2535     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
2536     todo_wine
2537     {
2538         CHECK_DEL_REG_DWORD(props, "EstimatedSize", 12);
2539     }
2540
2541     RegDeleteKeyA(props, "");
2542     RegCloseKey(props);
2543
2544     res = RegOpenKeyA(hkey, "Usage", &usage);
2545     todo_wine
2546     {
2547         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2548     }
2549
2550     RegDeleteKeyA(usage, "");
2551     RegCloseKey(usage);
2552     RegDeleteKeyA(hkey, "");
2553     RegCloseKey(hkey);
2554
2555     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
2556     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2557
2558     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2559
2560     RegDeleteKeyA(hkey, "");
2561     RegCloseKey(hkey);
2562
2563     /* RegisterProduct, machine */
2564     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 ALLUSERS=1");
2565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2566     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2567     ok(delete_pf("msitest", FALSE), "File not installed\n");
2568
2569     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, userugkey, &hkey);
2570     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2571
2572     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, uninstall, &hkey);
2573     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2574
2575     CHECK_DEL_REG_STR(hkey, "DisplayName", "MSITEST");
2576     CHECK_DEL_REG_STR(hkey, "DisplayVersion", "1.1.1");
2577     CHECK_DEL_REG_STR(hkey, "InstallDate", date);
2578     CHECK_DEL_REG_STR(hkey, "InstallSource", temp);
2579     CHECK_DEL_REG_ISTR(hkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2580     CHECK_DEL_REG_STR(hkey, "Publisher", "Wine");
2581     CHECK_DEL_REG_STR(hkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2582     CHECK_DEL_REG_STR(hkey, "AuthorizedCDFPrefix", NULL);
2583     CHECK_DEL_REG_STR(hkey, "Comments", NULL);
2584     CHECK_DEL_REG_STR(hkey, "Contact", NULL);
2585     CHECK_DEL_REG_STR(hkey, "HelpLink", NULL);
2586     CHECK_DEL_REG_STR(hkey, "HelpTelephone", NULL);
2587     CHECK_DEL_REG_STR(hkey, "InstallLocation", NULL);
2588     CHECK_DEL_REG_STR(hkey, "Readme", NULL);
2589     CHECK_DEL_REG_STR(hkey, "Size", NULL);
2590     CHECK_DEL_REG_STR(hkey, "URLInfoAbout", NULL);
2591     CHECK_DEL_REG_STR(hkey, "URLUpdateInfo", NULL);
2592     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2593     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2594     CHECK_DEL_REG_DWORD(hkey, "VersionMajor", 1);
2595     CHECK_DEL_REG_DWORD(hkey, "VersionMinor", 1);
2596     CHECK_DEL_REG_DWORD(hkey, "WindowsInstaller", 1);
2597     todo_wine
2598     {
2599         CHECK_DEL_REG_DWORD(hkey, "EstimatedSize", 12);
2600     }
2601
2602     RegDeleteKeyA(hkey, "");
2603     RegCloseKey(hkey);
2604
2605     sprintf(keypath, userdata, "S-1-5-18");
2606     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2607     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2608
2609     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2610     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2611
2612     RegDeleteValueA(props, "LocalPackage"); /* LocalPackage is nondeterministic */
2613     CHECK_DEL_REG_STR(props, "DisplayName", "MSITEST");
2614     CHECK_DEL_REG_STR(props, "DisplayVersion", "1.1.1");
2615     CHECK_DEL_REG_STR(props, "InstallDate", date);
2616     CHECK_DEL_REG_STR(props, "InstallSource", temp);
2617     CHECK_DEL_REG_ISTR(props, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2618     CHECK_DEL_REG_STR(props, "Publisher", "Wine");
2619     CHECK_DEL_REG_STR(props, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
2620     CHECK_DEL_REG_STR(props, "AuthorizedCDFPrefix", NULL);
2621     CHECK_DEL_REG_STR(props, "Comments", NULL);
2622     CHECK_DEL_REG_STR(props, "Contact", NULL);
2623     CHECK_DEL_REG_STR(props, "HelpLink", NULL);
2624     CHECK_DEL_REG_STR(props, "HelpTelephone", NULL);
2625     CHECK_DEL_REG_STR(props, "InstallLocation", NULL);
2626     CHECK_DEL_REG_STR(props, "Readme", NULL);
2627     CHECK_DEL_REG_STR(props, "Size", NULL);
2628     CHECK_DEL_REG_STR(props, "URLInfoAbout", NULL);
2629     CHECK_DEL_REG_STR(props, "URLUpdateInfo", NULL);
2630     CHECK_DEL_REG_DWORD(props, "Language", 1033);
2631     CHECK_DEL_REG_DWORD(props, "Version", 0x1010001);
2632     CHECK_DEL_REG_DWORD(props, "VersionMajor", 1);
2633     CHECK_DEL_REG_DWORD(props, "VersionMinor", 1);
2634     CHECK_DEL_REG_DWORD(props, "WindowsInstaller", 1);
2635     todo_wine
2636     {
2637         CHECK_DEL_REG_DWORD(props, "EstimatedSize", 12);
2638     }
2639
2640     RegDeleteKeyA(props, "");
2641     RegCloseKey(props);
2642
2643     res = RegOpenKeyA(hkey, "Usage", &usage);
2644     todo_wine
2645     {
2646         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2647     }
2648
2649     RegDeleteKeyA(usage, "");
2650     RegCloseKey(usage);
2651     RegDeleteKeyA(hkey, "");
2652     RegCloseKey(hkey);
2653
2654     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, ugkey, &hkey);
2655     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2656
2657     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2658
2659     RegDeleteKeyA(hkey, "");
2660     RegCloseKey(hkey);
2661
2662     DeleteFile(msifile);
2663     DeleteFile("msitest\\maximus");
2664     RemoveDirectory("msitest");
2665     HeapFree(GetProcessHeap(), 0, usersid);
2666 }
2667
2668 static void test_publish_publishproduct(void)
2669 {
2670     UINT r;
2671     LONG res;
2672     LPSTR usersid;
2673     HKEY sourcelist, net, props;
2674     HKEY hkey, patches, media;
2675     CHAR keypath[MAX_PATH];
2676     CHAR temp[MAX_PATH];
2677     CHAR path[MAX_PATH];
2678
2679     static const CHAR prodpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2680                                    "\\Installer\\UserData\\%s\\Products"
2681                                    "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2682     static const CHAR cuprodpath[] = "Software\\Microsoft\\Installer\\Products"
2683                                      "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2684     static const CHAR cuupgrades[] = "Software\\Microsoft\\Installer\\UpgradeCodes"
2685                                      "\\51AAE0C44620A5E4788506E91F249BD2";
2686     static const CHAR badprod[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2687                                   "\\Installer\\Products"
2688                                   "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2689     static const CHAR machprod[] = "Installer\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2690     static const CHAR machup[] = "Installer\\UpgradeCodes\\51AAE0C44620A5E4788506E91F249BD2";
2691
2692     get_user_sid(&usersid);
2693     if (!usersid)
2694     {
2695         skip("ConvertSidToStringSidA is not available\n");
2696         return;
2697     }
2698
2699     GetTempPath(MAX_PATH, temp);
2700
2701     CreateDirectoryA("msitest", NULL);
2702     create_file("msitest\\maximus", 500);
2703
2704     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2705
2706     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2707
2708     /* PublishProduct, current user */
2709     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
2710     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2711     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2712     ok(delete_pf("msitest", FALSE), "File not installed\n");
2713
2714     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
2715     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2716
2717     sprintf(keypath, prodpath, usersid);
2718     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2719     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2720
2721     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2722     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2723
2724     res = RegOpenKeyA(hkey, "Patches", &patches);
2725     todo_wine
2726     {
2727         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2728
2729         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
2730     }
2731
2732     RegDeleteKeyA(patches, "");
2733     RegCloseKey(patches);
2734     RegDeleteKeyA(hkey, "");
2735     RegCloseKey(hkey);
2736
2737     res = RegOpenKeyA(HKEY_CURRENT_USER, cuprodpath, &hkey);
2738     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2739
2740     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
2741     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
2742     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2743     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2744     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
2745     CHECK_DEL_REG_DWORD(hkey, "Assignment", 0);
2746     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
2747     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
2748     CHECK_DEL_REG_STR(hkey, "Clients", ":");
2749
2750     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
2751     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2752
2753     lstrcpyA(path, "n;1;");
2754     lstrcatA(path, temp);
2755     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
2756     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
2757
2758     res = RegOpenKeyA(sourcelist, "Net", &net);
2759     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2760
2761     CHECK_DEL_REG_STR(net, "1", temp);
2762
2763     RegDeleteKeyA(net, "");
2764     RegCloseKey(net);
2765
2766     res = RegOpenKeyA(sourcelist, "Media", &media);
2767     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2768
2769     CHECK_DEL_REG_STR(media, "1", "DISK1;");
2770
2771     RegDeleteKeyA(media, "");
2772     RegCloseKey(media);
2773     RegDeleteKeyA(sourcelist, "");
2774     RegCloseKey(sourcelist);
2775     RegDeleteKeyA(hkey, "");
2776     RegCloseKey(hkey);
2777
2778     res = RegOpenKeyA(HKEY_CURRENT_USER, cuupgrades, &hkey);
2779     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2780
2781     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2782
2783     RegDeleteKeyA(hkey, "");
2784     RegCloseKey(hkey);
2785
2786     /* PublishProduct, machine */
2787     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1 ALLUSERS=1");
2788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2789     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2790     ok(delete_pf("msitest", FALSE), "File not installed\n");
2791
2792     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, badprod, &hkey);
2793     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2794
2795     sprintf(keypath, prodpath, "S-1-5-18");
2796     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2797     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2798
2799     res = RegOpenKeyA(hkey, "InstallProperties", &props);
2800     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2801
2802     res = RegOpenKeyA(hkey, "Patches", &patches);
2803     todo_wine
2804     {
2805         ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2806
2807         CHECK_DEL_REG_STR(patches, "AllPatches", NULL);
2808     }
2809
2810     RegDeleteKeyA(patches, "");
2811     RegCloseKey(patches);
2812     RegDeleteKeyA(hkey, "");
2813     RegCloseKey(hkey);
2814
2815     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machprod, &hkey);
2816     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2817
2818     CHECK_DEL_REG_STR(hkey, "ProductName", "MSITEST");
2819     CHECK_DEL_REG_STR(hkey, "PackageCode", "AC75740029052c94DA02821EECD05F2F");
2820     CHECK_DEL_REG_DWORD(hkey, "Language", 1033);
2821     CHECK_DEL_REG_DWORD(hkey, "Version", 0x1010001);
2822     CHECK_DEL_REG_DWORD(hkey, "AuthorizedLUAApp", 0);
2823     todo_wine CHECK_DEL_REG_DWORD(hkey, "Assignment", 1);
2824     CHECK_DEL_REG_DWORD(hkey, "AdvertiseFlags", 0x184);
2825     CHECK_DEL_REG_DWORD(hkey, "InstanceType", 0);
2826     CHECK_DEL_REG_STR(hkey, "Clients", ":");
2827
2828     res = RegOpenKeyA(hkey, "SourceList", &sourcelist);
2829     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2830
2831     lstrcpyA(path, "n;1;");
2832     lstrcatA(path, temp);
2833     CHECK_DEL_REG_STR(sourcelist, "LastUsedSource", path);
2834     CHECK_DEL_REG_STR(sourcelist, "PackageName", "msitest.msi");
2835
2836     res = RegOpenKeyA(sourcelist, "Net", &net);
2837     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2838
2839     CHECK_DEL_REG_STR(net, "1", temp);
2840
2841     RegDeleteKeyA(net, "");
2842     RegCloseKey(net);
2843
2844     res = RegOpenKeyA(sourcelist, "Media", &media);
2845     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2846
2847     CHECK_DEL_REG_STR(media, "1", "DISK1;");
2848
2849     RegDeleteKeyA(media, "");
2850     RegCloseKey(media);
2851     RegDeleteKeyA(sourcelist, "");
2852     RegCloseKey(sourcelist);
2853     RegDeleteKeyA(hkey, "");
2854     RegCloseKey(hkey);
2855
2856     res = RegOpenKeyA(HKEY_CLASSES_ROOT, machup, &hkey);
2857     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2858
2859     CHECK_DEL_REG_STR(hkey, "84A88FD7F6998CE40A22FB59F6B9C2BB", NULL);
2860
2861     RegDeleteKeyA(hkey, "");
2862     RegCloseKey(hkey);
2863
2864     DeleteFile(msifile);
2865     DeleteFile("msitest\\maximus");
2866     RemoveDirectory("msitest");
2867     HeapFree(GetProcessHeap(), 0, usersid);
2868 }
2869
2870 static void test_publish_publishfeatures(void)
2871 {
2872     UINT r;
2873     LONG res;
2874     HKEY hkey;
2875     LPSTR usersid;
2876     CHAR keypath[MAX_PATH];
2877
2878     static const CHAR cupath[] = "Software\\Microsoft\\Installer\\Features"
2879                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2880     static const CHAR udpath[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2881                                  "\\Installer\\UserData\\%s\\Products"
2882                                  "\\84A88FD7F6998CE40A22FB59F6B9C2BB\\Features";
2883     static const CHAR featkey[] = "Software\\Microsoft\\Windows\\CurrentVersion"
2884                                   "\\Installer\\Features";
2885     static const CHAR classfeat[] = "Software\\Classes\\Installer\\Features"
2886                                     "\\84A88FD7F6998CE40A22FB59F6B9C2BB";
2887
2888     get_user_sid(&usersid);
2889     if (!usersid)
2890     {
2891         skip("ConvertSidToStringSidA is not available\n");
2892         return;
2893     }
2894
2895     CreateDirectoryA("msitest", NULL);
2896     create_file("msitest\\maximus", 500);
2897
2898     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
2899
2900     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
2901
2902     /* PublishFeatures, current user */
2903     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
2904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2905     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2906     ok(delete_pf("msitest", FALSE), "File not installed\n");
2907
2908     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
2909     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2910
2911     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
2912     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2913
2914     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
2915     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2916
2917     CHECK_REG_STR(hkey, "feature", "");
2918     CHECK_REG_STR(hkey, "montecristo", "");
2919
2920     RegDeleteValueA(hkey, "feature");
2921     RegDeleteValueA(hkey, "montecristo");
2922     RegDeleteKeyA(hkey, "");
2923     RegCloseKey(hkey);
2924
2925     sprintf(keypath, udpath, usersid);
2926     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2927     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2928
2929     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
2930     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
2931
2932     RegDeleteValueA(hkey, "feature");
2933     RegDeleteValueA(hkey, "montecristo");
2934     RegDeleteKeyA(hkey, "");
2935     RegCloseKey(hkey);
2936
2937     /* PublishFeatures, machine */
2938     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1 ALLUSERS=1");
2939     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
2940     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
2941     ok(delete_pf("msitest", FALSE), "File not installed\n");
2942
2943     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, featkey, &hkey);
2944     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2945
2946     res = RegOpenKeyA(HKEY_CURRENT_USER, cupath, &hkey);
2947     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
2948
2949     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, classfeat, &hkey);
2950     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2951
2952     CHECK_REG_STR(hkey, "feature", "");
2953     CHECK_REG_STR(hkey, "montecristo", "");
2954
2955     RegDeleteValueA(hkey, "feature");
2956     RegDeleteValueA(hkey, "montecristo");
2957     RegDeleteKeyA(hkey, "");
2958     RegCloseKey(hkey);
2959
2960     sprintf(keypath, udpath, "S-1-5-18");
2961     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &hkey);
2962     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
2963
2964     CHECK_REG_STR(hkey, "feature", "VGtfp^p+,?82@JU1j_KE");
2965     CHECK_REG_STR(hkey, "montecristo", "VGtfp^p+,?82@JU1j_KE");
2966
2967     RegDeleteValueA(hkey, "feature");
2968     RegDeleteValueA(hkey, "montecristo");
2969     RegDeleteKeyA(hkey, "");
2970     RegCloseKey(hkey);
2971
2972     DeleteFile(msifile);
2973     DeleteFile("msitest\\maximus");
2974     RemoveDirectory("msitest");
2975     HeapFree(GetProcessHeap(), 0, usersid);
2976 }
2977
2978 static LPSTR reg_get_val_str(HKEY hkey, LPCSTR name)
2979 {
2980     DWORD len = 0;
2981     LPSTR val;
2982     LONG r;
2983
2984     r = RegQueryValueExA(hkey, name, NULL, NULL, NULL, &len);
2985     if (r != ERROR_SUCCESS)
2986         return NULL;
2987
2988     len += sizeof (WCHAR);
2989     val = HeapAlloc(GetProcessHeap(), 0, len);
2990     if (!val) return NULL;
2991     val[0] = 0;
2992     RegQueryValueExA(hkey, name, NULL, NULL, (LPBYTE)val, &len);
2993     return val;
2994 }
2995
2996 static void get_owner_company(LPSTR *owner, LPSTR *company)
2997 {
2998     LONG res;
2999     HKEY hkey;
3000
3001     *owner = *company = NULL;
3002
3003     res = RegOpenKeyA(HKEY_CURRENT_USER,
3004                       "Software\\Microsoft\\MS Setup (ACME)\\User Info", &hkey);
3005     if (res == ERROR_SUCCESS)
3006     {
3007         *owner = reg_get_val_str(hkey, "DefName");
3008         *company = reg_get_val_str(hkey, "DefCompany");
3009         RegCloseKey(hkey);
3010     }
3011
3012     if (!*owner || !*company)
3013     {
3014         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
3015                           "Software\\Microsoft\\Windows\\CurrentVersion", &hkey);
3016         if (res == ERROR_SUCCESS)
3017         {
3018             *owner = reg_get_val_str(hkey, "RegisteredOwner");
3019             *company = reg_get_val_str(hkey, "RegisteredOrganization");
3020             RegCloseKey(hkey);
3021         }
3022     }
3023
3024     if (!*owner || !*company)
3025     {
3026         res = RegOpenKeyA(HKEY_LOCAL_MACHINE,
3027                           "Software\\Microsoft\\Windows NT\\CurrentVersion", &hkey);
3028         if (res == ERROR_SUCCESS)
3029         {
3030             *owner = reg_get_val_str(hkey, "RegisteredOwner");
3031             *company = reg_get_val_str(hkey, "RegisteredOrganization");
3032             RegCloseKey(hkey);
3033         }
3034     }
3035 }
3036
3037 static void test_publish_registeruser(void)
3038 {
3039     UINT r;
3040     LONG res;
3041     HKEY props;
3042     LPSTR usersid;
3043     LPSTR owner, company;
3044     CHAR keypath[MAX_PATH];
3045
3046     static const CHAR keyfmt[] =
3047         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
3048         "UserData\\%s\\Products\\84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties";
3049
3050     get_user_sid(&usersid);
3051     if (!usersid)
3052     {
3053         skip("ConvertSidToStringSidA is not available\n");
3054         return;
3055     }
3056
3057     get_owner_company(&owner, &company);
3058
3059     CreateDirectoryA("msitest", NULL);
3060     create_file("msitest\\maximus", 500);
3061
3062     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3063
3064     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3065
3066     /* RegisterUser, per-user */
3067     r = MsiInstallProductA(msifile, "REGISTER_USER=1");
3068     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3069     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3070     ok(delete_pf("msitest", FALSE), "File not installed\n");
3071
3072     sprintf(keypath, keyfmt, usersid);
3073
3074     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
3075     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3076
3077     CHECK_REG_STR(props, "ProductID", "none");
3078     CHECK_REG_STR(props, "RegCompany", company);
3079     CHECK_REG_STR(props, "RegOwner", owner);
3080
3081     RegDeleteValueA(props, "ProductID");
3082     RegDeleteValueA(props, "RegCompany");
3083     RegDeleteValueA(props, "RegOwner");
3084     RegDeleteKeyA(props, "");
3085     RegCloseKey(props);
3086
3087     /* RegisterUser, machine */
3088     r = MsiInstallProductA(msifile, "REGISTER_USER=1 ALLUSERS=1");
3089     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3090     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3091     ok(delete_pf("msitest", FALSE), "File not installed\n");
3092
3093     sprintf(keypath, keyfmt, "S-1-5-18");
3094
3095     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
3096     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3097
3098     CHECK_REG_STR(props, "ProductID", "none");
3099     CHECK_REG_STR(props, "RegCompany", company);
3100     CHECK_REG_STR(props, "RegOwner", owner);
3101
3102     RegDeleteValueA(props, "ProductID");
3103     RegDeleteValueA(props, "RegCompany");
3104     RegDeleteValueA(props, "RegOwner");
3105     RegDeleteKeyA(props, "");
3106     RegCloseKey(props);
3107
3108     HeapFree(GetProcessHeap(), 0, company);
3109     HeapFree(GetProcessHeap(), 0, owner);
3110
3111     DeleteFile(msifile);
3112     DeleteFile("msitest\\maximus");
3113     RemoveDirectory("msitest");
3114 }
3115
3116 static void test_publish_processcomponents(void)
3117 {
3118     UINT r;
3119     LONG res;
3120     DWORD size;
3121     HKEY comp, hkey;
3122     LPSTR usersid;
3123     CHAR val[MAX_PATH];
3124     CHAR keypath[MAX_PATH];
3125     CHAR program_files_maximus[MAX_PATH];
3126
3127     static const CHAR keyfmt[] =
3128         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\"
3129         "UserData\\%s\\Components\\%s";
3130     static const CHAR compkey[] =
3131         "Software\\Microsoft\\Windows\\CurrentVersion\\Installer\\Components";
3132
3133     get_user_sid(&usersid);
3134     if (!usersid)
3135     {
3136         skip("ConvertSidToStringSidA is not available\n");
3137         return;
3138     }
3139
3140     CreateDirectoryA("msitest", NULL);
3141     create_file("msitest\\maximus", 500);
3142
3143     create_database(msifile, ppc_tables, sizeof(ppc_tables) / sizeof(msi_table));
3144
3145     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3146
3147     /* ProcessComponents, per-user */
3148     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3149     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3150     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3151     ok(delete_pf("msitest", FALSE), "File not installed\n");
3152
3153     sprintf(keypath, keyfmt, usersid, "CBABC2FDCCB35E749A8944D8C1C098B5");
3154
3155     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3156     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3157
3158     size = MAX_PATH;
3159     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3160                            NULL, NULL, (LPBYTE)val, &size);
3161     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3162
3163     lstrcpyA(program_files_maximus,PROG_FILES_DIR);
3164     lstrcatA(program_files_maximus,"\\msitest\\maximus");
3165
3166     ok(!lstrcmpA(val, program_files_maximus),
3167        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
3168
3169     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3170     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3171
3172     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3173     RegDeleteKeyA(comp, "");
3174     RegCloseKey(comp);
3175
3176     sprintf(keypath, keyfmt, usersid, "241C3DA58FECD0945B9687D408766058");
3177
3178     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3179     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3180
3181     size = MAX_PATH;
3182     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3183                            NULL, NULL, (LPBYTE)val, &size);
3184     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3185     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
3186        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
3187
3188     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3189     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3190
3191     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3192     RegDeleteKeyA(comp, "");
3193     RegCloseKey(comp);
3194
3195     /* ProcessComponents, machine */
3196     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1 ALLUSERS=1");
3197     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3198     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
3199     ok(delete_pf("msitest", FALSE), "File not installed\n");
3200
3201     sprintf(keypath, keyfmt, "S-1-5-18", "CBABC2FDCCB35E749A8944D8C1C098B5");
3202
3203     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3204     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3205
3206     size = MAX_PATH;
3207     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3208                            NULL, NULL, (LPBYTE)val, &size);
3209     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3210     ok(!lstrcmpA(val, program_files_maximus),
3211        "Expected \"%s\", got \"%s\"\n", program_files_maximus, val);
3212
3213     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3214     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3215
3216     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3217     RegDeleteKeyA(comp, "");
3218     RegCloseKey(comp);
3219
3220     sprintf(keypath, keyfmt, "S-1-5-18", "241C3DA58FECD0945B9687D408766058");
3221
3222     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &comp);
3223     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3224
3225     size = MAX_PATH;
3226     res = RegQueryValueExA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB",
3227                            NULL, NULL, (LPBYTE)val, &size);
3228     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3229     ok(!lstrcmpA(val, "01\\msitest\\augustus"),
3230        "Expected \"01\\msitest\\augustus\", got \"%s\"\n", val);
3231
3232     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, compkey, &hkey);
3233     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3234
3235     RegDeleteValueA(comp, "84A88FD7F6998CE40A22FB59F6B9C2BB");
3236     RegDeleteKeyA(comp, "");
3237     RegCloseKey(comp);
3238
3239     DeleteFile(msifile);
3240     DeleteFile("msitest\\maximus");
3241     RemoveDirectory("msitest");
3242 }
3243
3244 static void test_publish(void)
3245 {
3246     UINT r;
3247     LONG res;
3248     HKEY uninstall, prodkey;
3249     INSTALLSTATE state;
3250     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3251     char date[MAX_PATH];
3252     char temp[MAX_PATH];
3253
3254     static const CHAR subkey[] = "Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
3255
3256     if (!pMsiQueryComponentStateA)
3257     {
3258         skip("MsiQueryComponentStateA is not available\n");
3259         return;
3260     }
3261
3262     get_date_str(date);
3263     GetTempPath(MAX_PATH, temp);
3264
3265     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, subkey, &uninstall);
3266     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3267
3268     CreateDirectoryA("msitest", NULL);
3269     create_file("msitest\\maximus", 500);
3270
3271     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3272
3273     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3274
3275     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3276     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3277
3278     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3279     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3280
3281     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3282     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3283
3284     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3285                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3286     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3287     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3288
3289     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3290     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3291
3292     /* nothing published */
3293     r = MsiInstallProductA(msifile, NULL);
3294     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3295     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3296     ok(pf_exists("msitest"), "File not installed\n");
3297
3298     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3299     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3300
3301     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3302     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3303
3304     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3305     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3306
3307     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3308                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3309     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3310     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3311
3312     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3313     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3314
3315     /* PublishProduct and RegisterProduct */
3316     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1 PUBLISH_PRODUCT=1");
3317     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3318     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3319     ok(pf_exists("msitest"), "File not installed\n");
3320
3321     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3322     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3323
3324     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3325     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3326
3327     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3328     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3329
3330     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3331                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3332     ok(r == ERROR_UNKNOWN_COMPONENT, "Expected ERROR_UNKNOWN_COMPONENT, got %d\n", r);
3333     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3334
3335     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3336     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3337
3338     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3339     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3340     CHECK_REG_STR(prodkey, "InstallDate", date);
3341     CHECK_REG_STR(prodkey, "InstallSource", temp);
3342     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3343     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3344     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3345     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3346     CHECK_REG_STR(prodkey, "Comments", NULL);
3347     CHECK_REG_STR(prodkey, "Contact", NULL);
3348     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3349     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3350     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3351     CHECK_REG_STR(prodkey, "Readme", NULL);
3352     CHECK_REG_STR(prodkey, "Size", NULL);
3353     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3354     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3355     CHECK_REG_DWORD(prodkey, "Language", 1033);
3356     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3357     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3358     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3359     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3360     todo_wine
3361     {
3362         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3363     }
3364
3365     RegCloseKey(prodkey);
3366
3367     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3368     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3369     ok(pf_exists("msitest\\maximus"), "File deleted\n");
3370     ok(pf_exists("msitest"), "File deleted\n");
3371
3372     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3373     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3374
3375     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3376     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3377
3378     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3379     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3380
3381     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3382                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3383     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3384     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3385
3386     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3387     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3388
3389     /* complete install */
3390     r = MsiInstallProductA(msifile, "FULL=1");
3391     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3392     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3393     ok(pf_exists("msitest"), "File not installed\n");
3394
3395     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3396     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3397
3398     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3399     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3400
3401     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3402     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3403
3404     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3405                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3406     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3407     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3408
3409     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3410     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3411
3412     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3413     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3414     CHECK_REG_STR(prodkey, "InstallDate", date);
3415     CHECK_REG_STR(prodkey, "InstallSource", temp);
3416     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3417     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3418     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3419     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3420     CHECK_REG_STR(prodkey, "Comments", NULL);
3421     CHECK_REG_STR(prodkey, "Contact", NULL);
3422     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3423     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3424     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3425     CHECK_REG_STR(prodkey, "Readme", NULL);
3426     CHECK_REG_STR(prodkey, "Size", NULL);
3427     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3428     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3429     CHECK_REG_DWORD(prodkey, "Language", 1033);
3430     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3431     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3432     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3433     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3434     todo_wine
3435     {
3436         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3437     }
3438
3439     RegCloseKey(prodkey);
3440
3441     /* no UnpublishFeatures */
3442     r = MsiInstallProductA(msifile, "REMOVE=ALL");
3443     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3444     ok(!pf_exists("msitest\\maximus"), "File deleted\n");
3445     todo_wine
3446     {
3447         ok(!pf_exists("msitest"), "File deleted\n");
3448     }
3449
3450     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3451     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3452
3453     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3454     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3455
3456     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3457     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3458
3459     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3460                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3461     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3462     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3463
3464     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3465     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3466
3467     /* complete install */
3468     r = MsiInstallProductA(msifile, "FULL=1");
3469     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3470     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3471     ok(pf_exists("msitest"), "File not installed\n");
3472
3473     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3474     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3475
3476     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3477     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3478
3479     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3480     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3481
3482     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3483                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3484     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3485     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3486
3487     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3488     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3489
3490     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3491     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3492     CHECK_REG_STR(prodkey, "InstallDate", date);
3493     CHECK_REG_STR(prodkey, "InstallSource", temp);
3494     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3495     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3496     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3497     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3498     CHECK_REG_STR(prodkey, "Comments", NULL);
3499     CHECK_REG_STR(prodkey, "Contact", NULL);
3500     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3501     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3502     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3503     CHECK_REG_STR(prodkey, "Readme", NULL);
3504     CHECK_REG_STR(prodkey, "Size", NULL);
3505     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3506     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3507     CHECK_REG_DWORD(prodkey, "Language", 1033);
3508     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3509     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3510     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3511     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3512     todo_wine
3513     {
3514         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3515     }
3516
3517     RegCloseKey(prodkey);
3518
3519     /* UnpublishFeatures, only feature removed.  Only works when entire product is removed */
3520     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature");
3521     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3522     todo_wine ok(pf_exists("msitest\\maximus"), "File deleted\n");
3523     ok(pf_exists("msitest"), "File deleted\n");
3524
3525     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3526     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3527
3528     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3529     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3530
3531     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3532     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3533
3534     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3535                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3536     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3537     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3538
3539     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3540     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3541
3542     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3543     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3544     CHECK_REG_STR(prodkey, "InstallDate", date);
3545     CHECK_REG_STR(prodkey, "InstallSource", temp);
3546     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3547     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3548     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3549     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3550     CHECK_REG_STR(prodkey, "Comments", NULL);
3551     CHECK_REG_STR(prodkey, "Contact", NULL);
3552     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3553     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3554     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3555     CHECK_REG_STR(prodkey, "Readme", NULL);
3556     CHECK_REG_STR(prodkey, "Size", NULL);
3557     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3558     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3559     CHECK_REG_DWORD(prodkey, "Language", 1033);
3560     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3561     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3562     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3563     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3564     todo_wine
3565     {
3566         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3567     }
3568
3569     RegCloseKey(prodkey);
3570
3571     /* complete install */
3572     r = MsiInstallProductA(msifile, "FULL=1");
3573     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3574     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3575     ok(pf_exists("msitest"), "File not installed\n");
3576
3577     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3578     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3579
3580     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3581     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3582
3583     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3584     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3585
3586     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3587                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3588     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3589     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3590
3591     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3592     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3593
3594     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3595     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3596     CHECK_REG_STR(prodkey, "InstallDate", date);
3597     CHECK_REG_STR(prodkey, "InstallSource", temp);
3598     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3599     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3600     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3601     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3602     CHECK_REG_STR(prodkey, "Comments", NULL);
3603     CHECK_REG_STR(prodkey, "Contact", NULL);
3604     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3605     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3606     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3607     CHECK_REG_STR(prodkey, "Readme", NULL);
3608     CHECK_REG_STR(prodkey, "Size", NULL);
3609     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3610     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3611     CHECK_REG_DWORD(prodkey, "Language", 1033);
3612     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3613     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3614     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3615     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3616     todo_wine
3617     {
3618         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3619     }
3620
3621     RegCloseKey(prodkey);
3622
3623     /* UnpublishFeatures, both features removed */
3624     r = MsiInstallProductA(msifile, "UNPUBLISH_FEATURES=1 REMOVE=feature,montecristo");
3625     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3626     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3627     todo_wine
3628     {
3629         ok(!pf_exists("msitest"), "File not deleted\n");
3630     }
3631
3632     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3633     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3634
3635     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3636     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3637
3638     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3639     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3640
3641     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3642                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3643     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3644     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3645
3646     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3647     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3648
3649     /* complete install */
3650     r = MsiInstallProductA(msifile, "FULL=1");
3651     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3652     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3653     ok(pf_exists("msitest"), "File not installed\n");
3654
3655     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3656     ok(state == INSTALLSTATE_DEFAULT, "Expected INSTALLSTATE_DEFAULT, got %d\n", state);
3657
3658     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3659     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3660
3661     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3662     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3663
3664     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3665                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3666     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3667     ok(state == INSTALLSTATE_LOCAL, "Expected INSTALLSTATE_LOCAL, got %d\n", state);
3668
3669     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3670     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
3671
3672     CHECK_REG_STR(prodkey, "DisplayName", "MSITEST");
3673     CHECK_REG_STR(prodkey, "DisplayVersion", "1.1.1");
3674     CHECK_REG_STR(prodkey, "InstallDate", date);
3675     CHECK_REG_STR(prodkey, "InstallSource", temp);
3676     CHECK_REG_ISTR(prodkey, "ModifyPath", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3677     CHECK_REG_STR(prodkey, "Publisher", "Wine");
3678     CHECK_REG_STR(prodkey, "UninstallString", "MsiExec.exe /I{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3679     CHECK_REG_STR(prodkey, "AuthorizedCDFPrefix", NULL);
3680     CHECK_REG_STR(prodkey, "Comments", NULL);
3681     CHECK_REG_STR(prodkey, "Contact", NULL);
3682     CHECK_REG_STR(prodkey, "HelpLink", NULL);
3683     CHECK_REG_STR(prodkey, "HelpTelephone", NULL);
3684     CHECK_REG_STR(prodkey, "InstallLocation", NULL);
3685     CHECK_REG_STR(prodkey, "Readme", NULL);
3686     CHECK_REG_STR(prodkey, "Size", NULL);
3687     CHECK_REG_STR(prodkey, "URLInfoAbout", NULL);
3688     CHECK_REG_STR(prodkey, "URLUpdateInfo", NULL);
3689     CHECK_REG_DWORD(prodkey, "Language", 1033);
3690     CHECK_REG_DWORD(prodkey, "Version", 0x1010001);
3691     CHECK_REG_DWORD(prodkey, "VersionMajor", 1);
3692     CHECK_REG_DWORD(prodkey, "VersionMinor", 1);
3693     CHECK_REG_DWORD(prodkey, "WindowsInstaller", 1);
3694     todo_wine
3695     {
3696         CHECK_REG_DWORD(prodkey, "EstimatedSize", 12);
3697     }
3698
3699     RegCloseKey(prodkey);
3700
3701     /* complete uninstall */
3702     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3703     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3704     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3705     todo_wine
3706     {
3707         ok(!pf_exists("msitest"), "File not deleted\n");
3708     }
3709
3710     state = MsiQueryProductState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}");
3711     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3712
3713     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "feature");
3714     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3715
3716     state = MsiQueryFeatureState("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}", "montecristo");
3717     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3718
3719     r = pMsiQueryComponentStateA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3720                                 "{DF2CBABC-3BCC-47E5-A998-448D1C0C895B}", &state);
3721     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3722     ok(state == INSTALLSTATE_UNKNOWN, "Expected INSTALLSTATE_UNKNOWN, got %d\n", state);
3723
3724     res = RegOpenKeyA(uninstall, prodcode, &prodkey);
3725     ok(res == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %d\n", res);
3726
3727     /* make sure 'Program Files\msitest' is removed */
3728     delete_pfmsitest_files();
3729
3730     RegCloseKey(uninstall);
3731     DeleteFile(msifile);
3732     DeleteFile("msitest\\maximus");
3733     RemoveDirectory("msitest");
3734 }
3735
3736 static void test_publishsourcelist(void)
3737 {
3738     UINT r;
3739     DWORD size;
3740     CHAR value[MAX_PATH];
3741     CHAR path[MAX_PATH];
3742     CHAR prodcode[] = "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}";
3743
3744     if (!pMsiSourceListEnumSourcesA || !pMsiSourceListGetInfoA)
3745     {
3746         skip("MsiSourceListEnumSourcesA and/or MsiSourceListGetInfoA are not available\n");
3747         return;
3748     }
3749
3750     CreateDirectoryA("msitest", NULL);
3751     create_file("msitest\\maximus", 500);
3752
3753     create_database(msifile, pp_tables, sizeof(pp_tables) / sizeof(msi_table));
3754
3755     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
3756
3757     r = MsiInstallProductA(msifile, NULL);
3758     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3759     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3760     ok(pf_exists("msitest"), "File not installed\n");
3761
3762     /* nothing published */
3763     size = 0xdeadbeef;
3764     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3765                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3766     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3767     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3768
3769     size = 0xdeadbeef;
3770     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3771                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3772     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3773     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3774
3775     r = MsiInstallProductA(msifile, "REGISTER_PRODUCT=1");
3776     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3777     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3778     ok(pf_exists("msitest"), "File not installed\n");
3779
3780     /* after RegisterProduct */
3781     size = 0xdeadbeef;
3782     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3783                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3784     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3785     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3786
3787     size = 0xdeadbeef;
3788     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3789                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3790     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3791     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3792
3793     r = MsiInstallProductA(msifile, "PROCESS_COMPONENTS=1");
3794     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3795     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3796     ok(pf_exists("msitest"), "File not installed\n");
3797
3798     /* after ProcessComponents */
3799     size = 0xdeadbeef;
3800     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3801                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3802     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3803     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3804
3805     size = 0xdeadbeef;
3806     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3807                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3808     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3809     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3810
3811     r = MsiInstallProductA(msifile, "PUBLISH_FEATURES=1");
3812     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3813     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3814     ok(pf_exists("msitest"), "File not installed\n");
3815
3816     /* after PublishFeatures */
3817     size = 0xdeadbeef;
3818     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3819                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, NULL, &size);
3820     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3821     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3822
3823     size = 0xdeadbeef;
3824     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3825                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, NULL, &size);
3826     ok(r == ERROR_UNKNOWN_PRODUCT, "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
3827     ok(size == 0xdeadbeef, "Expected 0xdeadbeef, got %d\n", size);
3828
3829     r = MsiInstallProductA(msifile, "PUBLISH_PRODUCT=1");
3830     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
3831     ok(pf_exists("msitest\\maximus"), "File not installed\n");
3832     ok(pf_exists("msitest"), "File not installed\n");
3833
3834     /* after PublishProduct */
3835     size = MAX_PATH;
3836     lstrcpyA(value, "aaa");
3837     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3838                                MSICODE_PRODUCT, INSTALLPROPERTY_PACKAGENAME, value, &size);
3839     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3840     ok(!lstrcmpA(value, "msitest.msi"), "Expected 'msitest.msi', got %s\n", value);
3841     ok(size == 11, "Expected 11, got %d\n", size);
3842
3843     size = MAX_PATH;
3844     lstrcpyA(value, "aaa");
3845     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3846                                MSICODE_PRODUCT, INSTALLPROPERTY_MEDIAPACKAGEPATH, value, &size);
3847     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3848     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3849     ok(size == 0, "Expected 0, got %d\n", size);
3850
3851     size = MAX_PATH;
3852     lstrcpyA(value, "aaa");
3853     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3854                                MSICODE_PRODUCT, INSTALLPROPERTY_DISKPROMPT, value, &size);
3855     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3856     ok(!lstrcmpA(value, ""), "Expected \"\", got \"%s\"\n", value);
3857     ok(size == 0, "Expected 0, got %d\n", size);
3858
3859     lstrcpyA(path, CURR_DIR);
3860     lstrcatA(path, "\\");
3861
3862     size = MAX_PATH;
3863     lstrcpyA(value, "aaa");
3864     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3865                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDSOURCE, value, &size);
3866     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3867     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3868     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3869
3870     size = MAX_PATH;
3871     lstrcpyA(value, "aaa");
3872     r = pMsiSourceListGetInfoA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3873                                MSICODE_PRODUCT, INSTALLPROPERTY_LASTUSEDTYPE, value, &size);
3874     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3875     ok(!lstrcmpA(value, "n"), "Expected \"n\", got \"%s\"\n", value);
3876     ok(size == 1, "Expected 1, got %d\n", size);
3877
3878     size = MAX_PATH;
3879     lstrcpyA(value, "aaa");
3880     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3881                                    MSICODE_PRODUCT | MSISOURCETYPE_URL, 0, value, &size);
3882     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3883     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3884     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3885
3886     size = MAX_PATH;
3887     lstrcpyA(value, "aaa");
3888     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3889                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 0, value, &size);
3890     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3891     ok(!lstrcmpA(value, path), "Expected \"%s\", got \"%s\"\n", path, value);
3892     ok(size == lstrlenA(path), "Expected %d, got %d\n", lstrlenA(path), size);
3893
3894     size = MAX_PATH;
3895     lstrcpyA(value, "aaa");
3896     r = pMsiSourceListEnumSourcesA(prodcode, NULL, MSIINSTALLCONTEXT_USERUNMANAGED,
3897                                    MSICODE_PRODUCT | MSISOURCETYPE_NETWORK, 1, value, &size);
3898     ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
3899     ok(!lstrcmpA(value, "aaa"), "Expected value to be unchanged, got %s\n", value);
3900     ok(size == MAX_PATH, "Expected MAX_PATH, got %d\n", size);
3901
3902     /* complete uninstall */
3903     r = MsiInstallProductA(msifile, "FULL=1 REMOVE=ALL");
3904     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
3905     ok(!pf_exists("msitest\\maximus"), "File not deleted\n");
3906     todo_wine
3907     {
3908         ok(!pf_exists("msitest"), "File not deleted\n");
3909     }
3910
3911     /* make sure 'Program Files\msitest' is removed */
3912     delete_pfmsitest_files();
3913
3914     DeleteFile(msifile);
3915     DeleteFile("msitest\\maximus");
3916     RemoveDirectory("msitest");
3917 }
3918
3919 static UINT run_query(MSIHANDLE hdb, MSIHANDLE hrec, const char *query)
3920 {
3921     MSIHANDLE hview = 0;
3922     UINT r;
3923
3924     r = MsiDatabaseOpenView(hdb, query, &hview);
3925     if(r != ERROR_SUCCESS)
3926         return r;
3927
3928     r = MsiViewExecute(hview, hrec);
3929     if(r == ERROR_SUCCESS)
3930         r = MsiViewClose(hview);
3931     MsiCloseHandle(hview);
3932     return r;
3933 }
3934
3935 static void set_transform_summary_info(void)
3936 {
3937     UINT r;
3938     MSIHANDLE suminfo = 0;
3939
3940     /* build summary info */
3941     r = MsiGetSummaryInformation(0, mstfile, 3, &suminfo);
3942     todo_wine
3943     {
3944         ok(r == ERROR_SUCCESS , "Failed to open summaryinfo\n");
3945     }
3946
3947     r = MsiSummaryInfoSetProperty(suminfo, PID_TITLE, VT_LPSTR, 0, NULL, "MSITEST");
3948     todo_wine
3949     {
3950         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3951     }
3952
3953     r = MsiSummaryInfoSetProperty(suminfo, PID_REVNUMBER, VT_LPSTR, 0, NULL,
3954                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3955                         "{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}1.1.1;"
3956                         "{4C0EAA15-0264-4E5A-8758-609EF142B92D}");
3957     todo_wine
3958     {
3959         ok(r == ERROR_SUCCESS , "Failed to set summary info\n");
3960     }
3961
3962     r = MsiSummaryInfoSetProperty(suminfo, PID_PAGECOUNT, VT_I4, 100, NULL, NULL);
3963     todo_wine
3964     {
3965         ok(r == ERROR_SUCCESS, "Failed to set summary info\n");
3966     }
3967
3968     r = MsiSummaryInfoPersist(suminfo);
3969     todo_wine
3970     {
3971         ok(r == ERROR_SUCCESS , "Failed to make summary info persist\n");
3972     }
3973
3974     r = MsiCloseHandle(suminfo);
3975     ok(r == ERROR_SUCCESS , "Failed to close suminfo\n");
3976 }
3977
3978 static void generate_transform(void)
3979 {
3980     MSIHANDLE hdb1, hdb2;
3981     LPCSTR query;
3982     UINT r;
3983
3984     /* start with two identical databases */
3985     CopyFile(msifile, msifile2, FALSE);
3986
3987     r = MsiOpenDatabase(msifile2, MSIDBOPEN_TRANSACT, &hdb1);
3988     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3989
3990     r = MsiDatabaseCommit(hdb1);
3991     ok(r == ERROR_SUCCESS , "Failed to commit database\n");
3992
3993     r = MsiOpenDatabase(msifile, MSIDBOPEN_READONLY, &hdb2);
3994     ok(r == ERROR_SUCCESS , "Failed to create database\n");
3995
3996     query = "INSERT INTO `Property` ( `Property`, `Value` ) VALUES ( 'prop', 'val' )";
3997     r = run_query(hdb1, 0, query);
3998     ok(r == ERROR_SUCCESS, "failed to add property\n");
3999
4000     /* database needs to be committed */
4001     MsiDatabaseCommit(hdb1);
4002
4003     r = MsiDatabaseGenerateTransform(hdb1, hdb2, mstfile, 0, 0);
4004     ok(r == ERROR_SUCCESS, "return code %d, should be ERROR_SUCCESS\n", r);
4005
4006 #if 0  /* not implemented in wine yet */
4007     r = MsiCreateTransformSummaryInfo(hdb2, hdb2, mstfile, 0, 0);
4008     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
4009 #endif
4010
4011     MsiCloseHandle(hdb1);
4012     MsiCloseHandle(hdb2);
4013 }
4014
4015 /* data for generating a transform */
4016
4017 /* tables transform names - encoded as they would be in an msi database file */
4018 static const WCHAR name1[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3b6a, 0x45e4, 0x4824, 0 }; /* _StringData */
4019 static const WCHAR name2[] = { 0x4840, 0x3f3f, 0x4577, 0x446c, 0x3e6a, 0x44b2, 0x482f, 0 }; /* _StringPool */
4020 static const WCHAR name3[] = { 0x4840, 0x4559, 0x44f2, 0x4568, 0x4737, 0 }; /* Property */
4021
4022 /* data in each table */
4023 static const char data1[] = /* _StringData */
4024     "propval";  /* all the strings squashed together */
4025
4026 static const WCHAR data2[] = { /* _StringPool */
4027 /*  len, refs */
4028     0,   0,    /* string 0 ''     */
4029     4,   1,    /* string 1 'prop' */
4030     3,   1,    /* string 2 'val'  */
4031 };
4032
4033 static const WCHAR data3[] = { /* Property */
4034     0x0201, 0x0001, 0x0002,
4035 };
4036
4037 static const struct {
4038     LPCWSTR name;
4039     const void *data;
4040     DWORD size;
4041 } table_transform_data[] =
4042 {
4043     { name1, data1, sizeof data1 - 1 },
4044     { name2, data2, sizeof data2 },
4045     { name3, data3, sizeof data3 },
4046 };
4047
4048 #define NUM_TRANSFORM_TABLES (sizeof table_transform_data/sizeof table_transform_data[0])
4049
4050 static void generate_transform_manual(void)
4051 {
4052     IStorage *stg = NULL;
4053     IStream *stm;
4054     WCHAR name[0x20];
4055     HRESULT r;
4056     DWORD i, count;
4057     const DWORD mode = STGM_CREATE|STGM_READWRITE|STGM_DIRECT|STGM_SHARE_EXCLUSIVE;
4058
4059     const CLSID CLSID_MsiTransform = { 0xc1082,0,0,{0xc0,0,0,0,0,0,0,0x46}};
4060
4061     MultiByteToWideChar(CP_ACP, 0, mstfile, -1, name, 0x20);
4062
4063     r = StgCreateDocfile(name, mode, 0, &stg);
4064     ok(r == S_OK, "failed to create storage\n");
4065     if (!stg)
4066         return;
4067
4068     r = IStorage_SetClass(stg, &CLSID_MsiTransform);
4069     ok(r == S_OK, "failed to set storage type\n");
4070
4071     for (i=0; i<NUM_TRANSFORM_TABLES; i++)
4072     {
4073         r = IStorage_CreateStream(stg, table_transform_data[i].name,
4074                             STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4075         if (FAILED(r))
4076         {
4077             ok(0, "failed to create stream %08x\n", r);
4078             continue;
4079         }
4080
4081         r = IStream_Write(stm, table_transform_data[i].data,
4082                           table_transform_data[i].size, &count);
4083         if (FAILED(r) || count != table_transform_data[i].size)
4084             ok(0, "failed to write stream\n");
4085         IStream_Release(stm);
4086     }
4087
4088     IStorage_Release(stg);
4089
4090     set_transform_summary_info();
4091 }
4092
4093 static void test_transformprop(void)
4094 {
4095     UINT r;
4096
4097     CreateDirectoryA("msitest", NULL);
4098     create_file("msitest\\augustus", 500);
4099
4100     create_database(msifile, tp_tables, sizeof(tp_tables) / sizeof(msi_table));
4101
4102     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4103
4104     r = MsiInstallProductA(msifile, NULL);
4105     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4106     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4107     ok(!delete_pf("msitest", FALSE), "File installed\n");
4108
4109     if (0)
4110         generate_transform();
4111     else
4112         generate_transform_manual();
4113
4114     r = MsiInstallProductA(msifile, "TRANSFORMS=winetest.mst");
4115     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4116     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4117     ok(delete_pf("msitest", FALSE), "File not installed\n");
4118
4119     /* Delete the files in the temp (current) folder */
4120     DeleteFile(msifile);
4121     DeleteFile(msifile2);
4122     DeleteFile(mstfile);
4123     DeleteFile("msitest\\augustus");
4124     RemoveDirectory("msitest");
4125 }
4126
4127 static void test_currentworkingdir(void)
4128 {
4129     UINT r;
4130     CHAR path[MAX_PATH];
4131     LPSTR ptr, ptr2;
4132
4133     CreateDirectoryA("msitest", NULL);
4134     create_file("msitest\\augustus", 500);
4135
4136     create_database(msifile, cwd_tables, sizeof(cwd_tables) / sizeof(msi_table));
4137
4138     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4139
4140     CreateDirectoryA("diffdir", NULL);
4141     SetCurrentDirectoryA("diffdir");
4142
4143     sprintf(path, "..\\%s", msifile);
4144     r = MsiInstallProductA(path, NULL);
4145     todo_wine
4146     {
4147         ok(r == ERROR_FILE_NOT_FOUND, "Expected ERROR_FILE_NOT_FOUND, got %u\n", r);
4148         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4149         ok(!delete_pf("msitest", FALSE), "File installed\n");
4150     }
4151
4152     sprintf(path, "%s\\%s", CURR_DIR, msifile);
4153     r = MsiInstallProductA(path, NULL);
4154     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4155     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4156     ok(delete_pf("msitest", FALSE), "File not installed\n");
4157
4158     lstrcpyA(path, CURR_DIR);
4159     if (path[lstrlenA(path) - 1] != '\\')
4160         lstrcatA(path, "\\");
4161     lstrcatA(path, "msitest.msi");
4162
4163     ptr2 = strrchr(path, '\\');
4164     *ptr2 = '\0';
4165     ptr = strrchr(path, '\\');
4166     *ptr2 = '\\';
4167     *(ptr++) = '\0';
4168
4169     SetCurrentDirectoryA(path);
4170
4171     r = MsiInstallProductA(ptr, NULL);
4172     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4173     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4174     ok(delete_pf("msitest", FALSE), "File not installed\n");
4175
4176     SetCurrentDirectoryA(CURR_DIR);
4177
4178     DeleteFile(msifile);
4179     DeleteFile("msitest\\augustus");
4180     RemoveDirectory("msitest");
4181     RemoveDirectory("diffdir");
4182 }
4183
4184 static void set_admin_summary_info(const CHAR *name)
4185 {
4186     MSIHANDLE db, summary;
4187     UINT r;
4188
4189     r = MsiOpenDatabaseA(name, MSIDBOPEN_DIRECT, &db);
4190     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4191
4192     r = MsiGetSummaryInformationA(db, NULL, 1, &summary);
4193     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4194
4195     r = MsiSummaryInfoSetPropertyA(summary, PID_WORDCOUNT, VT_I4, 5, NULL, NULL);
4196     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4197
4198     /* write the summary changes back to the stream */
4199     r = MsiSummaryInfoPersist(summary);
4200     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4201
4202     MsiCloseHandle(summary);
4203
4204     r = MsiDatabaseCommit(db);
4205     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4206
4207     MsiCloseHandle(db);
4208 }
4209
4210 static void test_admin(void)
4211 {
4212     UINT r;
4213
4214     CreateDirectoryA("msitest", NULL);
4215     create_file("msitest\\augustus", 500);
4216
4217     create_database(msifile, adm_tables, sizeof(adm_tables) / sizeof(msi_table));
4218     set_admin_summary_info(msifile);
4219
4220     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4221
4222     r = MsiInstallProductA(msifile, NULL);
4223     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4224     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4225     ok(!delete_pf("msitest", FALSE), "File installed\n");
4226     ok(!DeleteFile("c:\\msitest\\augustus"), "File installed\n");
4227     ok(!RemoveDirectory("c:\\msitest"), "File installed\n");
4228
4229     r = MsiInstallProductA(msifile, "ACTION=ADMIN");
4230     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4231     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4232     ok(!delete_pf("msitest", FALSE), "File installed\n");
4233     todo_wine
4234     {
4235         ok(DeleteFile("c:\\msitest\\augustus"), "File not installed\n");
4236         ok(RemoveDirectory("c:\\msitest"), "File not installed\n");
4237     }
4238
4239     DeleteFile(msifile);
4240     DeleteFile("msitest\\augustus");
4241     RemoveDirectory("msitest");
4242 }
4243
4244 static void set_admin_property_stream(LPCSTR file)
4245 {
4246     IStorage *stg;
4247     IStream *stm;
4248     WCHAR fileW[MAX_PATH];
4249     HRESULT hr;
4250     DWORD count;
4251     const DWORD mode = STGM_DIRECT | STGM_READWRITE | STGM_SHARE_EXCLUSIVE;
4252
4253     /* AdminProperties */
4254     static const WCHAR stmname[] = {0x41ca,0x4330,0x3e71,0x44b5,0x4233,0x45f5,0x422c,0x4836,0};
4255     static const WCHAR data[] = {'M','Y','P','R','O','P','=','2','7','1','8',' ',
4256         'M','y','P','r','o','p','=','4','2',0};
4257
4258     MultiByteToWideChar(CP_ACP, 0, file, -1, fileW, MAX_PATH);
4259
4260     hr = StgOpenStorage(fileW, NULL, mode, NULL, 0, &stg);
4261     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4262     if (!stg)
4263         return;
4264
4265     hr = IStorage_CreateStream(stg, stmname, STGM_WRITE | STGM_SHARE_EXCLUSIVE, 0, 0, &stm);
4266     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4267
4268     hr = IStream_Write(stm, data, sizeof(data), &count);
4269     ok(hr == S_OK, "Expected S_OK, got %d\n", hr);
4270
4271     IStream_Release(stm);
4272     IStorage_Release(stg);
4273 }
4274
4275 static void test_adminprops(void)
4276 {
4277     UINT r;
4278
4279     CreateDirectoryA("msitest", NULL);
4280     create_file("msitest\\augustus", 500);
4281
4282     create_database(msifile, amp_tables, sizeof(amp_tables) / sizeof(msi_table));
4283     set_admin_summary_info(msifile);
4284     set_admin_property_stream(msifile);
4285
4286     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4287
4288     r = MsiInstallProductA(msifile, NULL);
4289     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4290     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4291     ok(delete_pf("msitest", FALSE), "File installed\n");
4292
4293     DeleteFile(msifile);
4294     DeleteFile("msitest\\augustus");
4295     RemoveDirectory("msitest");
4296 }
4297
4298 static void create_pf_data(LPCSTR file, LPCSTR data, BOOL is_file)
4299 {
4300     CHAR path[MAX_PATH];
4301
4302     lstrcpyA(path, PROG_FILES_DIR);
4303     lstrcatA(path, "\\");
4304     lstrcatA(path, file);
4305
4306     if (is_file)
4307         create_file_data(path, data, 500);
4308     else
4309         CreateDirectoryA(path, NULL);
4310 }
4311
4312 #define create_pf(file, is_file) create_pf_data(file, file, is_file)
4313
4314 static void test_removefiles(void)
4315 {
4316     UINT r;
4317
4318     CreateDirectoryA("msitest", NULL);
4319     create_file("msitest\\hydrogen", 500);
4320     create_file("msitest\\helium", 500);
4321     create_file("msitest\\lithium", 500);
4322
4323     create_database(msifile, rem_tables, sizeof(rem_tables) / sizeof(msi_table));
4324
4325     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4326
4327     r = MsiInstallProductA(msifile, NULL);
4328     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4329     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4330     ok(!pf_exists("msitest\\helium"), "File installed\n");
4331     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4332     ok(pf_exists("msitest"), "File not installed\n");
4333
4334     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4335     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4336     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
4337     ok(!pf_exists("msitest\\helium"), "File not deleted\n");
4338     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4339     ok(delete_pf("msitest", FALSE), "File deleted\n");
4340
4341     create_pf("msitest", FALSE);
4342     create_pf("msitest\\hydrogen", TRUE);
4343     create_pf("msitest\\helium", TRUE);
4344     create_pf("msitest\\lithium", TRUE);
4345
4346     r = MsiInstallProductA(msifile, NULL);
4347     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4348     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4349     ok(pf_exists("msitest\\helium"), "File not installed\n");
4350     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4351     ok(pf_exists("msitest"), "File not installed\n");
4352
4353     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4354     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4355     ok(!pf_exists("msitest\\hydrogen"), "File not deleted\n");
4356     ok(delete_pf("msitest\\helium", TRUE), "File deleted\n");
4357     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4358     ok(delete_pf("msitest", FALSE), "File deleted\n");
4359
4360     create_pf("msitest", FALSE);
4361     create_pf("msitest\\furlong", TRUE);
4362     create_pf("msitest\\firkin", TRUE);
4363     create_pf("msitest\\fortnight", TRUE);
4364     create_pf("msitest\\becquerel", TRUE);
4365     create_pf("msitest\\dioptre", TRUE);
4366     create_pf("msitest\\attoparsec", TRUE);
4367     create_pf("msitest\\storeys", TRUE);
4368     create_pf("msitest\\block", TRUE);
4369     create_pf("msitest\\siriometer", TRUE);
4370     create_pf("msitest\\cabout", FALSE);
4371     create_pf("msitest\\cabout\\blocker", TRUE);
4372
4373     r = MsiInstallProductA(msifile, NULL);
4374     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4375     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
4376     ok(!pf_exists("msitest\\helium"), "File installed\n");
4377     ok(pf_exists("msitest\\lithium"), "File not installed\n");
4378     ok(!pf_exists("msitest\\furlong"), "File not deleted\n");
4379     ok(!pf_exists("msitest\\firkin"), "File not deleted\n");
4380     ok(!pf_exists("msitest\\fortnight"), "File not deleted\n");
4381     ok(pf_exists("msitest\\becquerel"), "File not installed\n");
4382     ok(pf_exists("msitest\\dioptre"), "File not installed\n");
4383     ok(pf_exists("msitest\\attoparsec"), "File not installed\n");
4384     ok(!pf_exists("msitest\\storeys"), "File not deleted\n");
4385     ok(!pf_exists("msitest\\block"), "File not deleted\n");
4386     ok(!pf_exists("msitest\\siriometer"), "File not deleted\n");
4387     ok(pf_exists("msitest\\cabout"), "Directory removed\n");
4388     ok(pf_exists("msitest"), "File not installed\n");
4389
4390     create_pf("msitest\\furlong", TRUE);
4391     create_pf("msitest\\firkin", TRUE);
4392     create_pf("msitest\\fortnight", TRUE);
4393     create_pf("msitest\\storeys", TRUE);
4394     create_pf("msitest\\block", TRUE);
4395     create_pf("msitest\\siriometer", TRUE);
4396
4397     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4398     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4399     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not deleted\n");
4400     ok(!delete_pf("msitest\\helium", TRUE), "File not deleted\n");
4401     ok(delete_pf("msitest\\lithium", TRUE), "File deleted\n");
4402     ok(delete_pf("msitest\\furlong", TRUE), "File deleted\n");
4403     ok(delete_pf("msitest\\firkin", TRUE), "File deleted\n");
4404     ok(delete_pf("msitest\\fortnight", TRUE), "File deleted\n");
4405     ok(!delete_pf("msitest\\becquerel", TRUE), "File not deleted\n");
4406     ok(!delete_pf("msitest\\dioptre", TRUE), "File not deleted\n");
4407     ok(delete_pf("msitest\\attoparsec", TRUE), "File deleted\n");
4408     ok(!delete_pf("msitest\\storeys", TRUE), "File not deleted\n");
4409     ok(!delete_pf("msitest\\block", TRUE), "File not deleted\n");
4410     ok(delete_pf("msitest\\siriometer", TRUE), "File deleted\n");
4411     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
4412     ok(pf_exists("msitest"), "Directory deleted\n");
4413
4414     r = MsiInstallProductA(msifile, NULL);
4415     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4416     ok(delete_pf("msitest\\hydrogen", TRUE), "File not installed\n");
4417     ok(!delete_pf("msitest\\helium", TRUE), "File installed\n");
4418     ok(delete_pf("msitest\\lithium", TRUE), "File not installed\n");
4419     ok(pf_exists("msitest\\cabout"), "Directory deleted\n");
4420     ok(pf_exists("msitest"), "Directory deleted\n");
4421
4422     delete_pf("msitest\\cabout\\blocker", TRUE);
4423
4424     r = MsiInstallProductA(msifile, "REMOVE=ALL");
4425     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4426     ok(!delete_pf("msitest\\cabout", FALSE), "Directory not deleted\n");
4427     ok(delete_pf("msitest", FALSE), "Directory deleted\n");
4428
4429     DeleteFile(msifile);
4430     DeleteFile("msitest\\hydrogen");
4431     DeleteFile("msitest\\helium");
4432     DeleteFile("msitest\\lithium");
4433     RemoveDirectory("msitest");
4434 }
4435
4436 static void test_movefiles(void)
4437 {
4438     UINT r;
4439     char props[MAX_PATH];
4440
4441     CreateDirectoryA("msitest", NULL);
4442     create_file("msitest\\augustus", 100);
4443     create_file("cameroon", 100);
4444     create_file("djibouti", 100);
4445     create_file("egypt", 100);
4446     create_file("finland", 100);
4447     create_file("gambai", 100);
4448     create_file("honduras", 100);
4449     create_file("msitest\\india", 100);
4450     create_file("japan", 100);
4451     create_file("kenya", 100);
4452     CreateDirectoryA("latvia", NULL);
4453     create_file("nauru", 100);
4454     create_file("peru", 100);
4455     create_file("apple", 100);
4456     create_file("application", 100);
4457     create_file("ape", 100);
4458     create_file("foo", 100);
4459     create_file("fao", 100);
4460     create_file("fbod", 100);
4461     create_file("budding", 100);
4462     create_file("buddy", 100);
4463     create_file("bud", 100);
4464     create_file("bar", 100);
4465     create_file("bur", 100);
4466     create_file("bird", 100);
4467
4468     create_database(msifile, mov_tables, sizeof(mov_tables) / sizeof(msi_table));
4469
4470     MsiSetInternalUI(INSTALLUILEVEL_FULL, NULL);
4471
4472     /* if the source or dest property is not a full path,
4473      * windows tries to access it as a network resource
4474      */
4475
4476     sprintf(props, "SOURCEFULL=\"%s\\\" DESTFULL=\"%s\\msitest\" "
4477             "FILEPATHBAD=\"%s\\japan\" FILEPATHGOOD=\"%s\\kenya\"",
4478             CURR_DIR, PROG_FILES_DIR, CURR_DIR, CURR_DIR);
4479
4480     r = MsiInstallProductA(msifile, props);
4481     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4482     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4483     ok(!delete_pf("msitest\\dest", TRUE), "File copied\n");
4484     ok(delete_pf("msitest\\canada", TRUE), "File not copied\n");
4485     ok(delete_pf("msitest\\dominica", TRUE), "File not moved\n");
4486     ok(!delete_pf("msitest\\elsalvador", TRUE), "File moved\n");
4487     ok(!delete_pf("msitest\\france", TRUE), "File moved\n");
4488     ok(!delete_pf("msitest\\georgia", TRUE), "File moved\n");
4489     ok(delete_pf("msitest\\hungary", TRUE), "File not moved\n");
4490     ok(!delete_pf("msitest\\indonesia", TRUE), "File moved\n");
4491     ok(!delete_pf("msitest\\jordan", TRUE), "File moved\n");
4492     ok(delete_pf("msitest\\kiribati", TRUE), "File not moved\n");
4493     ok(!delete_pf("msitest\\lebanon", TRUE), "File moved\n");
4494     ok(!delete_pf("msitest\\lebanon", FALSE), "Directory moved\n");
4495     ok(delete_pf("msitest\\poland", TRUE), "File not moved\n");
4496     /* either apple or application will be moved depending on directory order */
4497     if (!delete_pf("msitest\\apple", TRUE))
4498         ok(delete_pf("msitest\\application", TRUE), "File not moved\n");
4499     else
4500         ok(!delete_pf("msitest\\application", TRUE), "File should not exist\n");
4501     ok(delete_pf("msitest\\wildcard", TRUE), "File not moved\n");
4502     ok(!delete_pf("msitest\\ape", TRUE), "File moved\n");
4503     /* either fao or foo will be moved depending on directory order */
4504     if (delete_pf("msitest\\foo", TRUE))
4505         ok(!delete_pf("msitest\\fao", TRUE), "File should not exist\n");
4506     else
4507         ok(delete_pf("msitest\\fao", TRUE), "File not moved\n");
4508     ok(delete_pf("msitest\\single", TRUE), "File not moved\n");
4509     ok(!delete_pf("msitest\\fbod", TRUE), "File moved\n");
4510     ok(delete_pf("msitest\\budding", TRUE), "File not moved\n");
4511     ok(delete_pf("msitest\\buddy", TRUE), "File not moved\n");
4512     ok(!delete_pf("msitest\\bud", TRUE), "File moved\n");
4513     ok(delete_pf("msitest\\bar", TRUE), "File not moved\n");
4514     ok(delete_pf("msitest\\bur", TRUE), "File not moved\n");
4515     ok(!delete_pf("msitest\\bird", TRUE), "File moved\n");
4516     ok(delete_pf("msitest", FALSE), "File not installed\n");
4517     ok(DeleteFileA("cameroon"), "File moved\n");
4518     ok(!DeleteFileA("djibouti"), "File not moved\n");
4519     ok(DeleteFileA("egypt"), "File moved\n");
4520     ok(DeleteFileA("finland"), "File moved\n");
4521     ok(DeleteFileA("gambai"), "File moved\n");
4522     ok(!DeleteFileA("honduras"), "File not moved\n");
4523     ok(DeleteFileA("msitest\\india"), "File moved\n");
4524     ok(DeleteFileA("japan"), "File moved\n");
4525     ok(!DeleteFileA("kenya"), "File not moved\n");
4526     ok(RemoveDirectoryA("latvia"), "Directory moved\n");
4527     ok(!DeleteFileA("nauru"), "File not moved\n");
4528     ok(!DeleteFileA("peru"), "File not moved\n");
4529     ok(!DeleteFileA("apple"), "File not moved\n");
4530     ok(!DeleteFileA("application"), "File not moved\n");
4531     ok(DeleteFileA("ape"), "File moved\n");
4532     ok(!DeleteFileA("foo"), "File not moved\n");
4533     ok(!DeleteFileA("fao"), "File not moved\n");
4534     ok(DeleteFileA("fbod"), "File moved\n");
4535     ok(!DeleteFileA("budding"), "File not moved\n");
4536     ok(!DeleteFileA("buddy"), "File not moved\n");
4537     ok(DeleteFileA("bud"), "File moved\n");
4538     ok(!DeleteFileA("bar"), "File not moved\n");
4539     ok(!DeleteFileA("bur"), "File not moved\n");
4540     ok(DeleteFileA("bird"), "File moved\n");
4541
4542     DeleteFile("msitest\\augustus");
4543     RemoveDirectory("msitest");
4544     DeleteFile(msifile);
4545 }
4546
4547 static void test_missingcab(void)
4548 {
4549     UINT r;
4550
4551     CreateDirectoryA("msitest", NULL);
4552     create_file("msitest\\augustus", 500);
4553     create_file("maximus", 500);
4554
4555     create_database(msifile, mc_tables, sizeof(mc_tables) / sizeof(msi_table));
4556
4557     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4558
4559     create_cab_file("test1.cab", MEDIA_SIZE, "maximus\0");
4560
4561     create_pf("msitest", FALSE);
4562     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4563
4564     r = MsiInstallProductA(msifile, NULL);
4565     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4566     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
4567     ok(delete_pf("msitest\\caesar", TRUE), "File not installed\n");
4568     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4569     ok(!delete_pf("msitest\\gaius", TRUE), "File installed\n");
4570     ok(delete_pf("msitest", FALSE), "File not installed\n");
4571
4572     create_pf("msitest", FALSE);
4573     create_pf_data("msitest\\caesar", "abcdefgh", TRUE);
4574     create_pf("msitest\\gaius", TRUE);
4575
4576     r = MsiInstallProductA(msifile, "GAIUS=1");
4577     ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4578     todo_wine
4579     {
4580         ok(!delete_pf("msitest\\maximus", TRUE), "File installed\n");
4581         ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4582     }
4583     ok(delete_pf("msitest\\caesar", TRUE), "File removed\n");
4584     ok(delete_pf("msitest\\gaius", TRUE), "File removed\n");
4585     ok(delete_pf("msitest", FALSE), "File not installed\n");
4586
4587     DeleteFile("msitest\\augustus");
4588     RemoveDirectory("msitest");
4589     DeleteFile("maximus");
4590     DeleteFile("test1.cab");
4591     DeleteFile(msifile);
4592 }
4593
4594 static void test_duplicatefiles(void)
4595 {
4596     UINT r;
4597
4598     CreateDirectoryA("msitest", NULL);
4599     create_file("msitest\\maximus", 500);
4600     create_database(msifile, df_tables, sizeof(df_tables) / sizeof(msi_table));
4601
4602     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4603
4604     /* fails if the destination folder is not a valid property */
4605
4606     r = MsiInstallProductA(msifile, NULL);
4607     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4608     ok(delete_pf("msitest\\maximus", TRUE), "File not installed\n");
4609     ok(delete_pf("msitest\\augustus", TRUE), "File not duplicated\n");
4610     ok(delete_pf("msitest\\this\\doesnot\\exist\\maximus", TRUE), "File not duplicated\n");
4611     ok(delete_pf("msitest\\this\\doesnot\\exist", FALSE), "File not duplicated\n");
4612     ok(delete_pf("msitest\\this\\doesnot", FALSE), "File not duplicated\n");
4613     ok(delete_pf("msitest\\this", FALSE), "File not duplicated\n");
4614     ok(delete_pf("msitest", FALSE), "File not installed\n");
4615
4616     DeleteFile("msitest\\maximus");
4617     RemoveDirectory("msitest");
4618     DeleteFile(msifile);
4619 }
4620
4621 static void test_writeregistryvalues(void)
4622 {
4623     UINT r;
4624     LONG res;
4625     HKEY hkey;
4626     DWORD type, size;
4627     CHAR path[MAX_PATH];
4628
4629     CreateDirectoryA("msitest", NULL);
4630     create_file("msitest\\augustus", 500);
4631
4632     create_database(msifile, wrv_tables, sizeof(wrv_tables) / sizeof(msi_table));
4633
4634     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4635
4636     r = MsiInstallProductA(msifile, NULL);
4637     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4638     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4639     ok(delete_pf("msitest", FALSE), "File installed\n");
4640
4641     res = RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest", &hkey);
4642     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4643
4644     size = MAX_PATH;
4645     type = REG_MULTI_SZ;
4646     memset(path, 'a', MAX_PATH);
4647     res = RegQueryValueExA(hkey, "Value", NULL, &type, (LPBYTE)path, &size);
4648     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
4649     ok(!memcmp(path, "one\0two\0three\0\0", size), "Wrong multi-sz data\n");
4650     ok(size == 15, "Expected 15, got %d\n", size);
4651     ok(type == REG_MULTI_SZ, "Expected REG_MULTI_SZ, got %d\n", type);
4652
4653     DeleteFile(msifile);
4654     DeleteFile("msitest\\augustus");
4655     RemoveDirectory("msitest");
4656
4657     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine\\msitest");
4658     RegDeleteKeyA(HKEY_LOCAL_MACHINE, "SOFTWARE\\Wine");
4659 }
4660
4661 static void test_sourcefolder(void)
4662 {
4663     UINT r;
4664
4665     CreateDirectoryA("msitest", NULL);
4666     create_file("augustus", 500);
4667
4668     create_database(msifile, sf_tables, sizeof(sf_tables) / sizeof(msi_table));
4669
4670     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4671
4672     r = MsiInstallProductA(msifile, NULL);
4673     ok(r == ERROR_INSTALL_FAILURE,
4674        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4675     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4676     todo_wine
4677     {
4678         ok(!delete_pf("msitest", FALSE), "File installed\n");
4679     }
4680
4681     RemoveDirectoryA("msitest");
4682
4683     r = MsiInstallProductA(msifile, NULL);
4684     ok(r == ERROR_INSTALL_FAILURE,
4685        "Expected ERROR_INSTALL_FAILURE, got %u\n", r);
4686     ok(!delete_pf("msitest\\augustus", TRUE), "File installed\n");
4687     todo_wine
4688     {
4689         ok(!delete_pf("msitest", FALSE), "File installed\n");
4690     }
4691
4692     DeleteFile(msifile);
4693     DeleteFile("augustus");
4694 }
4695
4696 static void test_customaction51(void)
4697 {
4698     UINT r;
4699
4700     CreateDirectoryA("msitest", NULL);
4701     create_file("msitest\\augustus", 500);
4702
4703     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
4704
4705     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4706
4707     r = MsiInstallProductA(msifile, NULL);
4708     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4709     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
4710     ok(delete_pf("msitest", FALSE), "File installed\n");
4711
4712     DeleteFile(msifile);
4713     DeleteFile("msitest\\augustus");
4714     RemoveDirectory("msitest");
4715 }
4716
4717 static void test_installstate(void)
4718 {
4719     UINT r;
4720
4721     CreateDirectoryA("msitest", NULL);
4722     create_file("msitest\\alpha", 500);
4723     create_file("msitest\\beta", 500);
4724     create_file("msitest\\gamma", 500);
4725     create_file("msitest\\theta", 500);
4726     create_file("msitest\\delta", 500);
4727     create_file("msitest\\epsilon", 500);
4728     create_file("msitest\\zeta", 500);
4729     create_file("msitest\\iota", 500);
4730     create_file("msitest\\eta", 500);
4731     create_file("msitest\\kappa", 500);
4732     create_file("msitest\\lambda", 500);
4733     create_file("msitest\\mu", 500);
4734
4735     create_database(msifile, is_tables, sizeof(is_tables) / sizeof(msi_table));
4736
4737     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
4738
4739     r = MsiInstallProductA(msifile, NULL);
4740     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4741     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4742     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4743     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4744     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4745     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4746     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4747     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4748     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4749     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4750     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4751     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4752     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4753     ok(delete_pf("msitest", FALSE), "File not installed\n");
4754
4755     r = MsiInstallProductA(msifile, "ADDLOCAL=\"one,two,three,four\"");
4756     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4757     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4758     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4759     ok(delete_pf("msitest\\gamma", TRUE), "File not installed\n");
4760     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4761     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4762     ok(delete_pf("msitest\\epsilon", TRUE), "File not installed\n");
4763     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4764     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4765     ok(delete_pf("msitest\\eta", TRUE), "File not installed\n");
4766     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4767     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4768     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4769     ok(delete_pf("msitest", FALSE), "File not installed\n");
4770
4771     r = MsiInstallProductA(msifile, "ADDSOURCE=\"one,two,three,four\"");
4772     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4773     ok(delete_pf("msitest\\alpha", TRUE), "File not installed\n");
4774     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4775     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4776     ok(delete_pf("msitest\\theta", TRUE), "File not installed\n");
4777     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4778     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4779     ok(delete_pf("msitest\\zeta", TRUE), "File not installed\n");
4780     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4781     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4782     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4783     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4784     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4785     ok(delete_pf("msitest", FALSE), "File not installed\n");
4786
4787     r = MsiInstallProductA(msifile, "REMOVE=\"one,two,three,four\"");
4788     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
4789     ok(!delete_pf("msitest\\alpha", TRUE), "File installed\n");
4790     ok(!delete_pf("msitest\\beta", TRUE), "File installed\n");
4791     ok(!delete_pf("msitest\\gamma", TRUE), "File installed\n");
4792     ok(!delete_pf("msitest\\theta", TRUE), "File installed\n");
4793     ok(!delete_pf("msitest\\delta", TRUE), "File installed\n");
4794     ok(!delete_pf("msitest\\epsilon", TRUE), "File installed\n");
4795     ok(!delete_pf("msitest\\zeta", TRUE), "File installed\n");
4796     ok(!delete_pf("msitest\\iota", TRUE), "File installed\n");
4797     ok(!delete_pf("msitest\\eta", TRUE), "File installed\n");
4798     ok(!delete_pf("msitest\\kappa", TRUE), "File installed\n");
4799     ok(!delete_pf("msitest\\lambda", TRUE), "File installed\n");
4800     ok(!delete_pf("msitest\\mu", TRUE), "File installed\n");
4801     ok(!delete_pf("msitest", FALSE), "File installed\n");
4802
4803     DeleteFile(msifile);
4804     DeleteFile("msitest\\alpha");
4805     DeleteFile("msitest\\beta");
4806     DeleteFile("msitest\\gamma");
4807     DeleteFile("msitest\\theta");
4808     DeleteFile("msitest\\delta");
4809     DeleteFile("msitest\\epsilon");
4810     DeleteFile("msitest\\zeta");
4811     DeleteFile("msitest\\iota");
4812     DeleteFile("msitest\\eta");
4813     DeleteFile("msitest\\kappa");
4814     DeleteFile("msitest\\lambda");
4815     DeleteFile("msitest\\mu");
4816     RemoveDirectory("msitest");
4817 }
4818
4819 struct sourcepathmap
4820 {
4821     BOOL sost; /* shortone\shorttwo */
4822     BOOL solt; /* shortone\longtwo */
4823     BOOL lost; /* longone\shorttwo */
4824     BOOL lolt; /* longone\longtwo */
4825     BOOL soste; /* shortone\shorttwo source exists */
4826     BOOL solte; /* shortone\longtwo source exists */
4827     BOOL loste; /* longone\shorttwo source exists */
4828     BOOL lolte; /* longone\longtwo source exists */
4829     UINT err;
4830     DWORD size;
4831 } spmap[256] =
4832 {
4833     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4834     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4835     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4836     {TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4837     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4838     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4839     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4840     {TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4841     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4842     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4843     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4844     {TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4845     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4846     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4847     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4848     {TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4849     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4850     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4851     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4852     {TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4853     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4854     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4855     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4856     {TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4857     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4858     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4859     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4860     {TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4861     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4862     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4863     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4864     {TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4865     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4866     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4867     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4868     {TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4869     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4870     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4871     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4872     {TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4873     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4874     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4875     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4876     {TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4877     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4878     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4879     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4880     {TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4881     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4882     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4883     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4884     {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4885     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4886     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4887     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4888     {TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4889     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4890     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4891     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4892     {TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4893     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4894     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4895     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4896     {TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4897     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4898     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4899     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4900     {TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4901     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4902     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4903     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4904     {TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4905     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4906     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4907     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4908     {TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4909     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4910     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4911     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4912     {TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4913     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4914     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4915     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4916     {TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4917     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4918     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4919     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4920     {TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4921     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4922     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4923     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4924     {TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4925     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4926     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4927     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4928     {TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4929     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4930     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4931     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4932     {TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4933     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4934     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4935     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4936     {TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4937     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4938     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4939     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4940     {TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4941     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4942     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4943     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4944     {TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4945     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4946     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4947     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4948     {TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4949     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4950     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4951     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4952     {TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4953     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4954     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4955     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4956     {TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4957     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4958     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4959     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4960     {TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4961     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4962     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4963     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4964     {FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4965     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4966     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4967     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4968     {FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4969     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4970     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4971     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4972     {FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4973     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4974     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4975     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
4976     {FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4977     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4978     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4979     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4980     {FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4981     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4982     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4983     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4984     {FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4985     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4986     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4987     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4988     {FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4989     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
4990     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4991     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
4992     {FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4993     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
4994     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4995     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
4996     {FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
4997     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
4998     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
4999     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5000     {FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5001     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5002     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5003     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5004     {FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5005     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5006     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5007     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5008     {FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5009     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5010     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5011     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5012     {FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5013     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5014     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5015     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5016     {FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5017     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5018     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5019     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5020     {FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5021     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5022     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5023     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5024     {FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5025     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5026     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5027     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5028     {FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5029     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5030     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5031     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5032     {FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5033     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5034     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5035     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5036     {FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5037     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5038     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5039     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5040     {FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5041     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5042     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5043     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5044     {FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5045     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5046     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5047     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5048     {FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5049     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5050     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5051     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5052     {FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5053     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5054     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5055     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5056     {FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5057     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5058     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5059     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5060     {FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5061     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5062     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5063     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5064     {FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5065     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE, ERROR_SUCCESS, 200},
5066     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5067     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, ERROR_SUCCESS, 200},
5068     {FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5069     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE, ERROR_SUCCESS, 200},
5070     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5071     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, TRUE, ERROR_SUCCESS, 200},
5072     {FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5073     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5074     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5075     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5076     {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5077     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5078     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5079     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5080     {FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5081     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5082     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5083     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5084     {FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5085     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, ERROR_INSTALL_FAILURE, 0},
5086     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, ERROR_INSTALL_FAILURE, 0},
5087     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, ERROR_INSTALL_FAILURE, 0},
5088     {FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, ERROR_INSTALL_FAILURE, 0},
5089 };
5090
5091 static DWORD get_pf_file_size(LPCSTR file)
5092 {
5093     CHAR path[MAX_PATH];
5094     HANDLE hfile;
5095     DWORD size;
5096
5097     lstrcpyA(path, PROG_FILES_DIR);
5098     lstrcatA(path, "\\");
5099     lstrcatA(path, file);
5100
5101     hfile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
5102     if (hfile == INVALID_HANDLE_VALUE)
5103         return 0;
5104
5105     size = GetFileSize(hfile, NULL);
5106     CloseHandle(hfile);
5107     return size;
5108 }
5109
5110 static void test_sourcepath(void)
5111 {
5112     UINT r, i;
5113
5114     if (!winetest_interactive)
5115     {
5116         skip("Run in interactive mode to run source path tests.\n");
5117         return;
5118     }
5119
5120     create_database(msifile, sp_tables, sizeof(sp_tables) / sizeof(msi_table));
5121
5122     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5123
5124     for (i = 0; i < sizeof(spmap) / sizeof(spmap[0]); i++)
5125     {
5126         if (spmap[i].sost)
5127         {
5128             CreateDirectoryA("shortone", NULL);
5129             CreateDirectoryA("shortone\\shorttwo", NULL);
5130         }
5131
5132         if (spmap[i].solt)
5133         {
5134             CreateDirectoryA("shortone", NULL);
5135             CreateDirectoryA("shortone\\longtwo", NULL);
5136         }
5137
5138         if (spmap[i].lost)
5139         {
5140             CreateDirectoryA("longone", NULL);
5141             CreateDirectoryA("longone\\shorttwo", NULL);
5142         }
5143
5144         if (spmap[i].lolt)
5145         {
5146             CreateDirectoryA("longone", NULL);
5147             CreateDirectoryA("longone\\longtwo", NULL);
5148         }
5149
5150         if (spmap[i].soste)
5151             create_file("shortone\\shorttwo\\augustus", 50);
5152         if (spmap[i].solte)
5153             create_file("shortone\\longtwo\\augustus", 100);
5154         if (spmap[i].loste)
5155             create_file("longone\\shorttwo\\augustus", 150);
5156         if (spmap[i].lolte)
5157             create_file("longone\\longtwo\\augustus", 200);
5158
5159         r = MsiInstallProductA(msifile, NULL);
5160         ok(r == spmap[i].err, "%d: Expected %d, got %d\n", i, spmap[i].err, r);
5161         ok(get_pf_file_size("msitest\\augustus") == spmap[i].size,
5162            "%d: Expected %d, got %d\n", i, spmap[i].size,
5163            get_pf_file_size("msitest\\augustus"));
5164
5165         if (r == ERROR_SUCCESS)
5166         {
5167             ok(delete_pf("msitest\\augustus", TRUE), "%d: File not installed\n", i);
5168             ok(delete_pf("msitest", FALSE), "%d: File not installed\n", i);
5169         }
5170         else
5171         {
5172             ok(!delete_pf("msitest\\augustus", TRUE), "%d: File installed\n", i);
5173             todo_wine ok(!delete_pf("msitest", FALSE), "%d: File installed\n", i);
5174         }
5175
5176         DeleteFileA("shortone\\shorttwo\\augustus");
5177         DeleteFileA("shortone\\longtwo\\augustus");
5178         DeleteFileA("longone\\shorttwo\\augustus");
5179         DeleteFileA("longone\\longtwo\\augustus");
5180         RemoveDirectoryA("shortone\\shorttwo");
5181         RemoveDirectoryA("shortone\\longtwo");
5182         RemoveDirectoryA("longone\\shorttwo");
5183         RemoveDirectoryA("longone\\longtwo");
5184         RemoveDirectoryA("shortone");
5185         RemoveDirectoryA("longone");
5186     }
5187
5188     DeleteFileA(msifile);
5189 }
5190
5191 static void test_MsiConfigureProductEx(void)
5192 {
5193     UINT r;
5194     LONG res;
5195     DWORD type, size;
5196     HKEY props, source;
5197     CHAR keypath[MAX_PATH * 2];
5198     CHAR localpack[MAX_PATH];
5199
5200     if (on_win9x)
5201     {
5202         win_skip("Different registry keys on Win9x and WinMe\n");
5203         return;
5204     }
5205
5206     CreateDirectoryA("msitest", NULL);
5207     create_file("msitest\\hydrogen", 500);
5208     create_file("msitest\\helium", 500);
5209     create_file("msitest\\lithium", 500);
5210
5211     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5212
5213     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5214
5215     /* NULL szProduct */
5216     r = MsiConfigureProductExA(NULL, INSTALLLEVEL_DEFAULT,
5217                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5218     ok(r == ERROR_INVALID_PARAMETER,
5219        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5220
5221     /* empty szProduct */
5222     r = MsiConfigureProductExA("", INSTALLLEVEL_DEFAULT,
5223                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5224     ok(r == ERROR_INVALID_PARAMETER,
5225        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5226
5227     /* garbage szProduct */
5228     r = MsiConfigureProductExA("garbage", INSTALLLEVEL_DEFAULT,
5229                                INSTALLSTATE_DEFAULT, "PROPVAR=42");
5230     ok(r == ERROR_INVALID_PARAMETER,
5231        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5232
5233     /* guid without brackets */
5234     r = MsiConfigureProductExA("6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D",
5235                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5236                                "PROPVAR=42");
5237     ok(r == ERROR_INVALID_PARAMETER,
5238        "Expected ERROR_INVALID_PARAMETER, got %d\n", r);
5239
5240     /* guid with brackets */
5241     r = MsiConfigureProductExA("{6700E8CF-95AB-4D9C-BC2C-15840DEA7A5D}",
5242                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5243                                "PROPVAR=42");
5244     ok(r == ERROR_UNKNOWN_PRODUCT,
5245        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5246
5247     /* same length as guid, but random */
5248     r = MsiConfigureProductExA("A938G02JF-2NF3N93-VN3-2NNF-3KGKALDNF93",
5249                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5250                                "PROPVAR=42");
5251     ok(r == ERROR_UNKNOWN_PRODUCT,
5252        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5253
5254     /* product not installed yet */
5255     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5256                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5257                                "PROPVAR=42");
5258     ok(r == ERROR_UNKNOWN_PRODUCT,
5259        "Expected ERROR_UNKNOWN_PRODUCT, got %d\n", r);
5260
5261     /* install the product, per-user unmanaged */
5262     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
5263     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5264     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5265     ok(pf_exists("msitest\\helium"), "File not installed\n");
5266     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5267     ok(pf_exists("msitest"), "File not installed\n");
5268
5269     /* product is installed per-user managed, remove it */
5270     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5271                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5272                                "PROPVAR=42");
5273     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5274     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5275     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5276     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5277     todo_wine
5278     {
5279         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5280     }
5281
5282     /* product has been removed */
5283     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5284                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5285                                "PROPVAR=42");
5286     ok(r == ERROR_UNKNOWN_PRODUCT,
5287        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
5288
5289     /* install the product, machine */
5290     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5291     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5292     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5293     ok(pf_exists("msitest\\helium"), "File not installed\n");
5294     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5295     ok(pf_exists("msitest"), "File not installed\n");
5296
5297     /* product is installed machine, remove it */
5298     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5299                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5300                                "PROPVAR=42");
5301     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5302     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5303     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5304     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5305     todo_wine
5306     {
5307         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5308     }
5309
5310     /* product has been removed */
5311     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5312                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_DEFAULT,
5313                                "PROPVAR=42");
5314     ok(r == ERROR_UNKNOWN_PRODUCT,
5315        "Expected ERROR_UNKNOWN_PRODUCT, got %u\n", r);
5316
5317     /* install the product, machine */
5318     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5319     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5320     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5321     ok(pf_exists("msitest\\helium"), "File not installed\n");
5322     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5323     ok(pf_exists("msitest"), "File not installed\n");
5324
5325     DeleteFileA(msifile);
5326
5327     /* local msifile is removed */
5328     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5329                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5330                                "PROPVAR=42");
5331     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5332     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5333     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5334     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5335     todo_wine
5336     {
5337         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5338     }
5339
5340     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5341
5342     /* install the product, machine */
5343     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5344     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5345     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5346     ok(pf_exists("msitest\\helium"), "File not installed\n");
5347     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5348     ok(pf_exists("msitest"), "File not installed\n");
5349
5350     DeleteFileA(msifile);
5351
5352     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
5353     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
5354     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
5355
5356     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
5357     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5358
5359     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
5360                          (const BYTE *)"C:\\idontexist.msi", 18);
5361     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5362
5363     /* LocalPackage is used to find the cached msi package */
5364     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5365                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5366                                "PROPVAR=42");
5367     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
5368        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
5369     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5370     ok(pf_exists("msitest\\helium"), "File not installed\n");
5371     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5372     ok(pf_exists("msitest"), "File not installed\n");
5373
5374     RegCloseKey(props);
5375     create_database(msifile, mcp_tables, sizeof(mcp_tables) / sizeof(msi_table));
5376
5377     /* LastUsedSource (local msi package) can be used as a last resort */
5378     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5379                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5380                                "PROPVAR=42");
5381     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5382     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5383     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5384     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5385     todo_wine
5386     {
5387         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5388     }
5389
5390     /* install the product, machine */
5391     r = MsiInstallProductA(msifile, "ALLUSERS=1 INSTALLLEVEL=10 PROPVAR=42");
5392     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5393     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5394     ok(pf_exists("msitest\\helium"), "File not installed\n");
5395     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5396     ok(pf_exists("msitest"), "File not installed\n");
5397
5398     lstrcpyA(keypath, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\");
5399     lstrcatA(keypath, "Installer\\UserData\\S-1-5-18\\Products\\");
5400     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\InstallProperties");
5401
5402     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &props);
5403     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5404
5405     res = RegSetValueExA(props, "LocalPackage", 0, REG_SZ,
5406                          (const BYTE *)"C:\\idontexist.msi", 18);
5407     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5408
5409     lstrcpyA(keypath, "SOFTWARE\\Classes\\Installer\\Products\\");
5410     lstrcatA(keypath, "84A88FD7F6998CE40A22FB59F6B9C2BB\\SourceList");
5411
5412     res = RegOpenKeyA(HKEY_LOCAL_MACHINE, keypath, &source);
5413     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5414
5415     type = REG_SZ;
5416     size = MAX_PATH;
5417     res = RegQueryValueExA(source, "PackageName", NULL, &type,
5418                            (LPBYTE)localpack, &size);
5419     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5420
5421     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
5422                          (const BYTE *)"idontexist.msi", 15);
5423     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5424
5425     /* SourceList is altered */
5426     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5427                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5428                                "PROPVAR=42");
5429     ok(r == ERROR_INSTALL_SOURCE_ABSENT,
5430        "Expected ERROR_INSTALL_SOURCE_ABSENT, got %d\n", r);
5431     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5432     ok(pf_exists("msitest\\helium"), "File not installed\n");
5433     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5434     ok(pf_exists("msitest"), "File not installed\n");
5435
5436     /* restore the SourceList */
5437     res = RegSetValueExA(source, "PackageName", 0, REG_SZ,
5438                          (const BYTE *)localpack, lstrlenA(localpack) + 1);
5439     ok(res == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", res);
5440
5441     /* finally remove the product */
5442     r = MsiConfigureProductExA("{7DF88A48-996F-4EC8-A022-BF956F9B2CBB}",
5443                                INSTALLLEVEL_DEFAULT, INSTALLSTATE_ABSENT,
5444                                "PROPVAR=42");
5445     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
5446     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5447     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5448     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5449     todo_wine
5450     {
5451         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5452     }
5453
5454     DeleteFileA(msifile);
5455     RegCloseKey(source);
5456     RegCloseKey(props);
5457     DeleteFileA("msitest\\hydrogen");
5458     DeleteFileA("msitest\\helium");
5459     DeleteFileA("msitest\\lithium");
5460     RemoveDirectoryA("msitest");
5461 }
5462
5463 static void test_missingcomponent(void)
5464 {
5465     UINT r;
5466
5467     CreateDirectoryA("msitest", NULL);
5468     create_file("msitest\\hydrogen", 500);
5469     create_file("msitest\\helium", 500);
5470     create_file("msitest\\lithium", 500);
5471     create_file("beryllium", 500);
5472
5473     create_database(msifile, mcomp_tables, sizeof(mcomp_tables) / sizeof(msi_table));
5474
5475     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5476
5477     r = MsiInstallProductA(msifile, "INSTALLLEVEL=10 PROPVAR=42");
5478     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5479     ok(pf_exists("msitest\\hydrogen"), "File not installed\n");
5480     ok(pf_exists("msitest\\helium"), "File not installed\n");
5481     ok(pf_exists("msitest\\lithium"), "File not installed\n");
5482     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
5483     ok(pf_exists("msitest"), "File not installed\n");
5484
5485     r = MsiInstallProductA(msifile, "REMOVE=ALL INSTALLLEVEL=10 PROPVAR=42");
5486     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5487     ok(!delete_pf("msitest\\hydrogen", TRUE), "File not removed\n");
5488     ok(!delete_pf("msitest\\helium", TRUE), "File not removed\n");
5489     ok(!delete_pf("msitest\\lithium", TRUE), "File not removed\n");
5490     ok(!pf_exists("msitest\\beryllium"), "File installed\n");
5491     todo_wine
5492     {
5493         ok(!delete_pf("msitest", FALSE), "File not removed\n");
5494     }
5495
5496     DeleteFileA(msifile);
5497     DeleteFileA("msitest\\hydrogen");
5498     DeleteFileA("msitest\\helium");
5499     DeleteFileA("msitest\\lithium");
5500     DeleteFileA("beryllium");
5501     RemoveDirectoryA("msitest");
5502 }
5503
5504 static void test_sourcedirprop(void)
5505 {
5506     UINT r;
5507     CHAR props[MAX_PATH];
5508
5509     CreateDirectoryA("msitest", NULL);
5510     create_file("msitest\\augustus", 500);
5511
5512     create_database(msifile, ca51_tables, sizeof(ca51_tables) / sizeof(msi_table));
5513
5514     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5515
5516     r = MsiInstallProductA(msifile, NULL);
5517     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5518     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5519     ok(delete_pf("msitest", FALSE), "File installed\n");
5520
5521     DeleteFile("msitest\\augustus");
5522     RemoveDirectory("msitest");
5523
5524     CreateDirectoryA("altsource", NULL);
5525     CreateDirectoryA("altsource\\msitest", NULL);
5526     create_file("altsource\\msitest\\augustus", 500);
5527
5528     sprintf(props, "SRCDIR=%s\\altsource\\", CURR_DIR);
5529
5530     r = MsiInstallProductA(msifile, props);
5531     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5532     ok(delete_pf("msitest\\augustus", TRUE), "File installed\n");
5533     ok(delete_pf("msitest", FALSE), "File installed\n");
5534
5535     DeleteFile(msifile);
5536     DeleteFile("altsource\\msitest\\augustus");
5537     RemoveDirectory("altsource\\msitest");
5538     RemoveDirectory("altsource");
5539 }
5540
5541 static void test_adminimage(void)
5542 {
5543     UINT r;
5544
5545     CreateDirectoryA("msitest", NULL);
5546     CreateDirectoryA("msitest\\first", NULL);
5547     CreateDirectoryA("msitest\\second", NULL);
5548     CreateDirectoryA("msitest\\cabout", NULL);
5549     CreateDirectoryA("msitest\\cabout\\new", NULL);
5550     create_file("msitest\\one.txt", 100);
5551     create_file("msitest\\first\\two.txt", 100);
5552     create_file("msitest\\second\\three.txt", 100);
5553     create_file("msitest\\cabout\\four.txt", 100);
5554     create_file("msitest\\cabout\\new\\five.txt", 100);
5555     create_file("msitest\\filename", 100);
5556     create_file("msitest\\service.exe", 100);
5557
5558     create_database_wordcount(msifile, ai_tables,
5559                               sizeof(ai_tables) / sizeof(msi_table),
5560                               msidbSumInfoSourceTypeAdminImage);
5561
5562     r = MsiInstallProductA(msifile, NULL);
5563     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5564
5565     ok(delete_pf("msitest\\cabout\\new\\five.txt", TRUE), "File not installed\n");
5566     ok(delete_pf("msitest\\cabout\\new", FALSE), "File not installed\n");
5567     ok(delete_pf("msitest\\cabout\\four.txt", TRUE), "File not installed\n");
5568     ok(delete_pf("msitest\\cabout", FALSE), "File not installed\n");
5569     ok(delete_pf("msitest\\changed\\three.txt", TRUE), "File not installed\n");
5570     ok(delete_pf("msitest\\changed", FALSE), "File not installed\n");
5571     ok(delete_pf("msitest\\first\\two.txt", TRUE), "File not installed\n");
5572     ok(delete_pf("msitest\\first", FALSE), "File not installed\n");
5573     ok(delete_pf("msitest\\one.txt", TRUE), "File not installed\n");
5574     ok(delete_pf("msitest\\filename", TRUE), "File not installed\n");
5575     ok(delete_pf("msitest\\service.exe", TRUE), "File not installed\n");
5576     ok(delete_pf("msitest", FALSE), "File not installed\n");
5577
5578     DeleteFileA("msitest.msi");
5579     DeleteFileA("msitest\\cabout\\new\\five.txt");
5580     DeleteFileA("msitest\\cabout\\four.txt");
5581     DeleteFileA("msitest\\second\\three.txt");
5582     DeleteFileA("msitest\\first\\two.txt");
5583     DeleteFileA("msitest\\one.txt");
5584     DeleteFileA("msitest\\service.exe");
5585     DeleteFileA("msitest\\filename");
5586     RemoveDirectoryA("msitest\\cabout\\new");
5587     RemoveDirectoryA("msitest\\cabout");
5588     RemoveDirectoryA("msitest\\second");
5589     RemoveDirectoryA("msitest\\first");
5590     RemoveDirectoryA("msitest");
5591 }
5592
5593 static void test_propcase(void)
5594 {
5595     UINT r;
5596
5597     CreateDirectoryA("msitest", NULL);
5598     create_file("msitest\\augustus", 500);
5599
5600     create_database(msifile, pc_tables, sizeof(pc_tables) / sizeof(msi_table));
5601
5602     MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
5603
5604     r = MsiInstallProductA(msifile, "MyProp=42");
5605     ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
5606     ok(delete_pf("msitest\\augustus", TRUE), "File not installed\n");
5607     ok(delete_pf("msitest", FALSE), "File not installed\n");
5608
5609     DeleteFile(msifile);
5610     DeleteFile("msitest\\augustus");
5611     RemoveDirectory("msitest");
5612 }
5613
5614 START_TEST(install)
5615 {
5616     DWORD len;
5617     char temp_path[MAX_PATH], prev_path[MAX_PATH];
5618     STATEMGRSTATUS status;
5619     BOOL ret = FALSE;
5620
5621     init_functionpointers();
5622
5623     on_win9x = check_win9x();
5624
5625     GetCurrentDirectoryA(MAX_PATH, prev_path);
5626     GetTempPath(MAX_PATH, temp_path);
5627     SetCurrentDirectoryA(temp_path);
5628
5629     lstrcpyA(CURR_DIR, temp_path);
5630     len = lstrlenA(CURR_DIR);
5631
5632     if(len && (CURR_DIR[len - 1] == '\\'))
5633         CURR_DIR[len - 1] = 0;
5634
5635     get_program_files_dir(PROG_FILES_DIR, COMMON_FILES_DIR);
5636
5637     /* Create a restore point ourselves so we circumvent the multitude of restore points
5638      * that would have been created by all the installation and removal tests.
5639      */
5640     if (pSRSetRestorePointA)
5641     {
5642         memset(&status, 0, sizeof(status));
5643         ret = notify_system_change(BEGIN_NESTED_SYSTEM_CHANGE, &status);
5644     }
5645
5646     /* Create only one log file and don't append. We have to pass something
5647      * for the log mode for this to work.
5648      */
5649     MsiEnableLogA(INSTALLLOGMODE_FATALEXIT, "msitest.log", 0);
5650
5651     test_MsiInstallProduct();
5652     test_MsiSetComponentState();
5653     test_packagecoltypes();
5654     test_continuouscabs();
5655     test_caborder();
5656     test_mixedmedia();
5657     test_samesequence();
5658     test_uiLevelFlags();
5659     test_readonlyfile();
5660     test_setdirproperty();
5661     test_cabisextracted();
5662     test_concurrentinstall();
5663     test_setpropertyfolder();
5664     test_publish_registerproduct();
5665     test_publish_publishproduct();
5666     test_publish_publishfeatures();
5667     test_publish_registeruser();
5668     test_publish_processcomponents();
5669     test_publish();
5670     test_publishsourcelist();
5671     test_transformprop();
5672     test_currentworkingdir();
5673     test_admin();
5674     test_adminprops();
5675     test_removefiles();
5676     test_movefiles();
5677     test_missingcab();
5678     test_duplicatefiles();
5679     test_writeregistryvalues();
5680     test_sourcefolder();
5681     test_customaction51();
5682     test_installstate();
5683     test_sourcepath();
5684     test_MsiConfigureProductEx();
5685     test_missingcomponent();
5686     test_sourcedirprop();
5687     test_adminimage();
5688     test_propcase();
5689
5690     DeleteFileA("msitest.log");
5691
5692     if (pSRSetRestorePointA && ret)
5693     {
5694         ret = notify_system_change(END_NESTED_SYSTEM_CHANGE, &status);
5695         if (ret)
5696             remove_restore_point(status.llSequenceNumber);
5697     }
5698     FreeLibrary(hsrclient);
5699
5700     SetCurrentDirectoryA(prev_path);
5701 }