shell32: Initialize fAnyOperationsAborted in SHFileOperation.
[wine] / dlls / shell32 / shell32_main.c
1 /*
2  *                 Shell basics
3  *
4  * Copyright 1998 Marcus Meissner
5  * Copyright 1998 Juergen Schmied (jsch)  *  <juergen.schmied@metronet.de>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * 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
20  */
21
22 #include "config.h"
23
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28
29 #define COBJMACROS
30
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winerror.h"
34 #include "winreg.h"
35 #include "dlgs.h"
36 #include "shellapi.h"
37 #include "winuser.h"
38 #include "wingdi.h"
39 #include "shlobj.h"
40 #include "rpcproxy.h"
41 #include "shlwapi.h"
42 #include "propsys.h"
43
44 #include "undocshell.h"
45 #include "pidl.h"
46 #include "shell32_main.h"
47 #include "version.h"
48 #include "shresdef.h"
49 #include "initguid.h"
50 #include "shfldr.h"
51
52 #include "wine/debug.h"
53 #include "wine/unicode.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(shell);
56
57 /*************************************************************************
58  * CommandLineToArgvW            [SHELL32.@]
59  *
60  * We must interpret the quotes in the command line to rebuild the argv
61  * array correctly:
62  * - arguments are separated by spaces or tabs
63  * - quotes serve as optional argument delimiters
64  *   '"a b"'   -> 'a b'
65  * - escaped quotes must be converted back to '"'
66  *   '\"'      -> '"'
67  * - consecutive backslashes preceding a quote see their number halved with
68  *   the remainder escaping the quote:
69  *   2n   backslashes + quote -> n backslashes + quote as an argument delimiter
70  *   2n+1 backslashes + quote -> n backslashes + literal quote
71  * - backslashes that are not followed by a quote are copied literally:
72  *   'a\b'     -> 'a\b'
73  *   'a\\b'    -> 'a\\b'
74  * - in quoted strings, consecutive quotes see their number divided by three
75  *   with the remainder modulo 3 deciding whether to close the string or not.
76  *   Note that the opening quote must be counted in the consecutive quotes,
77  *   that's the (1+) below:
78  *   (1+) 3n   quotes -> n quotes
79  *   (1+) 3n+1 quotes -> n quotes plus closes the quoted string
80  *   (1+) 3n+2 quotes -> n+1 quotes plus closes the quoted string
81  * - in unquoted strings, the first quote opens the quoted string and the
82  *   remaining consecutive quotes follow the above rule.
83  */
84 LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
85 {
86     DWORD argc;
87     LPWSTR  *argv;
88     LPCWSTR s;
89     LPWSTR d;
90     LPWSTR cmdline;
91     int qcount,bcount;
92
93     if(!numargs)
94     {
95         SetLastError(ERROR_INVALID_PARAMETER);
96         return NULL;
97     }
98
99     if (*lpCmdline==0)
100     {
101         /* Return the path to the executable */
102         DWORD len, deslen=MAX_PATH, size;
103
104         size = sizeof(LPWSTR) + deslen*sizeof(WCHAR) + sizeof(LPWSTR);
105         for (;;)
106         {
107             if (!(argv = LocalAlloc(LMEM_FIXED, size))) return NULL;
108             len = GetModuleFileNameW(0, (LPWSTR)(argv+1), deslen);
109             if (!len)
110             {
111                 LocalFree(argv);
112                 return NULL;
113             }
114             if (len < deslen) break;
115             deslen*=2;
116             size = sizeof(LPWSTR) + deslen*sizeof(WCHAR) + sizeof(LPWSTR);
117             LocalFree( argv );
118         }
119         argv[0]=(LPWSTR)(argv+1);
120         *numargs=1;
121
122         return argv;
123     }
124
125     /* --- First count the arguments */
126     argc=1;
127     s=lpCmdline;
128     /* The first argument, the executable path, follows special rules */
129     if (*s=='"')
130     {
131         /* The executable path ends at the next quote, no matter what */
132         s++;
133         while (*s)
134             if (*s++=='"')
135                 break;
136     }
137     else
138     {
139         /* The executable path ends at the next space, no matter what */
140         while (*s && *s!=' ' && *s!='\t')
141             s++;
142     }
143     /* skip to the first argument, if any */
144     while (*s==' ' || *s=='\t')
145         s++;
146     if (*s)
147         argc++;
148
149     /* Analyze the remaining arguments */
150     qcount=bcount=0;
151     while (*s)
152     {
153         if ((*s==' ' || *s=='\t') && qcount==0)
154         {
155             /* skip to the next argument and count it if any */
156             while (*s==' ' || *s=='\t')
157                 s++;
158             if (*s)
159                 argc++;
160             bcount=0;
161         }
162         else if (*s=='\\')
163         {
164             /* '\', count them */
165             bcount++;
166             s++;
167         }
168         else if (*s=='"')
169         {
170             /* '"' */
171             if ((bcount & 1)==0)
172                 qcount++; /* unescaped '"' */
173             s++;
174             bcount=0;
175             /* consecutive quotes, see comment in copying code below */
176             while (*s=='"')
177             {
178                 qcount++;
179                 s++;
180             }
181             qcount=qcount % 3;
182             if (qcount==2)
183                 qcount=0;
184         }
185         else
186         {
187             /* a regular character */
188             bcount=0;
189             s++;
190         }
191     }
192
193     /* Allocate in a single lump, the string array, and the strings that go
194      * with it. This way the caller can make a single LocalFree() call to free
195      * both, as per MSDN.
196      */
197     argv=LocalAlloc(LMEM_FIXED, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR));
198     if (!argv)
199         return NULL;
200     cmdline=(LPWSTR)(argv+argc);
201     strcpyW(cmdline, lpCmdline);
202
203     /* --- Then split and copy the arguments */
204     argv[0]=d=cmdline;
205     argc=1;
206     /* The first argument, the executable path, follows special rules */
207     if (*d=='"')
208     {
209         /* The executable path ends at the next quote, no matter what */
210         s=d+1;
211         while (*s)
212         {
213             if (*s=='"')
214             {
215                 s++;
216                 break;
217             }
218             *d++=*s++;
219         }
220     }
221     else
222     {
223         /* The executable path ends at the next space, no matter what */
224         while (*d && *d!=' ' && *d!='\t')
225             d++;
226         s=d;
227         if (*s)
228             s++;
229     }
230     /* close the argument */
231     *d++=0;
232     /* skip to the first argument and initialize it if any */
233     while (*s==' ' || *s=='\t')
234         s++;
235     if (*s)
236         argv[argc++]=d;
237
238     /* Split and copy the remaining arguments */
239     qcount=bcount=0;
240     while (*s)
241     {
242         if ((*s==' ' || *s=='\t') && qcount==0)
243         {
244             /* close the argument */
245             *d++=0;
246             bcount=0;
247
248             /* skip to the next one and initialize it if any */
249             do {
250                 s++;
251             } while (*s==' ' || *s=='\t');
252             if (*s)
253                 argv[argc++]=d;
254         }
255         else if (*s=='\\')
256         {
257             *d++=*s++;
258             bcount++;
259         }
260         else if (*s=='"')
261         {
262             if ((bcount & 1)==0)
263             {
264                 /* Preceded by an even number of '\', this is half that
265                  * number of '\', plus a quote which we erase.
266                  */
267                 d-=bcount/2;
268                 qcount++;
269             }
270             else
271             {
272                 /* Preceded by an odd number of '\', this is half that
273                  * number of '\' followed by a '"'
274                  */
275                 d=d-bcount/2-1;
276                 *d++='"';
277             }
278             s++;
279             bcount=0;
280             /* Now count the number of consecutive quotes. Note that qcount
281              * already takes into account the opening quote if any, as well as
282              * the quote that lead us here.
283              */
284             while (*s=='"')
285             {
286                 if (++qcount==3)
287                 {
288                     *d++='"';
289                     qcount=0;
290                 }
291                 s++;
292             }
293             if (qcount==2)
294                 qcount=0;
295         }
296         else
297         {
298             /* a regular character */
299             *d++=*s++;
300             bcount=0;
301         }
302     }
303     *d='\0';
304     *numargs=argc;
305
306     return argv;
307 }
308
309 static DWORD shgfi_get_exe_type(LPCWSTR szFullPath)
310 {
311     BOOL status = FALSE;
312     HANDLE hfile;
313     DWORD BinaryType;
314     IMAGE_DOS_HEADER mz_header;
315     IMAGE_NT_HEADERS nt;
316     DWORD len;
317     char magic[4];
318
319     status = GetBinaryTypeW (szFullPath, &BinaryType);
320     if (!status)
321         return 0;
322     if (BinaryType == SCS_DOS_BINARY || BinaryType == SCS_PIF_BINARY)
323         return 0x4d5a;
324
325     hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ,
326                          NULL, OPEN_EXISTING, 0, 0 );
327     if ( hfile == INVALID_HANDLE_VALUE )
328         return 0;
329
330     /*
331      * The next section is adapted from MODULE_GetBinaryType, as we need
332      * to examine the image header to get OS and version information. We
333      * know from calling GetBinaryTypeA that the image is valid and either
334      * an NE or PE, so much error handling can be omitted.
335      * Seek to the start of the file and read the header information.
336      */
337
338     SetFilePointer( hfile, 0, NULL, SEEK_SET );
339     ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL );
340
341     SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
342     ReadFile( hfile, magic, sizeof(magic), &len, NULL );
343     if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
344     {
345         SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
346         ReadFile( hfile, &nt, sizeof(nt), &len, NULL );
347         CloseHandle( hfile );
348         /* DLL files are not executable and should return 0 */
349         if (nt.FileHeader.Characteristics & IMAGE_FILE_DLL)
350             return 0;
351         if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
352         {
353              return IMAGE_NT_SIGNATURE | 
354                    (nt.OptionalHeader.MajorSubsystemVersion << 24) |
355                    (nt.OptionalHeader.MinorSubsystemVersion << 16);
356         }
357         return IMAGE_NT_SIGNATURE;
358     }
359     else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
360     {
361         IMAGE_OS2_HEADER ne;
362         SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
363         ReadFile( hfile, &ne, sizeof(ne), &len, NULL );
364         CloseHandle( hfile );
365         if (ne.ne_exetyp == 2)
366             return IMAGE_OS2_SIGNATURE | (ne.ne_expver << 16);
367         return 0;
368     }
369     CloseHandle( hfile );
370     return 0;
371 }
372
373 /*************************************************************************
374  * SHELL_IsShortcut             [internal]
375  *
376  * Decide if an item id list points to a shell shortcut
377  */
378 BOOL SHELL_IsShortcut(LPCITEMIDLIST pidlLast)
379 {
380     char szTemp[MAX_PATH];
381     HKEY keyCls;
382     BOOL ret = FALSE;
383
384     if (_ILGetExtension(pidlLast, szTemp, MAX_PATH) &&
385           HCR_MapTypeToValueA(szTemp, szTemp, MAX_PATH, TRUE))
386     {
387         if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls))
388         {
389           if (ERROR_SUCCESS == RegQueryValueExA(keyCls, "IsShortcut", NULL, NULL, NULL, NULL))
390             ret = TRUE;
391
392           RegCloseKey(keyCls);
393         }
394     }
395
396     return ret;
397 }
398
399 #define SHGFI_KNOWN_FLAGS \
400     (SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \
401      SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \
402      SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ATTRIBUTES | \
403      SHGFI_ICONLOCATION | SHGFI_EXETYPE | SHGFI_SYSICONINDEX | \
404      SHGFI_LINKOVERLAY | SHGFI_SELECTED | SHGFI_ATTR_SPECIFIED)
405
406 /*************************************************************************
407  * SHGetFileInfoW            [SHELL32.@]
408  *
409  */
410 DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
411                                 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags )
412 {
413     WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH];
414     int iIndex;
415     DWORD_PTR ret = TRUE;
416     DWORD dwAttributes = 0;
417     IShellFolder * psfParent = NULL;
418     IExtractIconW * pei = NULL;
419     LPITEMIDLIST    pidlLast = NULL, pidl = NULL;
420     HRESULT hr = S_OK;
421     BOOL IconNotYetLoaded=TRUE;
422     UINT uGilFlags = 0;
423
424     TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
425           (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes,
426           psfi, psfi->dwAttributes, sizeofpsfi, flags);
427
428     if (!path)
429         return FALSE;
430
431     /* windows initializes these values regardless of the flags */
432     if (psfi != NULL)
433     {
434         psfi->szDisplayName[0] = '\0';
435         psfi->szTypeName[0] = '\0';
436         psfi->iIcon = 0;
437     }
438
439     if (!(flags & SHGFI_PIDL))
440     {
441         /* SHGetFileInfo should work with absolute and relative paths */
442         if (PathIsRelativeW(path))
443         {
444             GetCurrentDirectoryW(MAX_PATH, szLocation);
445             PathCombineW(szFullPath, szLocation, path);
446         }
447         else
448         {
449             lstrcpynW(szFullPath, path, MAX_PATH);
450         }
451     }
452
453     if (flags & SHGFI_EXETYPE)
454     {
455         if (flags != SHGFI_EXETYPE)
456             return 0;
457         return shgfi_get_exe_type(szFullPath);
458     }
459
460     /*
461      * psfi is NULL normally to query EXE type. If it is NULL, none of the
462      * below makes sense anyway. Windows allows this and just returns FALSE
463      */
464     if (psfi == NULL)
465         return FALSE;
466
467     /*
468      * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES
469      * is not specified.
470      * The pidl functions fail on not existing file names
471      */
472
473     if (flags & SHGFI_PIDL)
474     {
475         pidl = ILClone((LPCITEMIDLIST)path);
476     }
477     else if (!(flags & SHGFI_USEFILEATTRIBUTES))
478     {
479         hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes);
480     }
481
482     if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES))
483     {
484         /* get the parent shellfolder */
485         if (pidl)
486         {
487             hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent,
488                                 (LPCITEMIDLIST*)&pidlLast );
489             if (SUCCEEDED(hr))
490                 pidlLast = ILClone(pidlLast);
491             ILFree(pidl);
492         }
493         else
494         {
495             ERR("pidl is null!\n");
496             return FALSE;
497         }
498     }
499
500     /* get the attributes of the child */
501     if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
502     {
503         if (!(flags & SHGFI_ATTR_SPECIFIED))
504         {
505             psfi->dwAttributes = 0xffffffff;
506         }
507         if (psfParent)
508             IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
509                                       &(psfi->dwAttributes) );
510     }
511
512     /* get the displayname */
513     if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
514     {
515         if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
516         {
517             lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath));
518         }
519         else
520         {
521             STRRET str;
522             hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast,
523                                                 SHGDN_INFOLDER, &str);
524             StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
525         }
526     }
527
528     /* get the type name */
529     if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
530     {
531         static const WCHAR szFile[] = { 'F','i','l','e',0 };
532         static const WCHAR szDashFile[] = { '-','f','i','l','e',0 };
533
534         if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL))
535         {
536             char ftype[80];
537
538             _ILGetFileType(pidlLast, ftype, 80);
539             MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 );
540         }
541         else
542         {
543             if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
544                 strcatW (psfi->szTypeName, szFile);
545             else 
546             {
547                 WCHAR sTemp[64];
548
549                 lstrcpyW(sTemp,PathFindExtensionW(szFullPath));
550                 if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) &&
551                     HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE )))
552                 {
553                     lstrcpynW (psfi->szTypeName, sTemp, 64);
554                     strcatW (psfi->szTypeName, szDashFile);
555                 }
556             }
557         }
558     }
559
560     /* ### icons ###*/
561     if (flags & SHGFI_OPENICON)
562         uGilFlags |= GIL_OPENICON;
563
564     if (flags & SHGFI_LINKOVERLAY)
565         uGilFlags |= GIL_FORSHORTCUT;
566     else if ((flags&SHGFI_ADDOVERLAYS) ||
567              (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON)
568     {
569         if (SHELL_IsShortcut(pidlLast))
570             uGilFlags |= GIL_FORSHORTCUT;
571     }
572
573     if (flags & SHGFI_OVERLAYINDEX)
574         FIXME("SHGFI_OVERLAYINDEX unhandled\n");
575
576     if (flags & SHGFI_SELECTED)
577         FIXME("set icon to selected, stub\n");
578
579     if (flags & SHGFI_SHELLICONSIZE)
580         FIXME("set icon to shell size, stub\n");
581
582     /* get the iconlocation */
583     if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
584     {
585         UINT uDummy,uFlags;
586
587         if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
588         {
589             if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
590             {
591                 lstrcpyW(psfi->szDisplayName, swShell32Name);
592                 psfi->iIcon = -IDI_SHELL_FOLDER;
593             }
594             else
595             {
596                 WCHAR* szExt;
597                 static const WCHAR p1W[] = {'%','1',0};
598                 WCHAR sTemp [MAX_PATH];
599
600                 szExt = PathFindExtensionW(szFullPath);
601                 TRACE("szExt=%s\n", debugstr_w(szExt));
602                 if ( szExt &&
603                      HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
604                      HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &psfi->iIcon))
605                 {
606                     if (lstrcmpW(p1W, sTemp))
607                         strcpyW(psfi->szDisplayName, sTemp);
608                     else
609                     {
610                         /* the icon is in the file */
611                         strcpyW(psfi->szDisplayName, szFullPath);
612                     }
613                 }
614                 else
615                     ret = FALSE;
616             }
617         }
618         else
619         {
620             hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1,
621                 (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW,
622                 &uDummy, (LPVOID*)&pei);
623             if (SUCCEEDED(hr))
624             {
625                 hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
626                     szLocation, MAX_PATH, &iIndex, &uFlags);
627
628                 if (uFlags & GIL_NOTFILENAME)
629                     ret = FALSE;
630                 else
631                 {
632                     lstrcpyW (psfi->szDisplayName, szLocation);
633                     psfi->iIcon = iIndex;
634                 }
635                 IExtractIconW_Release(pei);
636             }
637         }
638     }
639
640     /* get icon index (or load icon)*/
641     if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
642     {
643         if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
644         {
645             WCHAR sTemp [MAX_PATH];
646             WCHAR * szExt;
647             int icon_idx=0;
648
649             lstrcpynW(sTemp, szFullPath, MAX_PATH);
650
651             if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
652                 psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0);
653             else
654             {
655                 static const WCHAR p1W[] = {'%','1',0};
656
657                 psfi->iIcon = 0;
658                 szExt = PathFindExtensionW(sTemp);
659                 if ( szExt &&
660                      HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
661                      HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &icon_idx))
662                 {
663                     if (!lstrcmpW(p1W,sTemp))            /* icon is in the file */
664                         strcpyW(sTemp, szFullPath);
665
666                     if (flags & SHGFI_SYSICONINDEX) 
667                     {
668                         psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0);
669                         if (psfi->iIcon == -1)
670                             psfi->iIcon = 0;
671                     }
672                     else 
673                     {
674                         UINT ret;
675                         if (flags & SHGFI_SMALLICON)
676                             ret = PrivateExtractIconsW( sTemp,icon_idx,
677                                 GetSystemMetrics( SM_CXSMICON ),
678                                 GetSystemMetrics( SM_CYSMICON ),
679                                 &psfi->hIcon, 0, 1, 0);
680                         else
681                             ret = PrivateExtractIconsW( sTemp, icon_idx,
682                                 GetSystemMetrics( SM_CXICON),
683                                 GetSystemMetrics( SM_CYICON),
684                                 &psfi->hIcon, 0, 1, 0);
685                         if (ret != 0 && ret != (UINT)-1)
686                         {
687                             IconNotYetLoaded=FALSE;
688                             psfi->iIcon = icon_idx;
689                         }
690                     }
691                 }
692             }
693         }
694         else
695         {
696             if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
697                 uGilFlags, &(psfi->iIcon))))
698             {
699                 ret = FALSE;
700             }
701         }
702         if (ret && (flags & SHGFI_SYSICONINDEX))
703         {
704             if (flags & SHGFI_SMALLICON)
705                 ret = (DWORD_PTR) ShellSmallIconList;
706             else
707                 ret = (DWORD_PTR) ShellBigIconList;
708         }
709     }
710
711     /* icon handle */
712     if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded)
713     {
714         if (flags & SHGFI_SMALLICON)
715             psfi->hIcon = ImageList_GetIcon( ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
716         else
717             psfi->hIcon = ImageList_GetIcon( ShellBigIconList, psfi->iIcon, ILD_NORMAL);
718     }
719
720     if (flags & ~SHGFI_KNOWN_FLAGS)
721         FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS);
722
723     if (psfParent)
724         IShellFolder_Release(psfParent);
725
726     if (hr != S_OK)
727         ret = FALSE;
728
729     SHFree(pidlLast);
730
731     TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
732            psfi->hIcon, psfi->iIcon, psfi->dwAttributes,
733            debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret);
734
735     return ret;
736 }
737
738 /*************************************************************************
739  * SHGetFileInfoA            [SHELL32.@]
740  *
741  * Note:
742  *    MSVBVM60.__vbaNew2 expects this function to return a value in range
743  *    1 .. 0x7fff when the function succeeds and flags does not contain
744  *    SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701)
745  */
746 DWORD_PTR WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
747                                 SHFILEINFOA *psfi, UINT sizeofpsfi,
748                                 UINT flags )
749 {
750     INT len;
751     LPWSTR temppath = NULL;
752     LPCWSTR pathW;
753     DWORD_PTR ret;
754     SHFILEINFOW temppsfi;
755
756     if (flags & SHGFI_PIDL)
757     {
758         /* path contains a pidl */
759         pathW = (LPCWSTR)path;
760     }
761     else
762     {
763         len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
764         temppath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
765         MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len);
766         pathW = temppath;
767     }
768
769     if (psfi && (flags & SHGFI_ATTR_SPECIFIED))
770         temppsfi.dwAttributes=psfi->dwAttributes;
771
772     if (psfi == NULL)
773         ret = SHGetFileInfoW(pathW, dwFileAttributes, NULL, sizeof(temppsfi), flags);
774     else
775         ret = SHGetFileInfoW(pathW, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
776
777     if (psfi)
778     {
779         if(flags & SHGFI_ICON)
780             psfi->hIcon=temppsfi.hIcon;
781         if(flags & (SHGFI_SYSICONINDEX|SHGFI_ICON|SHGFI_ICONLOCATION))
782             psfi->iIcon=temppsfi.iIcon;
783         if(flags & SHGFI_ATTRIBUTES)
784             psfi->dwAttributes=temppsfi.dwAttributes;
785         if(flags & (SHGFI_DISPLAYNAME|SHGFI_ICONLOCATION))
786         {
787             WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1,
788                   psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL);
789         }
790         if(flags & SHGFI_TYPENAME)
791         {
792             WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1,
793                   psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL);
794         }
795     }
796
797     HeapFree(GetProcessHeap(), 0, temppath);
798
799     return ret;
800 }
801
802 /*************************************************************************
803  * DuplicateIcon            [SHELL32.@]
804  */
805 HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
806 {
807     ICONINFO IconInfo;
808     HICON hDupIcon = 0;
809
810     TRACE("%p %p\n", hInstance, hIcon);
811
812     if (GetIconInfo(hIcon, &IconInfo))
813     {
814         hDupIcon = CreateIconIndirect(&IconInfo);
815
816         /* clean up hbmMask and hbmColor */
817         DeleteObject(IconInfo.hbmMask);
818         DeleteObject(IconInfo.hbmColor);
819     }
820
821     return hDupIcon;
822 }
823
824 /*************************************************************************
825  * ExtractIconA                [SHELL32.@]
826  */
827 HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex)
828 {   
829     HICON ret;
830     INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0);
831     LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
832
833     TRACE("%p %s %d\n", hInstance, lpszFile, nIconIndex);
834
835     MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len);
836     ret = ExtractIconW(hInstance, lpwstrFile, nIconIndex);
837     HeapFree(GetProcessHeap(), 0, lpwstrFile);
838
839     return ret;
840 }
841
842 /*************************************************************************
843  * ExtractIconW                [SHELL32.@]
844  */
845 HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
846 {
847     HICON  hIcon = NULL;
848     UINT ret;
849     UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON);
850
851     TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex);
852
853     if (nIconIndex == (UINT)-1)
854     {
855         ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR);
856         if (ret != (UINT)-1 && ret)
857             return (HICON)(UINT_PTR)ret;
858         return NULL;
859     }
860     else
861         ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR);
862
863     if (ret == (UINT)-1)
864         return (HICON)1;
865     else if (ret > 0 && hIcon)
866         return hIcon;
867
868     return NULL;
869 }
870
871 HRESULT WINAPI SHCreateFileExtractIconW(LPCWSTR file, DWORD attribs, REFIID riid, void **ppv)
872 {
873   FIXME("%s, %x, %s, %p\n", debugstr_w(file), attribs, debugstr_guid(riid), ppv);
874   *ppv = NULL;
875   return E_NOTIMPL;
876 }
877
878 /*************************************************************************
879  * Printer_LoadIconsW        [SHELL32.205]
880  */
881 VOID WINAPI Printer_LoadIconsW(LPCWSTR wsPrinterName, HICON * pLargeIcon, HICON * pSmallIcon)
882 {
883     INT iconindex=IDI_SHELL_PRINTER;
884
885     TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName), pLargeIcon, pSmallIcon);
886
887     /* We should check if wsPrinterName is
888        1. the Default Printer or not
889        2. connected or not
890        3. a Local Printer or a Network-Printer
891        and use different Icons
892     */
893     if((wsPrinterName != NULL) && (wsPrinterName[0] != 0))
894     {
895         FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName));
896     }
897
898     if(pLargeIcon != NULL)
899         *pLargeIcon = LoadImageW(shell32_hInstance,
900                                  (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
901                                  0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
902
903     if(pSmallIcon != NULL)
904         *pSmallIcon = LoadImageW(shell32_hInstance,
905                                  (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
906                                  16, 16, LR_DEFAULTCOLOR);
907 }
908
909 /*************************************************************************
910  * Printers_RegisterWindowW        [SHELL32.213]
911  * used by "printui.dll":
912  * find the Window of the given Type for the specific Printer and 
913  * return the already existent hwnd or open a new window
914  */
915 BOOL WINAPI Printers_RegisterWindowW(LPCWSTR wsPrinter, DWORD dwType,
916             HANDLE * phClassPidl, HWND * phwnd)
917 {
918     FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType,
919                 phClassPidl, (phClassPidl != NULL) ? *(phClassPidl) : NULL,
920                 phwnd, (phwnd != NULL) ? *(phwnd) : NULL);
921
922     return FALSE;
923
924
925 /*************************************************************************
926  * Printers_UnregisterWindow      [SHELL32.214]
927  */
928 VOID WINAPI Printers_UnregisterWindow(HANDLE hClassPidl, HWND hwnd)
929 {
930     FIXME("(%p, %p) stub!\n", hClassPidl, hwnd);
931
932
933 /*************************************************************************
934  * SHGetPropertyStoreFromParsingName [SHELL32.@]
935  */
936 HRESULT WINAPI SHGetPropertyStoreFromParsingName(PCWSTR pszPath, IBindCtx *pbc, GETPROPERTYSTOREFLAGS flags, REFIID riid, void **ppv)
937 {
938     FIXME("(%s %p %u %p %p) stub!\n", debugstr_w(pszPath), pbc, flags, riid, ppv);
939     return E_NOTIMPL;
940 }
941
942 /*************************************************************************/
943
944 typedef struct
945 {
946     LPCWSTR  szApp;
947     LPCWSTR  szOtherStuff;
948     HICON hIcon;
949     HFONT hFont;
950 } ABOUT_INFO;
951
952 #define DROP_FIELD_TOP    (-12)
953
954 static void paint_dropline( HDC hdc, HWND hWnd )
955 {
956     HWND hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_WINE_TEXT);
957     RECT rect;
958
959     if (!hWndCtl) return;
960     GetWindowRect( hWndCtl, &rect );
961     MapWindowPoints( 0, hWnd, (LPPOINT)&rect, 2 );
962     rect.top += DROP_FIELD_TOP;
963     rect.bottom = rect.top + 2;
964     DrawEdge( hdc, &rect, BDR_SUNKENOUTER, BF_RECT );
965 }
966
967 /*************************************************************************
968  * SHHelpShortcuts_RunDLLA        [SHELL32.@]
969  *
970  */
971 DWORD WINAPI SHHelpShortcuts_RunDLLA(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
972 {
973     FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
974     return 0;
975 }
976
977 /*************************************************************************
978  * SHHelpShortcuts_RunDLLA        [SHELL32.@]
979  *
980  */
981 DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
982 {
983     FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
984     return 0;
985 }
986
987 /*************************************************************************
988  * SHLoadInProc                [SHELL32.@]
989  * Create an instance of specified object class from within
990  * the shell process and release it immediately
991  */
992 HRESULT WINAPI SHLoadInProc (REFCLSID rclsid)
993 {
994     void *ptr = NULL;
995
996     TRACE("%s\n", debugstr_guid(rclsid));
997
998     CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr);
999     if(ptr)
1000     {
1001         IUnknown * pUnk = ptr;
1002         IUnknown_Release(pUnk);
1003         return S_OK;
1004     }
1005     return DISP_E_MEMBERNOTFOUND;
1006 }
1007
1008 static void add_authors( HWND list )
1009 {
1010     static const WCHAR eol[] = {'\r','\n',0};
1011     static const WCHAR authors[] = {'A','U','T','H','O','R','S',0};
1012     WCHAR *strW, *start, *end;
1013     HRSRC rsrc = FindResourceW( shell32_hInstance, authors, (LPCWSTR)RT_RCDATA );
1014     char *strA = LockResource( LoadResource( shell32_hInstance, rsrc ));
1015     DWORD sizeW, sizeA = SizeofResource( shell32_hInstance, rsrc );
1016
1017     if (!strA) return;
1018     sizeW = MultiByteToWideChar( CP_UTF8, 0, strA, sizeA, NULL, 0 ) + 1;
1019     if (!(strW = HeapAlloc( GetProcessHeap(), 0, sizeW * sizeof(WCHAR) ))) return;
1020     MultiByteToWideChar( CP_UTF8, 0, strA, sizeA, strW, sizeW );
1021     strW[sizeW - 1] = 0;
1022
1023     start = strpbrkW( strW, eol );  /* skip the header line */
1024     while (start)
1025     {
1026         while (*start && strchrW( eol, *start )) start++;
1027         if (!*start) break;
1028         end = strpbrkW( start, eol );
1029         if (end) *end++ = 0;
1030         SendMessageW( list, LB_ADDSTRING, -1, (LPARAM)start );
1031         start = end;
1032     }
1033     HeapFree( GetProcessHeap(), 0, strW );
1034 }
1035
1036 /*************************************************************************
1037  * AboutDlgProc            (internal)
1038  */
1039 static INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
1040                                       LPARAM lParam )
1041 {
1042     HWND hWndCtl;
1043
1044     TRACE("\n");
1045
1046     switch(msg)
1047     {
1048     case WM_INITDIALOG:
1049         {
1050             ABOUT_INFO *info = (ABOUT_INFO *)lParam;
1051             WCHAR template[512], buffer[512], version[64];
1052             extern const char *wine_get_build_id(void);
1053
1054             if (info)
1055             {
1056                 SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0);
1057                 GetWindowTextW( hWnd, template, sizeof(template)/sizeof(WCHAR) );
1058                 sprintfW( buffer, template, info->szApp );
1059                 SetWindowTextW( hWnd, buffer );
1060                 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT1), info->szApp );
1061                 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT2), info->szOtherStuff );
1062                 GetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3),
1063                                 template, sizeof(template)/sizeof(WCHAR) );
1064                 MultiByteToWideChar( CP_UTF8, 0, wine_get_build_id(), -1,
1065                                      version, sizeof(version)/sizeof(WCHAR) );
1066                 sprintfW( buffer, template, version );
1067                 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3), buffer );
1068                 hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_LISTBOX);
1069                 SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 );
1070                 SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 );
1071                 add_authors( hWndCtl );
1072                 SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 );
1073             }
1074         }
1075         return 1;
1076
1077     case WM_PAINT:
1078         {
1079             PAINTSTRUCT ps;
1080             HDC hDC = BeginPaint( hWnd, &ps );
1081             paint_dropline( hDC, hWnd );
1082             EndPaint( hWnd, &ps );
1083         }
1084     break;
1085
1086     case WM_COMMAND:
1087         if (wParam == IDOK || wParam == IDCANCEL)
1088         {
1089             EndDialog(hWnd, TRUE);
1090             return TRUE;
1091         }
1092         if (wParam == IDC_ABOUT_LICENSE)
1093         {
1094             MSGBOXPARAMSW params;
1095
1096             params.cbSize = sizeof(params);
1097             params.hwndOwner = hWnd;
1098             params.hInstance = shell32_hInstance;
1099             params.lpszText = MAKEINTRESOURCEW(IDS_LICENSE);
1100             params.lpszCaption = MAKEINTRESOURCEW(IDS_LICENSE_CAPTION);
1101             params.dwStyle = MB_ICONINFORMATION | MB_OK;
1102             params.lpszIcon = 0;
1103             params.dwContextHelpId = 0;
1104             params.lpfnMsgBoxCallback = NULL;
1105             params.dwLanguageId = LANG_NEUTRAL;
1106             MessageBoxIndirectW( &params );
1107         }
1108         break;
1109     case WM_CLOSE:
1110       EndDialog(hWnd, TRUE);
1111       break;
1112     }
1113
1114     return 0;
1115 }
1116
1117
1118 /*************************************************************************
1119  * ShellAboutA                [SHELL32.288]
1120  */
1121 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon )
1122 {
1123     BOOL ret;
1124     LPWSTR appW = NULL, otherW = NULL;
1125     int len;
1126
1127     if (szApp)
1128     {
1129         len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0);
1130         appW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1131         MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len);
1132     }
1133     if (szOtherStuff)
1134     {
1135         len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0);
1136         otherW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1137         MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len);
1138     }
1139
1140     ret = ShellAboutW(hWnd, appW, otherW, hIcon);
1141
1142     HeapFree(GetProcessHeap(), 0, otherW);
1143     HeapFree(GetProcessHeap(), 0, appW);
1144     return ret;
1145 }
1146
1147
1148 /*************************************************************************
1149  * ShellAboutW                [SHELL32.289]
1150  */
1151 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
1152                              HICON hIcon )
1153 {
1154     ABOUT_INFO info;
1155     LOGFONTW logFont;
1156     BOOL bRet;
1157     static const WCHAR wszSHELL_ABOUT_MSGBOX[] =
1158         {'S','H','E','L','L','_','A','B','O','U','T','_','M','S','G','B','O','X',0};
1159
1160     TRACE("\n");
1161
1162     if (!hIcon) hIcon = LoadImageW( 0, (LPWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED );
1163     info.szApp        = szApp;
1164     info.szOtherStuff = szOtherStuff;
1165     info.hIcon        = hIcon;
1166
1167     SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
1168     info.hFont = CreateFontIndirectW( &logFont );
1169
1170     bRet = DialogBoxParamW( shell32_hInstance, wszSHELL_ABOUT_MSGBOX, hWnd, AboutDlgProc, (LPARAM)&info );
1171     DeleteObject(info.hFont);
1172     return bRet;
1173 }
1174
1175 /*************************************************************************
1176  * FreeIconList (SHELL32.@)
1177  */
1178 void WINAPI FreeIconList( DWORD dw )
1179 {
1180     FIXME("%x: stub\n",dw);
1181 }
1182
1183 /*************************************************************************
1184  * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
1185  */
1186 HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID )
1187 {
1188     FIXME("stub\n");
1189     return S_OK;
1190 }
1191
1192 /***********************************************************************
1193  * DllGetVersion [SHELL32.@]
1194  *
1195  * Retrieves version information of the 'SHELL32.DLL'
1196  *
1197  * PARAMS
1198  *     pdvi [O] pointer to version information structure.
1199  *
1200  * RETURNS
1201  *     Success: S_OK
1202  *     Failure: E_INVALIDARG
1203  *
1204  * NOTES
1205  *     Returns version of a shell32.dll from IE4.01 SP1.
1206  */
1207
1208 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
1209 {
1210     /* FIXME: shouldn't these values come from the version resource? */
1211     if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
1212         pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1213     {
1214         pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
1215         pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
1216         pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
1217         pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
1218         if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1219         {
1220             DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
1221
1222             pdvi2->dwFlags = 0;
1223             pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
1224                                               WINE_FILEVERSION_MINOR,
1225                                               WINE_FILEVERSION_BUILD,
1226                                               WINE_FILEVERSION_PLATFORMID);
1227         }
1228         TRACE("%u.%u.%u.%u\n",
1229               pdvi->dwMajorVersion, pdvi->dwMinorVersion,
1230               pdvi->dwBuildNumber, pdvi->dwPlatformID);
1231         return S_OK;
1232     }
1233     else
1234     {
1235         WARN("wrong DLLVERSIONINFO size from app\n");
1236         return E_INVALIDARG;
1237     }
1238 }
1239
1240 /*************************************************************************
1241  * global variables of the shell32.dll
1242  * all are once per process
1243  *
1244  */
1245 HINSTANCE    shell32_hInstance = 0;
1246 HIMAGELIST   ShellSmallIconList = 0;
1247 HIMAGELIST   ShellBigIconList = 0;
1248
1249
1250 /*************************************************************************
1251  * SHELL32 DllMain
1252  *
1253  * NOTES
1254  *  calling oleinitialize here breaks some apps.
1255  */
1256 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1257 {
1258     TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
1259
1260     switch (fdwReason)
1261     {
1262     case DLL_PROCESS_ATTACH:
1263         shell32_hInstance = hinstDLL;
1264         DisableThreadLibraryCalls(shell32_hInstance);
1265
1266         /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
1267         GetModuleFileNameW(hinstDLL, swShell32Name, MAX_PATH);
1268         swShell32Name[MAX_PATH - 1] = '\0';
1269
1270         InitCommonControlsEx(NULL);
1271
1272         SIC_Initialize();
1273         InitChangeNotifications();
1274         break;
1275
1276     case DLL_PROCESS_DETACH:
1277         shell32_hInstance = 0;
1278         SIC_Destroy();
1279         FreeChangeNotifications();
1280         break;
1281     }
1282     return TRUE;
1283 }
1284
1285 /*************************************************************************
1286  * DllInstall         [SHELL32.@]
1287  *
1288  * PARAMETERS
1289  *
1290  *    BOOL bInstall - TRUE for install, FALSE for uninstall
1291  *    LPCWSTR pszCmdLine - command line (unused by shell32?)
1292  */
1293
1294 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1295 {
1296     FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
1297     return S_OK;        /* indicate success */
1298 }
1299
1300 /***********************************************************************
1301  *              DllCanUnloadNow (SHELL32.@)
1302  */
1303 HRESULT WINAPI DllCanUnloadNow(void)
1304 {
1305     return S_FALSE;
1306 }
1307
1308 /***********************************************************************
1309  *              DllRegisterServer (SHELL32.@)
1310  */
1311 HRESULT WINAPI DllRegisterServer(void)
1312 {
1313     HRESULT hr = __wine_register_resources( shell32_hInstance );
1314     if (SUCCEEDED(hr)) hr = SHELL_RegisterShellFolders();
1315     return hr;
1316 }
1317
1318 /***********************************************************************
1319  *              DllUnregisterServer (SHELL32.@)
1320  */
1321 HRESULT WINAPI DllUnregisterServer(void)
1322 {
1323     return __wine_unregister_resources( shell32_hInstance );
1324 }
1325
1326 /***********************************************************************
1327  *              ExtractVersionResource16W (SHELL32.@)
1328  */
1329 BOOL WINAPI ExtractVersionResource16W(LPWSTR s, DWORD d)
1330 {
1331     FIXME("(%s %x) stub!\n", debugstr_w(s), d);
1332     return FALSE;
1333 }
1334
1335 /***********************************************************************
1336  *              InitNetworkAddressControl (SHELL32.@)
1337  */
1338 BOOL WINAPI InitNetworkAddressControl(void)
1339 {
1340     FIXME("stub\n");
1341     return FALSE;
1342 }
1343
1344 /***********************************************************************
1345  *              ShellHookProc (SHELL32.@)
1346  */
1347 LRESULT CALLBACK ShellHookProc(DWORD a, DWORD b, DWORD c)
1348 {
1349     FIXME("Stub\n");
1350     return 0;
1351 }
1352
1353 /***********************************************************************
1354  *              SHGetLocalizedName (SHELL32.@)
1355  */
1356 HRESULT WINAPI SHGetLocalizedName(LPCWSTR path, LPWSTR module, UINT size, INT *res)
1357 {
1358     FIXME("%s %p %u %p: stub\n", debugstr_w(path), module, size, res);
1359     return E_NOTIMPL;
1360 }
1361
1362 /***********************************************************************
1363  *              SetCurrentProcessExplicitAppUserModelID (SHELL32.@)
1364  */
1365 HRESULT WINAPI SetCurrentProcessExplicitAppUserModelID(PCWSTR appid)
1366 {
1367     FIXME("%s: stub\n", debugstr_w(appid));
1368     return E_NOTIMPL;
1369 }
1370
1371 /***********************************************************************
1372  *              SHSetUnreadMailCountW (SHELL32.@)
1373  */
1374 HRESULT WINAPI SHSetUnreadMailCountW(LPCWSTR mailaddress, DWORD count, LPCWSTR executecommand)
1375 {
1376     FIXME("%s %x %s: stub\n", debugstr_w(mailaddress), count, debugstr_w(executecommand));
1377     return E_NOTIMPL;
1378 }