Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenclasses.c
Go to the documentation of this file.
00001 /* 00002 * Implementation of the Microsoft Installer (msi.dll) 00003 * 00004 * Copyright 2005 Aric Stewart for CodeWeavers 00005 * 00006 * This library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * This library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with this library; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00019 */ 00020 00021 /* Actions handled in this module: 00022 * 00023 * RegisterClassInfo 00024 * RegisterProgIdInfo 00025 * RegisterExtensionInfo 00026 * RegisterMIMEInfo 00027 * UnregisterClassInfo 00028 * UnregisterProgIdInfo 00029 * UnregisterExtensionInfo 00030 * UnregisterMIMEInfo 00031 */ 00032 00033 #include <stdarg.h> 00034 00035 #include "windef.h" 00036 #include "winbase.h" 00037 #include "winerror.h" 00038 #include "winreg.h" 00039 #include "wine/debug.h" 00040 #include "msipriv.h" 00041 #include "winuser.h" 00042 #include "wine/unicode.h" 00043 00044 WINE_DEFAULT_DEBUG_CHANNEL(msi); 00045 00046 static MSIAPPID *load_appid( MSIPACKAGE* package, MSIRECORD *row ) 00047 { 00048 LPCWSTR buffer; 00049 MSIAPPID *appid; 00050 00051 /* fill in the data */ 00052 00053 appid = msi_alloc_zero( sizeof(MSIAPPID) ); 00054 if (!appid) 00055 return NULL; 00056 00057 appid->AppID = msi_dup_record_field( row, 1 ); 00058 TRACE("loading appid %s\n", debugstr_w( appid->AppID )); 00059 00060 buffer = MSI_RecordGetString(row,2); 00061 deformat_string( package, buffer, &appid->RemoteServerName ); 00062 00063 appid->LocalServer = msi_dup_record_field(row,3); 00064 appid->ServiceParameters = msi_dup_record_field(row,4); 00065 appid->DllSurrogate = msi_dup_record_field(row,5); 00066 00067 appid->ActivateAtStorage = !MSI_RecordIsNull(row,6); 00068 appid->RunAsInteractiveUser = !MSI_RecordIsNull(row,7); 00069 00070 list_add_tail( &package->appids, &appid->entry ); 00071 00072 return appid; 00073 } 00074 00075 static MSIAPPID *load_given_appid( MSIPACKAGE *package, LPCWSTR name ) 00076 { 00077 static const WCHAR query[] = { 00078 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 00079 '`','A','p','p','I','d','`',' ','W','H','E','R','E',' ', 00080 '`','A','p','p','I','d','`',' ','=',' ','\'','%','s','\'',0}; 00081 MSIRECORD *row; 00082 MSIAPPID *appid; 00083 00084 if (!name) 00085 return NULL; 00086 00087 /* check for appids already loaded */ 00088 LIST_FOR_EACH_ENTRY( appid, &package->appids, MSIAPPID, entry ) 00089 { 00090 if (!strcmpiW( appid->AppID, name )) 00091 { 00092 TRACE("found appid %s %p\n", debugstr_w(name), appid); 00093 return appid; 00094 } 00095 } 00096 00097 row = MSI_QueryGetRecord(package->db, query, name); 00098 if (!row) 00099 return NULL; 00100 00101 appid = load_appid(package, row); 00102 msiobj_release(&row->hdr); 00103 return appid; 00104 } 00105 00106 static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR progid); 00107 static MSICLASS *load_given_class( MSIPACKAGE *package, LPCWSTR classid ); 00108 00109 static MSIPROGID *load_progid( MSIPACKAGE* package, MSIRECORD *row ) 00110 { 00111 MSIPROGID *progid; 00112 LPCWSTR buffer; 00113 00114 /* fill in the data */ 00115 00116 progid = msi_alloc_zero( sizeof(MSIPROGID) ); 00117 if (!progid) 00118 return NULL; 00119 00120 list_add_tail( &package->progids, &progid->entry ); 00121 00122 progid->ProgID = msi_dup_record_field(row,1); 00123 TRACE("loading progid %s\n",debugstr_w(progid->ProgID)); 00124 00125 buffer = MSI_RecordGetString(row,2); 00126 progid->Parent = load_given_progid(package,buffer); 00127 if (progid->Parent == NULL && buffer) 00128 FIXME("Unknown parent ProgID %s\n",debugstr_w(buffer)); 00129 00130 buffer = MSI_RecordGetString(row,3); 00131 progid->Class = load_given_class(package,buffer); 00132 if (progid->Class == NULL && buffer) 00133 FIXME("Unknown class %s\n",debugstr_w(buffer)); 00134 00135 progid->Description = msi_dup_record_field(row,4); 00136 00137 if (!MSI_RecordIsNull(row,6)) 00138 { 00139 INT icon_index = MSI_RecordGetInteger(row,6); 00140 LPCWSTR FileName = MSI_RecordGetString(row,5); 00141 LPWSTR FilePath; 00142 static const WCHAR fmt[] = {'%','s',',','%','i',0}; 00143 00144 FilePath = msi_build_icon_path(package, FileName); 00145 00146 progid->IconPath = msi_alloc( (strlenW(FilePath)+10)* sizeof(WCHAR) ); 00147 00148 sprintfW(progid->IconPath,fmt,FilePath,icon_index); 00149 00150 msi_free(FilePath); 00151 } 00152 else 00153 { 00154 buffer = MSI_RecordGetString(row,5); 00155 if (buffer) 00156 progid->IconPath = msi_build_icon_path(package, buffer); 00157 } 00158 00159 progid->CurVer = NULL; 00160 progid->VersionInd = NULL; 00161 00162 /* if we have a parent then we may be that parents CurVer */ 00163 if (progid->Parent && progid->Parent != progid) 00164 { 00165 MSIPROGID *parent = progid->Parent; 00166 00167 while (parent->Parent && parent->Parent != parent) 00168 parent = parent->Parent; 00169 00170 /* FIXME: need to determine if we are really the CurVer */ 00171 00172 progid->CurVer = parent; 00173 parent->VersionInd = progid; 00174 } 00175 00176 return progid; 00177 } 00178 00179 static MSIPROGID *load_given_progid(MSIPACKAGE *package, LPCWSTR name) 00180 { 00181 static const WCHAR query[] = { 00182 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 00183 '`','P','r','o','g','I','d','`',' ','W','H','E','R','E',' ', 00184 '`','P','r','o','g','I','d','`',' ','=',' ','\'','%','s','\'',0}; 00185 MSIPROGID *progid; 00186 MSIRECORD *row; 00187 00188 if (!name) 00189 return NULL; 00190 00191 /* check for progids already loaded */ 00192 LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry ) 00193 { 00194 if (!strcmpiW( progid->ProgID, name )) 00195 { 00196 TRACE("found progid %s (%p)\n",debugstr_w(name), progid ); 00197 return progid; 00198 } 00199 } 00200 00201 row = MSI_QueryGetRecord( package->db, query, name ); 00202 if (!row) 00203 return NULL; 00204 00205 progid = load_progid(package, row); 00206 msiobj_release(&row->hdr); 00207 return progid; 00208 } 00209 00210 static MSICLASS *load_class( MSIPACKAGE* package, MSIRECORD *row ) 00211 { 00212 MSICLASS *cls; 00213 DWORD i; 00214 LPCWSTR buffer; 00215 00216 /* fill in the data */ 00217 00218 cls = msi_alloc_zero( sizeof(MSICLASS) ); 00219 if (!cls) 00220 return NULL; 00221 00222 list_add_tail( &package->classes, &cls->entry ); 00223 00224 cls->clsid = msi_dup_record_field( row, 1 ); 00225 TRACE("loading class %s\n",debugstr_w(cls->clsid)); 00226 cls->Context = msi_dup_record_field( row, 2 ); 00227 buffer = MSI_RecordGetString(row,3); 00228 cls->Component = msi_get_loaded_component( package, buffer ); 00229 00230 cls->ProgIDText = msi_dup_record_field(row,4); 00231 cls->ProgID = load_given_progid(package, cls->ProgIDText); 00232 00233 cls->Description = msi_dup_record_field(row,5); 00234 00235 buffer = MSI_RecordGetString(row,6); 00236 if (buffer) 00237 cls->AppID = load_given_appid(package, buffer); 00238 00239 cls->FileTypeMask = msi_dup_record_field(row,7); 00240 00241 if (!MSI_RecordIsNull(row,9)) 00242 { 00243 00244 INT icon_index = MSI_RecordGetInteger(row,9); 00245 LPCWSTR FileName = MSI_RecordGetString(row,8); 00246 LPWSTR FilePath; 00247 static const WCHAR fmt[] = {'%','s',',','%','i',0}; 00248 00249 FilePath = msi_build_icon_path(package, FileName); 00250 00251 cls->IconPath = msi_alloc( (strlenW(FilePath)+5)* sizeof(WCHAR) ); 00252 00253 sprintfW(cls->IconPath,fmt,FilePath,icon_index); 00254 00255 msi_free(FilePath); 00256 } 00257 else 00258 { 00259 buffer = MSI_RecordGetString(row,8); 00260 if (buffer) 00261 cls->IconPath = msi_build_icon_path(package, buffer); 00262 } 00263 00264 if (!MSI_RecordIsNull(row,10)) 00265 { 00266 i = MSI_RecordGetInteger(row,10); 00267 if (i != MSI_NULL_INTEGER && i > 0 && i < 4) 00268 { 00269 static const WCHAR ole2[] = {'o','l','e','2','.','d','l','l',0}; 00270 static const WCHAR ole32[] = {'o','l','e','3','2','.','d','l','l',0}; 00271 00272 switch(i) 00273 { 00274 case 1: 00275 cls->DefInprocHandler = strdupW(ole2); 00276 break; 00277 case 2: 00278 cls->DefInprocHandler32 = strdupW(ole32); 00279 break; 00280 case 3: 00281 cls->DefInprocHandler = strdupW(ole2); 00282 cls->DefInprocHandler32 = strdupW(ole32); 00283 break; 00284 } 00285 } 00286 else 00287 { 00288 cls->DefInprocHandler32 = msi_dup_record_field( row, 10 ); 00289 msi_reduce_to_long_filename( cls->DefInprocHandler32 ); 00290 } 00291 } 00292 buffer = MSI_RecordGetString(row,11); 00293 deformat_string(package,buffer,&cls->Argument); 00294 00295 buffer = MSI_RecordGetString(row,12); 00296 cls->Feature = msi_get_loaded_feature(package, buffer); 00297 00298 cls->Attributes = MSI_RecordGetInteger(row,13); 00299 00300 return cls; 00301 } 00302 00303 /* 00304 * the Class table has 3 primary keys. Generally it is only 00305 * referenced through the first CLSID key. However when loading 00306 * all of the classes we need to make sure we do not ignore rows 00307 * with other Context and ComponentIndexs 00308 */ 00309 static MSICLASS *load_given_class(MSIPACKAGE *package, LPCWSTR classid) 00310 { 00311 static const WCHAR query[] = { 00312 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 00313 '`','C','l','a','s','s','`',' ','W','H','E','R','E',' ', 00314 '`','C','L','S','I','D','`',' ','=',' ','\'','%','s','\'',0}; 00315 MSICLASS *cls; 00316 MSIRECORD *row; 00317 00318 if (!classid) 00319 return NULL; 00320 00321 /* check for classes already loaded */ 00322 LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry ) 00323 { 00324 if (!strcmpiW( cls->clsid, classid )) 00325 { 00326 TRACE("found class %s (%p)\n",debugstr_w(classid), cls); 00327 return cls; 00328 } 00329 } 00330 00331 row = MSI_QueryGetRecord(package->db, query, classid); 00332 if (!row) 00333 return NULL; 00334 00335 cls = load_class(package, row); 00336 msiobj_release(&row->hdr); 00337 return cls; 00338 } 00339 00340 static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR extension ); 00341 00342 static MSIMIME *load_mime( MSIPACKAGE* package, MSIRECORD *row ) 00343 { 00344 LPCWSTR extension; 00345 MSIMIME *mt; 00346 00347 /* fill in the data */ 00348 00349 mt = msi_alloc_zero( sizeof(MSIMIME) ); 00350 if (!mt) 00351 return mt; 00352 00353 mt->ContentType = msi_dup_record_field( row, 1 ); 00354 TRACE("loading mime %s\n", debugstr_w(mt->ContentType)); 00355 00356 extension = MSI_RecordGetString( row, 2 ); 00357 mt->Extension = load_given_extension( package, extension ); 00358 mt->suffix = strdupW( extension ); 00359 00360 mt->clsid = msi_dup_record_field( row, 3 ); 00361 mt->Class = load_given_class( package, mt->clsid ); 00362 00363 list_add_tail( &package->mimes, &mt->entry ); 00364 00365 return mt; 00366 } 00367 00368 static MSIMIME *load_given_mime( MSIPACKAGE *package, LPCWSTR mime ) 00369 { 00370 static const WCHAR query[] = { 00371 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 00372 '`','M','I','M','E','`',' ','W','H','E','R','E',' ', 00373 '`','C','o','n','t','e','n','t','T','y','p','e','`',' ','=',' ','\'','%','s','\'',0}; 00374 MSIRECORD *row; 00375 MSIMIME *mt; 00376 00377 if (!mime) 00378 return NULL; 00379 00380 /* check for mime already loaded */ 00381 LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry ) 00382 { 00383 if (!strcmpiW( mt->ContentType, mime )) 00384 { 00385 TRACE("found mime %s (%p)\n",debugstr_w(mime), mt); 00386 return mt; 00387 } 00388 } 00389 00390 row = MSI_QueryGetRecord(package->db, query, mime); 00391 if (!row) 00392 return NULL; 00393 00394 mt = load_mime(package, row); 00395 msiobj_release(&row->hdr); 00396 return mt; 00397 } 00398 00399 static MSIEXTENSION *load_extension( MSIPACKAGE* package, MSIRECORD *row ) 00400 { 00401 MSIEXTENSION *ext; 00402 LPCWSTR buffer; 00403 00404 /* fill in the data */ 00405 00406 ext = msi_alloc_zero( sizeof(MSIEXTENSION) ); 00407 if (!ext) 00408 return NULL; 00409 00410 list_init( &ext->verbs ); 00411 00412 list_add_tail( &package->extensions, &ext->entry ); 00413 00414 ext->Extension = msi_dup_record_field( row, 1 ); 00415 TRACE("loading extension %s\n", debugstr_w(ext->Extension)); 00416 00417 buffer = MSI_RecordGetString( row, 2 ); 00418 ext->Component = msi_get_loaded_component( package, buffer ); 00419 00420 ext->ProgIDText = msi_dup_record_field( row, 3 ); 00421 ext->ProgID = load_given_progid( package, ext->ProgIDText ); 00422 00423 buffer = MSI_RecordGetString( row, 4 ); 00424 ext->Mime = load_given_mime( package, buffer ); 00425 00426 buffer = MSI_RecordGetString(row,5); 00427 ext->Feature = msi_get_loaded_feature( package, buffer ); 00428 00429 return ext; 00430 } 00431 00432 /* 00433 * While the extension table has 2 primary keys, this function is only looking 00434 * at the Extension key which is what is referenced as a foreign key 00435 */ 00436 static MSIEXTENSION *load_given_extension( MSIPACKAGE *package, LPCWSTR name ) 00437 { 00438 static const WCHAR query[] = { 00439 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ', 00440 '`','E','x','t','e','n','s','i','o','n','`',' ','W','H','E','R','E',' ', 00441 '`','E','x','t','e','n','s','i','o','n','`',' ','=',' ','\'','%','s','\'',0}; 00442 MSIEXTENSION *ext; 00443 MSIRECORD *row; 00444 00445 if (!name) 00446 return NULL; 00447 00448 if (name[0] == '.') 00449 name++; 00450 00451 /* check for extensions already loaded */ 00452 LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry ) 00453 { 00454 if (!strcmpiW( ext->Extension, name )) 00455 { 00456 TRACE("extension %s already loaded %p\n", debugstr_w(name), ext); 00457 return ext; 00458 } 00459 } 00460 00461 row = MSI_QueryGetRecord( package->db, query, name ); 00462 if (!row) 00463 return NULL; 00464 00465 ext = load_extension(package, row); 00466 msiobj_release(&row->hdr); 00467 return ext; 00468 } 00469 00470 static UINT iterate_load_verb(MSIRECORD *row, LPVOID param) 00471 { 00472 MSIPACKAGE* package = param; 00473 MSIVERB *verb; 00474 LPCWSTR buffer; 00475 MSIEXTENSION *extension; 00476 00477 buffer = MSI_RecordGetString(row,1); 00478 extension = load_given_extension( package, buffer ); 00479 if (!extension) 00480 { 00481 ERR("Verb unable to find loaded extension %s\n", debugstr_w(buffer)); 00482 return ERROR_SUCCESS; 00483 } 00484 00485 /* fill in the data */ 00486 00487 verb = msi_alloc_zero( sizeof(MSIVERB) ); 00488 if (!verb) 00489 return ERROR_OUTOFMEMORY; 00490 00491 verb->Verb = msi_dup_record_field(row,2); 00492 TRACE("loading verb %s\n",debugstr_w(verb->Verb)); 00493 verb->Sequence = MSI_RecordGetInteger(row,3); 00494 00495 buffer = MSI_RecordGetString(row,4); 00496 deformat_string(package,buffer,&verb->Command); 00497 00498 buffer = MSI_RecordGetString(row,5); 00499 deformat_string(package,buffer,&verb->Argument); 00500 00501 /* associate the verb with the correct extension */ 00502 list_add_tail( &extension->verbs, &verb->entry ); 00503 00504 return ERROR_SUCCESS; 00505 } 00506 00507 static UINT iterate_all_classes(MSIRECORD *rec, LPVOID param) 00508 { 00509 MSICOMPONENT *comp; 00510 LPCWSTR clsid; 00511 LPCWSTR context; 00512 LPCWSTR buffer; 00513 MSIPACKAGE* package = param; 00514 MSICLASS *cls; 00515 BOOL match = FALSE; 00516 00517 clsid = MSI_RecordGetString(rec,1); 00518 context = MSI_RecordGetString(rec,2); 00519 buffer = MSI_RecordGetString(rec,3); 00520 comp = msi_get_loaded_component(package, buffer); 00521 00522 LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry ) 00523 { 00524 if (strcmpiW( clsid, cls->clsid )) 00525 continue; 00526 if (strcmpW( context, cls->Context )) 00527 continue; 00528 if (comp == cls->Component) 00529 { 00530 match = TRUE; 00531 break; 00532 } 00533 } 00534 00535 if (!match) 00536 load_class(package, rec); 00537 00538 return ERROR_SUCCESS; 00539 } 00540 00541 static UINT load_all_classes( MSIPACKAGE *package ) 00542 { 00543 static const WCHAR query[] = { 00544 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ','`','C','l','a','s','s','`',0}; 00545 MSIQUERY *view; 00546 UINT rc; 00547 00548 rc = MSI_DatabaseOpenViewW(package->db, query, &view); 00549 if (rc != ERROR_SUCCESS) 00550 return ERROR_SUCCESS; 00551 00552 rc = MSI_IterateRecords(view, NULL, iterate_all_classes, package); 00553 msiobj_release(&view->hdr); 00554 return rc; 00555 } 00556 00557 static UINT iterate_all_extensions(MSIRECORD *rec, LPVOID param) 00558 { 00559 MSICOMPONENT *comp; 00560 LPCWSTR buffer; 00561 LPCWSTR extension; 00562 MSIPACKAGE* package = param; 00563 BOOL match = FALSE; 00564 MSIEXTENSION *ext; 00565 00566 extension = MSI_RecordGetString(rec,1); 00567 buffer = MSI_RecordGetString(rec,2); 00568 comp = msi_get_loaded_component(package, buffer); 00569 00570 LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry ) 00571 { 00572 if (strcmpiW(extension, ext->Extension)) 00573 continue; 00574 if (comp == ext->Component) 00575 { 00576 match = TRUE; 00577 break; 00578 } 00579 } 00580 00581 if (!match) 00582 load_extension(package, rec); 00583 00584 return ERROR_SUCCESS; 00585 } 00586 00587 static UINT load_all_extensions( MSIPACKAGE *package ) 00588 { 00589 static const WCHAR query[] = { 00590 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','E','x','t','e','n','s','i','o','n','`',0}; 00591 MSIQUERY *view; 00592 UINT rc; 00593 00594 rc = MSI_DatabaseOpenViewW( package->db, query, &view ); 00595 if (rc != ERROR_SUCCESS) 00596 return ERROR_SUCCESS; 00597 00598 rc = MSI_IterateRecords(view, NULL, iterate_all_extensions, package); 00599 msiobj_release(&view->hdr); 00600 return rc; 00601 } 00602 00603 static UINT iterate_all_progids(MSIRECORD *rec, LPVOID param) 00604 { 00605 LPCWSTR buffer; 00606 MSIPACKAGE* package = param; 00607 00608 buffer = MSI_RecordGetString(rec,1); 00609 load_given_progid(package,buffer); 00610 return ERROR_SUCCESS; 00611 } 00612 00613 static UINT load_all_progids( MSIPACKAGE *package ) 00614 { 00615 static const WCHAR query[] = { 00616 'S','E','L','E','C','T',' ','`','P','r','o','g','I','d','`',' ','F','R','O','M',' ', 00617 '`','P','r','o','g','I','d','`',0}; 00618 MSIQUERY *view; 00619 UINT rc; 00620 00621 rc = MSI_DatabaseOpenViewW(package->db, query, &view); 00622 if (rc != ERROR_SUCCESS) 00623 return ERROR_SUCCESS; 00624 00625 rc = MSI_IterateRecords(view, NULL, iterate_all_progids, package); 00626 msiobj_release(&view->hdr); 00627 return rc; 00628 } 00629 00630 static UINT load_all_verbs( MSIPACKAGE *package ) 00631 { 00632 static const WCHAR query[] = { 00633 'S','E','L','E','C','T',' ','*',' ','F','R','O','M',' ','`','V','e','r','b','`',0}; 00634 MSIQUERY *view; 00635 UINT rc; 00636 00637 rc = MSI_DatabaseOpenViewW(package->db, query, &view); 00638 if (rc != ERROR_SUCCESS) 00639 return ERROR_SUCCESS; 00640 00641 rc = MSI_IterateRecords(view, NULL, iterate_load_verb, package); 00642 msiobj_release(&view->hdr); 00643 return rc; 00644 } 00645 00646 static UINT iterate_all_mimes(MSIRECORD *rec, LPVOID param) 00647 { 00648 LPCWSTR buffer; 00649 MSIPACKAGE* package = param; 00650 00651 buffer = MSI_RecordGetString(rec,1); 00652 load_given_mime(package,buffer); 00653 return ERROR_SUCCESS; 00654 } 00655 00656 static UINT load_all_mimes( MSIPACKAGE *package ) 00657 { 00658 static const WCHAR query[] = { 00659 'S','E','L','E','C','T',' ','`','C','o','n','t','e','n','t','T','y','p','e','`',' ', 00660 'F','R','O','M',' ','`','M','I','M','E','`',0}; 00661 MSIQUERY *view; 00662 UINT rc; 00663 00664 rc = MSI_DatabaseOpenViewW(package->db, query, &view); 00665 if (rc != ERROR_SUCCESS) 00666 return ERROR_SUCCESS; 00667 00668 rc = MSI_IterateRecords(view, NULL, iterate_all_mimes, package); 00669 msiobj_release(&view->hdr); 00670 return rc; 00671 } 00672 00673 static UINT load_classes_and_such( MSIPACKAGE *package ) 00674 { 00675 UINT r; 00676 00677 TRACE("Loading all the class info and related tables\n"); 00678 00679 /* check if already loaded */ 00680 if (!list_empty( &package->classes ) || 00681 !list_empty( &package->mimes ) || 00682 !list_empty( &package->extensions ) || 00683 !list_empty( &package->progids )) return ERROR_SUCCESS; 00684 00685 r = load_all_classes( package ); 00686 if (r != ERROR_SUCCESS) return r; 00687 00688 r = load_all_extensions( package ); 00689 if (r != ERROR_SUCCESS) return r; 00690 00691 r = load_all_progids( package ); 00692 if (r != ERROR_SUCCESS) return r; 00693 00694 /* these loads must come after the other loads */ 00695 r = load_all_verbs( package ); 00696 if (r != ERROR_SUCCESS) return r; 00697 00698 return load_all_mimes( package ); 00699 } 00700 00701 static void mark_progid_for_install( MSIPACKAGE* package, MSIPROGID *progid ) 00702 { 00703 MSIPROGID *child; 00704 00705 if (!progid) 00706 return; 00707 00708 if (progid->InstallMe) 00709 return; 00710 00711 progid->InstallMe = TRUE; 00712 00713 /* all children if this is a parent also install */ 00714 LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry ) 00715 { 00716 if (child->Parent == progid) 00717 mark_progid_for_install( package, child ); 00718 } 00719 } 00720 00721 static void mark_progid_for_uninstall( MSIPACKAGE *package, MSIPROGID *progid ) 00722 { 00723 MSIPROGID *child; 00724 00725 if (!progid) 00726 return; 00727 00728 if (!progid->InstallMe) 00729 return; 00730 00731 progid->InstallMe = FALSE; 00732 00733 LIST_FOR_EACH_ENTRY( child, &package->progids, MSIPROGID, entry ) 00734 { 00735 if (child->Parent == progid) 00736 mark_progid_for_uninstall( package, child ); 00737 } 00738 } 00739 00740 static void mark_mime_for_install( MSIMIME *mime ) 00741 { 00742 if (!mime) 00743 return; 00744 mime->InstallMe = TRUE; 00745 } 00746 00747 static void mark_mime_for_uninstall( MSIMIME *mime ) 00748 { 00749 if (!mime) 00750 return; 00751 mime->InstallMe = FALSE; 00752 } 00753 00754 static UINT register_appid(const MSIAPPID *appid, LPCWSTR app ) 00755 { 00756 static const WCHAR szRemoteServerName[] = 00757 {'R','e','m','o','t','e','S','e','r','v','e','r','N','a','m','e',0}; 00758 static const WCHAR szLocalService[] = 00759 {'L','o','c','a','l','S','e','r','v','i','c','e',0}; 00760 static const WCHAR szService[] = 00761 {'S','e','r','v','i','c','e','P','a','r','a','m','e','t','e','r','s',0}; 00762 static const WCHAR szDLL[] = 00763 {'D','l','l','S','u','r','r','o','g','a','t','e',0}; 00764 static const WCHAR szActivate[] = 00765 {'A','c','t','i','v','a','t','e','A','s','S','t','o','r','a','g','e',0}; 00766 static const WCHAR szY[] = {'Y',0}; 00767 static const WCHAR szRunAs[] = {'R','u','n','A','s',0}; 00768 static const WCHAR szUser[] = 00769 {'I','n','t','e','r','a','c','t','i','v','e',' ','U','s','e','r',0}; 00770 00771 HKEY hkey2,hkey3; 00772 00773 RegCreateKeyW(HKEY_CLASSES_ROOT,szAppID,&hkey2); 00774 RegCreateKeyW( hkey2, appid->AppID, &hkey3 ); 00775 RegCloseKey(hkey2); 00776 msi_reg_set_val_str( hkey3, NULL, app ); 00777 00778 if (appid->RemoteServerName) 00779 msi_reg_set_val_str( hkey3, szRemoteServerName, appid->RemoteServerName ); 00780 00781 if (appid->LocalServer) 00782 msi_reg_set_val_str( hkey3, szLocalService, appid->LocalServer ); 00783 00784 if (appid->ServiceParameters) 00785 msi_reg_set_val_str( hkey3, szService, appid->ServiceParameters ); 00786 00787 if (appid->DllSurrogate) 00788 msi_reg_set_val_str( hkey3, szDLL, appid->DllSurrogate ); 00789 00790 if (appid->ActivateAtStorage) 00791 msi_reg_set_val_str( hkey3, szActivate, szY ); 00792 00793 if (appid->RunAsInteractiveUser) 00794 msi_reg_set_val_str( hkey3, szRunAs, szUser ); 00795 00796 RegCloseKey(hkey3); 00797 return ERROR_SUCCESS; 00798 } 00799 00800 UINT ACTION_RegisterClassInfo(MSIPACKAGE *package) 00801 { 00802 static const WCHAR szFileType_fmt[] = {'F','i','l','e','T','y','p','e','\\','%','s','\\','%','i',0}; 00803 const WCHAR *keypath; 00804 MSIRECORD *uirow; 00805 HKEY hkey, hkey2, hkey3; 00806 MSICLASS *cls; 00807 UINT r; 00808 00809 r = load_classes_and_such( package ); 00810 if (r != ERROR_SUCCESS) 00811 return r; 00812 00813 if (is_64bit && package->platform == PLATFORM_INTEL) 00814 keypath = szWow6432NodeCLSID; 00815 else 00816 keypath = szCLSID; 00817 00818 if (RegCreateKeyW(HKEY_CLASSES_ROOT, keypath, &hkey) != ERROR_SUCCESS) 00819 return ERROR_FUNCTION_FAILED; 00820 00821 LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry ) 00822 { 00823 MSICOMPONENT *comp; 00824 MSIFILE *file; 00825 DWORD size; 00826 LPWSTR argument; 00827 MSIFEATURE *feature; 00828 00829 comp = cls->Component; 00830 if ( !comp ) 00831 continue; 00832 00833 if (!comp->Enabled) 00834 { 00835 TRACE("component is disabled\n"); 00836 continue; 00837 } 00838 00839 feature = cls->Feature; 00840 if (!feature) 00841 continue; 00842 00843 feature->Action = msi_get_feature_action( package, feature ); 00844 if (feature->Action != INSTALLSTATE_LOCAL && 00845 feature->Action != INSTALLSTATE_ADVERTISED ) 00846 { 00847 TRACE("feature %s not scheduled for installation, skipping registration of class %s\n", 00848 debugstr_w(feature->Feature), debugstr_w(cls->clsid)); 00849 continue; 00850 } 00851 00852 if (!comp->KeyPath || !(file = msi_get_loaded_file( package, comp->KeyPath ))) 00853 { 00854 TRACE("COM server not provided, skipping class %s\n", debugstr_w(cls->clsid)); 00855 continue; 00856 } 00857 TRACE("Registering class %s (%p)\n", debugstr_w(cls->clsid), cls); 00858 00859 cls->Installed = TRUE; 00860 mark_progid_for_install( package, cls->ProgID ); 00861 00862 RegCreateKeyW( hkey, cls->clsid, &hkey2 ); 00863 00864 if (cls->Description) 00865 msi_reg_set_val_str( hkey2, NULL, cls->Description ); 00866 00867 RegCreateKeyW( hkey2, cls->Context, &hkey3 ); 00868 00869 /* 00870 * FIXME: Implement install on demand (advertised components). 00871 * 00872 * ole32.dll should call msi.MsiProvideComponentFromDescriptor() 00873 * when it needs an InProcServer that doesn't exist. 00874 * The component advertise string should be in the "InProcServer" value. 00875 */ 00876 size = lstrlenW( file->TargetPath )+1; 00877 if (cls->Argument) 00878 size += lstrlenW(cls->Argument)+1; 00879 00880 argument = msi_alloc( size * sizeof(WCHAR) ); 00881 lstrcpyW( argument, file->TargetPath ); 00882 00883 if (cls->Argument) 00884 { 00885 lstrcatW( argument, szSpace ); 00886 lstrcatW( argument, cls->Argument ); 00887 } 00888 00889 msi_reg_set_val_str( hkey3, NULL, argument ); 00890 msi_free(argument); 00891 00892 RegCloseKey(hkey3); 00893 00894 if (cls->ProgID || cls->ProgIDText) 00895 { 00896 LPCWSTR progid; 00897 00898 if (cls->ProgID) 00899 progid = cls->ProgID->ProgID; 00900 else 00901 progid = cls->ProgIDText; 00902 00903 msi_reg_set_subkey_val( hkey2, szProgID, NULL, progid ); 00904 00905 if (cls->ProgID && cls->ProgID->VersionInd) 00906 { 00907 msi_reg_set_subkey_val( hkey2, szVIProgID, NULL, 00908 cls->ProgID->VersionInd->ProgID ); 00909 } 00910 } 00911 00912 if (cls->AppID) 00913 { 00914 MSIAPPID *appid = cls->AppID; 00915 msi_reg_set_val_str( hkey2, szAppID, appid->AppID ); 00916 register_appid( appid, cls->Description ); 00917 } 00918 00919 if (cls->IconPath) 00920 msi_reg_set_subkey_val( hkey2, szDefaultIcon, NULL, cls->IconPath ); 00921 00922 if (cls->DefInprocHandler) 00923 msi_reg_set_subkey_val( hkey2, szInprocHandler, NULL, cls->DefInprocHandler ); 00924 00925 if (cls->DefInprocHandler32) 00926 msi_reg_set_subkey_val( hkey2, szInprocHandler32, NULL, cls->DefInprocHandler32 ); 00927 00928 RegCloseKey(hkey2); 00929 00930 /* if there is a FileTypeMask, register the FileType */ 00931 if (cls->FileTypeMask) 00932 { 00933 LPWSTR ptr, ptr2; 00934 LPWSTR keyname; 00935 INT index = 0; 00936 ptr = cls->FileTypeMask; 00937 while (ptr && *ptr) 00938 { 00939 ptr2 = strchrW(ptr,';'); 00940 if (ptr2) 00941 *ptr2 = 0; 00942 keyname = msi_alloc( (strlenW(szFileType_fmt) + strlenW(cls->clsid) + 4) * sizeof(WCHAR)); 00943 sprintfW( keyname, szFileType_fmt, cls->clsid, index ); 00944 00945 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, ptr ); 00946 msi_free(keyname); 00947 00948 if (ptr2) 00949 ptr = ptr2+1; 00950 else 00951 ptr = NULL; 00952 00953 index ++; 00954 } 00955 } 00956 00957 uirow = MSI_CreateRecord(1); 00958 MSI_RecordSetStringW( uirow, 1, cls->clsid ); 00959 msi_ui_actiondata( package, szRegisterClassInfo, uirow ); 00960 msiobj_release(&uirow->hdr); 00961 } 00962 RegCloseKey(hkey); 00963 return ERROR_SUCCESS; 00964 } 00965 00966 UINT ACTION_UnregisterClassInfo( MSIPACKAGE *package ) 00967 { 00968 static const WCHAR szFileType[] = {'F','i','l','e','T','y','p','e','\\',0}; 00969 const WCHAR *keypath; 00970 MSIRECORD *uirow; 00971 MSICLASS *cls; 00972 HKEY hkey, hkey2; 00973 UINT r; 00974 00975 r = load_classes_and_such( package ); 00976 if (r != ERROR_SUCCESS) 00977 return r; 00978 00979 if (is_64bit && package->platform == PLATFORM_INTEL) 00980 keypath = szWow6432NodeCLSID; 00981 else 00982 keypath = szCLSID; 00983 00984 if (RegOpenKeyW( HKEY_CLASSES_ROOT, keypath, &hkey ) != ERROR_SUCCESS) 00985 return ERROR_SUCCESS; 00986 00987 LIST_FOR_EACH_ENTRY( cls, &package->classes, MSICLASS, entry ) 00988 { 00989 MSIFEATURE *feature; 00990 MSICOMPONENT *comp; 00991 LPWSTR filetype; 00992 LONG res; 00993 00994 comp = cls->Component; 00995 if (!comp) 00996 continue; 00997 00998 if (!comp->Enabled) 00999 { 01000 TRACE("component is disabled\n"); 01001 continue; 01002 } 01003 01004 feature = cls->Feature; 01005 if (!feature) 01006 continue; 01007 01008 feature->Action = msi_get_feature_action( package, feature ); 01009 if (feature->Action != INSTALLSTATE_ABSENT) 01010 { 01011 TRACE("feature %s not scheduled for removal, skipping unregistration of class %s\n", 01012 debugstr_w(feature->Feature), debugstr_w(cls->clsid)); 01013 continue; 01014 } 01015 TRACE("Unregistering class %s (%p)\n", debugstr_w(cls->clsid), cls); 01016 01017 cls->Installed = FALSE; 01018 mark_progid_for_uninstall( package, cls->ProgID ); 01019 01020 res = RegDeleteTreeW( hkey, cls->clsid ); 01021 if (res != ERROR_SUCCESS) 01022 WARN("Failed to delete class key %d\n", res); 01023 01024 if (cls->AppID) 01025 { 01026 res = RegOpenKeyW( HKEY_CLASSES_ROOT, szAppID, &hkey2 ); 01027 if (res == ERROR_SUCCESS) 01028 { 01029 res = RegDeleteKeyW( hkey2, cls->AppID->AppID ); 01030 if (res != ERROR_SUCCESS) 01031 WARN("Failed to delete appid key %d\n", res); 01032 RegCloseKey( hkey2 ); 01033 } 01034 } 01035 if (cls->FileTypeMask) 01036 { 01037 filetype = msi_alloc( (strlenW( szFileType ) + strlenW( cls->clsid ) + 1) * sizeof(WCHAR) ); 01038 if (filetype) 01039 { 01040 strcpyW( filetype, szFileType ); 01041 strcatW( filetype, cls->clsid ); 01042 res = RegDeleteTreeW( HKEY_CLASSES_ROOT, filetype ); 01043 msi_free( filetype ); 01044 01045 if (res != ERROR_SUCCESS) 01046 WARN("Failed to delete file type %d\n", res); 01047 } 01048 } 01049 01050 uirow = MSI_CreateRecord( 1 ); 01051 MSI_RecordSetStringW( uirow, 1, cls->clsid ); 01052 msi_ui_actiondata( package, szUnregisterClassInfo, uirow ); 01053 msiobj_release( &uirow->hdr ); 01054 } 01055 RegCloseKey( hkey ); 01056 return ERROR_SUCCESS; 01057 } 01058 01059 static LPCWSTR get_clsid_of_progid( const MSIPROGID *progid ) 01060 { 01061 while (progid) 01062 { 01063 if (progid->Class) 01064 return progid->Class->clsid; 01065 if (progid->Parent == progid) 01066 break; 01067 progid = progid->Parent; 01068 } 01069 return NULL; 01070 } 01071 01072 static UINT register_progid( const MSIPROGID* progid ) 01073 { 01074 static const WCHAR szCurVer[] = {'C','u','r','V','e','r',0}; 01075 HKEY hkey = 0; 01076 UINT rc; 01077 01078 rc = RegCreateKeyW( HKEY_CLASSES_ROOT, progid->ProgID, &hkey ); 01079 if (rc == ERROR_SUCCESS) 01080 { 01081 LPCWSTR clsid = get_clsid_of_progid( progid ); 01082 01083 if (clsid) 01084 msi_reg_set_subkey_val( hkey, szCLSID, NULL, clsid ); 01085 else 01086 TRACE("%s has no class\n", debugstr_w( progid->ProgID ) ); 01087 01088 if (progid->Description) 01089 msi_reg_set_val_str( hkey, NULL, progid->Description ); 01090 01091 if (progid->IconPath) 01092 msi_reg_set_subkey_val( hkey, szDefaultIcon, NULL, progid->IconPath ); 01093 01094 /* write out the current version */ 01095 if (progid->CurVer) 01096 msi_reg_set_subkey_val( hkey, szCurVer, NULL, progid->CurVer->ProgID ); 01097 01098 RegCloseKey(hkey); 01099 } 01100 else 01101 ERR("failed to create key %s\n", debugstr_w( progid->ProgID ) ); 01102 01103 return rc; 01104 } 01105 01106 UINT ACTION_RegisterProgIdInfo(MSIPACKAGE *package) 01107 { 01108 MSIPROGID *progid; 01109 MSIRECORD *uirow; 01110 UINT r; 01111 01112 r = load_classes_and_such( package ); 01113 if (r != ERROR_SUCCESS) 01114 return r; 01115 01116 LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry ) 01117 { 01118 /* check if this progid is to be installed */ 01119 if (progid->Class && progid->Class->Installed) 01120 progid->InstallMe = TRUE; 01121 01122 if (!progid->InstallMe) 01123 { 01124 TRACE("progid %s not scheduled to be installed\n", 01125 debugstr_w(progid->ProgID)); 01126 continue; 01127 } 01128 01129 TRACE("Registering progid %s\n", debugstr_w(progid->ProgID)); 01130 01131 register_progid( progid ); 01132 01133 uirow = MSI_CreateRecord( 1 ); 01134 MSI_RecordSetStringW( uirow, 1, progid->ProgID ); 01135 msi_ui_actiondata( package, szRegisterProgIdInfo, uirow ); 01136 msiobj_release( &uirow->hdr ); 01137 } 01138 return ERROR_SUCCESS; 01139 } 01140 01141 UINT ACTION_UnregisterProgIdInfo( MSIPACKAGE *package ) 01142 { 01143 MSIPROGID *progid; 01144 MSIRECORD *uirow; 01145 LONG res; 01146 UINT r; 01147 01148 r = load_classes_and_such( package ); 01149 if (r != ERROR_SUCCESS) 01150 return r; 01151 01152 LIST_FOR_EACH_ENTRY( progid, &package->progids, MSIPROGID, entry ) 01153 { 01154 /* check if this progid is to be removed */ 01155 if (progid->Class && !progid->Class->Installed) 01156 progid->InstallMe = FALSE; 01157 01158 if (progid->InstallMe) 01159 { 01160 TRACE("progid %s not scheduled to be removed\n", debugstr_w(progid->ProgID)); 01161 continue; 01162 } 01163 01164 TRACE("Unregistering progid %s\n", debugstr_w(progid->ProgID)); 01165 01166 res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid->ProgID ); 01167 if (res != ERROR_SUCCESS) 01168 TRACE("Failed to delete progid key %d\n", res); 01169 01170 uirow = MSI_CreateRecord( 1 ); 01171 MSI_RecordSetStringW( uirow, 1, progid->ProgID ); 01172 msi_ui_actiondata( package, szUnregisterProgIdInfo, uirow ); 01173 msiobj_release( &uirow->hdr ); 01174 } 01175 return ERROR_SUCCESS; 01176 } 01177 01178 static UINT register_verb(MSIPACKAGE *package, LPCWSTR progid, 01179 MSICOMPONENT* component, const MSIEXTENSION* extension, 01180 MSIVERB* verb, INT* Sequence ) 01181 { 01182 LPWSTR keyname; 01183 HKEY key; 01184 static const WCHAR szShell[] = {'s','h','e','l','l',0}; 01185 static const WCHAR szCommand[] = {'c','o','m','m','a','n','d',0}; 01186 static const WCHAR fmt[] = {'\"','%','s','\"',' ','%','s',0}; 01187 static const WCHAR fmt2[] = {'\"','%','s','\"',0}; 01188 LPWSTR command; 01189 DWORD size; 01190 LPWSTR advertise; 01191 01192 keyname = msi_build_directory_name(4, progid, szShell, verb->Verb, szCommand); 01193 01194 TRACE("Making Key %s\n",debugstr_w(keyname)); 01195 RegCreateKeyW(HKEY_CLASSES_ROOT, keyname, &key); 01196 size = strlenW(component->FullKeypath); 01197 if (verb->Argument) 01198 size += strlenW(verb->Argument); 01199 size += 4; 01200 01201 command = msi_alloc(size * sizeof (WCHAR)); 01202 if (verb->Argument) 01203 sprintfW(command, fmt, component->FullKeypath, verb->Argument); 01204 else 01205 sprintfW(command, fmt2, component->FullKeypath); 01206 01207 msi_reg_set_val_str( key, NULL, command ); 01208 msi_free(command); 01209 01210 advertise = msi_create_component_advertise_string(package, component, 01211 extension->Feature->Feature); 01212 size = strlenW(advertise); 01213 01214 if (verb->Argument) 01215 size += strlenW(verb->Argument); 01216 size += 4; 01217 01218 command = msi_alloc_zero(size * sizeof (WCHAR)); 01219 01220 strcpyW(command,advertise); 01221 if (verb->Argument) 01222 { 01223 strcatW(command,szSpace); 01224 strcatW(command,verb->Argument); 01225 } 01226 01227 msi_reg_set_val_multi_str( key, szCommand, command ); 01228 01229 RegCloseKey(key); 01230 msi_free(keyname); 01231 msi_free(advertise); 01232 msi_free(command); 01233 01234 if (verb->Command) 01235 { 01236 keyname = msi_build_directory_name( 3, progid, szShell, verb->Verb ); 01237 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Command ); 01238 msi_free(keyname); 01239 } 01240 01241 if (verb->Sequence != MSI_NULL_INTEGER) 01242 { 01243 if (*Sequence == MSI_NULL_INTEGER || verb->Sequence < *Sequence) 01244 { 01245 *Sequence = verb->Sequence; 01246 keyname = msi_build_directory_name( 2, progid, szShell ); 01247 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, keyname, NULL, verb->Verb ); 01248 msi_free(keyname); 01249 } 01250 } 01251 return ERROR_SUCCESS; 01252 } 01253 01254 UINT ACTION_RegisterExtensionInfo(MSIPACKAGE *package) 01255 { 01256 static const WCHAR szContentType[] = {'C','o','n','t','e','n','t',' ','T','y','p','e',0}; 01257 HKEY hkey = NULL; 01258 MSIEXTENSION *ext; 01259 MSIRECORD *uirow; 01260 BOOL install_on_demand = TRUE; 01261 LONG res; 01262 UINT r; 01263 01264 r = load_classes_and_such( package ); 01265 if (r != ERROR_SUCCESS) 01266 return r; 01267 01268 /* We need to set install_on_demand based on if the shell handles advertised 01269 * shortcuts and the like. Because Mike McCormack is working on this i am 01270 * going to default to TRUE 01271 */ 01272 01273 LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry ) 01274 { 01275 LPWSTR extension; 01276 MSIFEATURE *feature; 01277 01278 if (!ext->Component) 01279 continue; 01280 01281 if (!ext->Component->Enabled) 01282 { 01283 TRACE("component is disabled\n"); 01284 continue; 01285 } 01286 01287 feature = ext->Feature; 01288 if (!feature) 01289 continue; 01290 01291 /* 01292 * yes. MSDN says that these are based on _Feature_ not on 01293 * Component. So verify the feature is to be installed 01294 */ 01295 feature->Action = msi_get_feature_action( package, feature ); 01296 if (feature->Action != INSTALLSTATE_LOCAL && 01297 !(install_on_demand && feature->Action == INSTALLSTATE_ADVERTISED)) 01298 { 01299 TRACE("feature %s not scheduled for installation, skipping registration of extension %s\n", 01300 debugstr_w(feature->Feature), debugstr_w(ext->Extension)); 01301 continue; 01302 } 01303 TRACE("Registering extension %s (%p)\n", debugstr_w(ext->Extension), ext); 01304 01305 ext->Installed = TRUE; 01306 01307 /* this is only registered if the extension has at least 1 verb 01308 * according to MSDN 01309 */ 01310 if (ext->ProgID && !list_empty( &ext->verbs ) ) 01311 mark_progid_for_install( package, ext->ProgID ); 01312 01313 mark_mime_for_install(ext->Mime); 01314 01315 extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) ); 01316 if (extension) 01317 { 01318 extension[0] = '.'; 01319 strcpyW( extension + 1, ext->Extension ); 01320 res = RegCreateKeyW( HKEY_CLASSES_ROOT, extension, &hkey ); 01321 msi_free( extension ); 01322 if (res != ERROR_SUCCESS) 01323 WARN("Failed to create extension key %d\n", res); 01324 } 01325 01326 if (ext->Mime) 01327 msi_reg_set_val_str( hkey, szContentType, ext->Mime->ContentType ); 01328 01329 if (ext->ProgID || ext->ProgIDText) 01330 { 01331 static const WCHAR szSN[] = 01332 {'\\','S','h','e','l','l','N','e','w',0}; 01333 HKEY hkey2; 01334 LPWSTR newkey; 01335 LPCWSTR progid; 01336 MSIVERB *verb; 01337 INT Sequence = MSI_NULL_INTEGER; 01338 01339 if (ext->ProgID) 01340 progid = ext->ProgID->ProgID; 01341 else 01342 progid = ext->ProgIDText; 01343 01344 msi_reg_set_val_str( hkey, NULL, progid ); 01345 01346 newkey = msi_alloc( (strlenW(progid)+strlenW(szSN)+1) * sizeof(WCHAR)); 01347 01348 strcpyW(newkey,progid); 01349 strcatW(newkey,szSN); 01350 RegCreateKeyW(hkey,newkey,&hkey2); 01351 RegCloseKey(hkey2); 01352 01353 msi_free(newkey); 01354 01355 /* do all the verbs */ 01356 LIST_FOR_EACH_ENTRY( verb, &ext->verbs, MSIVERB, entry ) 01357 { 01358 register_verb( package, progid, ext->Component, 01359 ext, verb, &Sequence); 01360 } 01361 } 01362 01363 RegCloseKey(hkey); 01364 01365 uirow = MSI_CreateRecord(1); 01366 MSI_RecordSetStringW( uirow, 1, ext->Extension ); 01367 msi_ui_actiondata( package, szRegisterExtensionInfo, uirow ); 01368 msiobj_release(&uirow->hdr); 01369 } 01370 return ERROR_SUCCESS; 01371 } 01372 01373 UINT ACTION_UnregisterExtensionInfo( MSIPACKAGE *package ) 01374 { 01375 MSIEXTENSION *ext; 01376 MSIRECORD *uirow; 01377 LONG res; 01378 UINT r; 01379 01380 r = load_classes_and_such( package ); 01381 if (r != ERROR_SUCCESS) 01382 return r; 01383 01384 LIST_FOR_EACH_ENTRY( ext, &package->extensions, MSIEXTENSION, entry ) 01385 { 01386 LPWSTR extension; 01387 MSIFEATURE *feature; 01388 01389 if (!ext->Component) 01390 continue; 01391 01392 if (!ext->Component->Enabled) 01393 { 01394 TRACE("component is disabled\n"); 01395 continue; 01396 } 01397 01398 feature = ext->Feature; 01399 if (!feature) 01400 continue; 01401 01402 feature->Action = msi_get_feature_action( package, feature ); 01403 if (feature->Action != INSTALLSTATE_ABSENT) 01404 { 01405 TRACE("feature %s not scheduled for removal, skipping unregistration of extension %s\n", 01406 debugstr_w(feature->Feature), debugstr_w(ext->Extension)); 01407 continue; 01408 } 01409 TRACE("Unregistering extension %s\n", debugstr_w(ext->Extension)); 01410 01411 ext->Installed = FALSE; 01412 01413 if (ext->ProgID && !list_empty( &ext->verbs )) 01414 mark_progid_for_uninstall( package, ext->ProgID ); 01415 01416 mark_mime_for_uninstall( ext->Mime ); 01417 01418 extension = msi_alloc( (strlenW( ext->Extension ) + 2) * sizeof(WCHAR) ); 01419 if (extension) 01420 { 01421 extension[0] = '.'; 01422 strcpyW( extension + 1, ext->Extension ); 01423 res = RegDeleteTreeW( HKEY_CLASSES_ROOT, extension ); 01424 msi_free( extension ); 01425 if (res != ERROR_SUCCESS) 01426 WARN("Failed to delete extension key %d\n", res); 01427 } 01428 01429 if (ext->ProgID || ext->ProgIDText) 01430 { 01431 static const WCHAR shellW[] = {'\\','s','h','e','l','l',0}; 01432 LPCWSTR progid; 01433 LPWSTR progid_shell; 01434 01435 if (ext->ProgID) 01436 progid = ext->ProgID->ProgID; 01437 else 01438 progid = ext->ProgIDText; 01439 01440 progid_shell = msi_alloc( (strlenW( progid ) + strlenW( shellW ) + 1) * sizeof(WCHAR) ); 01441 if (progid_shell) 01442 { 01443 strcpyW( progid_shell, progid ); 01444 strcatW( progid_shell, shellW ); 01445 res = RegDeleteTreeW( HKEY_CLASSES_ROOT, progid_shell ); 01446 msi_free( progid_shell ); 01447 if (res != ERROR_SUCCESS) 01448 WARN("Failed to delete shell key %d\n", res); 01449 RegDeleteKeyW( HKEY_CLASSES_ROOT, progid ); 01450 } 01451 } 01452 01453 uirow = MSI_CreateRecord( 1 ); 01454 MSI_RecordSetStringW( uirow, 1, ext->Extension ); 01455 msi_ui_actiondata( package, szUnregisterExtensionInfo, uirow ); 01456 msiobj_release( &uirow->hdr ); 01457 } 01458 return ERROR_SUCCESS; 01459 } 01460 01461 UINT ACTION_RegisterMIMEInfo(MSIPACKAGE *package) 01462 { 01463 static const WCHAR szExtension[] = {'E','x','t','e','n','s','i','o','n',0}; 01464 MSIRECORD *uirow; 01465 MSIMIME *mt; 01466 UINT r; 01467 01468 r = load_classes_and_such( package ); 01469 if (r != ERROR_SUCCESS) 01470 return r; 01471 01472 LIST_FOR_EACH_ENTRY( mt, &package->mimes, MSIMIME, entry ) 01473 { 01474 LPWSTR extension, key; 01475 01476 /* 01477 * check if the MIME is to be installed. Either as requested by an 01478 * extension or Class 01479 */ 01480 mt->InstallMe = (mt->InstallMe || 01481 (mt->Class && mt->Class->Installed) || 01482 (mt->Extension && mt->Extension->Installed)); 01483 01484 if (!mt->InstallMe) 01485 { 01486 TRACE("MIME %s not scheduled to be installed\n", debugstr_w(mt->ContentType)); 01487 continue; 01488 } 01489 01490 TRACE("Registering MIME type %s\n", debugstr_w(mt->ContentType)); 01491 01492 extension = msi_alloc( (strlenW( mt->Extension->Extension ) + 2) * sizeof(WCHAR) ); 01493 key = msi_alloc( (strlenW( mt->ContentType ) + strlenW( szMIMEDatabase ) + 1) * sizeof(WCHAR) ); 01494 01495 if (extension && key) 01496 { 01497 extension[0] = '.'; 01498 strcpyW( extension + 1, mt->Extension->Extension ); 01499 01500 strcpyW( key, szMIMEDatabase ); 01501 strcatW( key, mt->ContentType ); 01502 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szExtension, extension ); 01503 01504 if (mt->clsid) 01505 msi_reg_set_subkey_val( HKEY_CLASSES_ROOT, key, szCLSID, mt->clsid ); 01506 } 01507 msi_free( extension ); 01508 msi_free( key ); 01509 01510 uirow = MSI_CreateRecord( 2 ); 01511 MSI_RecordSetStringW( uirow, 1, mt->ContentType ); 01512 MSI_RecordSetStringW( uirow, 2, mt->suffix ); 01513 msi_ui_actiondata( package, szRegisterMIMEInfo, uirow ); 01514 msiobj_release( &uirow->hdr ); 01515 } 01516 return ERROR_SUCCESS; 01517 } 01518 01519 UINT ACTION_UnregisterMIMEInfo( MSIPACKAGE *package ) 01520 { 01521 MSIRECORD *uirow; 01522 MSIMIME *mime; 01523 UINT r; 01524 01525 r = load_classes_and_such( package ); 01526 if (r != ERROR_SUCCESS) 01527 return r; 01528 01529 LIST_FOR_EACH_ENTRY( mime, &package->mimes, MSIMIME, entry ) 01530 { 01531 LONG res; 01532 LPWSTR mime_key; 01533 01534 mime->InstallMe = (mime->InstallMe || 01535 (mime->Class && mime->Class->Installed) || 01536 (mime->Extension && mime->Extension->Installed)); 01537 01538 if (mime->InstallMe) 01539 { 01540 TRACE("MIME %s not scheduled to be removed\n", debugstr_w(mime->ContentType)); 01541 continue; 01542 } 01543 01544 TRACE("Unregistering MIME type %s\n", debugstr_w(mime->ContentType)); 01545 01546 mime_key = msi_alloc( (strlenW( szMIMEDatabase ) + strlenW( mime->ContentType ) + 1) * sizeof(WCHAR) ); 01547 if (mime_key) 01548 { 01549 strcpyW( mime_key, szMIMEDatabase ); 01550 strcatW( mime_key, mime->ContentType ); 01551 res = RegDeleteKeyW( HKEY_CLASSES_ROOT, mime_key ); 01552 if (res != ERROR_SUCCESS) 01553 WARN("Failed to delete MIME key %d\n", res); 01554 msi_free( mime_key ); 01555 } 01556 01557 uirow = MSI_CreateRecord( 2 ); 01558 MSI_RecordSetStringW( uirow, 1, mime->ContentType ); 01559 MSI_RecordSetStringW( uirow, 2, mime->suffix ); 01560 msi_ui_actiondata( package, szUnregisterMIMEInfo, uirow ); 01561 msiobj_release( &uirow->hdr ); 01562 } 01563 return ERROR_SUCCESS; 01564 } Generated on Sun May 27 2012 04:25:13 for ReactOS by
1.7.6.1
|