install.c 23.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Implementation of the Microsoft Installer (msi.dll)
 *
 * Copyright 2005 Aric Stewart for CodeWeavers
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20 21 22 23 24 25 26 27 28 29 30 31
 */

/* Msi top level apis directly related to installs */

#include <stdarg.h>

#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msidefs.h"
#include "msipriv.h"
32
#include "wine/unicode.h"
33 34 35 36 37 38 39 40 41

WINE_DEFAULT_DEBUG_CHANNEL(msi);

/***********************************************************************
 * MsiDoActionA       (MSI.@)
 */
UINT WINAPI MsiDoActionA( MSIHANDLE hInstall, LPCSTR szAction )
{
    LPWSTR szwAction;
42
    UINT ret;
43

44
    TRACE("%s\n", debugstr_a(szAction));
45 46

    szwAction = strdupAtoW(szAction);
47
    if (szAction && !szwAction)
48 49
        return ERROR_FUNCTION_FAILED; 

50
    ret = MsiDoActionW( hInstall, szwAction );
51
    msi_free( szwAction );
52
    return ret;
53 54 55 56 57 58 59 60
}

/***********************************************************************
 * MsiDoActionW       (MSI.@)
 */
UINT WINAPI MsiDoActionW( MSIHANDLE hInstall, LPCWSTR szAction )
{
    MSIPACKAGE *package;
61 62 63 64 65 66
    UINT ret;

    TRACE("%s\n",debugstr_w(szAction));

    if (!szAction)
        return ERROR_INVALID_PARAMETER;
67

68 69 70 71 72 73
    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
    if (!package)
        return ERROR_INVALID_HANDLE;
 
    ret = ACTION_PerformUIAction( package, szAction );
    msiobj_release( &package->hdr );
74 75 76 77

    return ret;
}

78 79 80
/***********************************************************************
 * MsiSequenceA       (MSI.@)
 */
81
UINT WINAPI MsiSequenceA( MSIHANDLE hInstall, LPCSTR szTable, INT iSequenceMode )
82
{
83 84 85 86 87 88 89 90 91 92 93 94
    LPWSTR szwTable;
    UINT ret;

    TRACE("%s\n", debugstr_a(szTable));

    szwTable = strdupAtoW(szTable);
    if (szTable && !szwTable)
        return ERROR_FUNCTION_FAILED; 

    ret = MsiSequenceW( hInstall, szwTable, iSequenceMode );
    msi_free( szwTable );
    return ret;
95 96 97 98 99
}

/***********************************************************************
 * MsiSequenceW       (MSI.@)
 */
100
UINT WINAPI MsiSequenceW( MSIHANDLE hInstall, LPCWSTR szTable, INT iSequenceMode )
101
{
102 103 104 105 106 107 108 109 110 111 112 113 114
    MSIPACKAGE *package;
    UINT ret;

    TRACE("%s\n", debugstr_w(szTable));

    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
    if (!package)
        return ERROR_INVALID_HANDLE;

    ret = MSI_Sequence( package, szTable, iSequenceMode );
    msiobj_release( &package->hdr );
 
    return ret;
115 116
}

117
UINT msi_strcpy_to_awstring( LPCWSTR str, awstring *awbuf, DWORD *sz )
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
{
    UINT len, r = ERROR_SUCCESS;

    if (awbuf->str.w && !sz )
        return ERROR_INVALID_PARAMETER;

    if (!sz)
        return r;
 
    if (awbuf->unicode)
    {
        len = lstrlenW( str );
        if (awbuf->str.w) 
            lstrcpynW( awbuf->str.w, str, *sz );
    }
    else
    {
135 136 137 138
        len = WideCharToMultiByte( CP_ACP, 0, str, -1, NULL, 0, NULL, NULL );
        if (len)
            len--;
        WideCharToMultiByte( CP_ACP, 0, str, -1, awbuf->str.a, *sz, NULL, NULL );
139
        if ( awbuf->str.a && *sz && (len >= *sz) )
140
            awbuf->str.a[*sz - 1] = 0;
141 142
    }

143
    if (awbuf->str.w && len >= *sz)
144 145 146 147 148 149 150 151
        r = ERROR_MORE_DATA;
    *sz = len;
    return r;
}

/***********************************************************************
 * MsiGetTargetPath   (internal)
 */
152 153
static UINT WINAPI MSI_GetTargetPath( MSIHANDLE hInstall, LPCWSTR szFolder,
                                      awstring *szPathBuf, DWORD* pcchPathBuf )
154 155 156 157 158 159 160 161 162 163 164 165
{
    MSIPACKAGE *package;
    LPWSTR path;
    UINT r;

    if (!szFolder)
        return ERROR_INVALID_PARAMETER;

    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
    if (!package)
        return ERROR_INVALID_HANDLE;

166
    path = resolve_folder( package, szFolder, FALSE, FALSE, TRUE, NULL );
167 168 169 170 171 172
    msiobj_release( &package->hdr );

    if (!path)
        return ERROR_DIRECTORY;

    r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
173
    msi_free( path );
174 175 176
    return r;
}

177 178 179 180
/***********************************************************************
 * MsiGetTargetPathA        (MSI.@)
 */
UINT WINAPI MsiGetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder, 
181
                               LPSTR szPathBuf, DWORD* pcchPathBuf )
182 183
{
    LPWSTR szwFolder;
184 185
    awstring path;
    UINT r;
186

187
    TRACE("%s %p %p\n", debugstr_a(szFolder), szPathBuf, pcchPathBuf);
188 189

    szwFolder = strdupAtoW(szFolder);
190
    if (szFolder && !szwFolder)
191 192
        return ERROR_FUNCTION_FAILED; 

193 194
    path.unicode = FALSE;
    path.str.a = szPathBuf;
195

196
    r = MSI_GetTargetPath( hInstall, szwFolder, &path, pcchPathBuf );
197

198
    msi_free( szwFolder );
199

200
    return r;
201 202 203
}

/***********************************************************************
204 205 206 207
 * MsiGetTargetPathW        (MSI.@)
 */
UINT WINAPI MsiGetTargetPathW( MSIHANDLE hInstall, LPCWSTR szFolder,
                               LPWSTR szPathBuf, DWORD* pcchPathBuf )
208
{
209
    awstring path;
210

211
    TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf);
212

213 214
    path.unicode = TRUE;
    path.str.w = szPathBuf;
215

216
    return MSI_GetTargetPath( hInstall, szFolder, &path, pcchPathBuf );
217 218 219
}

/***********************************************************************
220 221 222 223
 * MsiGetSourcePath   (internal)
 */
static UINT MSI_GetSourcePath( MSIHANDLE hInstall, LPCWSTR szFolder,
                               awstring *szPathBuf, DWORD* pcchPathBuf )
224
{
225
    MSIPACKAGE *package;
226 227
    LPWSTR path;
    UINT r;
228

229
    TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );
230 231

    if (!szFolder)
232
        return ERROR_INVALID_PARAMETER;
233

234 235 236
    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
    if (!package)
        return ERROR_INVALID_HANDLE;
237

238 239 240 241 242
    if (szPathBuf->str.w && !pcchPathBuf )
    {
        msiobj_release( &package->hdr );
        return ERROR_INVALID_PARAMETER;
    }
243

244
    path = resolve_folder(package, szFolder, TRUE, FALSE, TRUE, NULL);
245
    msiobj_release( &package->hdr );
246

247 248 249
    TRACE("path = %s\n",debugstr_w(path));
    if (!path)
        return ERROR_DIRECTORY;
250

251
    r = msi_strcpy_to_awstring( path, szPathBuf, pcchPathBuf );
252
    msi_free( path );
253
    return r;
254 255 256
}

/***********************************************************************
257 258 259 260
 * MsiGetSourcePathA     (MSI.@)
 */
UINT WINAPI MsiGetSourcePathA( MSIHANDLE hInstall, LPCSTR szFolder, 
                               LPSTR szPathBuf, DWORD* pcchPathBuf )
261
{
262 263 264
    LPWSTR folder;
    awstring str;
    UINT r;
265

266
    TRACE("%s %p %p\n", szFolder, debugstr_a(szPathBuf), pcchPathBuf);
267

268 269
    str.unicode = FALSE;
    str.str.a = szPathBuf;
270

271 272
    folder = strdupAtoW( szFolder );
    r = MSI_GetSourcePath( hInstall, folder, &str, pcchPathBuf );
273
    msi_free( folder );
274 275

    return r;
276 277
}

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
/***********************************************************************
 * MsiGetSourcePathW     (MSI.@)
 */
UINT WINAPI MsiGetSourcePathW( MSIHANDLE hInstall, LPCWSTR szFolder,
                               LPWSTR szPathBuf, DWORD* pcchPathBuf )
{
    awstring str;

    TRACE("%s %p %p\n", debugstr_w(szFolder), szPathBuf, pcchPathBuf );

    str.unicode = TRUE;
    str.str.w = szPathBuf;

    return MSI_GetSourcePath( hInstall, szFolder, &str, pcchPathBuf );
}
293 294 295 296

/***********************************************************************
 * MsiSetTargetPathA  (MSI.@)
 */
297 298
UINT WINAPI MsiSetTargetPathA( MSIHANDLE hInstall, LPCSTR szFolder,
                               LPCSTR szFolderPath )
299
{
300 301
    LPWSTR szwFolder = NULL, szwFolderPath = NULL;
    UINT rc = ERROR_OUTOFMEMORY;
302

303 304
    if ( !szFolder || !szFolderPath )
        return ERROR_INVALID_PARAMETER;
305 306 307

    szwFolder = strdupAtoW(szFolder);
    szwFolderPath = strdupAtoW(szFolderPath);
308 309
    if (!szwFolder || !szwFolderPath)
        goto end;
310

311
    rc = MsiSetTargetPathW( hInstall, szwFolder, szwFolderPath );
312

313
end:
314 315
    msi_free(szwFolder);
    msi_free(szwFolderPath);
316 317 318 319

    return rc;
}

320 321 322 323 324
/*
 * Ok my original interpretation of this was wrong. And it looks like msdn has
 * changed a bit also. The given folder path does not have to actually already
 * exist, it just cannot be read only and must be a legal folder path.
 */
325 326 327
UINT MSI_SetTargetPathW(MSIPACKAGE *package, LPCWSTR szFolder, 
                             LPCWSTR szFolderPath)
{
328
    DWORD attrib;
329 330 331
    LPWSTR path = NULL;
    LPWSTR path2 = NULL;
    MSIFOLDER *folder;
332
    MSIFILE *file;
333

334
    TRACE("%p %s %s\n",package, debugstr_w(szFolder),debugstr_w(szFolderPath));
335

336
    attrib = GetFileAttributesW(szFolderPath);
337
    /* native MSI tests writeability by making temporary files at each drive */
338
    if ( attrib != INVALID_FILE_ATTRIBUTES &&
339
          (attrib & FILE_ATTRIBUTE_OFFLINE ||
340
           attrib & FILE_ATTRIBUTE_READONLY))
341 342
        return ERROR_FUNCTION_FAILED;

343
    path = resolve_folder(package,szFolder,FALSE,FALSE,FALSE,&folder);
344
    if (!path)
345
        return ERROR_DIRECTORY;
346

347
    msi_free(folder->Property);
348 349 350 351 352 353 354 355
    folder->Property = build_directory_name(2, szFolderPath, NULL);

    if (lstrcmpiW(path, folder->Property) == 0)
    {
        /*
         *  Resolved Target has not really changed, so just 
         *  set this folder and do not recalculate everything.
         */
356
        msi_free(folder->ResolvedTarget);
357
        folder->ResolvedTarget = NULL;
358
        path2 = resolve_folder(package,szFolder,FALSE,TRUE,FALSE,NULL);
359
        msi_free(path2);
360 361 362
    }
    else
    {
363 364 365
        MSIFOLDER *f;

        LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
366
        {
367
            msi_free(f->ResolvedTarget);
368
            f->ResolvedTarget=NULL;
369 370
        }

371
        LIST_FOR_EACH_ENTRY( f, &package->folders, MSIFOLDER, entry )
372
        {
373
            path2 = resolve_folder(package, f->Directory, FALSE, TRUE, FALSE, NULL);
374
            msi_free(path2);
375
        }
376 377 378 379 380 381 382 383 384

        LIST_FOR_EACH_ENTRY( file, &package->files, MSIFILE, entry )
        {
            MSICOMPONENT *comp = file->Component;
            LPWSTR p;

            if (!comp)
                continue;

385
            p = resolve_folder(package, comp->Directory, FALSE, FALSE, FALSE, NULL);
386 387 388 389 390
            msi_free(file->TargetPath);

            file->TargetPath = build_directory_name(2, p, file->FileName);
            msi_free(p);
        }
391
    }
392
    msi_free(path);
393 394 395 396 397 398 399 400 401 402 403 404 405

    return ERROR_SUCCESS;
}

/***********************************************************************
 * MsiSetTargetPathW  (MSI.@)
 */
UINT WINAPI MsiSetTargetPathW(MSIHANDLE hInstall, LPCWSTR szFolder, 
                             LPCWSTR szFolderPath)
{
    MSIPACKAGE *package;
    UINT ret;

406
    TRACE("%s %s\n",debugstr_w(szFolder),debugstr_w(szFolderPath));
407

408 409 410
    if ( !szFolder || !szFolderPath )
        return ERROR_INVALID_PARAMETER;

411
    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
412 413 414
    if (!package)
        return ERROR_INVALID_HANDLE;

415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
    ret = MSI_SetTargetPathW( package, szFolder, szFolderPath );
    msiobj_release( &package->hdr );
    return ret;
}

/***********************************************************************
 *           MsiGetMode    (MSI.@)
 *
 * Returns an internal installer state (if it is running in a mode iRunMode)
 *
 * PARAMS
 *   hInstall    [I]  Handle to the installation
 *   hRunMode    [I]  Checking run mode
 *        MSIRUNMODE_ADMIN             Administrative mode
 *        MSIRUNMODE_ADVERTISE         Advertisement mode
 *        MSIRUNMODE_MAINTENANCE       Maintenance mode
 *        MSIRUNMODE_ROLLBACKENABLED   Rollback is enabled
 *        MSIRUNMODE_LOGENABLED        Log file is writing
 *        MSIRUNMODE_OPERATIONS        Operations in progress??
 *        MSIRUNMODE_REBOOTATEND       We need to reboot after installation completed
 *        MSIRUNMODE_REBOOTNOW         We need to reboot to continue the installation
 *        MSIRUNMODE_CABINET           Files from cabinet are installed
 *        MSIRUNMODE_SOURCESHORTNAMES  Long names in source files is suppressed
 *        MSIRUNMODE_TARGETSHORTNAMES  Long names in destination files is suppressed
 *        MSIRUNMODE_RESERVED11        Reserved
 *        MSIRUNMODE_WINDOWS9X         Running under Windows95/98
 *        MSIRUNMODE_ZAWENABLED        Demand installation is supported
 *        MSIRUNMODE_RESERVED14        Reserved
 *        MSIRUNMODE_RESERVED15        Reserved
 *        MSIRUNMODE_SCHEDULED         called from install script
 *        MSIRUNMODE_ROLLBACK          called from rollback script
 *        MSIRUNMODE_COMMIT            called from commit script
 *
 * RETURNS
 *    In the state: TRUE
 *    Not in the state: FALSE
 *
 */
BOOL WINAPI MsiGetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode)
{
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479
    BOOL r = FALSE;

    switch (iRunMode)
    {
    case MSIRUNMODE_WINDOWS9X:
        if (GetVersion() & 0x80000000)
            r = TRUE;
        break;

    case MSIRUNMODE_RESERVED11:
    case MSIRUNMODE_RESERVED14:
    case MSIRUNMODE_RESERVED15:
        break;

    case MSIRUNMODE_SCHEDULED:
    case MSIRUNMODE_ROLLBACK:
    case MSIRUNMODE_COMMIT:
        break;

    default:
        FIXME("%ld %d\n", hInstall, iRunMode);
        r = TRUE;
    }

    return r;
480 481
}

482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
/***********************************************************************
 *           MsiSetMode    (MSI.@)
 */
BOOL WINAPI MsiSetMode(MSIHANDLE hInstall, MSIRUNMODE iRunMode, BOOL fState)
{
    switch (iRunMode)
    {
    case MSIRUNMODE_RESERVED11:
    case MSIRUNMODE_WINDOWS9X:
    case MSIRUNMODE_RESERVED14:
    case MSIRUNMODE_RESERVED15:
        return FALSE;
    default:
        FIXME("%ld %d %d\n", hInstall, iRunMode, fState);
    }
    return TRUE;
}

500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518
/***********************************************************************
 * MsiSetFeatureStateA (MSI.@)
 *
 * According to the docs, when this is called it immediately recalculates
 * all the component states as well
 */
UINT WINAPI MsiSetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
                                INSTALLSTATE iState)
{
    LPWSTR szwFeature = NULL;
    UINT rc;

    szwFeature = strdupAtoW(szFeature);

    if (!szwFeature)
        return ERROR_FUNCTION_FAILED;
   
    rc = MsiSetFeatureStateW(hInstall,szwFeature, iState); 

519
    msi_free(szwFeature);
520 521 522 523 524 525 526 527 528 529

    return rc;
}



UINT WINAPI MSI_SetFeatureStateW(MSIPACKAGE* package, LPCWSTR szFeature,
                                INSTALLSTATE iState)
{
    UINT rc = ERROR_SUCCESS;
530
    MSIFEATURE *feature, *child;
531

532
    TRACE("%s %i\n", debugstr_w(szFeature), iState);
533

534 535
    feature = get_loaded_feature(package,szFeature);
    if (!feature)
536 537 538
        return ERROR_UNKNOWN_FEATURE;

    if (iState == INSTALLSTATE_ADVERTISED && 
539
        feature->Attributes & msidbFeatureAttributesDisallowAdvertise)
540 541
        return ERROR_FUNCTION_FAILED;

542
    msi_feature_set_state( feature, iState );
543 544 545 546

    ACTION_UpdateComponentStates(package,szFeature);

    /* update all the features that are children of this feature */
547
    LIST_FOR_EACH_ENTRY( child, &package->features, MSIFEATURE, entry )
548
    {
549 550
        if (lstrcmpW(szFeature, child->Feature_Parent) == 0)
            MSI_SetFeatureStateW(package, child->Feature, iState);
551 552 553 554 555 556 557 558 559 560 561 562 563 564
    }
    
    return rc;
}

/***********************************************************************
 * MsiSetFeatureStateW (MSI.@)
 */
UINT WINAPI MsiSetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
                                INSTALLSTATE iState)
{
    MSIPACKAGE* package;
    UINT rc = ERROR_SUCCESS;

565
    TRACE("%s %i\n",debugstr_w(szFeature), iState);
566 567 568 569 570 571 572 573 574 575 576 577 578 579

    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
    if (!package)
        return ERROR_INVALID_HANDLE;

    rc = MSI_SetFeatureStateW(package,szFeature,iState);

    msiobj_release( &package->hdr );
    return rc;
}

/***********************************************************************
* MsiGetFeatureStateA   (MSI.@)
*/
580
UINT WINAPI MsiGetFeatureStateA(MSIHANDLE hInstall, LPCSTR szFeature,
581 582 583 584 585 586 587 588 589
                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
    LPWSTR szwFeature = NULL;
    UINT rc;
    
    szwFeature = strdupAtoW(szFeature);

    rc = MsiGetFeatureStateW(hInstall,szwFeature,piInstalled, piAction);

590
    msi_free( szwFeature);
591 592 593 594

    return rc;
}

595
UINT MSI_GetFeatureStateW(MSIPACKAGE *package, LPCWSTR szFeature,
596 597
                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
598
    MSIFEATURE *feature;
599

600 601
    feature = get_loaded_feature(package,szFeature);
    if (!feature)
602 603 604
        return ERROR_UNKNOWN_FEATURE;

    if (piInstalled)
605
        *piInstalled = feature->Installed;
606 607

    if (piAction)
608
        *piAction = feature->Action;
609

610
    TRACE("returning %i %i\n", feature->Installed, feature->Action);
611 612 613 614 615 616 617

    return ERROR_SUCCESS;
}

/***********************************************************************
* MsiGetFeatureStateW   (MSI.@)
*/
618
UINT WINAPI MsiGetFeatureStateW(MSIHANDLE hInstall, LPCWSTR szFeature,
619 620 621 622 623
                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
    MSIPACKAGE* package;
    UINT ret;

624
    TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szFeature), piInstalled, piAction);
625 626 627 628 629 630 631 632 633

    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
    if (!package)
        return ERROR_INVALID_HANDLE;
    ret = MSI_GetFeatureStateW(package, szFeature, piInstalled, piAction);
    msiobj_release( &package->hdr );
    return ret;
}

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
/***********************************************************************
* MsiGetFeatureCostA   (MSI.@)
*/
UINT WINAPI MsiGetFeatureCostA(MSIHANDLE hInstall, LPCSTR szFeature,
                  MSICOSTTREE iCostTree, INSTALLSTATE iState, INT *piCost)
{
    FIXME("(%ld %s %i %i %p): stub\n", hInstall, debugstr_a(szFeature),
          iCostTree, iState, piCost);
    if (piCost) *piCost = 0;
    return ERROR_SUCCESS;
}

/***********************************************************************
* MsiGetFeatureCostW   (MSI.@)
*/
UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
                  MSICOSTTREE iCostTree, INSTALLSTATE iState, INT *piCost)
{
    FIXME("(%ld %s %i %i %p): stub\n", hInstall, debugstr_w(szFeature),
          iCostTree, iState, piCost);
    if (piCost) *piCost = 0;
    return ERROR_SUCCESS;
}

658 659 660 661 662 663
/***********************************************************************
 * MsiSetComponentStateA (MSI.@)
 */
UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
                                  INSTALLSTATE iState)
{
664 665 666 667 668
    UINT rc;
    LPWSTR szwComponent = strdupAtoW(szComponent);

    rc = MsiSetComponentStateW(hInstall, szwComponent, iState);

669
    msi_free(szwComponent);
670 671

    return rc;
672 673
}

674 675 676
/***********************************************************************
 * MsiGetComponentStateA (MSI.@)
 */
677
UINT WINAPI MsiGetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
678 679 680 681 682 683 684 685 686
                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
    LPWSTR szwComponent= NULL;
    UINT rc;
    
    szwComponent= strdupAtoW(szComponent);

    rc = MsiGetComponentStateW(hInstall,szwComponent,piInstalled, piAction);

687
    msi_free( szwComponent);
688 689 690 691

    return rc;
}

692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
static UINT MSI_SetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
                                   INSTALLSTATE iState)
{
    MSICOMPONENT *comp;

    TRACE("%p %s %d\n", package, debugstr_w(szComponent), iState);

    comp = get_loaded_component(package, szComponent);
    if (!comp)
        return ERROR_UNKNOWN_COMPONENT;

    comp->Installed = iState;

    return ERROR_SUCCESS;
}

708
UINT MSI_GetComponentStateW(MSIPACKAGE *package, LPCWSTR szComponent,
709 710
                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
711
    MSICOMPONENT *comp;
712

713 714
    TRACE("%p %s %p %p\n", package, debugstr_w(szComponent),
           piInstalled, piAction);
715

716 717
    comp = get_loaded_component(package,szComponent);
    if (!comp)
718 719 720
        return ERROR_UNKNOWN_COMPONENT;

    if (piInstalled)
721
        *piInstalled = comp->Installed;
722 723

    if (piAction)
724
        *piAction = comp->Action;
725

726
    TRACE("states (%i, %i)\n", comp->Installed, comp->Action );
727 728 729 730

    return ERROR_SUCCESS;
}

731 732 733 734 735 736
/***********************************************************************
 * MsiSetComponentStateW (MSI.@)
 */
UINT WINAPI MsiSetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
                                  INSTALLSTATE iState)
{
737 738 739 740 741 742 743 744 745
    MSIPACKAGE* package;
    UINT ret;

    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
    if (!package)
        return ERROR_INVALID_HANDLE;
    ret = MSI_SetComponentStateW(package, szComponent, iState);
    msiobj_release(&package->hdr);
    return ret;
746 747
}

748 749 750
/***********************************************************************
 * MsiGetComponentStateW (MSI.@)
 */
751
UINT WINAPI MsiGetComponentStateW(MSIHANDLE hInstall, LPCWSTR szComponent,
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766
                  INSTALLSTATE *piInstalled, INSTALLSTATE *piAction)
{
    MSIPACKAGE* package;
    UINT ret;

    TRACE("%ld %s %p %p\n", hInstall, debugstr_w(szComponent),
           piInstalled, piAction);

    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
    if (!package)
        return ERROR_INVALID_HANDLE;
    ret = MSI_GetComponentStateW( package, szComponent, piInstalled, piAction);
    msiobj_release( &package->hdr );
    return ret;
}
Aric Stewart's avatar
Aric Stewart committed
767 768 769 770 771 772 773 774 775 776 777 778 779 780 781

/***********************************************************************
 * MsiGetLanguage (MSI.@)
 */
LANGID WINAPI MsiGetLanguage(MSIHANDLE hInstall)
{
    MSIPACKAGE* package;
    LANGID langid;
    static const WCHAR szProductLanguage[] =
        {'P','r','o','d','u','c','t','L','a','n','g','u','a','g','e',0};
    
    package = msihandle2msiinfo(hInstall, MSIHANDLETYPE_PACKAGE);
    if (!package)
        return ERROR_INVALID_HANDLE;

782 783
    langid = msi_get_property_int( package, szProductLanguage, 0 );
    msiobj_release( &package->hdr );
Aric Stewart's avatar
Aric Stewart committed
784 785
    return langid;
}
786

787
UINT MSI_SetInstallLevel( MSIPACKAGE *package, int iInstallLevel )
788 789 790 791 792 793 794
{
    static const WCHAR szInstallLevel[] = {
        'I','N','S','T','A','L','L','L','E','V','E','L',0 };
    static const WCHAR fmt[] = { '%','d',0 };
    WCHAR level[6];
    UINT r;

795
    TRACE("%p %i\n", package, iInstallLevel);
796 797 798 799 800 801

    if (iInstallLevel<1 || iInstallLevel>32767)
        return ERROR_INVALID_PARAMETER;

    sprintfW( level, fmt, iInstallLevel );
    r = MSI_SetPropertyW( package, szInstallLevel, level );
802 803 804 805 806
    if ( r == ERROR_SUCCESS )
    {
        r = MSI_SetFeatureStates( package );
    }

807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
    return r;
}

/***********************************************************************
 * MsiSetInstallLevel (MSI.@)
 */
UINT WINAPI MsiSetInstallLevel(MSIHANDLE hInstall, int iInstallLevel)
{
    MSIPACKAGE* package;
    UINT r;

    TRACE("%ld %i\n", hInstall, iInstallLevel);

    package = msihandle2msiinfo( hInstall, MSIHANDLETYPE_PACKAGE );
    if ( !package )
        return ERROR_INVALID_HANDLE;

    r = MSI_SetInstallLevel( package, iInstallLevel );

826
    msiobj_release( &package->hdr );
827

828 829
    return r;
}
830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858

/***********************************************************************
 * MsiGetFeatureValidStatesW (MSI.@)
 */
UINT WINAPI MsiGetFeatureValidStatesW(MSIHANDLE hInstall, LPCWSTR szFeature,
                  DWORD* pInstallState)
{
    if(pInstallState) *pInstallState = 1<<INSTALLSTATE_LOCAL;
    FIXME("%ld %s %p stub returning %d\n",
        hInstall, debugstr_w(szFeature), pInstallState, pInstallState ? *pInstallState : 0);

    return ERROR_SUCCESS;
}

/***********************************************************************
 * MsiGetFeatureValidStatesA (MSI.@)
 */
UINT WINAPI MsiGetFeatureValidStatesA(MSIHANDLE hInstall, LPCSTR szFeature,
                  DWORD* pInstallState)
{
    UINT ret;
    LPWSTR szwFeature = strdupAtoW(szFeature);

    ret = MsiGetFeatureValidStatesW(hInstall, szwFeature, pInstallState);

    msi_free(szwFeature);

    return ret;
}