shell32_main.c 37.7 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1
/*
2
 *                 Shell basics
Alexandre Julliard's avatar
Alexandre Julliard committed
3
 *
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * Copyright 1998 Marcus Meissner
 * Copyright 1998 Juergen Schmied (jsch)  *  <juergen.schmied@metronet.de>
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Alexandre Julliard's avatar
Alexandre Julliard committed
20
 */
21 22 23

#include "config.h"

Alexandre Julliard's avatar
Alexandre Julliard committed
24 25
#include <stdlib.h>
#include <string.h>
26
#include <stdarg.h>
27
#include <stdio.h>
28

29 30
#define COBJMACROS

31
#include "windef.h"
32
#include "winbase.h"
33 34
#include "winerror.h"
#include "winreg.h"
35 36
#include "dlgs.h"
#include "shellapi.h"
37 38
#include "winuser.h"
#include "wingdi.h"
39 40
#include "shlobj.h"
#include "shlwapi.h"
41

42
#include "undocshell.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
43
#include "pidl.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
44
#include "shell32_main.h"
45
#include "version.h"
46
#include "shresdef.h"
47

48
#include "wine/debug.h"
49
#include "wine/unicode.h"
50

51
WINE_DEFAULT_DEBUG_CHANNEL(shell);
52

53 54
extern const char * const SHELL_Authors[];

55
#define MORE_DEBUG 1
Alexandre Julliard's avatar
Alexandre Julliard committed
56
/*************************************************************************
57
 * CommandLineToArgvW            [SHELL32.@]
58
 *
59
 * We must interpret the quotes in the command line to rebuild the argv
60 61 62 63 64 65
 * array correctly:
 * - arguments are separated by spaces or tabs
 * - quotes serve as optional argument delimiters
 *   '"a b"'   -> 'a b'
 * - escaped quotes must be converted back to '"'
 *   '\"'      -> '"'
66
 * - an odd number of '\'s followed by '"' correspond to half that number
67 68 69 70
 *   of '\' followed by a '"' (extension of the above)
 *   '\\\"'    -> '\"'
 *   '\\\\\"'  -> '\\"'
 * - an even number of '\'s followed by a '"' correspond to half that number
71
 *   of '\', plus a regular quote serving as an argument delimiter (which
72 73 74 75 76 77 78 79 80 81 82 83
 *   means it does not appear in the result)
 *   'a\\"b c"'   -> 'a\b c'
 *   'a\\\\"b c"' -> 'a\\b c'
 * - '\' that are not followed by a '"' are copied literally
 *   'a\b'     -> 'a\b'
 *   'a\\b'    -> 'a\\b'
 *
 * Note:
 * '\t' == 0x0009
 * ' '  == 0x0020
 * '"'  == 0x0022
 * '\\' == 0x005c
Alexandre Julliard's avatar
Alexandre Julliard committed
84
 */
85
LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
86 87 88
{
    DWORD argc;
    LPWSTR  *argv;
89
    LPCWSTR cs;
90 91 92 93
    LPWSTR arg,s,d;
    LPWSTR cmdline;
    int in_quotes,bcount;

94 95
    if (*lpCmdline==0)
    {
96
        /* Return the path to the executable */
97
        DWORD len, size=16;
98

99
        argv=LocalAlloc(LMEM_FIXED, size);
100 101
        for (;;)
        {
102
            len = GetModuleFileNameW(0, (LPWSTR)(argv+1), (size-sizeof(LPWSTR))/sizeof(WCHAR));
103 104
            if (!len)
            {
105
                LocalFree(argv);
106 107 108
                return NULL;
            }
            if (len < size) break;
109
            size*=2;
110
            argv=LocalReAlloc(argv, size, 0);
111
        }
112
        argv[0]=(LPWSTR)(argv+1);
113 114 115 116 117 118
        if (numargs)
            *numargs=2;

        return argv;
    }

119
    /* to get a writable copy */
120 121 122
    argc=0;
    bcount=0;
    in_quotes=0;
123
    cs=lpCmdline;
124 125 126 127
    while (1)
    {
        if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes))
        {
128 129 130
            /* space */
            argc++;
            /* skip the remaining spaces */
131 132
            while (*cs==0x0009 || *cs==0x0020) {
                cs++;
133
            }
134
            if (*cs==0)
135 136 137
                break;
            bcount=0;
            continue;
138 139 140
        }
        else if (*cs==0x005c)
        {
141 142
            /* '\', count them */
            bcount++;
143 144 145
        }
        else if ((*cs==0x0022) && ((bcount & 1)==0))
        {
146 147 148
            /* unescaped '"' */
            in_quotes=!in_quotes;
            bcount=0;
149 150 151
        }
        else
        {
152 153 154
            /* a regular character */
            bcount=0;
        }
155
        cs++;
156
    }
157 158 159
    /* Allocate in a single lump, the string array, and the strings that go with it.
     * This way the caller can make a single GlobalFree call to free both, as per MSDN.
     */
160
    argv=LocalAlloc(LMEM_FIXED, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR));
161 162 163 164
    if (!argv)
        return NULL;
    cmdline=(LPWSTR)(argv+argc);
    strcpyW(cmdline, lpCmdline);
165 166 167 168 169

    argc=0;
    bcount=0;
    in_quotes=0;
    arg=d=s=cmdline;
170 171 172 173
    while (*s)
    {
        if ((*s==0x0009 || *s==0x0020) && !in_quotes)
        {
174 175 176 177 178 179 180 181 182 183 184 185
            /* Close the argument and copy it */
            *d=0;
            argv[argc++]=arg;

            /* skip the remaining spaces */
            do {
                s++;
            } while (*s==0x0009 || *s==0x0020);

            /* Start with a new argument */
            arg=d=s;
            bcount=0;
186 187 188
        }
        else if (*s==0x005c)
        {
189 190 191
            /* '\\' */
            *d++=*s++;
            bcount++;
192 193 194
        }
        else if (*s==0x0022)
        {
195
            /* '"' */
196 197
            if ((bcount & 1)==0)
            {
198
                /* Preceded by an even number of '\', this is half that
199 200 201 202 203
                 * number of '\', plus a quote which we erase.
                 */
                d-=bcount/2;
                in_quotes=!in_quotes;
                s++;
204 205 206
            }
            else
            {
207
                /* Preceded by an odd number of '\', this is half that
208 209 210 211 212 213 214
                 * number of '\' followed by a '"'
                 */
                d=d-bcount/2-1;
                *d++='"';
                s++;
            }
            bcount=0;
215 216 217
        }
        else
        {
218 219 220 221 222
            /* a regular character */
            *d++=*s++;
            bcount=0;
        }
    }
223 224
    if (*arg)
    {
225
        *d='\0';
226
        argv[argc++]=arg;
227 228 229 230 231
    }
    if (numargs)
        *numargs=argc;

    return argv;
Alexandre Julliard's avatar
Alexandre Julliard committed
232 233
}

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
static DWORD shgfi_get_exe_type(LPCWSTR szFullPath)
{
    BOOL status = FALSE;
    HANDLE hfile;
    DWORD BinaryType;
    IMAGE_DOS_HEADER mz_header;
    IMAGE_NT_HEADERS nt;
    DWORD len;
    char magic[4];

    status = GetBinaryTypeW (szFullPath, &BinaryType);
    if (!status)
        return 0;
    if (BinaryType == SCS_DOS_BINARY || BinaryType == SCS_PIF_BINARY)
        return 0x4d5a;

    hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ,
                         NULL, OPEN_EXISTING, 0, 0 );
    if ( hfile == INVALID_HANDLE_VALUE )
        return 0;

    /*
     * The next section is adapted from MODULE_GetBinaryType, as we need
     * to examine the image header to get OS and version information. We
     * know from calling GetBinaryTypeA that the image is valid and either
     * an NE or PE, so much error handling can be omitted.
     * Seek to the start of the file and read the header information.
     */

    SetFilePointer( hfile, 0, NULL, SEEK_SET );
    ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL );

    SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
    ReadFile( hfile, magic, sizeof(magic), &len, NULL );
    if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
    {
        SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
        ReadFile( hfile, &nt, sizeof(nt), &len, NULL );
        CloseHandle( hfile );
273 274 275
        /* DLL files are not executable and should return 0 */
        if (nt.FileHeader.Characteristics & IMAGE_FILE_DLL)
            return 0;
276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
        if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
        {
             return IMAGE_NT_SIGNATURE | 
                   (nt.OptionalHeader.MajorSubsystemVersion << 24) |
                   (nt.OptionalHeader.MinorSubsystemVersion << 16);
        }
        return IMAGE_NT_SIGNATURE;
    }
    else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
    {
        IMAGE_OS2_HEADER ne;
        SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
        ReadFile( hfile, &ne, sizeof(ne), &len, NULL );
        CloseHandle( hfile );
        if (ne.ne_exetyp == 2)
            return IMAGE_OS2_SIGNATURE | (ne.ne_expver << 16);
        return 0;
    }
    CloseHandle( hfile );
    return 0;
}

298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
/*************************************************************************
 * SHELL_IsShortcut		[internal]
 *
 * Decide if an item id list points to a shell shortcut
 */
BOOL SHELL_IsShortcut(LPCITEMIDLIST pidlLast)
{
    char szTemp[MAX_PATH];
    HKEY keyCls;
    BOOL ret = FALSE;

    if (_ILGetExtension(pidlLast, szTemp, MAX_PATH) &&
          HCR_MapTypeToValueA(szTemp, szTemp, MAX_PATH, TRUE))
    {
        if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls))
        {
          if (ERROR_SUCCESS == RegQueryValueExA(keyCls, "IsShortcut", NULL, NULL, NULL, NULL))
            ret = TRUE;

          RegCloseKey(keyCls);
        }
    }

    return ret;
}

324 325 326 327 328 329 330
#define SHGFI_KNOWN_FLAGS \
    (SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \
     SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \
     SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ATTRIBUTES | \
     SHGFI_ICONLOCATION | SHGFI_EXETYPE | SHGFI_SYSICONINDEX | \
     SHGFI_LINKOVERLAY | SHGFI_SELECTED | SHGFI_ATTR_SPECIFIED)

Alexandre Julliard's avatar
Alexandre Julliard committed
331
/*************************************************************************
332
 * SHGetFileInfoW            [SHELL32.@]
333
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
334
 */
Kevin Koltzau's avatar
Kevin Koltzau committed
335 336
DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
                                SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags )
337
{
338 339
    WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH];
    int iIndex;
Kevin Koltzau's avatar
Kevin Koltzau committed
340 341
    DWORD_PTR ret = TRUE;
    DWORD dwAttributes = 0;
342 343 344 345 346
    IShellFolder * psfParent = NULL;
    IExtractIconW * pei = NULL;
    LPITEMIDLIST    pidlLast = NULL, pidl = NULL;
    HRESULT hr = S_OK;
    BOOL IconNotYetLoaded=TRUE;
347
    UINT uGilFlags = 0;
348

349
    TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
350 351 352 353 354 355 356
          (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes,
          psfi, psfi->dwAttributes, sizeofpsfi, flags);

    if ( (flags & SHGFI_USEFILEATTRIBUTES) && 
         (flags & (SHGFI_ATTRIBUTES|SHGFI_EXETYPE|SHGFI_PIDL)))
        return FALSE;

357
    /* windows initializes these values regardless of the flags */
358 359 360 361 362 363 364 365 366
    if (psfi != NULL)
    {
        psfi->szDisplayName[0] = '\0';
        psfi->szTypeName[0] = '\0';
        psfi->iIcon = 0;
    }

    if (!(flags & SHGFI_PIDL))
    {
367
        /* SHGetFileInfo should work with absolute and relative paths */
368 369 370 371 372 373 374 375
        if (PathIsRelativeW(path))
        {
            GetCurrentDirectoryW(MAX_PATH, szLocation);
            PathCombineW(szFullPath, szLocation, path);
        }
        else
        {
            lstrcpynW(szFullPath, path, MAX_PATH);
376
        }
377
    }
378

379 380 381 382
    if (flags & SHGFI_EXETYPE)
    {
        if (flags != SHGFI_EXETYPE)
            return 0;
383
        return shgfi_get_exe_type(szFullPath);
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
    }

    /*
     * psfi is NULL normally to query EXE type. If it is NULL, none of the
     * below makes sense anyway. Windows allows this and just returns FALSE
     */
    if (psfi == NULL)
        return FALSE;

    /*
     * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES
     * is not specified.
     * The pidl functions fail on not existing file names
     */

    if (flags & SHGFI_PIDL)
    {
        pidl = ILClone((LPCITEMIDLIST)path);
    }
    else if (!(flags & SHGFI_USEFILEATTRIBUTES))
    {
        hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes);
    }

    if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES))
    {
        /* get the parent shellfolder */
        if (pidl)
        {
            hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent,
                                (LPCITEMIDLIST*)&pidlLast );
415 416
            if (SUCCEEDED(hr))
                pidlLast = ILClone(pidlLast);
417 418 419 420 421 422
            ILFree(pidl);
        }
        else
        {
            ERR("pidl is null!\n");
            return FALSE;
423
        }
424
    }
425

426 427 428 429
    /* get the attributes of the child */
    if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
    {
        if (!(flags & SHGFI_ATTR_SPECIFIED))
430
        {
431
            psfi->dwAttributes = 0xffffffff;
432
        }
433 434 435
        IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
                                      &(psfi->dwAttributes) );
    }
436

437 438 439 440
    /* get the displayname */
    if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
    {
        if (flags & SHGFI_USEFILEATTRIBUTES)
441
        {
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470
            lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath));
        }
        else
        {
            STRRET str;
            hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast,
                                                SHGDN_INFOLDER, &str);
            StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
        }
    }

    /* get the type name */
    if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
    {
        static const WCHAR szFile[] = { 'F','i','l','e',0 };
        static const WCHAR szDashFile[] = { '-','f','i','l','e',0 };

        if (!(flags & SHGFI_USEFILEATTRIBUTES))
        {
            char ftype[80];

            _ILGetFileType(pidlLast, ftype, 80);
            MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 );
        }
        else
        {
            if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
                strcatW (psfi->szTypeName, szFile);
            else 
471
            {
472 473 474 475 476
                WCHAR sTemp[64];

                lstrcpyW(sTemp,PathFindExtensionW(szFullPath));
                if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) &&
                    HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE )))
477
                {
478 479
                    lstrcpynW (psfi->szTypeName, sTemp, 64);
                    strcatW (psfi->szTypeName, szDashFile);
480 481
                }
            }
482
        }
483
    }
484

485
    /* ### icons ###*/
486 487 488 489 490 491 492 493 494 495 496
    if (flags & SHGFI_OPENICON)
        uGilFlags |= GIL_OPENICON;

    if (flags & SHGFI_LINKOVERLAY)
        uGilFlags |= GIL_FORSHORTCUT;
    else if ((flags&SHGFI_ADDOVERLAYS) ||
             (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON)
    {
        if (SHELL_IsShortcut(pidlLast))
            uGilFlags |= GIL_FORSHORTCUT;
    }
497

498 499
    if (flags & SHGFI_OVERLAYINDEX)
        FIXME("SHGFI_OVERLAYINDEX unhandled\n");
500

501 502
    if (flags & SHGFI_SELECTED)
        FIXME("set icon to selected, stub\n");
503

504 505
    if (flags & SHGFI_SHELLICONSIZE)
        FIXME("set icon to shell size, stub\n");
506

507 508 509 510
    /* get the iconlocation */
    if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
    {
        UINT uDummy,uFlags;
511

512
        if (flags & SHGFI_USEFILEATTRIBUTES)
513
        {
514 515 516 517 518
            if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
            {
                lstrcpyW(psfi->szDisplayName, swShell32Name);
                psfi->iIcon = -IDI_SHELL_FOLDER;
            }
519
            else
520 521 522 523 524
            {
                WCHAR* szExt;
                static const WCHAR p1W[] = {'%','1',0};
                WCHAR sTemp [MAX_PATH];

525
                szExt = PathFindExtensionW(szFullPath);
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
                TRACE("szExt=%s\n", debugstr_w(szExt));
                if ( szExt &&
                     HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
                     HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &psfi->iIcon))
                {
                    if (lstrcmpW(p1W, sTemp))
                        strcpyW(psfi->szDisplayName, sTemp);
                    else
                    {
                        /* the icon is in the file */
                        strcpyW(psfi->szDisplayName, szFullPath);
                    }
                }
                else
                    ret = FALSE;
            }
        }
        else
        {
            hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1,
                (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW,
                &uDummy, (LPVOID*)&pei);
            if (SUCCEEDED(hr))
            {
                hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
                    szLocation, MAX_PATH, &iIndex, &uFlags);
552

553 554 555 556 557 558 559 560 561
                if (uFlags & GIL_NOTFILENAME)
                    ret = FALSE;
                else
                {
                    lstrcpyW (psfi->szDisplayName, szLocation);
                    psfi->iIcon = iIndex;
                }
                IExtractIconW_Release(pei);
            }
562 563
        }
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
564

565 566 567 568 569 570 571
    /* get icon index (or load icon)*/
    if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
    {
        if (flags & SHGFI_USEFILEATTRIBUTES)
        {
            WCHAR sTemp [MAX_PATH];
            WCHAR * szExt;
572
            int icon_idx=0;
573

574
            lstrcpynW(sTemp, szFullPath, MAX_PATH);
575 576

            if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
577
                psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0);
578
            else
579
            {
580 581 582
                static const WCHAR p1W[] = {'%','1',0};

                psfi->iIcon = 0;
583
                szExt = PathFindExtensionW(sTemp);
584 585
                if ( szExt &&
                     HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
586
                     HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &icon_idx))
587 588 589 590 591 592
                {
                    if (!lstrcmpW(p1W,sTemp))            /* icon is in the file */
                        strcpyW(sTemp, szFullPath);

                    if (flags & SHGFI_SYSICONINDEX) 
                    {
593
                        psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0);
594 595 596 597 598 599 600
                        if (psfi->iIcon == -1)
                            psfi->iIcon = 0;
                    }
                    else 
                    {
                        IconNotYetLoaded=FALSE;
                        if (flags & SHGFI_SMALLICON)
601
                            PrivateExtractIconsW( sTemp,icon_idx,
602 603 604 605
                                GetSystemMetrics( SM_CXSMICON ),
                                GetSystemMetrics( SM_CYSMICON ),
                                &psfi->hIcon, 0, 1, 0);
                        else
606
                            PrivateExtractIconsW( sTemp, icon_idx,
607 608 609
                                GetSystemMetrics( SM_CXICON),
                                GetSystemMetrics( SM_CYICON),
                                &psfi->hIcon, 0, 1, 0);
610
                        psfi->iIcon = icon_idx;
611 612
                    }
                }
613
            }
614 615 616 617
        }
        else
        {
            if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
618
                uGilFlags, &(psfi->iIcon))))
619 620 621 622 623 624 625
            {
                ret = FALSE;
            }
        }
        if (ret)
        {
            if (flags & SHGFI_SMALLICON)
Kevin Koltzau's avatar
Kevin Koltzau committed
626
                ret = (DWORD_PTR) ShellSmallIconList;
627
            else
Kevin Koltzau's avatar
Kevin Koltzau committed
628
                ret = (DWORD_PTR) ShellBigIconList;
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
        }
    }

    /* icon handle */
    if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded)
    {
        if (flags & SHGFI_SMALLICON)
            psfi->hIcon = ImageList_GetIcon( ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
        else
            psfi->hIcon = ImageList_GetIcon( ShellBigIconList, psfi->iIcon, ILD_NORMAL);
    }

    if (flags & ~SHGFI_KNOWN_FLAGS)
        FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS);

    if (psfParent)
        IShellFolder_Release(psfParent);

    if (hr != S_OK)
        ret = FALSE;

650
    SHFree(pidlLast);
651

652
#ifdef MORE_DEBUG
653
    TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
654 655
           psfi->hIcon, psfi->iIcon, psfi->dwAttributes,
           debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret);
656
#endif
657 658

    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
659 660
}

661
/*************************************************************************
662
 * SHGetFileInfoA            [SHELL32.@]
663
 */
Kevin Koltzau's avatar
Kevin Koltzau committed
664 665 666
DWORD_PTR WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
                                SHFILEINFOA *psfi, UINT sizeofpsfi,
                                UINT flags )
667
{
668
    INT len;
669 670
    LPWSTR temppath = NULL;
    LPCWSTR pathW;
671 672 673 674 675 676
    DWORD ret;
    SHFILEINFOW temppsfi;

    if (flags & SHGFI_PIDL)
    {
        /* path contains a pidl */
677
        pathW = (LPCWSTR)path;
678 679 680 681 682 683
    }
    else
    {
        len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
        temppath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
        MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len);
684
        pathW = temppath;
685 686 687 688 689 690
    }

    if (psfi && (flags & SHGFI_ATTR_SPECIFIED))
        temppsfi.dwAttributes=psfi->dwAttributes;

    if (psfi == NULL)
691
        ret = SHGetFileInfoW(pathW, dwFileAttributes, NULL, sizeof(temppsfi), flags);
692
    else
693
        ret = SHGetFileInfoW(pathW, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708

    if (psfi)
    {
        if(flags & SHGFI_ICON)
            psfi->hIcon=temppsfi.hIcon;
        if(flags & (SHGFI_SYSICONINDEX|SHGFI_ICON|SHGFI_ICONLOCATION))
            psfi->iIcon=temppsfi.iIcon;
        if(flags & SHGFI_ATTRIBUTES)
            psfi->dwAttributes=temppsfi.dwAttributes;
        if(flags & (SHGFI_DISPLAYNAME|SHGFI_ICONLOCATION))
        {
            WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1,
                  psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL);
        }
        if(flags & SHGFI_TYPENAME)
709
        {
710 711
            WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1,
                  psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL);
712
        }
713 714
    }

715
    HeapFree(GetProcessHeap(), 0, temppath);
716 717

    return ret;
718 719
}

720
/*************************************************************************
721
 * DuplicateIcon            [SHELL32.@]
722 723 724 725
 */
HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
{
    ICONINFO IconInfo;
726
    HICON hDupIcon = 0;
727

728
    TRACE("%p %p\n", hInstance, hIcon);
729

730
    if (GetIconInfo(hIcon, &IconInfo))
731 732 733 734
    {
        hDupIcon = CreateIconIndirect(&IconInfo);

        /* clean up hbmMask and hbmColor */
735 736
        DeleteObject(IconInfo.hbmMask);
        DeleteObject(IconInfo.hbmColor);
737
    }
738

739 740
    return hDupIcon;
}
741

Alexandre Julliard's avatar
Alexandre Julliard committed
742
/*************************************************************************
743
 * ExtractIconA                [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
744
 */
745 746
HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex)
{   
747 748 749
    HICON ret;
    INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0);
    LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
750

751
    TRACE("%p %s %d\n", hInstance, lpszFile, nIconIndex);
752

753 754 755 756 757
    MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len);
    ret = ExtractIconW(hInstance, lpwstrFile, nIconIndex);
    HeapFree(GetProcessHeap(), 0, lpwstrFile);

    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
758 759 760
}

/*************************************************************************
761
 * ExtractIconW                [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
762
 */
763 764
HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
{
765 766 767 768 769 770 771 772 773 774
    HICON  hIcon = NULL;
    UINT ret;
    UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON);

    TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex);

    if (nIconIndex == 0xFFFFFFFF)
    {
        ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR);
        if (ret != 0xFFFFFFFF && ret)
Kevin Koltzau's avatar
Kevin Koltzau committed
775
            return (HICON)(UINT_PTR)ret;
776 777 778 779 780 781 782 783 784 785 786
        return NULL;
    }
    else
        ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR);

    if (ret == 0xFFFFFFFF)
        return (HICON)1;
    else if (ret > 0 && hIcon)
        return hIcon;

    return NULL;
Alexandre Julliard's avatar
Alexandre Julliard committed
787 788
}

789 790 791 792 793 794 795 796 797 798 799 800 801 802 803
/*************************************************************************
 * Printer_LoadIconsW        [SHELL32.205]
 */
VOID WINAPI Printer_LoadIconsW(LPCWSTR wsPrinterName, HICON * pLargeIcon, HICON * pSmallIcon)
{
    INT iconindex=IDI_SHELL_PRINTER;

    TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName), pLargeIcon, pSmallIcon);

    /* We should check if wsPrinterName is
       1. the Default Printer or not
       2. connected or not
       3. a Local Printer or a Network-Printer
       and use different Icons
    */
804 805 806 807
    if((wsPrinterName != NULL) && (wsPrinterName[0] != 0))
    {
        FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName));
    }
808 809 810 811 812 813 814 815 816 817 818 819

    if(pLargeIcon != NULL)
        *pLargeIcon = LoadImageW(shell32_hInstance,
                                 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
                                 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE);

    if(pSmallIcon != NULL)
        *pSmallIcon = LoadImageW(shell32_hInstance,
                                 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
                                 16, 16, LR_DEFAULTCOLOR);
}

820 821 822 823 824 825 826 827 828
/*************************************************************************
 * Printers_RegisterWindowW        [SHELL32.213]
 * used by "printui.dll":
 * find the Window of the given Type for the specific Printer and 
 * return the already existent hwnd or open a new window
 */
BOOL WINAPI Printers_RegisterWindowW(LPCWSTR wsPrinter, DWORD dwType,
            HANDLE * phClassPidl, HWND * phwnd)
{
829
    FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType,
830 831 832 833 834 835 836 837 838 839 840 841 842 843
                phClassPidl, (phClassPidl != NULL) ? *(phClassPidl) : NULL,
                phwnd, (phwnd != NULL) ? *(phwnd) : NULL);

    return FALSE;
} 

/*************************************************************************
 * Printers_UnregisterWindow      [SHELL32.214]
 */
VOID WINAPI Printers_UnregisterWindow(HANDLE hClassPidl, HWND hwnd)
{
    FIXME("(%p, %p) stub!\n", hClassPidl, hwnd);
} 

844 845
/*************************************************************************/

Alexandre Julliard's avatar
Alexandre Julliard committed
846
typedef struct
847 848 849
{
    LPCWSTR  szApp;
    LPCWSTR  szOtherStuff;
850
    HICON hIcon;
851
    HFONT hFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
852 853
} ABOUT_INFO;

854
#define DROP_FIELD_TOP    (-12)
Alexandre Julliard's avatar
Alexandre Julliard committed
855

856
static void paint_dropline( HDC hdc, HWND hWnd )
857
{
858
    HWND hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_WINE_TEXT);
859 860 861 862 863 864 865 866
    RECT rect;

    if (!hWndCtl) return;
    GetWindowRect( hWndCtl, &rect );
    MapWindowPoints( 0, hWnd, (LPPOINT)&rect, 2 );
    rect.top += DROP_FIELD_TOP;
    rect.bottom = rect.top + 2;
    DrawEdge( hdc, &rect, BDR_SUNKENOUTER, BF_RECT );
Alexandre Julliard's avatar
Alexandre Julliard committed
867 868 869
}

/*************************************************************************
870
 * SHAppBarMessage            [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
871
 */
872
UINT_PTR WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data)
873
{
874 875 876 877
    int width=data->rc.right - data->rc.left;
    int height=data->rc.bottom - data->rc.top;
    RECT rec=data->rc;

878
    FIXME("msg=%d, data={cb=%d, hwnd=%p, callback=%x, edge=%d, rc=%s, lparam=%lx}: stub\n",
879 880 881
          msg, data->cbSize, data->hWnd, data->uCallbackMessage, data->uEdge,
          wine_dbgstr_rect(&data->rc), data->lParam);

882 883 884 885 886
    switch (msg)
    {
    case ABM_GETSTATE:
        return ABS_ALWAYSONTOP | ABS_AUTOHIDE;
    case ABM_GETTASKBARPOS:
887 888
        /* FIXME: This is wrong.  It should return the taskbar co-ords and edge from the monitor
           which contains data->hWnd */
889 890 891 892 893 894 895
        GetWindowRect(data->hWnd, &rec);
        data->rc=rec;
        return TRUE;
    case ABM_ACTIVATE:
        SetActiveWindow(data->hWnd);
        return TRUE;
    case ABM_GETAUTOHIDEBAR:
896
        return 0; /* pretend there is no autohide bar */
897
    case ABM_NEW:
898 899
        /* cbSize, hWnd, and uCallbackMessage are used. All other ignored */
        SetWindowPos(data->hWnd,HWND_TOP,0,0,0,0,SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE);
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
        return TRUE;
    case ABM_QUERYPOS:
        GetWindowRect(data->hWnd, &(data->rc));
        return TRUE;
    case ABM_REMOVE:
        FIXME("ABM_REMOVE broken\n");
        /* FIXME: this is wrong; should it be DestroyWindow instead? */
        /*CloseHandle(data->hWnd);*/
        return TRUE;
    case ABM_SETAUTOHIDEBAR:
        SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top,
                         width,height,SWP_SHOWWINDOW);
        return TRUE;
    case ABM_SETPOS:
        data->uEdge=(ABE_RIGHT | ABE_LEFT);
        SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top,
                     width,height,SWP_SHOWWINDOW);
        return TRUE;
    case ABM_WINDOWPOSCHANGED:
        return TRUE;
    }
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
922 923 924
}

/*************************************************************************
925
 * SHHelpShortcuts_RunDLLA        [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
926 927
 *
 */
928 929
DWORD WINAPI SHHelpShortcuts_RunDLLA(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
{
930
    FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
931 932 933 934 935 936 937 938
    return 0;
}

/*************************************************************************
 * SHHelpShortcuts_RunDLLA        [SHELL32.@]
 *
 */
DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
939
{
940
    FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
941
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
942 943 944
}

/*************************************************************************
945
 * SHLoadInProc                [SHELL32.@]
946
 * Create an instance of specified object class from within
947
 * the shell process and release it immediately
Alexandre Julliard's avatar
Alexandre Julliard committed
948
 */
949
HRESULT WINAPI SHLoadInProc (REFCLSID rclsid)
950
{
951
    void *ptr = NULL;
952

953 954 955 956 957 958 959 960 961 962
    TRACE("%s\n", debugstr_guid(rclsid));

    CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr);
    if(ptr)
    {
        IUnknown * pUnk = ptr;
        IUnknown_Release(pUnk);
        return NOERROR;
    }
    return DISP_E_MEMBERNOTFOUND;
Alexandre Julliard's avatar
Alexandre Julliard committed
963 964 965
}

/*************************************************************************
966
 * AboutDlgProc            (internal)
Alexandre Julliard's avatar
Alexandre Julliard committed
967
 */
968
INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
969
                              LPARAM lParam )
970 971
{
    HWND hWndCtl;
Alexandre Julliard's avatar
Alexandre Julliard committed
972

973
    TRACE("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
974 975

    switch(msg)
976 977 978 979
    {
    case WM_INITDIALOG:
        {
            ABOUT_INFO *info = (ABOUT_INFO *)lParam;
980 981
            WCHAR template[512], buffer[512], version[64];
            extern const char *wine_get_build_id(void);
982

Alexandre Julliard's avatar
Alexandre Julliard committed
983
            if (info)
984 985 986
            {
                const char* const *pstr = SHELL_Authors;
                SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0);
987 988 989
                GetWindowTextW( hWnd, template, sizeof(template)/sizeof(WCHAR) );
                sprintfW( buffer, template, info->szApp );
                SetWindowTextW( hWnd, buffer );
990 991
                SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT1), info->szApp );
                SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT2), info->szOtherStuff );
992 993 994 995 996 997
                GetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3),
                                template, sizeof(template)/sizeof(WCHAR) );
                MultiByteToWideChar( CP_UTF8, 0, wine_get_build_id(), -1,
                                     version, sizeof(version)/sizeof(WCHAR) );
                sprintfW( buffer, template, version );
                SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3), buffer );
998
                hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_LISTBOX);
999
                SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 );
1000
                SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1001
                while (*pstr)
1002
                {
1003
                    /* authors list is in utf-8 format */
1004 1005
                    MultiByteToWideChar( CP_UTF8, 0, *pstr, -1, buffer, sizeof(buffer)/sizeof(WCHAR) );
                    SendMessageW( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)buffer );
Alexandre Julliard's avatar
Alexandre Julliard committed
1006 1007
                    pstr++;
                }
1008
                SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
1009 1010 1011 1012 1013
            }
        }
        return 1;

    case WM_PAINT:
1014 1015 1016
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint( hWnd, &ps );
1017
            paint_dropline( hDC, hWnd );
1018 1019 1020
            EndPaint( hWnd, &ps );
        }
    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1021 1022

    case WM_COMMAND:
1023 1024 1025
        if (wParam == IDOK || wParam == IDCANCEL)
        {
            EndDialog(hWnd, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
1026 1027
            return TRUE;
        }
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
        if (wParam == IDC_ABOUT_LICENSE)
        {
            MSGBOXPARAMSW params;

            params.cbSize = sizeof(params);
            params.hwndOwner = hWnd;
            params.hInstance = shell32_hInstance;
            params.lpszText = MAKEINTRESOURCEW(IDS_LICENSE);
            params.lpszCaption = MAKEINTRESOURCEW(IDS_LICENSE_CAPTION);
            params.dwStyle = MB_ICONINFORMATION | MB_OK;
            params.lpszIcon = 0;
            params.dwContextHelpId = 0;
            params.lpfnMsgBoxCallback = NULL;
            params.dwLanguageId = LANG_NEUTRAL;
            MessageBoxIndirectW( &params );
        }
Alexandre Julliard's avatar
Alexandre Julliard committed
1044
        break;
1045 1046 1047
    case WM_CLOSE:
      EndDialog(hWnd, TRUE);
      break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1048
    }
1049

Alexandre Julliard's avatar
Alexandre Julliard committed
1050 1051 1052 1053 1054
    return 0;
}


/*************************************************************************
1055
 * ShellAboutA                [SHELL32.288]
Alexandre Julliard's avatar
Alexandre Julliard committed
1056
 */
1057 1058 1059
BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon )
{
    BOOL ret;
1060 1061
    LPWSTR appW = NULL, otherW = NULL;
    int len;
1062

1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
    if (szApp)
    {
        len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0);
        appW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
        MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len);
    }
    if (szOtherStuff)
    {
        len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0);
        otherW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
        MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len);
    }

    ret = ShellAboutW(hWnd, appW, otherW, hIcon);

1078 1079
    HeapFree(GetProcessHeap(), 0, otherW);
    HeapFree(GetProcessHeap(), 0, appW);
1080
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1081 1082 1083 1084
}


/*************************************************************************
1085
 * ShellAboutW                [SHELL32.289]
Alexandre Julliard's avatar
Alexandre Julliard committed
1086
 */
1087 1088
BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
                             HICON hIcon )
1089
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1090
    ABOUT_INFO info;
1091
    LOGFONTW logFont;
1092 1093
    HRSRC hRes;
    LPVOID template;
1094
    BOOL bRet;
Jacek Caban's avatar
Jacek Caban committed
1095 1096
    static const WCHAR wszSHELL_ABOUT_MSGBOX[] =
        {'S','H','E','L','L','_','A','B','O','U','T','_','M','S','G','B','O','X',0};
Alexandre Julliard's avatar
Alexandre Julliard committed
1097

1098
    TRACE("\n");
1099

Jacek Caban's avatar
Jacek Caban committed
1100
    if(!(hRes = FindResourceW(shell32_hInstance, wszSHELL_ABOUT_MSGBOX, (LPWSTR)RT_DIALOG)))
1101
        return FALSE;
1102
    if(!(template = LoadResource(shell32_hInstance, hRes)))
1103
        return FALSE;
1104
    if (!hIcon) hIcon = LoadImageW( 0, (LPWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED );
1105 1106
    info.szApp        = szApp;
    info.szOtherStuff = szOtherStuff;
1107
    info.hIcon        = hIcon;
1108 1109 1110 1111

    SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
    info.hFont = CreateFontIndirectW( &logFont );

1112
    bRet = DialogBoxIndirectParamW((HINSTANCE)GetWindowLongPtrW( hWnd, GWLP_HINSTANCE ),
1113
                                   template, hWnd, AboutDlgProc, (LPARAM)&info );
1114 1115
    DeleteObject(info.hFont);
    return bRet;
Alexandre Julliard's avatar
Alexandre Julliard committed
1116 1117 1118
}

/*************************************************************************
1119
 * FreeIconList (SHELL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1120 1121
 */
void WINAPI FreeIconList( DWORD dw )
1122
{
1123
    FIXME("%x: stub\n",dw);
Alexandre Julliard's avatar
Alexandre Julliard committed
1124 1125
}

1126 1127 1128
/*************************************************************************
 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
 */
1129
HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID )
1130 1131 1132 1133
{
    FIXME("stub\n");
    return S_OK;
}
1134

1135
/***********************************************************************
1136
 * DllGetVersion [SHELL32.@]
1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150
 *
 * Retrieves version information of the 'SHELL32.DLL'
 *
 * PARAMS
 *     pdvi [O] pointer to version information structure.
 *
 * RETURNS
 *     Success: S_OK
 *     Failure: E_INVALIDARG
 *
 * NOTES
 *     Returns version of a shell32.dll from IE4.01 SP1.
 */

1151
HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
1152
{
1153 1154
    /* FIXME: shouldn't these values come from the version resource? */
    if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
1155
        pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1156
    {
1157 1158 1159 1160
        pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
        pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
        pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
        pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
1161 1162 1163
        if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
        {
            DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
1164

1165
            pdvi2->dwFlags = 0;
1166 1167 1168 1169
            pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
                                              WINE_FILEVERSION_MINOR,
                                              WINE_FILEVERSION_BUILD,
                                              WINE_FILEVERSION_PLATFORMID);
1170
        }
1171
        TRACE("%u.%u.%u.%u\n",
1172 1173
              pdvi->dwMajorVersion, pdvi->dwMinorVersion,
              pdvi->dwBuildNumber, pdvi->dwPlatformID);
1174 1175 1176
        return S_OK;
    }
    else
1177
    {
1178 1179 1180
        WARN("wrong DLLVERSIONINFO size from app\n");
        return E_INVALIDARG;
    }
1181
}
1182

1183 1184
/*************************************************************************
 * global variables of the shell32.dll
1185
 * all are once per process
1186 1187
 *
 */
1188 1189 1190
HINSTANCE    shell32_hInstance = 0;
HIMAGELIST   ShellSmallIconList = 0;
HIMAGELIST   ShellBigIconList = 0;
1191

Alexandre Julliard's avatar
Alexandre Julliard committed
1192

1193
/*************************************************************************
1194
 * SHELL32 DllMain
1195 1196 1197 1198
 *
 * NOTES
 *  calling oleinitialize here breaks sone apps.
 */
1199
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1200
{
1201
    TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225

    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        shell32_hInstance = hinstDLL;
        DisableThreadLibraryCalls(shell32_hInstance);

        /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
        GetModuleFileNameW(hinstDLL, swShell32Name, MAX_PATH);
        swShell32Name[MAX_PATH - 1] = '\0';

        InitCommonControlsEx(NULL);

        SIC_Initialize();
        InitChangeNotifications();
        break;

    case DLL_PROCESS_DETACH:
        shell32_hInstance = 0;
        SIC_Destroy();
        FreeChangeNotifications();
        break;
    }
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
1226
}
1227 1228

/*************************************************************************
1229
 * DllInstall         [SHELL32.@]
1230 1231
 *
 * PARAMETERS
1232
 *
1233 1234 1235 1236
 *    BOOL bInstall - TRUE for install, FALSE for uninstall
 *    LPCWSTR pszCmdLine - command line (unused by shell32?)
 */

1237
HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1238
{
1239 1240
    FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
    return S_OK;        /* indicate success */
1241
}
Andreas Mohr's avatar
Andreas Mohr committed
1242 1243 1244 1245

/***********************************************************************
 *              DllCanUnloadNow (SHELL32.@)
 */
1246
HRESULT WINAPI DllCanUnloadNow(void)
Andreas Mohr's avatar
Andreas Mohr committed
1247
{
1248
    FIXME("stub\n");
Andreas Mohr's avatar
Andreas Mohr committed
1249 1250
    return S_FALSE;
}