1 /* 2 * Copyright 2016 Michael Müller 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #define COBJMACROS 20 21 #include "config.h" 22 23 #include <stdarg.h> 24 #include <string.h> 25 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winuser.h" 29 #include "ole2.h" 30 #include "rpcproxy.h" 31 #include "inseng.h" 32 33 #include "inseng_private.h" 34 35 #include "wine/list.h" 36 #include "wine/debug.h" 37 38 WINE_DEFAULT_DEBUG_CHANNEL(inseng); 39 40 #define DEFAULT_INSTALLER_DESC "Active Setup Installation" 41 42 struct cifgroup 43 { 44 ICifGroup ICifGroup_iface; 45 46 struct list entry; 47 48 ICifFile *parent; 49 50 char *id; 51 char *description; 52 DWORD priority; 53 }; 54 55 struct ciffenum_components 56 { 57 IEnumCifComponents IEnumCifComponents_iface; 58 LONG ref; 59 60 ICifFile *file; 61 struct list *start; 62 struct list *position; 63 64 char *group_id; 65 }; 66 67 struct ciffenum_groups 68 { 69 IEnumCifGroups IEnumCifGroups_iface; 70 LONG ref; 71 72 ICifFile *file; 73 struct list *start; 74 struct list *position; 75 }; 76 77 struct url_info 78 { 79 struct list entry; 80 INT index; 81 char *url; 82 DWORD flags; 83 }; 84 85 struct dependency_info 86 { 87 struct list entry; 88 char *id; 89 char *type; 90 }; 91 92 struct cifcomponent 93 { 94 ICifComponent ICifComponent_iface; 95 96 struct list entry; 97 98 ICifFile *parent; 99 100 char *id; 101 char *guid; 102 char *description; 103 char *details; 104 char *group; 105 106 107 DWORD version; 108 DWORD build; 109 char *patchid; 110 111 char *locale; 112 char *key_uninstall; 113 114 DWORD size_win; 115 DWORD size_app; 116 DWORD size_download; 117 DWORD size_extracted; 118 119 char *key_success; 120 char *key_progress; 121 char *key_cancel; 122 123 DWORD as_aware; 124 DWORD reboot; 125 DWORD admin; 126 DWORD visibleui; 127 128 DWORD priority; 129 DWORD platform; 130 131 struct list dependencies; 132 struct list urls; 133 134 /* mode */ 135 /* det version */ 136 /* one component */ 137 /* custom data */ 138 139 /* in memory state */ 140 DWORD queue_state; 141 DWORD current_priority; 142 DWORD size_actual_download; 143 BOOL downloaded; 144 BOOL installed; 145 }; 146 147 struct ciffile 148 { 149 ICifFile ICifFile_iface; 150 LONG ref; 151 152 struct list components; 153 struct list groups; 154 155 char *name; 156 }; 157 158 static inline struct ciffile *impl_from_ICiffile(ICifFile *iface) 159 { 160 return CONTAINING_RECORD(iface, struct ciffile, ICifFile_iface); 161 } 162 163 static inline struct cifcomponent *impl_from_ICifComponent(ICifComponent *iface) 164 { 165 return CONTAINING_RECORD(iface, struct cifcomponent, ICifComponent_iface); 166 } 167 168 static inline struct cifgroup *impl_from_ICifGroup(ICifGroup *iface) 169 { 170 return CONTAINING_RECORD(iface, struct cifgroup, ICifGroup_iface); 171 } 172 173 static inline struct ciffenum_components *impl_from_IEnumCifComponents(IEnumCifComponents *iface) 174 { 175 return CONTAINING_RECORD(iface, struct ciffenum_components, IEnumCifComponents_iface); 176 } 177 178 static inline struct ciffenum_groups *impl_from_IEnumCifGroups(IEnumCifGroups *iface) 179 { 180 return CONTAINING_RECORD(iface, struct ciffenum_groups, IEnumCifGroups_iface); 181 } 182 183 static HRESULT enum_components_create(ICifFile *file, struct list *start, char *group_id, IEnumCifComponents **iface); 184 185 static HRESULT copy_substring_null(char *dest, int max_len, char *src) 186 { 187 if (!src) 188 return E_FAIL; 189 190 if (max_len <= 0) 191 return S_OK; 192 193 if (!dest) 194 return E_FAIL; 195 196 while (*src && max_len-- > 1) 197 *dest++ = *src++; 198 *dest = 0; 199 200 return S_OK; 201 } 202 203 static void url_entry_free(struct url_info *url) 204 { 205 heap_free(url->url); 206 heap_free(url); 207 } 208 209 static void dependency_entry_free(struct dependency_info *dependency) 210 { 211 heap_free(dependency->id); 212 heap_free(dependency); 213 } 214 215 static void component_free(struct cifcomponent *comp) 216 { 217 struct dependency_info *dependency, *dependency_next; 218 struct url_info *url, *url_next; 219 220 heap_free(comp->id); 221 heap_free(comp->guid); 222 heap_free(comp->description); 223 heap_free(comp->details); 224 heap_free(comp->group); 225 226 heap_free(comp->patchid); 227 228 heap_free(comp->locale); 229 heap_free(comp->key_uninstall); 230 231 heap_free(comp->key_success); 232 heap_free(comp->key_progress); 233 heap_free(comp->key_cancel); 234 235 LIST_FOR_EACH_ENTRY_SAFE(dependency, dependency_next, &comp->dependencies, struct dependency_info, entry) 236 { 237 list_remove(&dependency->entry); 238 dependency_entry_free(dependency); 239 } 240 241 LIST_FOR_EACH_ENTRY_SAFE(url, url_next, &comp->urls, struct url_info, entry) 242 { 243 list_remove(&url->entry); 244 url_entry_free(url); 245 } 246 247 heap_free(comp); 248 } 249 250 static void group_free(struct cifgroup *group) 251 { 252 heap_free(group->id); 253 heap_free(group->description); 254 heap_free(group); 255 } 256 257 static HRESULT WINAPI group_GetID(ICifGroup *iface, char *id, DWORD size) 258 { 259 struct cifgroup *This = impl_from_ICifGroup(iface); 260 261 TRACE("(%p)->(%p, %u)\n", This, id, size); 262 263 return copy_substring_null(id, size, This->id); 264 } 265 266 static HRESULT WINAPI group_GetDescription(ICifGroup *iface, char *desc, DWORD size) 267 { 268 struct cifgroup *This = impl_from_ICifGroup(iface); 269 270 TRACE("(%p)->(%p, %u)\n", This, desc, size); 271 272 return copy_substring_null(desc, size, This->description); 273 } 274 275 static DWORD WINAPI group_GetPriority(ICifGroup *iface) 276 { 277 struct cifgroup *This = impl_from_ICifGroup(iface); 278 279 TRACE("(%p)\n", This); 280 281 return This->priority; 282 } 283 284 static HRESULT WINAPI group_EnumComponents(ICifGroup *iface, IEnumCifComponents **enum_components, DWORD filter, LPVOID pv) 285 { 286 struct cifgroup *This = impl_from_ICifGroup(iface); 287 struct ciffile *file; 288 289 TRACE("(%p)->(%p, %u, %p)\n", This, enum_components, filter, pv); 290 291 if (filter) 292 FIXME("filter (%x) not supported\n", filter); 293 if (pv) 294 FIXME("how to handle pv (%p)?\n", pv); 295 296 file = impl_from_ICiffile(This->parent); 297 return enum_components_create(This->parent, &file->components, This->id, enum_components); 298 } 299 300 static DWORD WINAPI group_GetCurrentPriority(ICifGroup *iface) 301 { 302 struct cifgroup *This = impl_from_ICifGroup(iface); 303 304 FIXME("(%p): stub\n", This); 305 306 return 0; 307 } 308 309 static const ICifGroupVtbl cifgroupVtbl = 310 { 311 group_GetID, 312 group_GetDescription, 313 group_GetPriority, 314 group_EnumComponents, 315 group_GetCurrentPriority, 316 }; 317 318 void component_set_actual_download_size(ICifComponent *iface, DWORD size) 319 { 320 struct cifcomponent *This = impl_from_ICifComponent(iface); 321 322 This->size_actual_download = size; 323 } 324 325 void component_set_downloaded(ICifComponent *iface, BOOL value) 326 { 327 struct cifcomponent *This = impl_from_ICifComponent(iface); 328 329 This->downloaded = value; 330 } 331 332 void component_set_installed(ICifComponent *iface, BOOL value) 333 { 334 struct cifcomponent *This = impl_from_ICifComponent(iface); 335 336 This->installed = value; 337 } 338 339 char *component_get_id(ICifComponent *iface) 340 { 341 struct cifcomponent *This = impl_from_ICifComponent(iface); 342 343 return This->id; 344 } 345 346 static HRESULT WINAPI component_GetID(ICifComponent *iface, char *id, DWORD size) 347 { 348 struct cifcomponent *This = impl_from_ICifComponent(iface); 349 350 TRACE("(%p)->(%p, %u)\n", This, id, size); 351 352 return copy_substring_null(id, size, This->id); 353 } 354 355 static HRESULT WINAPI component_GetGUID(ICifComponent *iface, char *guid, DWORD size) 356 { 357 struct cifcomponent *This = impl_from_ICifComponent(iface); 358 359 TRACE("(%p)->(%p, %u)\n", This, guid, size); 360 361 return copy_substring_null(guid, size, This->guid); 362 } 363 364 static HRESULT WINAPI component_GetDescription(ICifComponent *iface, char *desc, DWORD size) 365 { 366 struct cifcomponent *This = impl_from_ICifComponent(iface); 367 368 TRACE("(%p)->(%p, %u)\n", This, desc, size); 369 370 return copy_substring_null(desc, size, This->description); 371 } 372 373 static HRESULT WINAPI component_GetDetails(ICifComponent *iface, char *details, DWORD size) 374 { 375 struct cifcomponent *This = impl_from_ICifComponent(iface); 376 377 TRACE("(%p)->(%p, %u)\n", This, details, size); 378 379 return copy_substring_null(details, size, This->details); 380 } 381 382 static HRESULT WINAPI component_GetUrl(ICifComponent *iface, UINT index, char *url, DWORD size, DWORD *flags) 383 { 384 struct cifcomponent *This = impl_from_ICifComponent(iface); 385 struct url_info *entry; 386 387 TRACE("(%p)->(%u, %p, %u, %p)\n", This, index, url, size, flags); 388 389 /* FIXME: check how functions behaves for url == NULL */ 390 391 if (!flags) 392 return E_FAIL; 393 394 LIST_FOR_EACH_ENTRY(entry, &This->urls, struct url_info, entry) 395 { 396 if (entry->index != index) 397 continue; 398 399 *flags = entry->flags; 400 return copy_substring_null(url, size, entry->url); 401 } 402 403 return E_FAIL; 404 } 405 406 static HRESULT WINAPI component_GetFileExtractList(ICifComponent *iface, UINT index, char *list, DWORD size) 407 { 408 struct cifcomponent *This = impl_from_ICifComponent(iface); 409 410 FIXME("(%p)->(%u, %p, %u): stub\n", This, index, list, size); 411 412 return E_NOTIMPL; 413 } 414 415 static HRESULT WINAPI component_GetUrlCheckRange(ICifComponent *iface, UINT index, DWORD *min, DWORD *max) 416 { 417 struct cifcomponent *This = impl_from_ICifComponent(iface); 418 419 FIXME("(%p)->(%u, %p, %p): stub\n", This, index, min, max); 420 421 return E_NOTIMPL; 422 } 423 424 static HRESULT WINAPI component_GetCommand(ICifComponent *iface, UINT index, char *cmd, DWORD cmd_size, char *switches, DWORD switch_size, DWORD *type) 425 { 426 struct cifcomponent *This = impl_from_ICifComponent(iface); 427 428 FIXME("(%p)->(%u, %p, %u, %p, %u, %p): stub\n", This, index, cmd, cmd_size, switches, switch_size, type); 429 430 return E_NOTIMPL; 431 } 432 433 static HRESULT WINAPI component_GetVersion(ICifComponent *iface, DWORD *version, DWORD *build) 434 { 435 struct cifcomponent *This = impl_from_ICifComponent(iface); 436 437 TRACE("(%p)->(%p, %p)\n", This, version, build); 438 439 if (!version || !build) 440 return E_FAIL; 441 442 *version = This->version; 443 *build = This->build; 444 445 return S_OK; 446 } 447 448 static HRESULT WINAPI component_GetLocale(ICifComponent *iface, char *locale, DWORD size) 449 { 450 struct cifcomponent *This = impl_from_ICifComponent(iface); 451 452 TRACE("(%p)->(%p, %u)\n", This, locale, size); 453 454 return copy_substring_null(locale, size, This->locale); 455 } 456 457 static HRESULT WINAPI component_GetUninstallKey(ICifComponent *iface, char *key, DWORD size) 458 { 459 struct cifcomponent *This = impl_from_ICifComponent(iface); 460 461 TRACE("(%p)->(%p, %u)\n", This, key, size); 462 463 return copy_substring_null(key, size, This->key_uninstall); 464 } 465 466 static HRESULT WINAPI component_GetInstalledSize(ICifComponent *iface, DWORD *win, DWORD *app) 467 { 468 struct cifcomponent *This = impl_from_ICifComponent(iface); 469 470 TRACE("(%p)->(%p, %p)\n", This, win, app); 471 472 if (!win || !app) 473 return E_FAIL; 474 475 *win = This->size_win; 476 *app = This->size_app; 477 478 return S_OK; 479 } 480 481 static DWORD WINAPI component_GetDownloadSize(ICifComponent *iface) 482 { 483 struct cifcomponent *This = impl_from_ICifComponent(iface); 484 485 TRACE("(%p)\n", This); 486 487 return This->size_download; 488 } 489 490 static DWORD WINAPI component_GetExtractSize(ICifComponent *iface) 491 { 492 struct cifcomponent *This = impl_from_ICifComponent(iface); 493 494 TRACE("(%p)\n", This); 495 496 return This->size_extracted; 497 } 498 499 static HRESULT WINAPI component_GetSuccessKey(ICifComponent *iface, char *key, DWORD size) 500 { 501 struct cifcomponent *This = impl_from_ICifComponent(iface); 502 503 TRACE("(%p)->(%p, %u)\n", This, key, size); 504 505 return copy_substring_null(key, size, This->key_success); 506 } 507 508 static HRESULT WINAPI component_GetProgressKeys(ICifComponent *iface, char *progress, DWORD progress_size, 509 char *cancel, DWORD cancel_size) 510 { 511 struct cifcomponent *This = impl_from_ICifComponent(iface); 512 HRESULT hr; 513 514 TRACE("(%p)->(%p, %u, %p, %u): semi-stub\n", This, progress, progress_size, cancel, cancel_size); 515 516 hr = copy_substring_null(progress, progress_size, This->key_progress); 517 if (hr != S_OK) return hr; 518 519 if (cancel_size > 0 && cancel) 520 *cancel = 0; 521 522 return S_OK; 523 } 524 525 static HRESULT WINAPI component_IsActiveSetupAware(ICifComponent *iface) 526 { 527 struct cifcomponent *This = impl_from_ICifComponent(iface); 528 529 TRACE("(%p)\n", This); 530 531 return This->as_aware ? S_OK : S_FALSE; 532 } 533 534 static HRESULT WINAPI component_IsRebootRequired(ICifComponent *iface) 535 { 536 struct cifcomponent *This = impl_from_ICifComponent(iface); 537 538 TRACE("(%p)\n", This); 539 540 return This->reboot ? S_OK : S_FALSE; 541 } 542 543 static HRESULT WINAPI component_RequiresAdminRights(ICifComponent *iface) 544 { 545 struct cifcomponent *This = impl_from_ICifComponent(iface); 546 547 TRACE("(%p)\n", This); 548 549 return This->admin ? S_OK : S_FALSE; 550 } 551 552 static DWORD WINAPI component_GetPriority(ICifComponent *iface) 553 { 554 struct cifcomponent *This = impl_from_ICifComponent(iface); 555 556 TRACE("(%p)\n", This); 557 558 return This->priority; 559 } 560 561 static HRESULT WINAPI component_GetDependency(ICifComponent *iface, UINT index, char *id, DWORD id_size, char *type, DWORD *ver, DWORD *build) 562 { 563 struct cifcomponent *This = impl_from_ICifComponent(iface); 564 struct dependency_info *entry; 565 ICifComponent *dependency; 566 int pos = 0; 567 568 TRACE("(%p)->(%u, %p, %u, %p, %p, %p)\n", This, index, id, id_size, type, ver, build); 569 570 if (!id || !ver || !build) 571 return E_FAIL; 572 573 LIST_FOR_EACH_ENTRY(entry, &This->dependencies, struct dependency_info, entry) 574 { 575 if (pos++ < index) 576 continue; 577 578 if (ICifFile_FindComponent(This->parent, entry->id, &dependency) == S_OK) 579 { 580 ICifComponent_GetVersion(dependency, ver, build); 581 } 582 else 583 { 584 *ver = -1; 585 *build = -1; 586 } 587 588 if (entry->type) 589 *type = *entry->type; 590 else 591 *type = 'I'; 592 593 return copy_substring_null(id, id_size, entry->id); 594 } 595 596 return E_FAIL; 597 } 598 599 static DWORD WINAPI component_GetPlatform(ICifComponent *iface) 600 { 601 struct cifcomponent *This = impl_from_ICifComponent(iface); 602 603 TRACE("(%p)\n", This); 604 605 return This->platform; 606 } 607 608 static HRESULT WINAPI component_GetMode(ICifComponent *iface, UINT index, char *mode, DWORD size) 609 { 610 struct cifcomponent *This = impl_from_ICifComponent(iface); 611 612 FIXME("(%p)->(%u, %p, %u): stub\n", This, index, mode, size); 613 614 return E_NOTIMPL; 615 } 616 617 static HRESULT WINAPI component_GetGroup(ICifComponent *iface, char *id, DWORD size) 618 { 619 struct cifcomponent *This = impl_from_ICifComponent(iface); 620 621 TRACE("(%p)->(%p, %u)\n", This, id, size); 622 623 return copy_substring_null(id, size, This->group); 624 } 625 626 static HRESULT WINAPI component_IsUIVisible(ICifComponent *iface) 627 { 628 struct cifcomponent *This = impl_from_ICifComponent(iface); 629 630 TRACE("(%p)\n", This); 631 632 return This->visibleui ? S_OK : S_FALSE; 633 } 634 635 static HRESULT WINAPI component_GetPatchID(ICifComponent *iface, char *id, DWORD size) 636 { 637 struct cifcomponent *This = impl_from_ICifComponent(iface); 638 639 TRACE("(%p)->(%p, %u)\n", This, id, size); 640 641 return copy_substring_null(id, size, This->patchid); 642 } 643 644 static HRESULT WINAPI component_GetDetVersion(ICifComponent *iface, char *dll, DWORD dll_size, char *entry, DWORD entry_size) 645 { 646 struct cifcomponent *This = impl_from_ICifComponent(iface); 647 648 FIXME("(%p)->(%p, %u, %p, %u): stub\n", This, dll, dll_size, entry, entry_size); 649 650 return E_NOTIMPL; 651 } 652 653 static HRESULT WINAPI component_GetTreatAsOneComponents(ICifComponent *iface, UINT index, char *id, DWORD size) 654 { 655 struct cifcomponent *This = impl_from_ICifComponent(iface); 656 657 FIXME("(%p)->(%u, %p, %u): stub\n", This, index, id, size); 658 659 return E_NOTIMPL; 660 } 661 662 static HRESULT WINAPI component_GetCustomData(ICifComponent *iface, char *key, char *data, DWORD size) 663 { 664 struct cifcomponent *This = impl_from_ICifComponent(iface); 665 666 FIXME("(%p)->(%s, %p, %u): stub\n", This, debugstr_a(key), data, size); 667 668 return E_NOTIMPL; 669 } 670 671 static DWORD WINAPI component_IsComponentInstalled(ICifComponent *iface) 672 { 673 struct cifcomponent *This = impl_from_ICifComponent(iface); 674 675 TRACE("(%p)\n", This); 676 677 return This->installed; 678 } 679 680 static HRESULT WINAPI component_IsComponentDownloaded(ICifComponent *iface) 681 { 682 struct cifcomponent *This = impl_from_ICifComponent(iface); 683 684 TRACE("(%p)\n", This); 685 686 return This->downloaded ? S_OK : S_FALSE; 687 } 688 689 static DWORD WINAPI component_IsThisVersionInstalled(ICifComponent *iface, DWORD version, DWORD build, DWORD *ret_version, DWORD *ret_build) 690 { 691 struct cifcomponent *This = impl_from_ICifComponent(iface); 692 693 FIXME("(%p)->(%u, %u, %p, %p): stub\n", This, version, build, ret_version, ret_build); 694 695 return 0; 696 } 697 698 static DWORD WINAPI component_GetInstallQueueState(ICifComponent *iface) 699 { 700 struct cifcomponent *This = impl_from_ICifComponent(iface); 701 702 TRACE("(%p)\n", This); 703 704 return This->queue_state; 705 } 706 707 static HRESULT WINAPI component_SetInstallQueueState(ICifComponent *iface, DWORD state) 708 { 709 struct cifcomponent *This = impl_from_ICifComponent(iface); 710 711 TRACE("(%p)->(%u)\n", This, state); 712 713 This->queue_state = state; 714 return S_OK; 715 } 716 717 static DWORD WINAPI component_GetActualDownloadSize(ICifComponent *iface) 718 { 719 struct cifcomponent *This = impl_from_ICifComponent(iface); 720 721 TRACE("(%p)\n", This); 722 723 return This->size_download; 724 } 725 726 static DWORD WINAPI component_GetCurrentPriority(ICifComponent *iface) 727 { 728 struct cifcomponent *This = impl_from_ICifComponent(iface); 729 730 TRACE("(%p)\n", This); 731 732 return This->current_priority; 733 } 734 735 736 static HRESULT WINAPI component_SetCurrentPriority(ICifComponent *iface, DWORD priority) 737 { 738 struct cifcomponent *This = impl_from_ICifComponent(iface); 739 740 TRACE("(%p)->(%u)\n", This, priority); 741 742 This->current_priority = priority; 743 return S_OK; 744 } 745 746 static const ICifComponentVtbl cifcomponentVtbl = 747 { 748 component_GetID, 749 component_GetGUID, 750 component_GetDescription, 751 component_GetDetails, 752 component_GetUrl, 753 component_GetFileExtractList, 754 component_GetUrlCheckRange, 755 component_GetCommand, 756 component_GetVersion, 757 component_GetLocale, 758 component_GetUninstallKey, 759 component_GetInstalledSize, 760 component_GetDownloadSize, 761 component_GetExtractSize, 762 component_GetSuccessKey, 763 component_GetProgressKeys, 764 component_IsActiveSetupAware, 765 component_IsRebootRequired, 766 component_RequiresAdminRights, 767 component_GetPriority, 768 component_GetDependency, 769 component_GetPlatform, 770 component_GetMode, 771 component_GetGroup, 772 component_IsUIVisible, 773 component_GetPatchID, 774 component_GetDetVersion, 775 component_GetTreatAsOneComponents, 776 component_GetCustomData, 777 component_IsComponentInstalled, 778 component_IsComponentDownloaded, 779 component_IsThisVersionInstalled, 780 component_GetInstallQueueState, 781 component_SetInstallQueueState, 782 component_GetActualDownloadSize, 783 component_GetCurrentPriority, 784 component_SetCurrentPriority, 785 }; 786 787 static HRESULT WINAPI enum_components_QueryInterface(IEnumCifComponents *iface, REFIID riid, void **ppv) 788 { 789 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface); 790 791 if (IsEqualGUID(&IID_IUnknown, riid)) 792 { 793 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 794 *ppv = &This->IEnumCifComponents_iface; 795 } 796 /* 797 else if (IsEqualGUID(&IID_IEnumCifComponents, riid)) 798 { 799 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv); 800 *ppv = &This->IEnumCifComponents_iface; 801 } 802 */ 803 else 804 { 805 FIXME("(%p)->(%s %p) not found\n", This, debugstr_guid(riid), ppv); 806 *ppv = NULL; 807 return E_NOINTERFACE; 808 } 809 810 IUnknown_AddRef((IUnknown *)*ppv); 811 return S_OK; 812 } 813 814 static ULONG WINAPI enum_components_AddRef(IEnumCifComponents *iface) 815 { 816 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface); 817 LONG ref = InterlockedIncrement(&This->ref); 818 819 TRACE("(%p) ref=%d\n", This, ref); 820 821 return ref; 822 } 823 824 static ULONG WINAPI enum_components_Release(IEnumCifComponents *iface) 825 { 826 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface); 827 LONG ref = InterlockedDecrement(&This->ref); 828 829 TRACE("(%p) ref=%d\n", This, ref); 830 831 if(!ref) 832 { 833 ICifFile_Release(This->file); 834 heap_free(This); 835 } 836 837 return ref; 838 } 839 840 static HRESULT WINAPI enum_components_Next(IEnumCifComponents *iface, ICifComponent **component) 841 { 842 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface); 843 struct cifcomponent *comp; 844 845 TRACE("(%p)->(%p)\n", This, component); 846 847 if (!component) 848 return E_FAIL; 849 850 if (!This->position) 851 { 852 *component = NULL; 853 return E_FAIL; 854 } 855 856 do 857 { 858 This->position = list_next(This->start, This->position); 859 if (!This->position) 860 { 861 *component = NULL; 862 return E_FAIL; 863 } 864 865 comp = CONTAINING_RECORD(This->position, struct cifcomponent, entry); 866 } while (This->group_id && (!comp->group || strcmp(This->group_id, comp->group))); 867 868 *component = &comp->ICifComponent_iface; 869 return S_OK; 870 } 871 872 static HRESULT WINAPI enum_components_Reset(IEnumCifComponents *iface) 873 { 874 struct ciffenum_components *This = impl_from_IEnumCifComponents(iface); 875 876 TRACE("(%p)\n", This); 877 878 This->position = This->start; 879 return S_OK; 880 } 881 882 static const IEnumCifComponentsVtbl enum_componentsVtbl = 883 { 884 enum_components_QueryInterface, 885 enum_components_AddRef, 886 enum_components_Release, 887 enum_components_Next, 888 enum_components_Reset, 889 }; 890 891 static HRESULT enum_components_create(ICifFile *file, struct list *start, char *group_id, IEnumCifComponents **iface) 892 { 893 struct ciffenum_components *enumerator; 894 895 enumerator = heap_alloc_zero(sizeof(*enumerator)); 896 if (!enumerator) return E_OUTOFMEMORY; 897 898 enumerator->IEnumCifComponents_iface.lpVtbl = &enum_componentsVtbl; 899 enumerator->ref = 1; 900 enumerator->file = file; 901 enumerator->start = start; 902 enumerator->position = start; 903 enumerator->group_id = group_id; 904 905 ICifFile_AddRef(file); 906 907 *iface = &enumerator->IEnumCifComponents_iface; 908 return S_OK; 909 } 910 911 static HRESULT WINAPI enum_groups_QueryInterface(IEnumCifGroups *iface, REFIID riid, void **ppv) 912 { 913 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface); 914 915 if (IsEqualGUID(&IID_IUnknown, riid)) 916 { 917 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 918 *ppv = &This->IEnumCifGroups_iface; 919 } 920 /* 921 else if (IsEqualGUID(&IID_IEnumCifGroups, riid)) 922 { 923 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv); 924 *ppv = &This->IEnumCifGroups_iface; 925 } 926 */ 927 else 928 { 929 FIXME("(%p)->(%s %p) not found\n", This, debugstr_guid(riid), ppv); 930 *ppv = NULL; 931 return E_NOINTERFACE; 932 } 933 934 IUnknown_AddRef((IUnknown *)*ppv); 935 return S_OK; 936 } 937 938 static ULONG WINAPI enum_groups_AddRef(IEnumCifGroups *iface) 939 { 940 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface); 941 LONG ref = InterlockedIncrement(&This->ref); 942 943 TRACE("(%p) ref=%d\n", This, ref); 944 945 return ref; 946 } 947 948 static ULONG WINAPI enum_groups_Release(IEnumCifGroups *iface) 949 { 950 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface); 951 LONG ref = InterlockedDecrement(&This->ref); 952 953 TRACE("(%p) ref=%d\n", This, ref); 954 955 if(!ref) 956 { 957 ICifFile_Release(This->file); 958 heap_free(This); 959 } 960 961 return ref; 962 } 963 964 static HRESULT WINAPI enum_groups_Next(IEnumCifGroups *iface, ICifGroup **group) 965 { 966 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface); 967 struct cifgroup *gp; 968 969 TRACE("(%p)->(%p)\n", This, group); 970 971 if (!This->position || !group) 972 return E_FAIL; 973 974 This->position = list_next(This->start, This->position); 975 976 if (!This->position) 977 return E_FAIL; 978 979 gp = CONTAINING_RECORD(This->position, struct cifgroup, entry); 980 *group = &gp->ICifGroup_iface; 981 return S_OK; 982 } 983 984 static HRESULT WINAPI enum_groups_Reset(IEnumCifGroups *iface) 985 { 986 struct ciffenum_groups *This = impl_from_IEnumCifGroups(iface); 987 988 TRACE("(%p)\n", This); 989 990 This->position = This->start; 991 return S_OK; 992 } 993 994 static const IEnumCifGroupsVtbl enum_groupsVtbl = 995 { 996 enum_groups_QueryInterface, 997 enum_groups_AddRef, 998 enum_groups_Release, 999 enum_groups_Next, 1000 enum_groups_Reset, 1001 }; 1002 1003 static HRESULT enum_groups_create(ICifFile *file, struct list *start, IEnumCifGroups **iface) 1004 { 1005 struct ciffenum_groups *enumerator; 1006 1007 enumerator = heap_alloc_zero(sizeof(*enumerator)); 1008 if (!enumerator) return E_OUTOFMEMORY; 1009 1010 enumerator->IEnumCifGroups_iface.lpVtbl = &enum_groupsVtbl; 1011 enumerator->ref = 1; 1012 enumerator->file = file; 1013 enumerator->start = start; 1014 enumerator->position = start; 1015 1016 ICifFile_AddRef(file); 1017 1018 *iface = &enumerator->IEnumCifGroups_iface; 1019 return S_OK; 1020 } 1021 1022 static HRESULT WINAPI ciffile_QueryInterface(ICifFile *iface, REFIID riid, void **ppv) 1023 { 1024 struct ciffile *This = impl_from_ICiffile(iface); 1025 1026 if (IsEqualGUID(&IID_IUnknown, riid)) 1027 { 1028 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 1029 *ppv = &This->ICifFile_iface; 1030 } 1031 else if (IsEqualGUID(&IID_ICifFile, riid)) 1032 { 1033 TRACE("(%p)->(IID_ICifFile %p)\n", This, ppv); 1034 *ppv = &This->ICifFile_iface; 1035 } 1036 else 1037 { 1038 FIXME("(%p)->(%s %p) not found\n", This, debugstr_guid(riid), ppv); 1039 *ppv = NULL; 1040 return E_NOINTERFACE; 1041 } 1042 1043 IUnknown_AddRef((IUnknown *)*ppv); 1044 return S_OK; 1045 } 1046 1047 static ULONG WINAPI ciffile_AddRef(ICifFile *iface) 1048 { 1049 struct ciffile *This = impl_from_ICiffile(iface); 1050 LONG ref = InterlockedIncrement(&This->ref); 1051 1052 TRACE("(%p) ref=%d\n", This, ref); 1053 1054 return ref; 1055 } 1056 1057 static ULONG WINAPI ciffile_Release(ICifFile *iface) 1058 { 1059 struct ciffile *This = impl_from_ICiffile(iface); 1060 LONG ref = InterlockedDecrement(&This->ref); 1061 1062 TRACE("(%p) ref=%d\n", This, ref); 1063 1064 if(!ref) 1065 { 1066 struct cifcomponent *comp, *comp_next; 1067 struct cifgroup *group, *group_next; 1068 1069 heap_free(This->name); 1070 1071 LIST_FOR_EACH_ENTRY_SAFE(comp, comp_next, &This->components, struct cifcomponent, entry) 1072 { 1073 list_remove(&comp->entry); 1074 component_free(comp); 1075 } 1076 1077 LIST_FOR_EACH_ENTRY_SAFE(group, group_next, &This->groups, struct cifgroup, entry) 1078 { 1079 list_remove(&group->entry); 1080 group_free(group); 1081 } 1082 1083 heap_free(This); 1084 } 1085 1086 return ref; 1087 } 1088 1089 static HRESULT WINAPI ciffile_EnumComponents(ICifFile *iface, IEnumCifComponents **enum_components, DWORD filter, void *pv) 1090 { 1091 struct ciffile *This = impl_from_ICiffile(iface); 1092 1093 TRACE("(%p)->(%p, %u, %p)\n", This, enum_components, filter, pv); 1094 1095 if (filter) 1096 FIXME("filter (%x) not supported\n", filter); 1097 if (pv) 1098 FIXME("how to handle pv (%p)?\n", pv); 1099 1100 return enum_components_create(iface, &This->components, NULL, enum_components); 1101 } 1102 1103 static HRESULT WINAPI ciffile_FindComponent(ICifFile *iface, const char *id, ICifComponent **component) 1104 { 1105 struct ciffile *This = impl_from_ICiffile(iface); 1106 struct cifcomponent *comp; 1107 1108 TRACE("(%p)->(%s, %p)\n", This, debugstr_a(id), component); 1109 1110 LIST_FOR_EACH_ENTRY(comp, &This->components, struct cifcomponent, entry) 1111 { 1112 if (strcmp(comp->id, id) != 0) 1113 continue; 1114 1115 *component = &comp->ICifComponent_iface; 1116 return S_OK; 1117 } 1118 1119 return E_FAIL; 1120 } 1121 1122 static HRESULT WINAPI ciffile_EnumGroups(ICifFile *iface, IEnumCifGroups **enum_groups, DWORD filter, void *pv) 1123 { 1124 struct ciffile *This = impl_from_ICiffile(iface); 1125 1126 TRACE("(%p)->(%p, %u, %p)\n", This, enum_groups, filter, pv); 1127 1128 if (filter) 1129 FIXME("filter (%x) not supported\n", filter); 1130 if (pv) 1131 FIXME("how to handle pv (%p)?\n", pv); 1132 1133 return enum_groups_create(iface, &This->groups, enum_groups); 1134 } 1135 1136 static HRESULT WINAPI ciffile_FindGroup(ICifFile *iface, const char *id, ICifGroup **group) 1137 { 1138 struct ciffile *This = impl_from_ICiffile(iface); 1139 struct cifgroup *gp; 1140 1141 TRACE("(%p)->(%s, %p)\n", This, debugstr_a(id), group); 1142 1143 LIST_FOR_EACH_ENTRY(gp, &This->groups, struct cifgroup, entry) 1144 { 1145 if (strcmp(gp->id, id) != 0) 1146 continue; 1147 1148 *group = &gp->ICifGroup_iface; 1149 return S_OK; 1150 } 1151 1152 return E_FAIL; 1153 } 1154 1155 static HRESULT WINAPI ciffile_EnumModes(ICifFile *iface, IEnumCifModes **cuf_modes, DWORD filter, void *pv) 1156 { 1157 struct ciffile *This = impl_from_ICiffile(iface); 1158 1159 FIXME("(%p)->(%p, %u, %p): stub\n", This, cuf_modes, filter, pv); 1160 1161 return E_NOTIMPL; 1162 } 1163 1164 static HRESULT WINAPI ciffile_FindMode(ICifFile *iface, const char *id, ICifMode **mode) 1165 { 1166 struct ciffile *This = impl_from_ICiffile(iface); 1167 1168 FIXME("(%p)->(%s, %p): stub\n", This, debugstr_a(id), mode); 1169 1170 return E_NOTIMPL; 1171 } 1172 1173 static HRESULT WINAPI ciffile_GetDescription(ICifFile *iface, char *desc, DWORD size) 1174 { 1175 struct ciffile *This = impl_from_ICiffile(iface); 1176 1177 TRACE("(%p)->(%p, %u)\n", This, desc, size); 1178 1179 return copy_substring_null(desc, size, This->name); 1180 } 1181 1182 static HRESULT WINAPI ciffile_GetDetDlls(ICifFile *iface, char *dlls, DWORD size) 1183 { 1184 struct ciffile *This = impl_from_ICiffile(iface); 1185 1186 FIXME("(%p)->(%p, %u): stub\n", This, dlls, size); 1187 1188 return E_NOTIMPL; 1189 } 1190 1191 static const ICifFileVtbl ciffileVtbl = 1192 { 1193 ciffile_QueryInterface, 1194 ciffile_AddRef, 1195 ciffile_Release, 1196 ciffile_EnumComponents, 1197 ciffile_FindComponent, 1198 ciffile_EnumGroups, 1199 ciffile_FindGroup, 1200 ciffile_EnumModes, 1201 ciffile_FindMode, 1202 ciffile_GetDescription, 1203 ciffile_GetDetDlls, 1204 }; 1205 1206 static BOOL copy_string(char **dest, const char *source) 1207 { 1208 if (!source) 1209 { 1210 *dest = NULL; 1211 return TRUE; 1212 } 1213 1214 *dest = strdupA(source); 1215 if (!dest) return FALSE; 1216 return TRUE; 1217 } 1218 1219 static BOOL section_get_str(struct inf_section *inf_sec, const char *key, char **value, const char *def) 1220 { 1221 struct inf_value *inf_val; 1222 1223 inf_val = inf_get_value(inf_sec, key); 1224 if (!inf_val) return copy_string(value, def); 1225 1226 *value = inf_value_get_value(inf_val); 1227 if (!*value) return FALSE; 1228 1229 return TRUE; 1230 } 1231 1232 static char *next_part(char **str, BOOL strip_quotes) 1233 { 1234 char *start = *str; 1235 char *next = *str; 1236 1237 while (*next && *next != ',') 1238 next++; 1239 1240 if (!*next) 1241 { 1242 *str = trim(start, NULL, strip_quotes); 1243 return NULL; 1244 } 1245 1246 *next = 0; 1247 *str = trim(start, NULL, strip_quotes); 1248 return ++next; 1249 } 1250 1251 static BOOL value_get_str_field(struct inf_value *inf_val, int field, char **value, const char *def) 1252 { 1253 char *line, *str, *next; 1254 int i = 0; 1255 1256 line = inf_value_get_value(inf_val); 1257 if (!line) return FALSE; 1258 1259 str = line; 1260 do 1261 { 1262 i++; 1263 next = next_part(&str, TRUE); 1264 1265 if (field == i) 1266 { 1267 BOOL ret = copy_string(value, str); 1268 heap_free(line); 1269 return ret; 1270 } 1271 1272 str = next; 1273 } while (str); 1274 1275 return copy_string(value, def); 1276 } 1277 1278 /* 1279 static BOOL section_get_str_field(struct inf_section *inf_sec, const char *key, int field, char **value, const char *def) 1280 { 1281 struct inf_value *inf_val; 1282 1283 inf_val = inf_get_value(inf_sec, key); 1284 if (!inf_val) return copy_string(value, def); 1285 1286 return value_get_str_field(inf_val, field, value, def); 1287 } 1288 */ 1289 1290 static BOOL section_get_dword(struct inf_section *inf_sec, const char *key, DWORD *value, DWORD def) 1291 { 1292 struct inf_value *inf_val; 1293 char *str; 1294 1295 inf_val = inf_get_value(inf_sec, key); 1296 if (!inf_val) 1297 { 1298 *value = def; 1299 return TRUE; 1300 } 1301 1302 str = inf_value_get_value(inf_val); 1303 if (!str) return FALSE; 1304 1305 *value = atoi(str); 1306 heap_free(str); 1307 1308 return TRUE; 1309 } 1310 1311 static BOOL value_get_dword_field(struct inf_value *inf_val, int field, DWORD *value, DWORD def) 1312 { 1313 char *value_str; 1314 BOOL ret; 1315 1316 ret = value_get_str_field(inf_val, field, &value_str, NULL); 1317 if (!ret) return FALSE; 1318 if (!value_str) 1319 { 1320 *value = def; 1321 return TRUE; 1322 } 1323 1324 *value = atoi(value_str); 1325 heap_free(value_str); 1326 1327 return TRUE; 1328 } 1329 1330 static BOOL section_get_dword_field(struct inf_section *inf_sec, const char *key, int field, DWORD *value, DWORD def) 1331 { 1332 struct inf_value *inf_val; 1333 1334 inf_val = inf_get_value(inf_sec, key); 1335 if (!inf_val) 1336 { 1337 *value = def; 1338 return TRUE; 1339 } 1340 1341 return value_get_dword_field(inf_val, field, value, def); 1342 } 1343 1344 static HRESULT process_version(struct ciffile *file, struct inf_section *section) 1345 { 1346 if (!section_get_str(section, "DisplayName", &file->name, DEFAULT_INSTALLER_DESC)) 1347 return E_OUTOFMEMORY; 1348 1349 return S_OK; 1350 } 1351 1352 static BOOL read_version_entry(struct inf_section *section, DWORD *ret_ver, DWORD *ret_build) 1353 { 1354 DWORD version = 0; 1355 DWORD build = 0; 1356 char *line, *str, *next; 1357 1358 if (!section_get_str(section, "Version", &line, NULL)) 1359 return FALSE; 1360 if (!line) goto done; 1361 1362 str = line; 1363 1364 next = next_part(&str, TRUE); 1365 version |= atoi(str) << 16; 1366 if (!next) goto done; 1367 str = next; 1368 1369 next = next_part(&str, TRUE); 1370 version |= atoi(str) & 0xffff; 1371 if (!next) goto done; 1372 str = next; 1373 1374 next = next_part(&str, TRUE); 1375 build |= atoi(str) << 16; 1376 if (!next) goto done; 1377 str = next; 1378 1379 next_part(&str, TRUE); 1380 build |= atoi(str) & 0xffff; 1381 1382 done: 1383 heap_free(line); 1384 *ret_ver = version; 1385 *ret_build = build; 1386 return TRUE; 1387 } 1388 1389 static BOOL read_platform_entry(struct inf_section *section, DWORD *ret_platform) 1390 { 1391 DWORD platform = PLATFORM_ALL; 1392 char *line, *str, *next; 1393 1394 if (!section_get_str(section, "Platform", &line, NULL)) 1395 return FALSE; 1396 if (!line) goto done; 1397 1398 platform = 0; 1399 str = line; 1400 do 1401 { 1402 next = next_part(&str, TRUE); 1403 1404 if (strcasecmp(str, "Win95") == 0) 1405 platform |= PLATFORM_WIN98; 1406 else if (strcasecmp(str, "Win98") == 0) 1407 platform |= PLATFORM_WIN98; 1408 else if (strcasecmp(str, "NT4") == 0) 1409 platform |= PLATFORM_NT4; 1410 else if (strcasecmp(str, "NT5") == 0) 1411 platform |= PLATFORM_NT5; 1412 else if (strcasecmp(str, "NT4Alpha") == 0) 1413 platform |= PLATFORM_NT4; 1414 else if (strcasecmp(str, "NT5Alpha") == 0) 1415 platform |= PLATFORM_NT5; 1416 else if (strcasecmp(str, "Millen") == 0) 1417 platform |= PLATFORM_MILLEN; 1418 else 1419 FIXME("Unknown platform: %s\n", debugstr_a(str)); 1420 1421 str = next; 1422 } while (str); 1423 1424 done: 1425 heap_free(line); 1426 *ret_platform = platform; 1427 return TRUE; 1428 } 1429 1430 static BOOL read_dependencies(struct cifcomponent *component, struct inf_section *section) 1431 { 1432 struct dependency_info *dependency; 1433 char *line, *str, *next; 1434 BOOL ret = TRUE; 1435 1436 if (!section_get_str(section, "Dependencies", &line, NULL)) 1437 return E_OUTOFMEMORY; 1438 if (!line) goto done; 1439 1440 ret = FALSE; 1441 str = line; 1442 do 1443 { 1444 next = next_part(&str, TRUE); 1445 1446 dependency = heap_alloc_zero(sizeof(*dependency)); 1447 if (!dependency) goto done; 1448 1449 dependency->id = strdupA(str); 1450 if (!dependency->id) 1451 { 1452 heap_free(dependency); 1453 goto done; 1454 } 1455 1456 dependency->type = strstr(dependency->id, ":"); 1457 if (dependency->type) *dependency->type++ = 0; 1458 1459 list_add_tail(&component->dependencies, &dependency->entry); 1460 1461 str = next; 1462 } while (str); 1463 1464 ret = TRUE; 1465 1466 done: 1467 heap_free(line); 1468 return ret; 1469 } 1470 1471 static BOOL read_urls(struct cifcomponent *component, struct inf_section *section) 1472 { 1473 struct inf_value *inf_value = NULL; 1474 struct url_info *url_entry; 1475 char *str, *next; 1476 int index; 1477 1478 while (inf_section_next_value(section, &inf_value)) 1479 { 1480 str = inf_value_get_key(inf_value); 1481 if (!str) return E_OUTOFMEMORY; 1482 1483 if (strncasecmp(str, "URL", 3)) 1484 goto next; 1485 1486 if (!str[3]) 1487 goto next; 1488 1489 index = strtol(str+3, &next, 10); 1490 if (next == str+3 || *next != 0 || index < 1) 1491 goto next; 1492 index--; 1493 1494 url_entry = heap_alloc_zero(sizeof(*url_entry)); 1495 if (!url_entry) goto error; 1496 1497 url_entry->index = index; 1498 1499 if (!value_get_str_field(inf_value, 1, &url_entry->url, NULL)) 1500 goto error; 1501 if (!url_entry->url || !*url_entry->url) 1502 { 1503 url_entry_free(url_entry); 1504 goto next; 1505 } 1506 1507 if (!value_get_dword_field(inf_value, 2, &url_entry->flags, 0)) 1508 goto error; 1509 1510 list_add_tail(&component->urls, &url_entry->entry); 1511 1512 next: 1513 heap_free(str); 1514 } 1515 1516 return TRUE; 1517 1518 error: 1519 heap_free(str); 1520 url_entry_free(url_entry); 1521 return FALSE; 1522 }; 1523 1524 void add_component_by_priority(struct ciffile *file, struct cifcomponent *component) 1525 { 1526 struct cifcomponent *entry; 1527 1528 LIST_FOR_EACH_ENTRY(entry, &file->components, struct cifcomponent, entry) 1529 { 1530 if (entry->priority > component->priority) 1531 continue; 1532 1533 list_add_before(&entry->entry, &component->entry); 1534 return; 1535 } 1536 1537 list_add_tail(&file->components, &component->entry); 1538 } 1539 1540 static HRESULT process_component(struct ciffile *file, struct inf_section *section, const char *section_name) 1541 { 1542 struct cifcomponent *component; 1543 HRESULT hr = E_OUTOFMEMORY; 1544 1545 component = heap_alloc_zero(sizeof(*component)); 1546 if (!component) return E_OUTOFMEMORY; 1547 1548 component->ICifComponent_iface.lpVtbl = &cifcomponentVtbl; 1549 component->parent = &file->ICifFile_iface; 1550 1551 list_init(&component->urls); 1552 list_init(&component->dependencies); 1553 1554 component->queue_state = ActionNone; 1555 1556 component->id = strdupA(section_name); 1557 if (!component->id) goto error; 1558 1559 if (!section_get_str(section, "DisplayName", &component->description, NULL)) 1560 goto error; 1561 if (!section_get_str(section, "GUID", &component->guid, NULL)) 1562 goto error; 1563 if (!section_get_str(section, "Details", &component->details, NULL)) 1564 goto error; 1565 if (!section_get_str(section, "Group", &component->group, NULL)) 1566 goto error; 1567 if (!section_get_str(section, "Locale", &component->locale, "en")) 1568 goto error; 1569 if (!section_get_str(section, "PatchID", &component->patchid, NULL)) 1570 goto error; 1571 1572 if (!section_get_dword_field(section, "Size", 1, &component->size_download, 0)) 1573 goto error; 1574 if (!section_get_dword_field(section, "Size", 2, &component->size_extracted, 0)) 1575 goto error; 1576 if (!section_get_dword_field(section, "InstalledSize", 1, &component->size_app, 0)) 1577 goto error; 1578 if (!section_get_dword_field(section, "InstalledSize", 2, &component->size_win, 0)) 1579 goto error; 1580 1581 if (!section_get_str(section, "SuccessKey", &component->key_success, NULL)) 1582 goto error; 1583 if (!section_get_str(section, "CancelKey", &component->key_cancel, NULL)) 1584 goto error; 1585 if (!section_get_str(section, "ProgressKey", &component->key_progress, NULL)) 1586 goto error; 1587 if (!section_get_str(section, "UninstallKey", &component->key_uninstall, NULL)) 1588 goto error; 1589 if (!section_get_dword(section, "Reboot", &component->reboot, 0)) 1590 goto error; 1591 if (!section_get_dword(section, "AdminCheck", &component->admin, 0)) 1592 goto error; 1593 if (!section_get_dword(section, "UIVisible", &component->visibleui, 1)) 1594 goto error; 1595 if (!section_get_dword(section, "ActiveSetupAware", &component->as_aware, 0)) 1596 goto error; 1597 if (!section_get_dword(section, "Priority", &component->priority, 0)) 1598 goto error; 1599 1600 if (!read_version_entry(section, &component->version, &component->build)) 1601 goto error; 1602 if (!read_platform_entry(section, &component->platform)) 1603 goto error; 1604 if (!read_urls(component, section)) 1605 goto error; 1606 if (!read_dependencies(component, section)) 1607 goto error; 1608 1609 component->current_priority = component->priority; 1610 1611 add_component_by_priority(file, component); 1612 return S_OK; 1613 1614 error: 1615 component_free(component); 1616 return hr; 1617 } 1618 1619 static HRESULT process_group(struct ciffile *file, struct inf_section *section, const char *section_name) 1620 { 1621 struct cifgroup *group; 1622 HRESULT hr = E_OUTOFMEMORY; 1623 1624 group = heap_alloc_zero(sizeof(*group)); 1625 if (!group) return E_OUTOFMEMORY; 1626 1627 group->ICifGroup_iface.lpVtbl = &cifgroupVtbl; 1628 group->parent = &file->ICifFile_iface; 1629 1630 group->id = strdupA(section_name); 1631 if (!group->id) goto error; 1632 1633 if (!section_get_str(section, "DisplayName", &group->description, NULL)) 1634 goto error; 1635 if (!section_get_dword(section, "Priority", &group->priority, 0)) 1636 goto error; 1637 1638 list_add_head(&file->groups, &group->entry); 1639 return S_OK; 1640 1641 error: 1642 group_free(group); 1643 return hr; 1644 } 1645 1646 static HRESULT process_section(struct ciffile *file, struct inf_section *section, const char *section_name) 1647 { 1648 HRESULT hr; 1649 char *type; 1650 1651 if (!section_get_str(section, "SectionType", &type, "Component")) 1652 return E_OUTOFMEMORY; 1653 1654 if (!strcasecmp(type, "Component")) 1655 hr = process_component(file, section, section_name); 1656 else if (strcasecmp(type, "Group") == 0) 1657 hr = process_group(file, section, section_name); 1658 else 1659 FIXME("Don't know how to process %s\n", debugstr_a(type)); 1660 1661 heap_free(type); 1662 return hr; 1663 } 1664 1665 static HRESULT process_inf(struct ciffile *file, struct inf_file *inf) 1666 { 1667 struct inf_section *section = NULL; 1668 char *section_name; 1669 HRESULT hr = S_OK; 1670 1671 while (SUCCEEDED(hr) && inf_next_section(inf, §ion)) 1672 { 1673 section_name = inf_section_get_name(section); 1674 if (!section_name) return E_OUTOFMEMORY; 1675 1676 TRACE("start processing section %s\n", debugstr_a(section_name)); 1677 1678 if (!strcasecmp(section_name, "Strings") || 1679 !strncasecmp(section_name, "Strings.", strlen("Strings."))) 1680 { 1681 /* Ignore string sections */ 1682 } 1683 else if (strcasecmp(section_name, "Version") == 0) 1684 hr = process_version(file, section); 1685 else 1686 hr = process_section(file, section, section_name); 1687 1688 TRACE("finished processing section %s (%x)\n", debugstr_a(section_name), hr); 1689 heap_free(section_name); 1690 } 1691 1692 /* In case there was no version section, set the default installer description */ 1693 if (SUCCEEDED(hr) && !file->name) 1694 { 1695 file->name = strdupA(DEFAULT_INSTALLER_DESC); 1696 if (!file->name) hr = E_OUTOFMEMORY; 1697 } 1698 1699 return hr; 1700 } 1701 1702 static HRESULT load_ciffile(const char *path, ICifFile **icif) 1703 { 1704 struct inf_file *inf = NULL; 1705 struct ciffile *file; 1706 HRESULT hr = E_FAIL; 1707 1708 file = heap_alloc_zero(sizeof(*file)); 1709 if(!file) return E_OUTOFMEMORY; 1710 1711 file->ICifFile_iface.lpVtbl = &ciffileVtbl; 1712 file->ref = 1; 1713 1714 list_init(&file->components); 1715 list_init(&file->groups); 1716 1717 hr = inf_load(path, &inf); 1718 if (FAILED(hr)) goto error; 1719 1720 hr = process_inf(file, inf); 1721 if (FAILED(hr)) goto error; 1722 1723 *icif = &file->ICifFile_iface; 1724 return S_OK; 1725 1726 error: 1727 if (inf) inf_free(inf); 1728 ICifFile_Release(&file->ICifFile_iface); 1729 return hr; 1730 } 1731 1732 HRESULT WINAPI GetICifFileFromFile(ICifFile **icif, const char *path) 1733 { 1734 TRACE("(%p, %s)\n", icif, debugstr_a(path)); 1735 1736 return load_ciffile(path, icif); 1737 } 1738 1739 1740 HRESULT WINAPI GetICifRWFileFromFile(ICifRWFile **icif, const char *path) 1741 { 1742 FIXME("(%p, %s): stub\n", icif, debugstr_a(path)); 1743 1744 return E_NOTIMPL; 1745 } 1746