1c2c66affSColin Finck /*
2c2c66affSColin Finck * Implementation of the Microsoft Installer (msi.dll)
3c2c66affSColin Finck *
4c2c66affSColin Finck * Copyright 2005 Aric Stewart for CodeWeavers
5c2c66affSColin Finck *
6c2c66affSColin Finck * This library is free software; you can redistribute it and/or
7c2c66affSColin Finck * modify it under the terms of the GNU Lesser General Public
8c2c66affSColin Finck * License as published by the Free Software Foundation; either
9c2c66affSColin Finck * version 2.1 of the License, or (at your option) any later version.
10c2c66affSColin Finck *
11c2c66affSColin Finck * This library is distributed in the hope that it will be useful,
12c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14c2c66affSColin Finck * Lesser General Public License for more details.
15c2c66affSColin Finck *
16c2c66affSColin Finck * You should have received a copy of the GNU Lesser General Public
17c2c66affSColin Finck * License along with this library; if not, write to the Free Software
18c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19c2c66affSColin Finck */
20c2c66affSColin Finck
21c2c66affSColin Finck /* Actions handled in this module:
22c2c66affSColin Finck *
23c2c66affSColin Finck * RegisterClassInfo
24c2c66affSColin Finck * RegisterProgIdInfo
25c2c66affSColin Finck * RegisterExtensionInfo
26c2c66affSColin Finck * RegisterMIMEInfo
27c2c66affSColin Finck * UnregisterClassInfo
28c2c66affSColin Finck * UnregisterProgIdInfo
29c2c66affSColin Finck * UnregisterExtensionInfo
30c2c66affSColin Finck * UnregisterMIMEInfo
31c2c66affSColin Finck */
32c2c66affSColin Finck
33c42b133eSAmine Khaldi #include <stdarg.h>
34c42b133eSAmine Khaldi
35c42b133eSAmine Khaldi #include "windef.h"
36c42b133eSAmine Khaldi #include "winbase.h"
37c42b133eSAmine Khaldi #include "winerror.h"
38c42b133eSAmine Khaldi #include "winreg.h"
39c42b133eSAmine Khaldi #include "wine/debug.h"
40c2c66affSColin Finck #include "msipriv.h"
41c42b133eSAmine Khaldi #include "winuser.h"
42c2c66affSColin Finck
43c2c66affSColin Finck WINE_DEFAULT_DEBUG_CHANNEL(msi);
44c2c66affSColin Finck
load_appid(MSIPACKAGE * package,MSIRECORD * row)45c2c66affSColin Finck static MSIAPPID *load_appid( MSIPACKAGE* package, MSIRECORD *row )
46c2c66affSColin Finck {
47c2c66affSColin Finck LPCWSTR buffer;
48c2c66affSColin Finck MSIAPPID *appid;
49c2c66affSColin Finck
50c2c66affSColin Finck /* fill in the data */
51c2c66affSColin Finck
52*f4be6dc3SMikhail appid = calloc( 1, sizeof(MSIAPPID) );
53c2c66affSColin Finck if (!appid)
54c2c66affSColin Finck return NULL;
55c2c66affSColin Finck
56c2c66affSColin Finck appid->AppID = msi_dup_record_field( row, 1 );
57c2c66affSColin Finck TRACE("loading appid %s\n", debugstr_w( appid->AppID ));
58c2c66affSColin Finck
59c2c66affSColin Finck buffer = MSI_RecordGetString(row,2);
60c2c66affSColin Finck deformat_string( package, buffer, &appid->RemoteServerName );
61c2c66affSColin Finck
62c2c66affSColin Finck appid->LocalServer = msi_dup_record_field(row,3);
63c2c66affSColin Finck appid->ServiceParameters = msi_dup_record_field(row,4);
64c2c66affSColin Finck appid->DllSurrogate = msi_dup_record_field(row,5);
65c2c66affSColin Finck
66c2c66affSColin Finck appid->ActivateAtStorage = !MSI_RecordIsNull(row,6);
67c2c66affSColin Finck appid->RunAsInteractiveUser = !MSI_RecordIsNull(row,7);
68c2c66affSColin Finck
69c2c66affSColin Finck list_add_tail( &package->appids, &appid->entry );
70c2c66affSColin Finck
71c2c66affSColin Finck return appid;
72c2c66affSColin Finck }
73c2c66affSColin Finck
load_given_appid(MSIPACKAGE * package,LPCWSTR name)74c2c66affSColin Finck static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name )
75c2c66affSColin Finck {
76c2c66affSColin Finck MSIRECORD *row;
77c2c66affSColin Finck MSIAPPID *appid;
78c2c66affSColin Finck
79c2c66affSColin Finck if (!name)
80c2c66affSColin Finck return NULL;
81c2c66affSColin Finck
82c2c66affSColin Finck /* check for appids already loaded */
83c2c66affSColin Finck LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry )
84c2c66affSColin Finck {
85958f1addSwinesync if (!wcsicmp( appid->AppID, name ))
86c2c66affSColin Finck {
87c2c66affSColin Finck TRACE("found appid %s %p\n", debugstr_w(name), appid);
88c2c66affSColin Finck return appid;
89c2c66affSColin Finck }
90c2c66affSColin Finck }
91c2c66affSColin Finck
92d012037fSwinesync row = MSI_QueryGetRecord(package->db, L"SELECT * FROM `AppId` WHERE `AppId` = '%s'", name);
93c2c66affSColin Finck if (!row)
94c2c66affSColin Finck return NULL;
95c2c66affSColin Finck
96c2c66affSColin Finck appid = load_appid(package, row);
97c2c66affSColin Finck msiobj_release(&row->hdr);
98c2c66affSColin Finck return appid;
99c2c66affSColin Finck }
100c2c66affSColin Finck
101c2c66affSColin Finck static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR progid);
102c2c66affSColin Finck static MSICLASS *load_given_class( MSIPACKAGE *package, LPCWSTR classid );
103c2c66affSColin Finck
load_progid(MSIPACKAGE * package,MSIRECORD * row)104c2c66affSColin Finck static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row )
105c2c66affSColin Finck {
106c2c66affSColin Finck MSIPROGID *progid;
107c2c66affSColin Finck LPCWSTR buffer;
108c2c66affSColin Finck
109c2c66affSColin Finck /* fill in the data */
110c2c66affSColin Finck
111*f4be6dc3SMikhail progid = calloc( 1, sizeof(MSIPROGID) );
112c2c66affSColin Finck if (!progid)
113c2c66affSColin Finck return NULL;
114c2c66affSColin Finck
115c2c66affSColin Finck list_add_tail( &package->progids, &progid->entry );
116c2c66affSColin Finck
117c2c66affSColin Finck progid->ProgID = msi_dup_record_field(row,1);
118c2c66affSColin Finck TRACE("loading progid %s\n",debugstr_w(progid->ProgID));
119c2c66affSColin Finck
120c2c66affSColin Finck buffer = MSI_RecordGetString(row,2);
121c2c66affSColin Finck progid->Parent = load_given_progid(package,buffer);
122c2c66affSColin Finck if (progid->Parent == NULL && buffer)
123c2c66affSColin Finck FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer));
124c2c66affSColin Finck
125c2c66affSColin Finck buffer = MSI_RecordGetString(row,3);
126c2c66affSColin Finck progid->Class = load_given_class(package,buffer);
127c2c66affSColin Finck if (progid->Class == NULL && buffer)
128c2c66affSColin Finck FIXME("Unknown class %s\n",debugstr_w(buffer));
129c2c66affSColin Finck
130c2c66affSColin Finck progid->Description = msi_dup_record_field(row,4);
131c2c66affSColin Finck
132c2c66affSColin Finck if (!MSI_RecordIsNull(row,6))
133c2c66affSColin Finck {
134c2c66affSColin Finck INT icon_index = MSI_RecordGetInteger(row,6);
135c2c66affSColin Finck LPCWSTR FileName = MSI_RecordGetString(row,5);
136c2c66affSColin Finck LPWSTR FilePath;
137c2c66affSColin Finck
138c2c66affSColin Finck FilePath = msi_build_icon_path(package, FileName);
139c2c66affSColin Finck
140*f4be6dc3SMikhail progid->IconPath = malloc( (wcslen(FilePath) + 10) * sizeof(WCHAR) );
141d012037fSwinesync swprintf( progid->IconPath, lstrlenW(FilePath) + 10, L"%s,%d", FilePath, icon_index );
142*f4be6dc3SMikhail free(FilePath);
143c2c66affSColin Finck }
144c2c66affSColin Finck else
145c2c66affSColin Finck {
146c2c66affSColin Finck buffer = MSI_RecordGetString(row,5);
147c2c66affSColin Finck if (buffer)
148c2c66affSColin Finck progid->IconPath = msi_build_icon_path(package, buffer);
149c2c66affSColin Finck }
150c2c66affSColin Finck
151c2c66affSColin Finck progid->CurVer = NULL;
152c2c66affSColin Finck progid->VersionInd = NULL;
153c2c66affSColin Finck
154c2c66affSColin Finck /* if we have a parent then we may be that parents CurVer */
155c2c66affSColin Finck if (progid->Parent && progid->Parent != progid)
156c2c66affSColin Finck {
157c2c66affSColin Finck MSIPROGID *parent = progid->Parent;
158c2c66affSColin Finck
159c2c66affSColin Finck while (parent->Parent && parent->Parent != parent)
160c2c66affSColin Finck parent = parent->Parent;
161c2c66affSColin Finck
162c2c66affSColin Finck /* FIXME: need to determine if we are really the CurVer */
163c2c66affSColin Finck
164c2c66affSColin Finck progid->CurVer = parent;
165c2c66affSColin Finck parent->VersionInd = progid;
166c2c66affSColin Finck }
167c2c66affSColin Finck
168c2c66affSColin Finck return progid;
169c2c66affSColin Finck }
170c2c66affSColin Finck
load_given_progid(MSIPACKAGE * package,LPCWSTR name)171c2c66affSColin Finck static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name)
172c2c66affSColin Finck {
173c2c66affSColin Finck MSIPROGID *progid;
174c2c66affSColin Finck MSIRECORD *row;
175c2c66affSColin Finck
176c2c66affSColin Finck if (!name)
177c2c66affSColin Finck return NULL;
178c2c66affSColin Finck
179c2c66affSColin Finck /* check for progids already loaded */
180c2c66affSColin Finck LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
181c2c66affSColin Finck {
182958f1addSwinesync if (!wcsicmp( progid->ProgID, name ))
183c2c66affSColin Finck {
184c2c66affSColin Finck TRACE("found progid %s (%p)\n",debugstr_w(name), progid );
185c2c66affSColin Finck return progid;
186c2c66affSColin Finck }
187c2c66affSColin Finck }
188c2c66affSColin Finck
189d012037fSwinesync row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `ProgId` WHERE `ProgId` = '%s'", name );
190c2c66affSColin Finck if (!row)
191c2c66affSColin Finck return NULL;
192c2c66affSColin Finck
193c2c66affSColin Finck progid = load_progid(package, row);
194c2c66affSColin Finck msiobj_release(&row->hdr);
195c2c66affSColin Finck return progid;
196c2c66affSColin Finck }
197c2c66affSColin Finck
load_class(MSIPACKAGE * package,MSIRECORD * row)198c2c66affSColin Finck static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row )
199c2c66affSColin Finck {
200c2c66affSColin Finck MSICLASS *cls;
201c2c66affSColin Finck DWORD i;
202c2c66affSColin Finck LPCWSTR buffer;
203c2c66affSColin Finck
204c2c66affSColin Finck /* fill in the data */
205c2c66affSColin Finck
206*f4be6dc3SMikhail cls = calloc( 1, sizeof(MSICLASS) );
207c2c66affSColin Finck if (!cls)
208c2c66affSColin Finck return NULL;
209c2c66affSColin Finck
210c2c66affSColin Finck list_add_tail( &package->classes, &cls->entry );
211c2c66affSColin Finck
212c2c66affSColin Finck cls->clsid = msi_dup_record_field( row, 1 );
213c2c66affSColin Finck TRACE("loading class %s\n",debugstr_w(cls->clsid));
214c2c66affSColin Finck cls->Context = msi_dup_record_field( row, 2 );
215c2c66affSColin Finck buffer = MSI_RecordGetString(row,3);
216c2c66affSColin Finck cls->Component = msi_get_loaded_component( package, buffer );
217c2c66affSColin Finck
218c2c66affSColin Finck cls->ProgIDText = msi_dup_record_field(row,4);
219c2c66affSColin Finck cls->ProgID = load_given_progid(package, cls->ProgIDText);
220c2c66affSColin Finck
221c2c66affSColin Finck cls->Description = msi_dup_record_field(row,5);
222c2c66affSColin Finck
223c2c66affSColin Finck buffer = MSI_RecordGetString(row,6);
224c2c66affSColin Finck if (buffer)
225c2c66affSColin Finck cls->AppID = load_given_appid(package, buffer);
226c2c66affSColin Finck
227c2c66affSColin Finck cls->FileTypeMask = msi_dup_record_field(row,7);
228c2c66affSColin Finck
229c2c66affSColin Finck if (!MSI_RecordIsNull(row,9))
230c2c66affSColin Finck {
231c2c66affSColin Finck
232c2c66affSColin Finck INT icon_index = MSI_RecordGetInteger(row,9);
233c2c66affSColin Finck LPCWSTR FileName = MSI_RecordGetString(row,8);
234c2c66affSColin Finck LPWSTR FilePath;
235c2c66affSColin Finck
236c2c66affSColin Finck FilePath = msi_build_icon_path(package, FileName);
237c2c66affSColin Finck
238*f4be6dc3SMikhail cls->IconPath = malloc( (wcslen(FilePath) + 5) * sizeof(WCHAR) );
239d012037fSwinesync swprintf( cls->IconPath, lstrlenW(FilePath) + 5, L"%s,%d", FilePath, icon_index );
240*f4be6dc3SMikhail free(FilePath);
241c2c66affSColin Finck }
242c2c66affSColin Finck else
243c2c66affSColin Finck {
244c2c66affSColin Finck buffer = MSI_RecordGetString(row,8);
245c2c66affSColin Finck if (buffer)
246c2c66affSColin Finck cls->IconPath = msi_build_icon_path(package, buffer);
247c2c66affSColin Finck }
248c2c66affSColin Finck
249c2c66affSColin Finck if (!MSI_RecordIsNull(row,10))
250c2c66affSColin Finck {
251c2c66affSColin Finck i = MSI_RecordGetInteger(row,10);
252c2c66affSColin Finck if (i != MSI_NULL_INTEGER && i > 0 && i < 4)
253c2c66affSColin Finck {
254c2c66affSColin Finck switch(i)
255c2c66affSColin Finck {
256c2c66affSColin Finck case 1:
257*f4be6dc3SMikhail cls->DefInprocHandler = wcsdup(L"ole2.dll");
258c2c66affSColin Finck break;
259c2c66affSColin Finck case 2:
260*f4be6dc3SMikhail cls->DefInprocHandler32 = wcsdup(L"ole32.dll");
261c2c66affSColin Finck break;
262c2c66affSColin Finck case 3:
263*f4be6dc3SMikhail cls->DefInprocHandler = wcsdup(L"ole2.dll");
264*f4be6dc3SMikhail cls->DefInprocHandler32 = wcsdup(L"ole32.dll");
265c2c66affSColin Finck break;
266c2c66affSColin Finck }
267c2c66affSColin Finck }
268c2c66affSColin Finck else
269c2c66affSColin Finck {
270c2c66affSColin Finck cls->DefInprocHandler32 = msi_dup_record_field( row, 10 );
271c2c66affSColin Finck msi_reduce_to_long_filename( cls->DefInprocHandler32 );
272c2c66affSColin Finck }
273c2c66affSColin Finck }
274c2c66affSColin Finck buffer = MSI_RecordGetString(row,11);
275c2c66affSColin Finck deformat_string(package,buffer,&cls->Argument);
276c2c66affSColin Finck
277c2c66affSColin Finck buffer = MSI_RecordGetString(row,12);
278c2c66affSColin Finck cls->Feature = msi_get_loaded_feature(package, buffer);
279c2c66affSColin Finck
280c2c66affSColin Finck cls->Attributes = MSI_RecordGetInteger(row,13);
281c2c66affSColin Finck cls->action = INSTALLSTATE_UNKNOWN;
282c2c66affSColin Finck return cls;
283c2c66affSColin Finck }
284c2c66affSColin Finck
285c2c66affSColin Finck /*
286c2c66affSColin Finck * the Class table has 3 primary keys. Generally it is only
287c2c66affSColin Finck * referenced through the first CLSID key. However when loading
288c2c66affSColin Finck * all of the classes we need to make sure we do not ignore rows
289c2c66affSColin Finck * with other Context and ComponentIndexs
290c2c66affSColin Finck */
load_given_class(MSIPACKAGE * package,LPCWSTR classid)291c2c66affSColin Finck static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid)
292c2c66affSColin Finck {
293c2c66affSColin Finck MSICLASS *cls;
294c2c66affSColin Finck MSIRECORD *row;
295c2c66affSColin Finck
296c2c66affSColin Finck if (!classid)
297c2c66affSColin Finck return NULL;
298c2c66affSColin Finck
299c2c66affSColin Finck /* check for classes already loaded */
300c2c66affSColin Finck LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
301c2c66affSColin Finck {
302958f1addSwinesync if (!wcsicmp( cls->clsid, classid ))
303c2c66affSColin Finck {
304c2c66affSColin Finck TRACE("found class %s (%p)\n",debugstr_w(classid), cls);
305c2c66affSColin Finck return cls;
306c2c66affSColin Finck }
307c2c66affSColin Finck }
308c2c66affSColin Finck
309d012037fSwinesync row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `Class` WHERE `CLSID` = '%s'", classid );
310c2c66affSColin Finck if (!row)
311c2c66affSColin Finck return NULL;
312c2c66affSColin Finck
313c2c66affSColin Finck cls = load_class(package, row);
314c2c66affSColin Finck msiobj_release(&row->hdr);
315c2c66affSColin Finck return cls;
316c2c66affSColin Finck }
317c2c66affSColin Finck
318c2c66affSColin Finck static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR extension );
319c2c66affSColin Finck
load_mime(MSIPACKAGE * package,MSIRECORD * row)320c2c66affSColin Finck static MSIMIME *load_mime( MSIPACKAGE* package, MSIRECORD *row )
321c2c66affSColin Finck {
322c2c66affSColin Finck LPCWSTR extension;
323c2c66affSColin Finck MSIMIME *mt;
324c2c66affSColin Finck
325c2c66affSColin Finck /* fill in the data */
326c2c66affSColin Finck
327*f4be6dc3SMikhail mt = calloc( 1, sizeof(MSIMIME) );
328c2c66affSColin Finck if (!mt)
329c2c66affSColin Finck return mt;
330c2c66affSColin Finck
331c2c66affSColin Finck mt->ContentType = msi_dup_record_field( row, 1 );
332c2c66affSColin Finck TRACE("loading mime %s\n", debugstr_w(mt->ContentType));
333c2c66affSColin Finck
334c2c66affSColin Finck extension = MSI_RecordGetString( row, 2 );
335c2c66affSColin Finck mt->Extension = load_given_extension( package, extension );
336*f4be6dc3SMikhail mt->suffix = wcsdup( extension );
337c2c66affSColin Finck
338c2c66affSColin Finck mt->clsid = msi_dup_record_field( row, 3 );
339c2c66affSColin Finck mt->Class = load_given_class( package, mt->clsid );
340c2c66affSColin Finck
341c2c66affSColin Finck list_add_tail( &package->mimes, &mt->entry );
342c2c66affSColin Finck
343c2c66affSColin Finck return mt;
344c2c66affSColin Finck }
345c2c66affSColin Finck
load_given_mime(MSIPACKAGE * package,LPCWSTR mime)346c2c66affSColin Finck static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime )
347c2c66affSColin Finck {
348c2c66affSColin Finck MSIRECORD *row;
349c2c66affSColin Finck MSIMIME *mt;
350c2c66affSColin Finck
351c2c66affSColin Finck if (!mime)
352c2c66affSColin Finck return NULL;
353c2c66affSColin Finck
354c2c66affSColin Finck /* check for mime already loaded */
355c2c66affSColin Finck LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
356c2c66affSColin Finck {
357958f1addSwinesync if (!wcsicmp( mt->ContentType, mime ))
358c2c66affSColin Finck {
359c2c66affSColin Finck TRACE("found mime %s (%p)\n",debugstr_w(mime), mt);
360c2c66affSColin Finck return mt;
361c2c66affSColin Finck }
362c2c66affSColin Finck }
363c2c66affSColin Finck
364d012037fSwinesync row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `MIME` WHERE `ContentType` = '%s'", mime );
365c2c66affSColin Finck if (!row)
366c2c66affSColin Finck return NULL;
367c2c66affSColin Finck
368c2c66affSColin Finck mt = load_mime(package, row);
369c2c66affSColin Finck msiobj_release(&row->hdr);
370c2c66affSColin Finck return mt;
371c2c66affSColin Finck }
372c2c66affSColin Finck
load_extension(MSIPACKAGE * package,MSIRECORD * row)373c2c66affSColin Finck static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row )
374c2c66affSColin Finck {
375c2c66affSColin Finck MSIEXTENSION *ext;
376c2c66affSColin Finck LPCWSTR buffer;
377c2c66affSColin Finck
378c2c66affSColin Finck /* fill in the data */
379c2c66affSColin Finck
380*f4be6dc3SMikhail ext = calloc( 1, sizeof(MSIEXTENSION) );
381c2c66affSColin Finck if (!ext)
382c2c66affSColin Finck return NULL;
383c2c66affSColin Finck
384c2c66affSColin Finck list_init( &ext->verbs );
385c2c66affSColin Finck
386c2c66affSColin Finck list_add_tail( &package->extensions, &ext->entry );
387c2c66affSColin Finck
388c2c66affSColin Finck ext->Extension = msi_dup_record_field( row, 1 );
389c2c66affSColin Finck TRACE("loading extension %s\n", debugstr_w(ext->Extension));
390c2c66affSColin Finck
391c2c66affSColin Finck buffer = MSI_RecordGetString( row, 2 );
392c2c66affSColin Finck ext->Component = msi_get_loaded_component( package, buffer );
393c2c66affSColin Finck
394c2c66affSColin Finck ext->ProgIDText = msi_dup_record_field( row, 3 );
395c2c66affSColin Finck ext->ProgID = load_given_progid( package, ext->ProgIDText );
396c2c66affSColin Finck
397c2c66affSColin Finck buffer = MSI_RecordGetString( row, 4 );
398c2c66affSColin Finck ext->Mime = load_given_mime( package, buffer );
399c2c66affSColin Finck
400c2c66affSColin Finck buffer = MSI_RecordGetString(row,5);
401c2c66affSColin Finck ext->Feature = msi_get_loaded_feature( package, buffer );
402c2c66affSColin Finck ext->action = INSTALLSTATE_UNKNOWN;
403c2c66affSColin Finck return ext;
404c2c66affSColin Finck }
405c2c66affSColin Finck
406c2c66affSColin Finck /*
407c2c66affSColin Finck * While the extension table has 2 primary keys, this function is only looking
408c2c66affSColin Finck * at the Extension key which is what is referenced as a foreign key
409c2c66affSColin Finck */
load_given_extension(MSIPACKAGE * package,LPCWSTR name)410c2c66affSColin Finck static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name )
411c2c66affSColin Finck {
412c2c66affSColin Finck MSIEXTENSION *ext;
413c2c66affSColin Finck MSIRECORD *row;
414c2c66affSColin Finck
415c2c66affSColin Finck if (!name)
416c2c66affSColin Finck return NULL;
417c2c66affSColin Finck
418c2c66affSColin Finck if (name[0] == '.')
419c2c66affSColin Finck name++;
420c2c66affSColin Finck
421c2c66affSColin Finck /* check for extensions already loaded */
422c2c66affSColin Finck LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
423c2c66affSColin Finck {
424958f1addSwinesync if (!wcsicmp( ext->Extension, name ))
425c2c66affSColin Finck {
426c2c66affSColin Finck TRACE("extension %s already loaded %p\n", debugstr_w(name), ext);
427c2c66affSColin Finck return ext;
428c2c66affSColin Finck }
429c2c66affSColin Finck }
430c2c66affSColin Finck
431d012037fSwinesync row = MSI_QueryGetRecord( package->db, L"SELECT * FROM `Extension` WHERE `Extension` = '%s'", name );
432c2c66affSColin Finck if (!row)
433c2c66affSColin Finck return NULL;
434c2c66affSColin Finck
435c2c66affSColin Finck ext = load_extension(package, row);
436c2c66affSColin Finck msiobj_release(&row->hdr);
437c2c66affSColin Finck return ext;
438c2c66affSColin Finck }
439c2c66affSColin Finck
iterate_load_verb(MSIRECORD * row,LPVOID param)440c2c66affSColin Finck static UINT iterate_load_verb(MSIRECORD *row, LPVOID param)
441c2c66affSColin Finck {
442c2c66affSColin Finck MSIPACKAGE* package = param;
443c2c66affSColin Finck MSIVERB *verb;
444c2c66affSColin Finck LPCWSTR buffer;
445c2c66affSColin Finck MSIEXTENSION *extension;
446c2c66affSColin Finck
447c2c66affSColin Finck buffer = MSI_RecordGetString(row,1);
448c2c66affSColin Finck extension = load_given_extension( package, buffer );
449c2c66affSColin Finck if (!extension)
450c2c66affSColin Finck {
451c2c66affSColin Finck ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer));
452c2c66affSColin Finck return ERROR_SUCCESS;
453c2c66affSColin Finck }
454c2c66affSColin Finck
455c2c66affSColin Finck /* fill in the data */
456c2c66affSColin Finck
457*f4be6dc3SMikhail verb = calloc( 1, sizeof(MSIVERB) );
458c2c66affSColin Finck if (!verb)
459c2c66affSColin Finck return ERROR_OUTOFMEMORY;
460c2c66affSColin Finck
461c2c66affSColin Finck verb->Verb = msi_dup_record_field(row,2);
462c2c66affSColin Finck TRACE("loading verb %s\n",debugstr_w(verb->Verb));
463c2c66affSColin Finck verb->Sequence = MSI_RecordGetInteger(row,3);
464c2c66affSColin Finck
465c2c66affSColin Finck buffer = MSI_RecordGetString(row,4);
466c2c66affSColin Finck deformat_string(package,buffer,&verb->Command);
467c2c66affSColin Finck
468c2c66affSColin Finck buffer = MSI_RecordGetString(row,5);
469c2c66affSColin Finck deformat_string(package,buffer,&verb->Argument);
470c2c66affSColin Finck
471c2c66affSColin Finck /* associate the verb with the correct extension */
472c2c66affSColin Finck list_add_tail( &extension->verbs, &verb->entry );
473c2c66affSColin Finck
474c2c66affSColin Finck return ERROR_SUCCESS;
475c2c66affSColin Finck }
476c2c66affSColin Finck
iterate_all_classes(MSIRECORD * rec,LPVOID param)477c2c66affSColin Finck static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param)
478c2c66affSColin Finck {
479c2c66affSColin Finck MSICOMPONENT *comp;
480c2c66affSColin Finck LPCWSTR clsid;
481c2c66affSColin Finck LPCWSTR context;
482c2c66affSColin Finck LPCWSTR buffer;
483c2c66affSColin Finck MSIPACKAGE* package = param;
484c2c66affSColin Finck MSICLASS *cls;
485c2c66affSColin Finck BOOL match = FALSE;
486c2c66affSColin Finck
487c2c66affSColin Finck clsid = MSI_RecordGetString(rec,1);
488c2c66affSColin Finck context = MSI_RecordGetString(rec,2);
489c2c66affSColin Finck buffer = MSI_RecordGetString(rec,3);
490c2c66affSColin Finck comp = msi_get_loaded_component(package, buffer);
491c2c66affSColin Finck
492c2c66affSColin Finck LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
493c2c66affSColin Finck {
494958f1addSwinesync if (wcsicmp( clsid, cls->clsid ))
495c2c66affSColin Finck continue;
496958f1addSwinesync if (wcscmp( context, cls->Context ))
497c2c66affSColin Finck continue;
498c2c66affSColin Finck if (comp == cls->Component)
499c2c66affSColin Finck {
500c2c66affSColin Finck match = TRUE;
501c2c66affSColin Finck break;
502c2c66affSColin Finck }
503c2c66affSColin Finck }
504c2c66affSColin Finck
505c2c66affSColin Finck if (!match)
506c2c66affSColin Finck load_class(package, rec);
507c2c66affSColin Finck
508c2c66affSColin Finck return ERROR_SUCCESS;
509c2c66affSColin Finck }
510c2c66affSColin Finck
load_all_classes(MSIPACKAGE * package)511c2c66affSColin Finck static UINT load_all_classes( MSIPACKAGE *package )
512c2c66affSColin Finck {
513c2c66affSColin Finck MSIQUERY *view;
514c2c66affSColin Finck UINT rc;
515c2c66affSColin Finck
516d012037fSwinesync rc = MSI_DatabaseOpenViewW( package->db, L"SELECT * FROM `Class`", &view );
517c2c66affSColin Finck if (rc != ERROR_SUCCESS)
518c2c66affSColin Finck return ERROR_SUCCESS;
519c2c66affSColin Finck
520c2c66affSColin Finck rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package);
521c2c66affSColin Finck msiobj_release(&view->hdr);
522c2c66affSColin Finck return rc;
523c2c66affSColin Finck }
524c2c66affSColin Finck
iterate_all_extensions(MSIRECORD * rec,LPVOID param)525c2c66affSColin Finck static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param)
526c2c66affSColin Finck {
527c2c66affSColin Finck MSICOMPONENT *comp;
528c2c66affSColin Finck LPCWSTR buffer;
529c2c66affSColin Finck LPCWSTR extension;
530c2c66affSColin Finck MSIPACKAGE* package = param;
531c2c66affSColin Finck BOOL match = FALSE;
532c2c66affSColin Finck MSIEXTENSION *ext;
533c2c66affSColin Finck
534c2c66affSColin Finck extension = MSI_RecordGetString(rec,1);
535c2c66affSColin Finck buffer = MSI_RecordGetString(rec,2);
536c2c66affSColin Finck comp = msi_get_loaded_component(package, buffer);
537c2c66affSColin Finck
538c2c66affSColin Finck LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
539c2c66affSColin Finck {
540958f1addSwinesync if (wcsicmp(extension, ext->Extension))
541c2c66affSColin Finck continue;
542c2c66affSColin Finck if (comp == ext->Component)
543c2c66affSColin Finck {
544c2c66affSColin Finck match = TRUE;
545c2c66affSColin Finck break;
546c2c66affSColin Finck }
547c2c66affSColin Finck }
548c2c66affSColin Finck
549c2c66affSColin Finck if (!match)
550c2c66affSColin Finck load_extension(package, rec);
551c2c66affSColin Finck
552c2c66affSColin Finck return ERROR_SUCCESS;
553c2c66affSColin Finck }
554c2c66affSColin Finck
load_all_extensions(MSIPACKAGE * package)555c2c66affSColin Finck static UINT load_all_extensions( MSIPACKAGE *package )
556c2c66affSColin Finck {
557c2c66affSColin Finck MSIQUERY *view;
558c2c66affSColin Finck UINT rc;
559c2c66affSColin Finck
560d012037fSwinesync rc = MSI_DatabaseOpenViewW( package->db, L"SELECT * FROM `Extension`", &view );
561c2c66affSColin Finck if (rc != ERROR_SUCCESS)
562c2c66affSColin Finck return ERROR_SUCCESS;
563c2c66affSColin Finck
564c2c66affSColin Finck rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package);
565c2c66affSColin Finck msiobj_release(&view->hdr);
566c2c66affSColin Finck return rc;
567c2c66affSColin Finck }
568c2c66affSColin Finck
iterate_all_progids(MSIRECORD * rec,LPVOID param)569c2c66affSColin Finck static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param)
570c2c66affSColin Finck {
571c2c66affSColin Finck LPCWSTR buffer;
572c2c66affSColin Finck MSIPACKAGE* package = param;
573c2c66affSColin Finck
574c2c66affSColin Finck buffer = MSI_RecordGetString(rec,1);
575c2c66affSColin Finck load_given_progid(package,buffer);
576c2c66affSColin Finck return ERROR_SUCCESS;
577c2c66affSColin Finck }
578c2c66affSColin Finck
load_all_progids(MSIPACKAGE * package)579c2c66affSColin Finck static UINT load_all_progids( MSIPACKAGE *package )
580c2c66affSColin Finck {
581c2c66affSColin Finck MSIQUERY *view;
582c2c66affSColin Finck UINT rc;
583c2c66affSColin Finck
584d012037fSwinesync rc = MSI_DatabaseOpenViewW( package->db, L"SELECT `ProgId` FROM `ProgId`", &view );
585c2c66affSColin Finck if (rc != ERROR_SUCCESS)
586c2c66affSColin Finck return ERROR_SUCCESS;
587c2c66affSColin Finck
588c2c66affSColin Finck rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package);
589c2c66affSColin Finck msiobj_release(&view->hdr);
590c2c66affSColin Finck return rc;
591c2c66affSColin Finck }
592c2c66affSColin Finck
load_all_verbs(MSIPACKAGE * package)593c2c66affSColin Finck static UINT load_all_verbs( MSIPACKAGE *package )
594c2c66affSColin Finck {
595c2c66affSColin Finck MSIQUERY *view;
596c2c66affSColin Finck UINT rc;
597c2c66affSColin Finck
598d012037fSwinesync rc = MSI_DatabaseOpenViewW( package->db, L"SELECT * FROM `Verb`", &view );
599c2c66affSColin Finck if (rc != ERROR_SUCCESS)
600c2c66affSColin Finck return ERROR_SUCCESS;
601c2c66affSColin Finck
602c2c66affSColin Finck rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package);
603c2c66affSColin Finck msiobj_release(&view->hdr);
604c2c66affSColin Finck return rc;
605c2c66affSColin Finck }
606c2c66affSColin Finck
iterate_all_mimes(MSIRECORD * rec,LPVOID param)607c2c66affSColin Finck static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param)
608c2c66affSColin Finck {
609c2c66affSColin Finck LPCWSTR buffer;
610c2c66affSColin Finck MSIPACKAGE* package = param;
611c2c66affSColin Finck
612c2c66affSColin Finck buffer = MSI_RecordGetString(rec,1);
613c2c66affSColin Finck load_given_mime(package,buffer);
614c2c66affSColin Finck return ERROR_SUCCESS;
615c2c66affSColin Finck }
616c2c66affSColin Finck
load_all_mimes(MSIPACKAGE * package)617c2c66affSColin Finck static UINT load_all_mimes( MSIPACKAGE *package )
618c2c66affSColin Finck {
619c2c66affSColin Finck MSIQUERY *view;
620c2c66affSColin Finck UINT rc;
621c2c66affSColin Finck
622d012037fSwinesync rc = MSI_DatabaseOpenViewW( package->db, L"SELECT `ContentType` FROM `MIME`", &view );
623c2c66affSColin Finck if (rc != ERROR_SUCCESS)
624c2c66affSColin Finck return ERROR_SUCCESS;
625c2c66affSColin Finck
626c2c66affSColin Finck rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package);
627c2c66affSColin Finck msiobj_release(&view->hdr);
628c2c66affSColin Finck return rc;
629c2c66affSColin Finck }
630c2c66affSColin Finck
load_classes_and_such(MSIPACKAGE * package)631c2c66affSColin Finck static UINT load_classes_and_such( MSIPACKAGE *package )
632c2c66affSColin Finck {
633c2c66affSColin Finck UINT r;
634c2c66affSColin Finck
635c2c66affSColin Finck TRACE("Loading all the class info and related tables\n");
636c2c66affSColin Finck
637c2c66affSColin Finck /* check if already loaded */
638c2c66affSColin Finck if (!list_empty( &package->classes ) ||
639c2c66affSColin Finck !list_empty( &package->mimes ) ||
640c2c66affSColin Finck !list_empty( &package->extensions ) ||
641c2c66affSColin Finck !list_empty( &package->progids )) return ERROR_SUCCESS;
642c2c66affSColin Finck
643c2c66affSColin Finck r = load_all_classes( package );
644c2c66affSColin Finck if (r != ERROR_SUCCESS) return r;
645c2c66affSColin Finck
646c2c66affSColin Finck r = load_all_extensions( package );
647c2c66affSColin Finck if (r != ERROR_SUCCESS) return r;
648c2c66affSColin Finck
649c2c66affSColin Finck r = load_all_progids( package );
650c2c66affSColin Finck if (r != ERROR_SUCCESS) return r;
651c2c66affSColin Finck
652c2c66affSColin Finck /* these loads must come after the other loads */
653c2c66affSColin Finck r = load_all_verbs( package );
654c2c66affSColin Finck if (r != ERROR_SUCCESS) return r;
655c2c66affSColin Finck
656c2c66affSColin Finck return load_all_mimes( package );
657c2c66affSColin Finck }
658c2c66affSColin Finck
register_appid(const MSIAPPID * appid,LPCWSTR app)659c2c66affSColin Finck static UINT register_appid(const MSIAPPID *appid, LPCWSTR app )
660c2c66affSColin Finck {
661c2c66affSColin Finck HKEY hkey2, hkey3;
662c2c66affSColin Finck
663d012037fSwinesync RegCreateKeyW( HKEY_CLASSES_ROOT, L"AppID", &hkey2 );
664c2c66affSColin Finck RegCreateKeyW( hkey2, appid->AppID, &hkey3 );
665c2c66affSColin Finck RegCloseKey(hkey2);
666c2c66affSColin Finck msi_reg_set_val_str( hkey3, NULL, app );
667c2c66affSColin Finck
668c2c66affSColin Finck if (appid->RemoteServerName)
669d012037fSwinesync msi_reg_set_val_str( hkey3, L"RemoteServerName", appid->RemoteServerName );
670c2c66affSColin Finck
671c2c66affSColin Finck if (appid->LocalServer)
672d012037fSwinesync msi_reg_set_val_str( hkey3, L"LocalService", appid->LocalServer );
673c2c66affSColin Finck
674c2c66affSColin Finck if (appid->ServiceParameters)
675d012037fSwinesync msi_reg_set_val_str( hkey3, L"ServiceParameters", appid->ServiceParameters );
676c2c66affSColin Finck
677c2c66affSColin Finck if (appid->DllSurrogate)
678d012037fSwinesync msi_reg_set_val_str( hkey3, L"DllSurrogate", appid->DllSurrogate );
679c2c66affSColin Finck
680c2c66affSColin Finck if (appid->ActivateAtStorage)
681d012037fSwinesync msi_reg_set_val_str( hkey3, L"ActivateAtStorage", L"Y" );
682c2c66affSColin Finck
683c2c66affSColin Finck if (appid->RunAsInteractiveUser)
684d012037fSwinesync msi_reg_set_val_str( hkey3, L"RunAs", L"Interactive User" );
685c2c66affSColin Finck
686c2c66affSColin Finck RegCloseKey(hkey3);
687c2c66affSColin Finck return ERROR_SUCCESS;
688c2c66affSColin Finck }
689c2c66affSColin Finck
ACTION_RegisterClassInfo(MSIPACKAGE * package)690c2c66affSColin Finck UINT ACTION_RegisterClassInfo(MSIPACKAGE *package)
691c2c66affSColin Finck {
6923635da20Swinesync REGSAM access = KEY_ALL_ACCESS;
693c2c66affSColin Finck MSIRECORD *uirow;
694c2c66affSColin Finck HKEY hkey, hkey2, hkey3;
695c2c66affSColin Finck MSICLASS *cls;
696c2c66affSColin Finck UINT r;
697c2c66affSColin Finck
698fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
699d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"RegisterClassInfo" );
700fd8b07bdSwinesync
701c2c66affSColin Finck r = load_classes_and_such( package );
702c2c66affSColin Finck if (r != ERROR_SUCCESS)
703c2c66affSColin Finck return r;
704c2c66affSColin Finck
7053635da20Swinesync if (package->platform == PLATFORM_INTEL)
7063635da20Swinesync access |= KEY_WOW64_32KEY;
707c2c66affSColin Finck else
7083635da20Swinesync access |= KEY_WOW64_64KEY;
709c2c66affSColin Finck
710d012037fSwinesync if (RegCreateKeyExW( HKEY_CLASSES_ROOT, L"CLSID", 0, NULL, 0, access, NULL, &hkey, NULL ))
711c2c66affSColin Finck return ERROR_FUNCTION_FAILED;
712c2c66affSColin Finck
713c2c66affSColin Finck LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
714c2c66affSColin Finck {
715c2c66affSColin Finck MSICOMPONENT *comp;
716c2c66affSColin Finck MSIFILE *file;
717c2c66affSColin Finck DWORD size;
718c2c66affSColin Finck LPWSTR argument;
719c2c66affSColin Finck MSIFEATURE *feature;
720c2c66affSColin Finck
721c2c66affSColin Finck comp = cls->Component;
722c2c66affSColin Finck if ( !comp )
723c2c66affSColin Finck continue;
724c2c66affSColin Finck
725c2c66affSColin Finck if (!comp->Enabled)
726c2c66affSColin Finck {
727c2c66affSColin Finck TRACE("component is disabled\n");
728c2c66affSColin Finck continue;
729c2c66affSColin Finck }
730c2c66affSColin Finck
731c2c66affSColin Finck feature = cls->Feature;
732c2c66affSColin Finck if (!feature)
733c2c66affSColin Finck continue;
734c2c66affSColin Finck
735c2c66affSColin Finck feature->Action = msi_get_feature_action( package, feature );
736c2c66affSColin Finck if (feature->Action != INSTALLSTATE_LOCAL &&
737c2c66affSColin Finck feature->Action != INSTALLSTATE_ADVERTISED )
738c2c66affSColin Finck {
739c2c66affSColin Finck TRACE("feature %s not scheduled for installation, skipping registration of class %s\n",
740c2c66affSColin Finck debugstr_w(feature->Feature), debugstr_w(cls->clsid));
741c2c66affSColin Finck continue;
742c2c66affSColin Finck }
743c2c66affSColin Finck
744c2c66affSColin Finck if (!comp->KeyPath || !(file = msi_get_loaded_file( package, comp->KeyPath )))
745c2c66affSColin Finck {
746c2c66affSColin Finck TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid));
747c2c66affSColin Finck continue;
748c2c66affSColin Finck }
749c2c66affSColin Finck TRACE("Registering class %s (%p)\n", debugstr_w(cls->clsid), cls);
750c2c66affSColin Finck
751c2c66affSColin Finck cls->action = INSTALLSTATE_LOCAL;
752c2c66affSColin Finck
753c2c66affSColin Finck RegCreateKeyW( hkey, cls->clsid, &hkey2 );
754c2c66affSColin Finck
755c2c66affSColin Finck if (cls->Description)
756c2c66affSColin Finck msi_reg_set_val_str( hkey2, NULL, cls->Description );
757c2c66affSColin Finck
758c2c66affSColin Finck RegCreateKeyW( hkey2, cls->Context, &hkey3 );
759c2c66affSColin Finck
760c2c66affSColin Finck /*
761c2c66affSColin Finck * FIXME: Implement install on demand (advertised components).
762c2c66affSColin Finck *
763c2c66affSColin Finck * ole32.dll should call msi.MsiProvideComponentFromDescriptor()
764c2c66affSColin Finck * when it needs an InProcServer that doesn't exist.
765c2c66affSColin Finck * The component advertise string should be in the "InProcServer" value.
766c2c66affSColin Finck */
767c2c66affSColin Finck size = lstrlenW( file->TargetPath )+1;
768c2c66affSColin Finck if (cls->Argument)
769c2c66affSColin Finck size += lstrlenW(cls->Argument)+1;
770c2c66affSColin Finck
771*f4be6dc3SMikhail argument = malloc( size * sizeof(WCHAR) );
772c2c66affSColin Finck lstrcpyW( argument, file->TargetPath );
773c2c66affSColin Finck
774c2c66affSColin Finck if (cls->Argument)
775c2c66affSColin Finck {
776d012037fSwinesync lstrcatW( argument, L" " );
777c2c66affSColin Finck lstrcatW( argument, cls->Argument );
778c2c66affSColin Finck }
779c2c66affSColin Finck
780c2c66affSColin Finck msi_reg_set_val_str( hkey3, NULL, argument );
781*f4be6dc3SMikhail free(argument);
782c2c66affSColin Finck
783c2c66affSColin Finck RegCloseKey(hkey3);
784c2c66affSColin Finck
785c2c66affSColin Finck if (cls->ProgID || cls->ProgIDText)
786c2c66affSColin Finck {
787c2c66affSColin Finck LPCWSTR progid;
788c2c66affSColin Finck
789c2c66affSColin Finck if (cls->ProgID)
790c2c66affSColin Finck progid = cls->ProgID->ProgID;
791c2c66affSColin Finck else
792c2c66affSColin Finck progid = cls->ProgIDText;
793c2c66affSColin Finck
794d012037fSwinesync msi_reg_set_subkey_val( hkey2, L"ProgID", NULL, progid );
795c2c66affSColin Finck
796c2c66affSColin Finck if (cls->ProgID && cls->ProgID->VersionInd)
797c2c66affSColin Finck {
798d012037fSwinesync msi_reg_set_subkey_val( hkey2, L"VersionIndependentProgID", NULL,
799c2c66affSColin Finck cls->ProgID->VersionInd->ProgID );
800c2c66affSColin Finck }
801c2c66affSColin Finck }
802c2c66affSColin Finck
803c2c66affSColin Finck if (cls->AppID)
804c2c66affSColin Finck {
805c2c66affSColin Finck MSIAPPID *appid = cls->AppID;
806d012037fSwinesync msi_reg_set_val_str( hkey2, L"AppID", appid->AppID );
807c2c66affSColin Finck register_appid( appid, cls->Description );
808c2c66affSColin Finck }
809c2c66affSColin Finck
810c2c66affSColin Finck if (cls->IconPath)
811d012037fSwinesync msi_reg_set_subkey_val( hkey2, L"DefaultIcon", NULL, cls->IconPath );
812c2c66affSColin Finck
813c2c66affSColin Finck if (cls->DefInprocHandler)
814d012037fSwinesync msi_reg_set_subkey_val( hkey2, L"InprocHandler", NULL, cls->DefInprocHandler );
815c2c66affSColin Finck
816c2c66affSColin Finck if (cls->DefInprocHandler32)
817d012037fSwinesync msi_reg_set_subkey_val( hkey2, L"InprocHandler32", NULL, cls->DefInprocHandler32 );
818c2c66affSColin Finck RegCloseKey(hkey2);
819c2c66affSColin Finck
820c2c66affSColin Finck /* if there is a FileTypeMask, register the FileType */
821c2c66affSColin Finck if (cls->FileTypeMask)
822c2c66affSColin Finck {
823c2c66affSColin Finck LPWSTR ptr, ptr2;
824c2c66affSColin Finck LPWSTR keyname;
825c2c66affSColin Finck INT index = 0;
826c2c66affSColin Finck ptr = cls->FileTypeMask;
827c2c66affSColin Finck while (ptr && *ptr)
828c2c66affSColin Finck {
829958f1addSwinesync ptr2 = wcschr(ptr,';');
830c2c66affSColin Finck if (ptr2)
831c2c66affSColin Finck *ptr2 = 0;
832*f4be6dc3SMikhail keyname = malloc( sizeof(L"FileType\\%s\\%d") + (wcslen(cls->clsid) + 3) * sizeof(WCHAR) );
833d012037fSwinesync swprintf( keyname, lstrlenW(L"FileType\\%s\\%d") + lstrlenW(cls->clsid) + 4,
834d012037fSwinesync L"FileType\\%s\\%d", cls->clsid, index );
835c2c66affSColin Finck
836c2c66affSColin Finck msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, ptr );
837*f4be6dc3SMikhail free( keyname );
838c2c66affSColin Finck
839c2c66affSColin Finck if (ptr2)
840c2c66affSColin Finck ptr = ptr2+1;
841c2c66affSColin Finck else
842c2c66affSColin Finck ptr = NULL;
843c2c66affSColin Finck
844c2c66affSColin Finck index ++;
845c2c66affSColin Finck }
846c2c66affSColin Finck }
847c2c66affSColin Finck
848c2c66affSColin Finck uirow = MSI_CreateRecord(1);
849c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, cls->clsid );
85071bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
851c2c66affSColin Finck msiobj_release(&uirow->hdr);
852c2c66affSColin Finck }
853c2c66affSColin Finck RegCloseKey(hkey);
854c2c66affSColin Finck return ERROR_SUCCESS;
855c2c66affSColin Finck }
856c2c66affSColin Finck
ACTION_UnregisterClassInfo(MSIPACKAGE * package)857c2c66affSColin Finck UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package )
858c2c66affSColin Finck {
8593635da20Swinesync REGSAM access = KEY_ALL_ACCESS;
860c2c66affSColin Finck MSIRECORD *uirow;
861c2c66affSColin Finck MSICLASS *cls;
862c2c66affSColin Finck HKEY hkey, hkey2;
863c2c66affSColin Finck UINT r;
864c2c66affSColin Finck
865fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
866d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"UnregisterClassInfo" );
867fd8b07bdSwinesync
868c2c66affSColin Finck r = load_classes_and_such( package );
869c2c66affSColin Finck if (r != ERROR_SUCCESS)
870c2c66affSColin Finck return r;
871c2c66affSColin Finck
8723635da20Swinesync if (package->platform == PLATFORM_INTEL)
8733635da20Swinesync access |= KEY_WOW64_32KEY;
874c2c66affSColin Finck else
8753635da20Swinesync access |= KEY_WOW64_64KEY;
876c2c66affSColin Finck
877d012037fSwinesync if (RegCreateKeyExW( HKEY_CLASSES_ROOT, L"CLSID", 0, NULL, 0, access, NULL, &hkey, NULL ))
8783635da20Swinesync return ERROR_FUNCTION_FAILED;
879c2c66affSColin Finck
880c2c66affSColin Finck LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry )
881c2c66affSColin Finck {
882c2c66affSColin Finck MSIFEATURE *feature;
883c2c66affSColin Finck MSICOMPONENT *comp;
884c2c66affSColin Finck LPWSTR filetype;
885c2c66affSColin Finck LONG res;
886c2c66affSColin Finck
887c2c66affSColin Finck comp = cls->Component;
888c2c66affSColin Finck if (!comp)
889c2c66affSColin Finck continue;
890c2c66affSColin Finck
891c2c66affSColin Finck if (!comp->Enabled)
892c2c66affSColin Finck {
893c2c66affSColin Finck TRACE("component is disabled\n");
894c2c66affSColin Finck continue;
895c2c66affSColin Finck }
896c2c66affSColin Finck
897c2c66affSColin Finck feature = cls->Feature;
898c2c66affSColin Finck if (!feature)
899c2c66affSColin Finck continue;
900c2c66affSColin Finck
901c2c66affSColin Finck feature->Action = msi_get_feature_action( package, feature );
902c2c66affSColin Finck if (feature->Action != INSTALLSTATE_ABSENT)
903c2c66affSColin Finck {
904c2c66affSColin Finck TRACE("feature %s not scheduled for removal, skipping unregistration of class %s\n",
905c2c66affSColin Finck debugstr_w(feature->Feature), debugstr_w(cls->clsid));
906c2c66affSColin Finck continue;
907c2c66affSColin Finck }
908c2c66affSColin Finck TRACE("Unregistering class %s (%p)\n", debugstr_w(cls->clsid), cls);
909c2c66affSColin Finck
910c2c66affSColin Finck cls->action = INSTALLSTATE_ABSENT;
911c2c66affSColin Finck
912c2c66affSColin Finck res = RegDeleteTreeW( hkey, cls->clsid );
913c2c66affSColin Finck if (res != ERROR_SUCCESS)
91402f995b2Swinesync WARN("failed to delete class key %ld\n", res);
915c2c66affSColin Finck
916c2c66affSColin Finck if (cls->AppID)
917c2c66affSColin Finck {
918d012037fSwinesync res = RegOpenKeyW( HKEY_CLASSES_ROOT, L"AppID", &hkey2 );
919c2c66affSColin Finck if (res == ERROR_SUCCESS)
920c2c66affSColin Finck {
921c2c66affSColin Finck res = RegDeleteKeyW( hkey2, cls->AppID->AppID );
922c2c66affSColin Finck if (res != ERROR_SUCCESS)
92302f995b2Swinesync WARN("failed to delete appid key %ld\n", res);
924c2c66affSColin Finck RegCloseKey( hkey2 );
925c2c66affSColin Finck }
926c2c66affSColin Finck }
927c2c66affSColin Finck if (cls->FileTypeMask)
928c2c66affSColin Finck {
929*f4be6dc3SMikhail filetype = malloc( sizeof( L"FileType\\" ) + wcslen( cls->clsid ) * sizeof(WCHAR) );
930c2c66affSColin Finck if (filetype)
931c2c66affSColin Finck {
932d012037fSwinesync lstrcpyW( filetype, L"FileType\\" );
933958f1addSwinesync lstrcatW( filetype, cls->clsid );
934c2c66affSColin Finck res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype );
935*f4be6dc3SMikhail free( filetype );
936c2c66affSColin Finck
937c2c66affSColin Finck if (res != ERROR_SUCCESS)
93802f995b2Swinesync WARN("failed to delete file type %ld\n", res);
939c2c66affSColin Finck }
940c2c66affSColin Finck }
941c2c66affSColin Finck
942c2c66affSColin Finck uirow = MSI_CreateRecord( 1 );
943c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, cls->clsid );
94471bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
945c2c66affSColin Finck msiobj_release( &uirow->hdr );
946c2c66affSColin Finck }
947c2c66affSColin Finck RegCloseKey( hkey );
948c2c66affSColin Finck return ERROR_SUCCESS;
949c2c66affSColin Finck }
950c2c66affSColin Finck
get_clsid_of_progid(const MSIPROGID * progid)951c2c66affSColin Finck static LPCWSTR get_clsid_of_progid( const MSIPROGID *progid )
952c2c66affSColin Finck {
953c2c66affSColin Finck while (progid)
954c2c66affSColin Finck {
955c2c66affSColin Finck if (progid->Class)
956c2c66affSColin Finck return progid->Class->clsid;
957c2c66affSColin Finck if (progid->Parent == progid)
958c2c66affSColin Finck break;
959c2c66affSColin Finck progid = progid->Parent;
960c2c66affSColin Finck }
961c2c66affSColin Finck return NULL;
962c2c66affSColin Finck }
963c2c66affSColin Finck
register_progid(const MSIPROGID * progid)964c2c66affSColin Finck static UINT register_progid( const MSIPROGID* progid )
965c2c66affSColin Finck {
966c2c66affSColin Finck HKEY hkey = 0;
967c2c66affSColin Finck UINT rc;
968c2c66affSColin Finck
969c2c66affSColin Finck rc = RegCreateKeyW( HKEY_CLASSES_ROOT, progid->ProgID, &hkey );
970c2c66affSColin Finck if (rc == ERROR_SUCCESS)
971c2c66affSColin Finck {
972c2c66affSColin Finck LPCWSTR clsid = get_clsid_of_progid( progid );
973c2c66affSColin Finck
974c2c66affSColin Finck if (clsid)
975d012037fSwinesync msi_reg_set_subkey_val( hkey, L"CLSID", NULL, clsid );
976c2c66affSColin Finck else
977c2c66affSColin Finck TRACE("%s has no class\n", debugstr_w( progid->ProgID ) );
978c2c66affSColin Finck
979c2c66affSColin Finck if (progid->Description)
980c2c66affSColin Finck msi_reg_set_val_str( hkey, NULL, progid->Description );
981c2c66affSColin Finck
982c2c66affSColin Finck if (progid->IconPath)
983d012037fSwinesync msi_reg_set_subkey_val( hkey, L"DefaultIcon", NULL, progid->IconPath );
984c2c66affSColin Finck
985c2c66affSColin Finck /* write out the current version */
986c2c66affSColin Finck if (progid->CurVer)
987d012037fSwinesync msi_reg_set_subkey_val( hkey, L"CurVer", NULL, progid->CurVer->ProgID );
988c2c66affSColin Finck
989c2c66affSColin Finck RegCloseKey(hkey);
990c2c66affSColin Finck }
991c2c66affSColin Finck else
992c2c66affSColin Finck ERR("failed to create key %s\n", debugstr_w( progid->ProgID ) );
993c2c66affSColin Finck
994c2c66affSColin Finck return rc;
995c2c66affSColin Finck }
996c2c66affSColin Finck
get_progid_class(const MSIPROGID * progid)997c2c66affSColin Finck static const MSICLASS *get_progid_class( const MSIPROGID *progid )
998c2c66affSColin Finck {
999c2c66affSColin Finck while (progid)
1000c2c66affSColin Finck {
1001c2c66affSColin Finck if (progid->Parent) progid = progid->Parent;
1002c2c66affSColin Finck if (progid->Class) return progid->Class;
1003c2c66affSColin Finck if (!progid->Parent || progid->Parent == progid) break;
1004c2c66affSColin Finck }
1005c2c66affSColin Finck return NULL;
1006c2c66affSColin Finck }
1007c2c66affSColin Finck
has_class_installed(const MSIPROGID * progid)1008c2c66affSColin Finck static BOOL has_class_installed( const MSIPROGID *progid )
1009c2c66affSColin Finck {
1010c2c66affSColin Finck const MSICLASS *class = get_progid_class( progid );
1011c2c66affSColin Finck if (!class || !class->ProgID) return FALSE;
1012c2c66affSColin Finck return (class->action == INSTALLSTATE_LOCAL);
1013c2c66affSColin Finck }
1014c2c66affSColin Finck
has_one_extension_installed(const MSIPACKAGE * package,const MSIPROGID * progid)1015c2c66affSColin Finck static BOOL has_one_extension_installed( const MSIPACKAGE *package, const MSIPROGID *progid )
1016c2c66affSColin Finck {
1017c2c66affSColin Finck const MSIEXTENSION *extension;
1018c2c66affSColin Finck LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
1019c2c66affSColin Finck {
1020c2c66affSColin Finck if (extension->ProgID == progid && !list_empty( &extension->verbs ) &&
1021c2c66affSColin Finck extension->action == INSTALLSTATE_LOCAL) return TRUE;
1022c2c66affSColin Finck }
1023c2c66affSColin Finck return FALSE;
1024c2c66affSColin Finck }
1025c2c66affSColin Finck
ACTION_RegisterProgIdInfo(MSIPACKAGE * package)1026c2c66affSColin Finck UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package)
1027c2c66affSColin Finck {
1028c2c66affSColin Finck MSIPROGID *progid;
1029c2c66affSColin Finck MSIRECORD *uirow;
1030c2c66affSColin Finck UINT r;
1031c2c66affSColin Finck
1032fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
1033d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"RegisterProgIdInfo" );
1034fd8b07bdSwinesync
1035c2c66affSColin Finck r = load_classes_and_such( package );
1036c2c66affSColin Finck if (r != ERROR_SUCCESS)
1037c2c66affSColin Finck return r;
1038c2c66affSColin Finck
1039c2c66affSColin Finck LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
1040c2c66affSColin Finck {
1041c2c66affSColin Finck if (!has_class_installed( progid ) && !has_one_extension_installed( package, progid ))
1042c2c66affSColin Finck {
1043c2c66affSColin Finck TRACE("progid %s not scheduled to be installed\n", debugstr_w(progid->ProgID));
1044c2c66affSColin Finck continue;
1045c2c66affSColin Finck }
1046c2c66affSColin Finck TRACE("Registering progid %s\n", debugstr_w(progid->ProgID));
1047c2c66affSColin Finck
1048c2c66affSColin Finck register_progid( progid );
1049c2c66affSColin Finck
1050c2c66affSColin Finck uirow = MSI_CreateRecord( 1 );
1051c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, progid->ProgID );
105271bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
1053c2c66affSColin Finck msiobj_release( &uirow->hdr );
1054c2c66affSColin Finck }
1055c2c66affSColin Finck return ERROR_SUCCESS;
1056c2c66affSColin Finck }
1057c2c66affSColin Finck
has_class_removed(const MSIPROGID * progid)1058c2c66affSColin Finck static BOOL has_class_removed( const MSIPROGID *progid )
1059c2c66affSColin Finck {
1060c2c66affSColin Finck const MSICLASS *class = get_progid_class( progid );
1061c2c66affSColin Finck if (!class || !class->ProgID) return FALSE;
1062c2c66affSColin Finck return (class->action == INSTALLSTATE_ABSENT);
1063c2c66affSColin Finck }
1064c2c66affSColin Finck
has_extensions(const MSIPACKAGE * package,const MSIPROGID * progid)1065c2c66affSColin Finck static BOOL has_extensions( const MSIPACKAGE *package, const MSIPROGID *progid )
1066c2c66affSColin Finck {
1067c2c66affSColin Finck const MSIEXTENSION *extension;
1068c2c66affSColin Finck LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
1069c2c66affSColin Finck {
1070c2c66affSColin Finck if (extension->ProgID == progid && !list_empty( &extension->verbs )) return TRUE;
1071c2c66affSColin Finck }
1072c2c66affSColin Finck return FALSE;
1073c2c66affSColin Finck }
1074c2c66affSColin Finck
has_all_extensions_removed(const MSIPACKAGE * package,const MSIPROGID * progid)1075c2c66affSColin Finck static BOOL has_all_extensions_removed( const MSIPACKAGE *package, const MSIPROGID *progid )
1076c2c66affSColin Finck {
1077c2c66affSColin Finck BOOL ret = FALSE;
1078c2c66affSColin Finck const MSIEXTENSION *extension;
1079c2c66affSColin Finck LIST_FOR_EACH_ENTRY( extension, &package->extensions, MSIEXTENSION, entry )
1080c2c66affSColin Finck {
1081c2c66affSColin Finck if (extension->ProgID == progid && !list_empty( &extension->verbs ) &&
1082c2c66affSColin Finck extension->action == INSTALLSTATE_ABSENT) ret = TRUE;
1083c2c66affSColin Finck else ret = FALSE;
1084c2c66affSColin Finck }
1085c2c66affSColin Finck return ret;
1086c2c66affSColin Finck }
1087c2c66affSColin Finck
ACTION_UnregisterProgIdInfo(MSIPACKAGE * package)1088c2c66affSColin Finck UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package )
1089c2c66affSColin Finck {
1090c2c66affSColin Finck MSIPROGID *progid;
1091c2c66affSColin Finck MSIRECORD *uirow;
1092c2c66affSColin Finck LONG res;
1093c2c66affSColin Finck UINT r;
1094c2c66affSColin Finck
1095fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
1096d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"UnregisterProgIdInfo" );
1097fd8b07bdSwinesync
1098c2c66affSColin Finck r = load_classes_and_such( package );
1099c2c66affSColin Finck if (r != ERROR_SUCCESS)
1100c2c66affSColin Finck return r;
1101c2c66affSColin Finck
1102c2c66affSColin Finck LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry )
1103c2c66affSColin Finck {
1104c2c66affSColin Finck if (!has_class_removed( progid ) ||
1105c2c66affSColin Finck (has_extensions( package, progid ) && !has_all_extensions_removed( package, progid )))
1106c2c66affSColin Finck {
1107c2c66affSColin Finck TRACE("progid %s not scheduled to be removed\n", debugstr_w(progid->ProgID));
1108c2c66affSColin Finck continue;
1109c2c66affSColin Finck }
1110c2c66affSColin Finck TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID));
1111c2c66affSColin Finck
1112c2c66affSColin Finck res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID );
1113c2c66affSColin Finck if (res != ERROR_SUCCESS)
111402f995b2Swinesync TRACE("failed to delete progid key %ld\n", res);
1115c2c66affSColin Finck
1116c2c66affSColin Finck uirow = MSI_CreateRecord( 1 );
1117c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, progid->ProgID );
111871bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
1119c2c66affSColin Finck msiobj_release( &uirow->hdr );
1120c2c66affSColin Finck }
1121c2c66affSColin Finck return ERROR_SUCCESS;
1122c2c66affSColin Finck }
1123c2c66affSColin Finck
register_verb(MSIPACKAGE * package,LPCWSTR progid,MSICOMPONENT * component,const MSIEXTENSION * extension,MSIVERB * verb,INT * Sequence)1124c2c66affSColin Finck static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid,
1125c2c66affSColin Finck MSICOMPONENT* component, const MSIEXTENSION* extension,
1126c2c66affSColin Finck MSIVERB* verb, INT* Sequence )
1127c2c66affSColin Finck {
1128c2c66affSColin Finck LPWSTR keyname;
1129c2c66affSColin Finck HKEY key;
1130c2c66affSColin Finck LPWSTR command;
1131c2c66affSColin Finck DWORD size;
1132c2c66affSColin Finck LPWSTR advertise;
1133c2c66affSColin Finck
1134d012037fSwinesync keyname = msi_build_directory_name(4, progid, L"shell", verb->Verb, L"command");
1135c2c66affSColin Finck
1136c2c66affSColin Finck TRACE("Making Key %s\n",debugstr_w(keyname));
1137c2c66affSColin Finck RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key);
1138958f1addSwinesync size = lstrlenW(component->FullKeypath);
1139c2c66affSColin Finck if (verb->Argument)
1140958f1addSwinesync size += lstrlenW(verb->Argument);
1141c2c66affSColin Finck size += 4;
1142c2c66affSColin Finck
1143*f4be6dc3SMikhail command = malloc(size * sizeof(WCHAR));
1144c2c66affSColin Finck if (verb->Argument)
1145d012037fSwinesync swprintf(command, size, L"\"%s\" %s", component->FullKeypath, verb->Argument);
1146c2c66affSColin Finck else
1147d012037fSwinesync swprintf(command, size, L"\"%s\"", component->FullKeypath);
1148c2c66affSColin Finck
1149c2c66affSColin Finck msi_reg_set_val_str( key, NULL, command );
1150*f4be6dc3SMikhail free(command);
1151c2c66affSColin Finck
1152c2c66affSColin Finck advertise = msi_create_component_advertise_string(package, component,
1153c2c66affSColin Finck extension->Feature->Feature);
1154958f1addSwinesync size = lstrlenW(advertise);
1155c2c66affSColin Finck
1156c2c66affSColin Finck if (verb->Argument)
1157958f1addSwinesync size += lstrlenW(verb->Argument);
1158c2c66affSColin Finck size += 4;
1159c2c66affSColin Finck
1160*f4be6dc3SMikhail command = calloc(size, sizeof(WCHAR));
1161c2c66affSColin Finck
1162958f1addSwinesync lstrcpyW(command,advertise);
1163c2c66affSColin Finck if (verb->Argument)
1164c2c66affSColin Finck {
1165d012037fSwinesync lstrcatW(command, L" ");
1166958f1addSwinesync lstrcatW(command, verb->Argument);
1167c2c66affSColin Finck }
1168c2c66affSColin Finck
1169d012037fSwinesync msi_reg_set_val_multi_str( key, L"command", command );
1170c2c66affSColin Finck
1171c2c66affSColin Finck RegCloseKey(key);
1172*f4be6dc3SMikhail free(keyname);
1173*f4be6dc3SMikhail free(advertise);
1174*f4be6dc3SMikhail free(command);
1175c2c66affSColin Finck
1176c2c66affSColin Finck if (verb->Command)
1177c2c66affSColin Finck {
1178d012037fSwinesync keyname = msi_build_directory_name( 3, progid, L"shell", verb->Verb );
1179c2c66affSColin Finck msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Command );
1180*f4be6dc3SMikhail free(keyname);
1181c2c66affSColin Finck }
1182c2c66affSColin Finck
1183c2c66affSColin Finck if (verb->Sequence != MSI_NULL_INTEGER)
1184c2c66affSColin Finck {
1185c2c66affSColin Finck if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence)
1186c2c66affSColin Finck {
1187c2c66affSColin Finck *Sequence = verb->Sequence;
1188d012037fSwinesync keyname = msi_build_directory_name( 2, progid, L"shell" );
1189c2c66affSColin Finck msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Verb );
1190*f4be6dc3SMikhail free(keyname);
1191c2c66affSColin Finck }
1192c2c66affSColin Finck }
1193c2c66affSColin Finck return ERROR_SUCCESS;
1194c2c66affSColin Finck }
1195c2c66affSColin Finck
ACTION_RegisterExtensionInfo(MSIPACKAGE * package)1196c2c66affSColin Finck UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package)
1197c2c66affSColin Finck {
1198c2c66affSColin Finck HKEY hkey = NULL;
1199c2c66affSColin Finck MSIEXTENSION *ext;
1200c2c66affSColin Finck MSIRECORD *uirow;
1201c2c66affSColin Finck BOOL install_on_demand = TRUE;
1202c2c66affSColin Finck LONG res;
1203c2c66affSColin Finck UINT r;
1204c2c66affSColin Finck
1205fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
1206d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"RegisterExtensionInfo" );
1207fd8b07bdSwinesync
1208c2c66affSColin Finck r = load_classes_and_such( package );
1209c2c66affSColin Finck if (r != ERROR_SUCCESS)
1210c2c66affSColin Finck return r;
1211c2c66affSColin Finck
1212c2c66affSColin Finck /* We need to set install_on_demand based on if the shell handles advertised
1213c2c66affSColin Finck * shortcuts and the like. Because Mike McCormack is working on this i am
1214c2c66affSColin Finck * going to default to TRUE
1215c2c66affSColin Finck */
1216c2c66affSColin Finck
1217c2c66affSColin Finck LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
1218c2c66affSColin Finck {
1219c2c66affSColin Finck LPWSTR extension;
1220c2c66affSColin Finck MSIFEATURE *feature;
1221c2c66affSColin Finck
1222c2c66affSColin Finck if (!ext->Component)
1223c2c66affSColin Finck continue;
1224c2c66affSColin Finck
1225c2c66affSColin Finck if (!ext->Component->Enabled)
1226c2c66affSColin Finck {
1227c2c66affSColin Finck TRACE("component is disabled\n");
1228c2c66affSColin Finck continue;
1229c2c66affSColin Finck }
1230c2c66affSColin Finck
1231c2c66affSColin Finck feature = ext->Feature;
1232c2c66affSColin Finck if (!feature)
1233c2c66affSColin Finck continue;
1234c2c66affSColin Finck
1235c2c66affSColin Finck /*
1236c2c66affSColin Finck * yes. MSDN says that these are based on _Feature_ not on
1237c2c66affSColin Finck * Component. So verify the feature is to be installed
1238c2c66affSColin Finck */
1239c2c66affSColin Finck feature->Action = msi_get_feature_action( package, feature );
1240c2c66affSColin Finck if (feature->Action != INSTALLSTATE_LOCAL &&
1241c2c66affSColin Finck !(install_on_demand && feature->Action == INSTALLSTATE_ADVERTISED))
1242c2c66affSColin Finck {
1243c2c66affSColin Finck TRACE("feature %s not scheduled for installation, skipping registration of extension %s\n",
1244c2c66affSColin Finck debugstr_w(feature->Feature), debugstr_w(ext->Extension));
1245c2c66affSColin Finck continue;
1246c2c66affSColin Finck }
1247c2c66affSColin Finck TRACE("Registering extension %s (%p)\n", debugstr_w(ext->Extension), ext);
1248c2c66affSColin Finck
1249c2c66affSColin Finck ext->action = INSTALLSTATE_LOCAL;
1250c2c66affSColin Finck
1251*f4be6dc3SMikhail extension = malloc( (wcslen( ext->Extension ) + 2) * sizeof(WCHAR) );
1252c2c66affSColin Finck if (extension)
1253c2c66affSColin Finck {
1254c2c66affSColin Finck extension[0] = '.';
1255958f1addSwinesync lstrcpyW( extension + 1, ext->Extension );
1256c2c66affSColin Finck res = RegCreateKeyW( HKEY_CLASSES_ROOT, extension, &hkey );
1257*f4be6dc3SMikhail free( extension );
1258c2c66affSColin Finck if (res != ERROR_SUCCESS)
125902f995b2Swinesync WARN("failed to create extension key %ld\n", res);
1260c2c66affSColin Finck }
1261c2c66affSColin Finck
1262c2c66affSColin Finck if (ext->Mime)
1263d012037fSwinesync msi_reg_set_val_str( hkey, L"Content Type", ext->Mime->ContentType );
1264c2c66affSColin Finck
1265c2c66affSColin Finck if (ext->ProgID || ext->ProgIDText)
1266c2c66affSColin Finck {
1267c2c66affSColin Finck HKEY hkey2;
1268c2c66affSColin Finck LPWSTR newkey;
1269c2c66affSColin Finck LPCWSTR progid;
1270c2c66affSColin Finck MSIVERB *verb;
1271c2c66affSColin Finck INT Sequence = MSI_NULL_INTEGER;
1272c2c66affSColin Finck
1273c2c66affSColin Finck if (ext->ProgID)
1274c2c66affSColin Finck progid = ext->ProgID->ProgID;
1275c2c66affSColin Finck else
1276c2c66affSColin Finck progid = ext->ProgIDText;
1277c2c66affSColin Finck
1278c2c66affSColin Finck msi_reg_set_val_str( hkey, NULL, progid );
1279c2c66affSColin Finck
1280*f4be6dc3SMikhail newkey = malloc( wcslen(progid) * sizeof(WCHAR) + sizeof(L"\\ShellNew") );
1281c2c66affSColin Finck
1282958f1addSwinesync lstrcpyW(newkey, progid);
1283d012037fSwinesync lstrcatW(newkey, L"\\ShellNew");
1284c2c66affSColin Finck RegCreateKeyW(hkey, newkey, &hkey2);
1285c2c66affSColin Finck RegCloseKey(hkey2);
1286c2c66affSColin Finck
1287*f4be6dc3SMikhail free(newkey);
1288c2c66affSColin Finck
1289c2c66affSColin Finck /* do all the verbs */
1290c2c66affSColin Finck LIST_FOR_EACH_ENTRY( verb, &ext->verbs, MSIVERB, entry )
1291c2c66affSColin Finck {
1292c2c66affSColin Finck register_verb( package, progid, ext->Component,
1293c2c66affSColin Finck ext, verb, &Sequence);
1294c2c66affSColin Finck }
1295c2c66affSColin Finck }
1296c2c66affSColin Finck
1297c2c66affSColin Finck RegCloseKey(hkey);
1298c2c66affSColin Finck
1299c2c66affSColin Finck uirow = MSI_CreateRecord(1);
1300c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, ext->Extension );
130171bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
1302c2c66affSColin Finck msiobj_release(&uirow->hdr);
1303c2c66affSColin Finck }
1304c2c66affSColin Finck return ERROR_SUCCESS;
1305c2c66affSColin Finck }
1306c2c66affSColin Finck
ACTION_UnregisterExtensionInfo(MSIPACKAGE * package)1307c2c66affSColin Finck UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package )
1308c2c66affSColin Finck {
1309c2c66affSColin Finck MSIEXTENSION *ext;
1310c2c66affSColin Finck MSIRECORD *uirow;
1311c2c66affSColin Finck LONG res;
1312c2c66affSColin Finck UINT r;
1313c2c66affSColin Finck
1314fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
1315d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"UnregisterExtensionInfo" );
1316fd8b07bdSwinesync
1317c2c66affSColin Finck r = load_classes_and_such( package );
1318c2c66affSColin Finck if (r != ERROR_SUCCESS)
1319c2c66affSColin Finck return r;
1320c2c66affSColin Finck
1321c2c66affSColin Finck LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry )
1322c2c66affSColin Finck {
1323c2c66affSColin Finck LPWSTR extension;
1324c2c66affSColin Finck MSIFEATURE *feature;
1325c2c66affSColin Finck
1326c2c66affSColin Finck if (!ext->Component)
1327c2c66affSColin Finck continue;
1328c2c66affSColin Finck
1329c2c66affSColin Finck if (!ext->Component->Enabled)
1330c2c66affSColin Finck {
1331c2c66affSColin Finck TRACE("component is disabled\n");
1332c2c66affSColin Finck continue;
1333c2c66affSColin Finck }
1334c2c66affSColin Finck
1335c2c66affSColin Finck feature = ext->Feature;
1336c2c66affSColin Finck if (!feature)
1337c2c66affSColin Finck continue;
1338c2c66affSColin Finck
1339c2c66affSColin Finck feature->Action = msi_get_feature_action( package, feature );
1340c2c66affSColin Finck if (feature->Action != INSTALLSTATE_ABSENT)
1341c2c66affSColin Finck {
1342c2c66affSColin Finck TRACE("feature %s not scheduled for removal, skipping unregistration of extension %s\n",
1343c2c66affSColin Finck debugstr_w(feature->Feature), debugstr_w(ext->Extension));
1344c2c66affSColin Finck continue;
1345c2c66affSColin Finck }
1346c2c66affSColin Finck TRACE("Unregistering extension %s\n", debugstr_w(ext->Extension));
1347c2c66affSColin Finck
1348c2c66affSColin Finck ext->action = INSTALLSTATE_ABSENT;
1349c2c66affSColin Finck
1350*f4be6dc3SMikhail extension = malloc( (wcslen( ext->Extension ) + 2) * sizeof(WCHAR) );
1351c2c66affSColin Finck if (extension)
1352c2c66affSColin Finck {
1353c2c66affSColin Finck extension[0] = '.';
1354958f1addSwinesync lstrcpyW( extension + 1, ext->Extension );
1355c2c66affSColin Finck res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension );
1356*f4be6dc3SMikhail free( extension );
1357c2c66affSColin Finck if (res != ERROR_SUCCESS)
135802f995b2Swinesync WARN("failed to delete extension key %ld\n", res);
1359c2c66affSColin Finck }
1360c2c66affSColin Finck
1361c2c66affSColin Finck if (ext->ProgID || ext->ProgIDText)
1362c2c66affSColin Finck {
1363c2c66affSColin Finck LPCWSTR progid;
1364c2c66affSColin Finck LPWSTR progid_shell;
1365c2c66affSColin Finck
1366c2c66affSColin Finck if (ext->ProgID)
1367c2c66affSColin Finck progid = ext->ProgID->ProgID;
1368c2c66affSColin Finck else
1369c2c66affSColin Finck progid = ext->ProgIDText;
1370c2c66affSColin Finck
1371*f4be6dc3SMikhail progid_shell = malloc( wcslen( progid ) * sizeof(WCHAR) + sizeof( L"\\shell" ) );
1372c2c66affSColin Finck if (progid_shell)
1373c2c66affSColin Finck {
1374958f1addSwinesync lstrcpyW( progid_shell, progid );
1375d012037fSwinesync lstrcatW( progid_shell, L"\\shell" );
1376c2c66affSColin Finck res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell );
1377*f4be6dc3SMikhail free( progid_shell );
1378c2c66affSColin Finck if (res != ERROR_SUCCESS)
137902f995b2Swinesync WARN("failed to delete shell key %ld\n", res);
1380c2c66affSColin Finck RegDeleteKeyW( HKEY_CLASSES_ROOT, progid );
1381c2c66affSColin Finck }
1382c2c66affSColin Finck }
1383c2c66affSColin Finck
1384c2c66affSColin Finck uirow = MSI_CreateRecord( 1 );
1385c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, ext->Extension );
138671bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
1387c2c66affSColin Finck msiobj_release( &uirow->hdr );
1388c2c66affSColin Finck }
1389c2c66affSColin Finck return ERROR_SUCCESS;
1390c2c66affSColin Finck }
1391c2c66affSColin Finck
ACTION_RegisterMIMEInfo(MSIPACKAGE * package)1392c2c66affSColin Finck UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package)
1393c2c66affSColin Finck {
1394c2c66affSColin Finck MSIRECORD *uirow;
1395c2c66affSColin Finck MSIMIME *mt;
1396c2c66affSColin Finck UINT r;
1397c2c66affSColin Finck
1398fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
1399d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"RegisterMIMEInfo" );
1400fd8b07bdSwinesync
1401c2c66affSColin Finck r = load_classes_and_such( package );
1402c2c66affSColin Finck if (r != ERROR_SUCCESS)
1403c2c66affSColin Finck return r;
1404c2c66affSColin Finck
1405c2c66affSColin Finck LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry )
1406c2c66affSColin Finck {
1407c2c66affSColin Finck LPWSTR extension = NULL, key;
1408c2c66affSColin Finck
1409c2c66affSColin Finck /*
1410c2c66affSColin Finck * check if the MIME is to be installed. Either as requested by an
1411c2c66affSColin Finck * extension or Class
1412c2c66affSColin Finck */
1413c2c66affSColin Finck if ((!mt->Class || mt->Class->action != INSTALLSTATE_LOCAL) &&
1414c2c66affSColin Finck (!mt->Extension || mt->Extension->action != INSTALLSTATE_LOCAL))
1415c2c66affSColin Finck {
1416c2c66affSColin Finck TRACE("MIME %s not scheduled to be installed\n", debugstr_w(mt->ContentType));
1417c2c66affSColin Finck continue;
1418c2c66affSColin Finck }
1419c2c66affSColin Finck
1420c2c66affSColin Finck TRACE("Registering MIME type %s\n", debugstr_w(mt->ContentType));
1421c2c66affSColin Finck
1422*f4be6dc3SMikhail if (mt->Extension) extension = malloc( (wcslen( mt->Extension->Extension ) + 2) * sizeof(WCHAR) );
1423*f4be6dc3SMikhail key = malloc( sizeof( L"MIME\\Database\\Content Type\\" ) +
1424*f4be6dc3SMikhail wcslen( mt->ContentType ) * sizeof(WCHAR) );
1425c2c66affSColin Finck
1426c2c66affSColin Finck if (extension && key)
1427c2c66affSColin Finck {
1428c2c66affSColin Finck extension[0] = '.';
1429958f1addSwinesync lstrcpyW( extension + 1, mt->Extension->Extension );
1430c2c66affSColin Finck
1431d012037fSwinesync lstrcpyW( key, L"MIME\\Database\\Content Type\\" );
1432958f1addSwinesync lstrcatW( key, mt->ContentType );
1433d012037fSwinesync msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, L"Extension", extension );
1434c2c66affSColin Finck
1435c2c66affSColin Finck if (mt->clsid)
1436d012037fSwinesync msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, L"CLSID", mt->clsid );
1437c2c66affSColin Finck }
1438*f4be6dc3SMikhail free( extension );
1439*f4be6dc3SMikhail free( key );
1440c2c66affSColin Finck
1441c2c66affSColin Finck uirow = MSI_CreateRecord( 2 );
1442c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, mt->ContentType );
1443c2c66affSColin Finck MSI_RecordSetStringW( uirow, 2, mt->suffix );
144471bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
1445c2c66affSColin Finck msiobj_release( &uirow->hdr );
1446c2c66affSColin Finck }
1447c2c66affSColin Finck return ERROR_SUCCESS;
1448c2c66affSColin Finck }
1449c2c66affSColin Finck
ACTION_UnregisterMIMEInfo(MSIPACKAGE * package)1450c2c66affSColin Finck UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package )
1451c2c66affSColin Finck {
1452c2c66affSColin Finck MSIRECORD *uirow;
1453c2c66affSColin Finck MSIMIME *mime;
1454c2c66affSColin Finck UINT r;
1455c2c66affSColin Finck
1456fd8b07bdSwinesync if (package->script == SCRIPT_NONE)
1457d012037fSwinesync return msi_schedule_action( package, SCRIPT_INSTALL, L"UnregisterMIMEInfo" );
1458fd8b07bdSwinesync
1459c2c66affSColin Finck r = load_classes_and_such( package );
1460c2c66affSColin Finck if (r != ERROR_SUCCESS)
1461c2c66affSColin Finck return r;
1462c2c66affSColin Finck
1463c2c66affSColin Finck LIST_FOR_EACH_ENTRY( mime, &package->mimes, MSIMIME, entry )
1464c2c66affSColin Finck {
1465c2c66affSColin Finck LONG res;
1466c2c66affSColin Finck LPWSTR mime_key;
1467c2c66affSColin Finck
1468c2c66affSColin Finck if ((!mime->Class || mime->Class->action != INSTALLSTATE_ABSENT) &&
1469c2c66affSColin Finck (!mime->Extension || mime->Extension->action != INSTALLSTATE_ABSENT))
1470c2c66affSColin Finck {
1471c2c66affSColin Finck TRACE("MIME %s not scheduled to be removed\n", debugstr_w(mime->ContentType));
1472c2c66affSColin Finck continue;
1473c2c66affSColin Finck }
1474c2c66affSColin Finck
1475c2c66affSColin Finck TRACE("Unregistering MIME type %s\n", debugstr_w(mime->ContentType));
1476c2c66affSColin Finck
1477*f4be6dc3SMikhail mime_key = malloc( sizeof( L"MIME\\Database\\Content Type\\" ) +
1478*f4be6dc3SMikhail wcslen( mime->ContentType ) * sizeof(WCHAR) );
1479c2c66affSColin Finck if (mime_key)
1480c2c66affSColin Finck {
1481d012037fSwinesync lstrcpyW( mime_key, L"MIME\\Database\\Content Type\\" );
1482958f1addSwinesync lstrcatW( mime_key, mime->ContentType );
1483c2c66affSColin Finck res = RegDeleteKeyW( HKEY_CLASSES_ROOT, mime_key );
1484c2c66affSColin Finck if (res != ERROR_SUCCESS)
148502f995b2Swinesync WARN("failed to delete MIME key %ld\n", res);
1486*f4be6dc3SMikhail free( mime_key );
1487c2c66affSColin Finck }
1488c2c66affSColin Finck
1489c2c66affSColin Finck uirow = MSI_CreateRecord( 2 );
1490c2c66affSColin Finck MSI_RecordSetStringW( uirow, 1, mime->ContentType );
1491c2c66affSColin Finck MSI_RecordSetStringW( uirow, 2, mime->suffix );
149271bffdcdSAmine Khaldi MSI_ProcessMessage(package, INSTALLMESSAGE_ACTIONDATA, uirow);
1493c2c66affSColin Finck msiobj_release( &uirow->hdr );
1494c2c66affSColin Finck }
1495c2c66affSColin Finck return ERROR_SUCCESS;
1496c2c66affSColin Finck }
1497