shell32_main.c 36.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
        if (numargs)
114
            *numargs=1;
115 116 117 118

        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 354 355
    if (!path)
        return FALSE;

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

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

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

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

425 426 427 428
    /* get the attributes of the child */
    if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
    {
        if (!(flags & SHGFI_ATTR_SPECIFIED))
429
        {
430
            psfi->dwAttributes = 0xffffffff;
431
        }
432 433
        if (psfParent)
            IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
434 435
                                      &(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
                        if (psfi->iIcon == -1)
                            psfi->iIcon = 0;
                    }
                    else 
                    {
599
                        UINT ret;
600
                        if (flags & SHGFI_SMALLICON)
601
                            ret = PrivateExtractIconsW( sTemp,icon_idx,
602 603 604 605
                                GetSystemMetrics( SM_CXSMICON ),
                                GetSystemMetrics( SM_CYSMICON ),
                                &psfi->hIcon, 0, 1, 0);
                        else
606
                            ret = PrivateExtractIconsW( sTemp, icon_idx,
607 608 609
                                GetSystemMetrics( SM_CXICON),
                                GetSystemMetrics( SM_CYICON),
                                &psfi->hIcon, 0, 1, 0);
610 611 612 613 614
                        if (ret != 0 && ret != 0xFFFFFFFF)
                        {
                            IconNotYetLoaded=FALSE;
                            psfi->iIcon = icon_idx;
                        }
615 616
                    }
                }
617
            }
618 619 620 621
        }
        else
        {
            if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
622
                uGilFlags, &(psfi->iIcon))))
623 624 625 626
            {
                ret = FALSE;
            }
        }
627
        if (ret && (flags & SHGFI_SYSICONINDEX))
628 629
        {
            if (flags & SHGFI_SMALLICON)
Kevin Koltzau's avatar
Kevin Koltzau committed
630
                ret = (DWORD_PTR) ShellSmallIconList;
631
            else
Kevin Koltzau's avatar
Kevin Koltzau committed
632
                ret = (DWORD_PTR) ShellBigIconList;
633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653
        }
    }

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

654
    SHFree(pidlLast);
655

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

    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
663 664
}

665
/*************************************************************************
666
 * SHGetFileInfoA            [SHELL32.@]
667 668 669 670 671
 *
 * Note:
 *    MSVBVM60.__vbaNew2 expects this function to return a value in range
 *    1 .. 0x7fff when the function succeeds and flags does not contain
 *    SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701)
672
 */
Kevin Koltzau's avatar
Kevin Koltzau committed
673 674 675
DWORD_PTR WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
                                SHFILEINFOA *psfi, UINT sizeofpsfi,
                                UINT flags )
676
{
677
    INT len;
678 679
    LPWSTR temppath = NULL;
    LPCWSTR pathW;
680 681 682 683 684 685
    DWORD ret;
    SHFILEINFOW temppsfi;

    if (flags & SHGFI_PIDL)
    {
        /* path contains a pidl */
686
        pathW = (LPCWSTR)path;
687 688 689 690 691 692
    }
    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);
693
        pathW = temppath;
694 695 696 697 698 699
    }

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

    if (psfi == NULL)
700
        ret = SHGetFileInfoW(pathW, dwFileAttributes, NULL, sizeof(temppsfi), flags);
701
    else
702
        ret = SHGetFileInfoW(pathW, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
703 704 705 706 707 708 709 710 711 712 713 714 715 716 717

    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)
718
        {
719 720
            WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1,
                  psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL);
721
        }
722 723
    }

724
    HeapFree(GetProcessHeap(), 0, temppath);
725 726

    return ret;
727 728
}

729
/*************************************************************************
730
 * DuplicateIcon            [SHELL32.@]
731 732 733 734
 */
HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
{
    ICONINFO IconInfo;
735
    HICON hDupIcon = 0;
736

737
    TRACE("%p %p\n", hInstance, hIcon);
738

739
    if (GetIconInfo(hIcon, &IconInfo))
740 741 742 743
    {
        hDupIcon = CreateIconIndirect(&IconInfo);

        /* clean up hbmMask and hbmColor */
744 745
        DeleteObject(IconInfo.hbmMask);
        DeleteObject(IconInfo.hbmColor);
746
    }
747

748 749
    return hDupIcon;
}
750

Alexandre Julliard's avatar
Alexandre Julliard committed
751
/*************************************************************************
752
 * ExtractIconA                [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
753
 */
754 755
HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex)
{   
756 757 758
    HICON ret;
    INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0);
    LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
759

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

762 763 764 765 766
    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
767 768 769
}

/*************************************************************************
770
 * ExtractIconW                [SHELL32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
771
 */
772 773
HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
{
774 775 776 777 778 779 780 781 782 783
    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
784
            return (HICON)(UINT_PTR)ret;
785 786 787 788 789 790 791 792 793 794 795
        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
796 797
}

798 799 800 801 802 803 804 805 806 807 808 809 810 811 812
/*************************************************************************
 * 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
    */
813 814 815 816
    if((wsPrinterName != NULL) && (wsPrinterName[0] != 0))
    {
        FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName));
    }
817 818 819 820 821 822 823 824 825 826 827 828

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

829 830 831 832 833 834 835 836 837
/*************************************************************************
 * 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)
{
838
    FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType,
839 840 841 842 843 844 845 846 847 848 849 850 851 852
                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);
} 

853 854
/*************************************************************************/

Alexandre Julliard's avatar
Alexandre Julliard committed
855
typedef struct
856 857 858
{
    LPCWSTR  szApp;
    LPCWSTR  szOtherStuff;
859
    HICON hIcon;
860
    HFONT hFont;
Alexandre Julliard's avatar
Alexandre Julliard committed
861 862
} ABOUT_INFO;

863
#define DROP_FIELD_TOP    (-12)
Alexandre Julliard's avatar
Alexandre Julliard committed
864

865
static void paint_dropline( HDC hdc, HWND hWnd )
866
{
867
    HWND hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_WINE_TEXT);
868 869 870 871 872 873 874 875
    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
876 877 878
}

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

/*************************************************************************
 * SHHelpShortcuts_RunDLLA        [SHELL32.@]
 *
 */
DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
893
{
894
    FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
895
    return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
896 897 898
}

/*************************************************************************
899
 * SHLoadInProc                [SHELL32.@]
900
 * Create an instance of specified object class from within
901
 * the shell process and release it immediately
Alexandre Julliard's avatar
Alexandre Julliard committed
902
 */
903
HRESULT WINAPI SHLoadInProc (REFCLSID rclsid)
904
{
905
    void *ptr = NULL;
906

907 908 909 910 911 912 913 914 915 916
    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
917 918 919
}

/*************************************************************************
920
 * AboutDlgProc            (internal)
Alexandre Julliard's avatar
Alexandre Julliard committed
921
 */
922 923
static INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
                                      LPARAM lParam )
924 925
{
    HWND hWndCtl;
Alexandre Julliard's avatar
Alexandre Julliard committed
926

927
    TRACE("\n");
Alexandre Julliard's avatar
Alexandre Julliard committed
928 929

    switch(msg)
930 931 932 933
    {
    case WM_INITDIALOG:
        {
            ABOUT_INFO *info = (ABOUT_INFO *)lParam;
934 935
            WCHAR template[512], buffer[512], version[64];
            extern const char *wine_get_build_id(void);
936

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

    case WM_PAINT:
968 969 970
        {
            PAINTSTRUCT ps;
            HDC hDC = BeginPaint( hWnd, &ps );
971
            paint_dropline( hDC, hWnd );
972 973 974
            EndPaint( hWnd, &ps );
        }
    break;
Alexandre Julliard's avatar
Alexandre Julliard committed
975 976

    case WM_COMMAND:
977 978 979
        if (wParam == IDOK || wParam == IDCANCEL)
        {
            EndDialog(hWnd, TRUE);
Alexandre Julliard's avatar
Alexandre Julliard committed
980 981
            return TRUE;
        }
982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
        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
998
        break;
999 1000 1001
    case WM_CLOSE:
      EndDialog(hWnd, TRUE);
      break;
Alexandre Julliard's avatar
Alexandre Julliard committed
1002
    }
1003

Alexandre Julliard's avatar
Alexandre Julliard committed
1004 1005 1006 1007 1008
    return 0;
}


/*************************************************************************
1009
 * ShellAboutA                [SHELL32.288]
Alexandre Julliard's avatar
Alexandre Julliard committed
1010
 */
1011 1012 1013
BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon )
{
    BOOL ret;
1014 1015
    LPWSTR appW = NULL, otherW = NULL;
    int len;
1016

1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031
    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);

1032 1033
    HeapFree(GetProcessHeap(), 0, otherW);
    HeapFree(GetProcessHeap(), 0, appW);
1034
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
1035 1036 1037 1038
}


/*************************************************************************
1039
 * ShellAboutW                [SHELL32.289]
Alexandre Julliard's avatar
Alexandre Julliard committed
1040
 */
1041 1042
BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
                             HICON hIcon )
1043
{
Alexandre Julliard's avatar
Alexandre Julliard committed
1044
    ABOUT_INFO info;
1045
    LOGFONTW logFont;
1046 1047
    HRSRC hRes;
    LPVOID template;
1048
    BOOL bRet;
Jacek Caban's avatar
Jacek Caban committed
1049 1050
    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
1051

1052
    TRACE("\n");
1053

Jacek Caban's avatar
Jacek Caban committed
1054
    if(!(hRes = FindResourceW(shell32_hInstance, wszSHELL_ABOUT_MSGBOX, (LPWSTR)RT_DIALOG)))
1055
        return FALSE;
1056
    if(!(template = LoadResource(shell32_hInstance, hRes)))
1057
        return FALSE;
1058
    if (!hIcon) hIcon = LoadImageW( 0, (LPWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED );
1059 1060
    info.szApp        = szApp;
    info.szOtherStuff = szOtherStuff;
1061
    info.hIcon        = hIcon;
1062 1063 1064 1065

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

1066
    bRet = DialogBoxIndirectParamW((HINSTANCE)GetWindowLongPtrW( hWnd, GWLP_HINSTANCE ),
1067
                                   template, hWnd, AboutDlgProc, (LPARAM)&info );
1068 1069
    DeleteObject(info.hFont);
    return bRet;
Alexandre Julliard's avatar
Alexandre Julliard committed
1070 1071 1072
}

/*************************************************************************
1073
 * FreeIconList (SHELL32.@)
Alexandre Julliard's avatar
Alexandre Julliard committed
1074 1075
 */
void WINAPI FreeIconList( DWORD dw )
1076
{
1077
    FIXME("%x: stub\n",dw);
Alexandre Julliard's avatar
Alexandre Julliard committed
1078 1079
}

1080 1081 1082
/*************************************************************************
 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
 */
1083
HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID )
1084 1085 1086 1087
{
    FIXME("stub\n");
    return S_OK;
}
1088

1089
/***********************************************************************
1090
 * DllGetVersion [SHELL32.@]
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104
 *
 * 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.
 */

1105
HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
1106
{
1107 1108
    /* FIXME: shouldn't these values come from the version resource? */
    if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
1109
        pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1110
    {
1111 1112 1113 1114
        pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
        pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
        pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
        pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
1115 1116 1117
        if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
        {
            DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
1118

1119
            pdvi2->dwFlags = 0;
1120 1121 1122 1123
            pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
                                              WINE_FILEVERSION_MINOR,
                                              WINE_FILEVERSION_BUILD,
                                              WINE_FILEVERSION_PLATFORMID);
1124
        }
1125
        TRACE("%u.%u.%u.%u\n",
1126 1127
              pdvi->dwMajorVersion, pdvi->dwMinorVersion,
              pdvi->dwBuildNumber, pdvi->dwPlatformID);
1128 1129 1130
        return S_OK;
    }
    else
1131
    {
1132 1133 1134
        WARN("wrong DLLVERSIONINFO size from app\n");
        return E_INVALIDARG;
    }
1135
}
1136

1137 1138
/*************************************************************************
 * global variables of the shell32.dll
1139
 * all are once per process
1140 1141
 *
 */
1142 1143 1144
HINSTANCE    shell32_hInstance = 0;
HIMAGELIST   ShellSmallIconList = 0;
HIMAGELIST   ShellBigIconList = 0;
1145

Alexandre Julliard's avatar
Alexandre Julliard committed
1146

1147
/*************************************************************************
1148
 * SHELL32 DllMain
1149 1150 1151 1152
 *
 * NOTES
 *  calling oleinitialize here breaks sone apps.
 */
1153
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1154
{
1155
    TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179

    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
1180
}
1181 1182

/*************************************************************************
1183
 * DllInstall         [SHELL32.@]
1184 1185
 *
 * PARAMETERS
1186
 *
1187 1188 1189 1190
 *    BOOL bInstall - TRUE for install, FALSE for uninstall
 *    LPCWSTR pszCmdLine - command line (unused by shell32?)
 */

1191
HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1192
{
1193 1194
    FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
    return S_OK;        /* indicate success */
1195
}
Andreas Mohr's avatar
Andreas Mohr committed
1196 1197 1198 1199

/***********************************************************************
 *              DllCanUnloadNow (SHELL32.@)
 */
1200
HRESULT WINAPI DllCanUnloadNow(void)
Andreas Mohr's avatar
Andreas Mohr committed
1201
{
1202
    FIXME("stub\n");
Andreas Mohr's avatar
Andreas Mohr committed
1203 1204
    return S_FALSE;
}
1205 1206 1207 1208 1209 1210 1211 1212 1213

/***********************************************************************
 *              ExtractVersionResource16W (SHELL32.@)
 */
BOOL WINAPI ExtractVersionResource16W(LPWSTR s, DWORD d)
{
    FIXME("(%s %x) stub!\n", debugstr_w(s), d);
    return FALSE;
}
1214 1215 1216 1217 1218 1219 1220 1221 1222

/***********************************************************************
 *              InitNetworkAddressControl (SHELL32.@)
 */
BOOL WINAPI InitNetworkAddressControl(void)
{
    FIXME("stub\n");
    return FALSE;
}
1223 1224 1225 1226 1227 1228 1229 1230 1231

/***********************************************************************
 *              ShellHookProc (SHELL32.@)
 */
LRESULT CALLBACK ShellHookProc(DWORD a, DWORD b, DWORD c)
{
    FIXME("Stub\n");
    return 0;
}