shell32_main.c 35.8 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
          (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes,
          psfi, psfi->dwAttributes, sizeofpsfi, flags);

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

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

375 376 377 378
    if (flags & SHGFI_EXETYPE)
    {
        if (flags != SHGFI_EXETYPE)
            return 0;
379
        return shgfi_get_exe_type(szFullPath);
380 381 382 383 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
    }

    /*
     * 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 );
411 412
            if (SUCCEEDED(hr))
                pidlLast = ILClone(pidlLast);
413 414 415 416 417 418
            ILFree(pidl);
        }
        else
        {
            ERR("pidl is null!\n");
            return FALSE;
419
        }
420
    }
421

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

434 435 436 437
    /* get the displayname */
    if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
    {
        if (flags & SHGFI_USEFILEATTRIBUTES)
438
        {
439 440 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
            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 
468
            {
469 470 471 472 473
                WCHAR sTemp[64];

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

482
    /* ### icons ###*/
483 484 485 486 487 488 489 490 491 492 493
    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;
    }
494

495 496
    if (flags & SHGFI_OVERLAYINDEX)
        FIXME("SHGFI_OVERLAYINDEX unhandled\n");
497

498 499
    if (flags & SHGFI_SELECTED)
        FIXME("set icon to selected, stub\n");
500

501 502
    if (flags & SHGFI_SHELLICONSIZE)
        FIXME("set icon to shell size, stub\n");
503

504 505 506 507
    /* get the iconlocation */
    if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
    {
        UINT uDummy,uFlags;
508

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

522
                szExt = PathFindExtensionW(szFullPath);
523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
                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);
549

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

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

571
            lstrcpynW(sTemp, szFullPath, MAX_PATH);
572 573

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

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

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

    /* 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;

651
    SHFree(pidlLast);
652

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

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

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

    if (flags & SHGFI_PIDL)
    {
        /* path contains a pidl */
678
        pathW = (LPCWSTR)path;
679 680 681 682 683 684
    }
    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);
685
        pathW = temppath;
686 687 688 689 690 691
    }

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

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

    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)
710
        {
711 712
            WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1,
                  psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL);
713
        }
714 715
    }

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

    return ret;
719 720
}

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

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

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

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

740 741
    return hDupIcon;
}
742

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

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

754 755 756 757 758
    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
759 760 761
}

/*************************************************************************
762
 * ExtractIconW                [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
763
 */
764 765
HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
{
766 767 768 769 770 771 772 773 774 775
    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
776
            return (HICON)(UINT_PTR)ret;
777 778 779 780 781 782 783 784 785 786 787
        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
788 789
}

790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
/*************************************************************************
 * 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
    */
805 806 807 808
    if((wsPrinterName != NULL) && (wsPrinterName[0] != 0))
    {
        FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName));
    }
809 810 811 812 813 814 815 816 817 818 819 820

    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);
}

821 822 823 824 825 826 827 828 829
/*************************************************************************
 * 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)
{
830
    FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType,
831 832 833 834 835 836 837 838 839 840 841 842 843 844
                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);
} 

845 846
/*************************************************************************/

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

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

857
static void paint_dropline( HDC hdc, HWND hWnd )
858
{
859
    HWND hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_WINE_TEXT);
860 861 862 863 864 865 866 867
    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
868 869 870
}

/*************************************************************************
871
 * SHHelpShortcuts_RunDLLA        [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
872 873
 *
 */
874 875
DWORD WINAPI SHHelpShortcuts_RunDLLA(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
{
876
    FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
877 878 879 880 881 882 883 884
    return 0;
}

/*************************************************************************
 * SHHelpShortcuts_RunDLLA        [SHELL32.@]
 *
 */
DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
885
{
886
    FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
887
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
888 889 890
}

/*************************************************************************
891
 * SHLoadInProc                [SHELL32.@]
892
 * Create an instance of specified object class from within
893
 * the shell process and release it immediately
Alexandre Julliard's avatar
Alexandre Julliard committed
894
 */
895
HRESULT WINAPI SHLoadInProc (REFCLSID rclsid)
896
{
897
    void *ptr = NULL;
898

899 900 901 902 903 904 905 906 907 908
    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
909 910 911
}

/*************************************************************************
912
 * AboutDlgProc            (internal)
Alexandre Julliard's avatar
Alexandre Julliard committed
913
 */
914
INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
915
                              LPARAM lParam )
916 917
{
    HWND hWndCtl;
Alexandre Julliard's avatar
Alexandre Julliard committed
918

919
    TRACE("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
920 921

    switch(msg)
922 923 924 925
    {
    case WM_INITDIALOG:
        {
            ABOUT_INFO *info = (ABOUT_INFO *)lParam;
926 927
            WCHAR template[512], buffer[512], version[64];
            extern const char *wine_get_build_id(void);
928

Alexandre Julliard's avatar
Alexandre Julliard committed
929
            if (info)
930 931 932
            {
                const char* const *pstr = SHELL_Authors;
                SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0);
933 934 935
                GetWindowTextW( hWnd, template, sizeof(template)/sizeof(WCHAR) );
                sprintfW( buffer, template, info->szApp );
                SetWindowTextW( hWnd, buffer );
936 937
                SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT1), info->szApp );
                SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT2), info->szOtherStuff );
938 939 940 941 942 943
                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 );
944
                hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_LISTBOX);
945
                SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 );
946
                SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
947
                while (*pstr)
948
                {
949
                    /* authors list is in utf-8 format */
950 951
                    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
952 953
                    pstr++;
                }
954
                SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 );
Alexandre Julliard's avatar
Alexandre Julliard committed
955 956 957 958 959
            }
        }
        return 1;

    case WM_PAINT:
960 961 962
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint( hWnd, &ps );
963
            paint_dropline( hDC, hWnd );
964 965 966
            EndPaint( hWnd, &ps );
        }
    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
967 968

    case WM_COMMAND:
969 970 971
        if (wParam == IDOK || wParam == IDCANCEL)
        {
            EndDialog(hWnd, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
972 973
            return TRUE;
        }
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989
        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
990
        break;
991 992 993
    case WM_CLOSE:
      EndDialog(hWnd, TRUE);
      break;
Alexandre Julliard's avatar
Alexandre Julliard committed
994
    }
995

Alexandre Julliard's avatar
Alexandre Julliard committed
996 997 998 999 1000
    return 0;
}


/*************************************************************************
1001
 * ShellAboutA                [SHELL32.288]
Alexandre Julliard's avatar
Alexandre Julliard committed
1002
 */
1003 1004 1005
BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon )
{
    BOOL ret;
1006 1007
    LPWSTR appW = NULL, otherW = NULL;
    int len;
1008

1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
    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);

1024 1025
    HeapFree(GetProcessHeap(), 0, otherW);
    HeapFree(GetProcessHeap(), 0, appW);
1026
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1027 1028 1029 1030
}


/*************************************************************************
1031
 * ShellAboutW                [SHELL32.289]
Alexandre Julliard's avatar
Alexandre Julliard committed
1032
 */
1033 1034
BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
                             HICON hIcon )
1035
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1036
    ABOUT_INFO info;
1037
    LOGFONTW logFont;
1038 1039
    HRSRC hRes;
    LPVOID template;
1040
    BOOL bRet;
Jacek Caban's avatar
Jacek Caban committed
1041 1042
    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
1043

1044
    TRACE("\n");
1045

Jacek Caban's avatar
Jacek Caban committed
1046
    if(!(hRes = FindResourceW(shell32_hInstance, wszSHELL_ABOUT_MSGBOX, (LPWSTR)RT_DIALOG)))
1047
        return FALSE;
1048
    if(!(template = LoadResource(shell32_hInstance, hRes)))
1049
        return FALSE;
1050
    if (!hIcon) hIcon = LoadImageW( 0, (LPWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED );
1051 1052
    info.szApp        = szApp;
    info.szOtherStuff = szOtherStuff;
1053
    info.hIcon        = hIcon;
1054 1055 1056 1057

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

1058
    bRet = DialogBoxIndirectParamW((HINSTANCE)GetWindowLongPtrW( hWnd, GWLP_HINSTANCE ),
1059
                                   template, hWnd, AboutDlgProc, (LPARAM)&info );
1060 1061
    DeleteObject(info.hFont);
    return bRet;
Alexandre Julliard's avatar
Alexandre Julliard committed
1062 1063 1064
}

/*************************************************************************
1065
 * FreeIconList (SHELL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1066 1067
 */
void WINAPI FreeIconList( DWORD dw )
1068
{
1069
    FIXME("%x: stub\n",dw);
Alexandre Julliard's avatar
Alexandre Julliard committed
1070 1071
}

1072 1073 1074
/*************************************************************************
 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
 */
1075
HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID )
1076 1077 1078 1079
{
    FIXME("stub\n");
    return S_OK;
}
1080

1081
/***********************************************************************
1082
 * DllGetVersion [SHELL32.@]
1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
 *
 * 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.
 */

1097
HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
1098
{
1099 1100
    /* FIXME: shouldn't these values come from the version resource? */
    if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
1101
        pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1102
    {
1103 1104 1105 1106
        pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
        pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
        pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
        pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
1107 1108 1109
        if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
        {
            DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
1110

1111
            pdvi2->dwFlags = 0;
1112 1113 1114 1115
            pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
                                              WINE_FILEVERSION_MINOR,
                                              WINE_FILEVERSION_BUILD,
                                              WINE_FILEVERSION_PLATFORMID);
1116
        }
1117
        TRACE("%u.%u.%u.%u\n",
1118 1119
              pdvi->dwMajorVersion, pdvi->dwMinorVersion,
              pdvi->dwBuildNumber, pdvi->dwPlatformID);
1120 1121 1122
        return S_OK;
    }
    else
1123
    {
1124 1125 1126
        WARN("wrong DLLVERSIONINFO size from app\n");
        return E_INVALIDARG;
    }
1127
}
1128

1129 1130
/*************************************************************************
 * global variables of the shell32.dll
1131
 * all are once per process
1132 1133
 *
 */
1134 1135 1136
HINSTANCE    shell32_hInstance = 0;
HIMAGELIST   ShellSmallIconList = 0;
HIMAGELIST   ShellBigIconList = 0;
1137

Alexandre Julliard's avatar
Alexandre Julliard committed
1138

1139
/*************************************************************************
1140
 * SHELL32 DllMain
1141 1142 1143 1144
 *
 * NOTES
 *  calling oleinitialize here breaks sone apps.
 */
1145
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1146
{
1147
    TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171

    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
1172
}
1173 1174

/*************************************************************************
1175
 * DllInstall         [SHELL32.@]
1176 1177
 *
 * PARAMETERS
1178
 *
1179 1180 1181 1182
 *    BOOL bInstall - TRUE for install, FALSE for uninstall
 *    LPCWSTR pszCmdLine - command line (unused by shell32?)
 */

1183
HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1184
{
1185 1186
    FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
    return S_OK;        /* indicate success */
1187
}
Andreas Mohr's avatar
Andreas Mohr committed
1188 1189 1190 1191

/***********************************************************************
 *              DllCanUnloadNow (SHELL32.@)
 */
1192
HRESULT WINAPI DllCanUnloadNow(void)
Andreas Mohr's avatar
Andreas Mohr committed
1193
{
1194
    FIXME("stub\n");
Andreas Mohr's avatar
Andreas Mohr committed
1195 1196
    return S_FALSE;
}