4 * Copyright 1998 Marcus Meissner
5 * Copyright 1998 Juergen Schmied (jsch) * <juergen.schmied@metronet.de>
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.
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.
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
43 #include "commoncontrols.h"
45 #include "undocshell.h"
47 #include "shell32_main.h"
53 #include "wine/debug.h"
54 #include "wine/unicode.h"
56 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
58 /*************************************************************************
59 * CommandLineToArgvW [SHELL32.@]
61 * We must interpret the quotes in the command line to rebuild the argv
63 * - arguments are separated by spaces or tabs
64 * - quotes serve as optional argument delimiters
66 * - escaped quotes must be converted back to '"'
68 * - consecutive backslashes preceding a quote see their number halved with
69 * the remainder escaping the quote:
70 * 2n backslashes + quote -> n backslashes + quote as an argument delimiter
71 * 2n+1 backslashes + quote -> n backslashes + literal quote
72 * - backslashes that are not followed by a quote are copied literally:
75 * - in quoted strings, consecutive quotes see their number divided by three
76 * with the remainder modulo 3 deciding whether to close the string or not.
77 * Note that the opening quote must be counted in the consecutive quotes,
78 * that's the (1+) below:
79 * (1+) 3n quotes -> n quotes
80 * (1+) 3n+1 quotes -> n quotes plus closes the quoted string
81 * (1+) 3n+2 quotes -> n+1 quotes plus closes the quoted string
82 * - in unquoted strings, the first quote opens the quoted string and the
83 * remaining consecutive quotes follow the above rule.
85 LPWSTR
* WINAPI
CommandLineToArgvW(LPCWSTR lpCmdline
, int* numargs
)
96 SetLastError(ERROR_INVALID_PARAMETER
);
102 /* Return the path to the executable */
103 DWORD len
, deslen
=MAX_PATH
, size
;
105 size
= sizeof(LPWSTR
)*2 + deslen
*sizeof(WCHAR
);
108 if (!(argv
= LocalAlloc(LMEM_FIXED
, size
))) return NULL
;
109 len
= GetModuleFileNameW(0, (LPWSTR
)(argv
+2), deslen
);
115 if (len
< deslen
) break;
117 size
= sizeof(LPWSTR
)*2 + deslen
*sizeof(WCHAR
);
120 argv
[0]=(LPWSTR
)(argv
+2);
127 /* --- First count the arguments */
130 /* The first argument, the executable path, follows special rules */
133 /* The executable path ends at the next quote, no matter what */
141 /* The executable path ends at the next space, no matter what */
142 while (*s
&& *s
!=' ' && *s
!='\t')
145 /* skip to the first argument, if any */
146 while (*s
==' ' || *s
=='\t')
151 /* Analyze the remaining arguments */
155 if ((*s
==' ' || *s
=='\t') && qcount
==0)
157 /* skip to the next argument and count it if any */
158 while (*s
==' ' || *s
=='\t')
166 /* '\', count them */
174 qcount
++; /* unescaped '"' */
177 /* consecutive quotes, see comment in copying code below */
189 /* a regular character */
195 /* Allocate in a single lump, the string array, and the strings that go
196 * with it. This way the caller can make a single LocalFree() call to free
199 argv
=LocalAlloc(LMEM_FIXED
, (argc
+1)*sizeof(LPWSTR
)+(strlenW(lpCmdline
)+1)*sizeof(WCHAR
));
202 cmdline
=(LPWSTR
)(argv
+argc
+1);
203 strcpyW(cmdline
, lpCmdline
);
205 /* --- Then split and copy the arguments */
208 /* The first argument, the executable path, follows special rules */
211 /* The executable path ends at the next quote, no matter what */
225 /* The executable path ends at the next space, no matter what */
226 while (*d
&& *d
!=' ' && *d
!='\t')
232 /* close the executable path */
234 /* skip to the first argument and initialize it if any */
235 while (*s
==' ' || *s
=='\t')
239 /* There are no parameters so we are all done */
245 /* Split and copy the remaining arguments */
250 if ((*s
==' ' || *s
=='\t') && qcount
==0)
252 /* close the argument */
256 /* skip to the next one and initialize it if any */
259 } while (*s
==' ' || *s
=='\t');
272 /* Preceded by an even number of '\', this is half that
273 * number of '\', plus a quote which we erase.
280 /* Preceded by an odd number of '\', this is half that
281 * number of '\' followed by a '"'
288 /* Now count the number of consecutive quotes. Note that qcount
289 * already takes into account the opening quote if any, as well as
290 * the quote that lead us here.
306 /* a regular character */
318 static DWORD
shgfi_get_exe_type(LPCWSTR szFullPath
)
323 IMAGE_DOS_HEADER mz_header
;
328 status
= GetBinaryTypeW (szFullPath
, &BinaryType
);
331 if (BinaryType
== SCS_DOS_BINARY
|| BinaryType
== SCS_PIF_BINARY
)
334 hfile
= CreateFileW( szFullPath
, GENERIC_READ
, FILE_SHARE_READ
,
335 NULL
, OPEN_EXISTING
, 0, 0 );
336 if ( hfile
== INVALID_HANDLE_VALUE
)
340 * The next section is adapted from MODULE_GetBinaryType, as we need
341 * to examine the image header to get OS and version information. We
342 * know from calling GetBinaryTypeA that the image is valid and either
343 * an NE or PE, so much error handling can be omitted.
344 * Seek to the start of the file and read the header information.
347 SetFilePointer( hfile
, 0, NULL
, SEEK_SET
);
348 ReadFile( hfile
, &mz_header
, sizeof(mz_header
), &len
, NULL
);
350 SetFilePointer( hfile
, mz_header
.e_lfanew
, NULL
, SEEK_SET
);
351 ReadFile( hfile
, magic
, sizeof(magic
), &len
, NULL
);
352 if ( *(DWORD
*)magic
== IMAGE_NT_SIGNATURE
)
354 SetFilePointer( hfile
, mz_header
.e_lfanew
, NULL
, SEEK_SET
);
355 ReadFile( hfile
, &nt
, sizeof(nt
), &len
, NULL
);
356 CloseHandle( hfile
);
357 /* DLL files are not executable and should return 0 */
358 if (nt
.FileHeader
.Characteristics
& IMAGE_FILE_DLL
)
360 if (nt
.OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
362 return IMAGE_NT_SIGNATURE
|
363 (nt
.OptionalHeader
.MajorSubsystemVersion
<< 24) |
364 (nt
.OptionalHeader
.MinorSubsystemVersion
<< 16);
366 return IMAGE_NT_SIGNATURE
;
368 else if ( *(WORD
*)magic
== IMAGE_OS2_SIGNATURE
)
371 SetFilePointer( hfile
, mz_header
.e_lfanew
, NULL
, SEEK_SET
);
372 ReadFile( hfile
, &ne
, sizeof(ne
), &len
, NULL
);
373 CloseHandle( hfile
);
374 if (ne
.ne_exetyp
== 2)
375 return IMAGE_OS2_SIGNATURE
| (ne
.ne_expver
<< 16);
378 CloseHandle( hfile
);
382 /*************************************************************************
383 * SHELL_IsShortcut [internal]
385 * Decide if an item id list points to a shell shortcut
387 BOOL
SHELL_IsShortcut(LPCITEMIDLIST pidlLast
)
389 char szTemp
[MAX_PATH
];
393 if (_ILGetExtension(pidlLast
, szTemp
, MAX_PATH
) &&
394 HCR_MapTypeToValueA(szTemp
, szTemp
, MAX_PATH
, TRUE
))
396 if (ERROR_SUCCESS
== RegOpenKeyExA(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_QUERY_VALUE
, &keyCls
))
398 if (ERROR_SUCCESS
== RegQueryValueExA(keyCls
, "IsShortcut", NULL
, NULL
, NULL
, NULL
))
408 #define SHGFI_KNOWN_FLAGS \
409 (SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \
410 SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \
411 SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ATTRIBUTES | \
412 SHGFI_ICONLOCATION | SHGFI_EXETYPE | SHGFI_SYSICONINDEX | \
413 SHGFI_LINKOVERLAY | SHGFI_SELECTED | SHGFI_ATTR_SPECIFIED)
415 /*************************************************************************
416 * SHGetFileInfoW [SHELL32.@]
419 DWORD_PTR WINAPI
SHGetFileInfoW(LPCWSTR path
,DWORD dwFileAttributes
,
420 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
422 WCHAR szLocation
[MAX_PATH
], szFullPath
[MAX_PATH
];
424 DWORD_PTR ret
= TRUE
;
425 DWORD dwAttributes
= 0;
426 IShellFolder
* psfParent
= NULL
;
427 IExtractIconW
* pei
= NULL
;
428 LPITEMIDLIST pidlLast
= NULL
, pidl
= NULL
;
432 TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
433 (flags
& SHGFI_PIDL
)? "pidl" : debugstr_w(path
), dwFileAttributes
,
434 psfi
, psfi
? psfi
->dwAttributes
: 0, sizeofpsfi
, flags
);
439 /* windows initializes these values regardless of the flags */
442 psfi
->szDisplayName
[0] = '\0';
443 psfi
->szTypeName
[0] = '\0';
447 if (!(flags
& SHGFI_PIDL
))
449 /* SHGetFileInfo should work with absolute and relative paths */
450 if (PathIsRelativeW(path
))
452 GetCurrentDirectoryW(MAX_PATH
, szLocation
);
453 PathCombineW(szFullPath
, szLocation
, path
);
457 lstrcpynW(szFullPath
, path
, MAX_PATH
);
461 if (flags
& SHGFI_EXETYPE
)
463 if (flags
!= SHGFI_EXETYPE
)
465 return shgfi_get_exe_type(szFullPath
);
469 * psfi is NULL normally to query EXE type. If it is NULL, none of the
470 * below makes sense anyway. Windows allows this and just returns FALSE
476 * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES
478 * The pidl functions fail on not existing file names
481 if (flags
& SHGFI_PIDL
)
483 pidl
= ILClone((LPCITEMIDLIST
)path
);
485 else if (!(flags
& SHGFI_USEFILEATTRIBUTES
))
487 hr
= SHILCreateFromPathW(szFullPath
, &pidl
, &dwAttributes
);
490 if ((flags
& SHGFI_PIDL
) || !(flags
& SHGFI_USEFILEATTRIBUTES
))
492 /* get the parent shellfolder */
495 hr
= SHBindToParent( pidl
, &IID_IShellFolder
, (LPVOID
*)&psfParent
,
496 (LPCITEMIDLIST
*)&pidlLast
);
498 pidlLast
= ILClone(pidlLast
);
503 ERR("pidl is null!\n");
508 /* get the attributes of the child */
509 if (SUCCEEDED(hr
) && (flags
& SHGFI_ATTRIBUTES
))
511 if (!(flags
& SHGFI_ATTR_SPECIFIED
))
513 psfi
->dwAttributes
= 0xffffffff;
516 IShellFolder_GetAttributesOf( psfParent
, 1, (LPCITEMIDLIST
*)&pidlLast
,
517 &(psfi
->dwAttributes
) );
520 /* get the displayname */
521 if (SUCCEEDED(hr
) && (flags
& SHGFI_DISPLAYNAME
))
523 if (flags
& SHGFI_USEFILEATTRIBUTES
&& !(flags
& SHGFI_PIDL
))
525 lstrcpyW (psfi
->szDisplayName
, PathFindFileNameW(szFullPath
));
530 hr
= IShellFolder_GetDisplayNameOf( psfParent
, pidlLast
,
531 SHGDN_INFOLDER
, &str
);
532 StrRetToStrNW (psfi
->szDisplayName
, MAX_PATH
, &str
, pidlLast
);
536 /* get the type name */
537 if (SUCCEEDED(hr
) && (flags
& SHGFI_TYPENAME
))
539 static const WCHAR szFolder
[] = { 'F','o','l','d','e','r',0 };
540 static const WCHAR szFile
[] = { 'F','i','l','e',0 };
541 static const WCHAR szSpaceFile
[] = { ' ','f','i','l','e',0 };
543 if (!(flags
& SHGFI_USEFILEATTRIBUTES
) || (flags
& SHGFI_PIDL
))
547 _ILGetFileType(pidlLast
, ftype
, 80);
548 MultiByteToWideChar(CP_ACP
, 0, ftype
, -1, psfi
->szTypeName
, 80 );
552 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
553 strcatW (psfi
->szTypeName
, szFolder
);
558 lstrcpyW(sTemp
,PathFindExtensionW(szFullPath
));
559 if (sTemp
[0] == 0 || (sTemp
[0] == '.' && sTemp
[1] == 0))
561 /* "name" or "name." => "File" */
562 lstrcpynW (psfi
->szTypeName
, szFile
, 64);
564 else if (!( HCR_MapTypeToValueW(sTemp
, sTemp
, 64, TRUE
) &&
565 HCR_MapTypeToValueW(sTemp
, psfi
->szTypeName
, 80, FALSE
)))
569 lstrcpynW (psfi
->szTypeName
, sTemp
, 64);
570 strcatW (psfi
->szTypeName
, szSpaceFile
);
574 lstrcpynW (psfi
->szTypeName
, szFile
, 64);
582 if (flags
& SHGFI_OPENICON
)
583 uGilFlags
|= GIL_OPENICON
;
585 if (flags
& SHGFI_LINKOVERLAY
)
586 uGilFlags
|= GIL_FORSHORTCUT
;
587 else if ((flags
&SHGFI_ADDOVERLAYS
) ||
588 (flags
&(SHGFI_ICON
|SHGFI_SMALLICON
))==SHGFI_ICON
)
590 if (SHELL_IsShortcut(pidlLast
))
591 uGilFlags
|= GIL_FORSHORTCUT
;
594 if (flags
& SHGFI_OVERLAYINDEX
)
595 FIXME("SHGFI_OVERLAYINDEX unhandled\n");
597 if (flags
& SHGFI_SELECTED
)
598 FIXME("set icon to selected, stub\n");
600 /* get the iconlocation */
601 if (SUCCEEDED(hr
) && (flags
& SHGFI_ICONLOCATION
))
605 if (flags
& SHGFI_USEFILEATTRIBUTES
&& !(flags
& SHGFI_PIDL
))
607 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
609 lstrcpyW(psfi
->szDisplayName
, swShell32Name
);
610 psfi
->iIcon
= -IDI_SHELL_FOLDER
;
615 static const WCHAR p1W
[] = {'%','1',0};
616 WCHAR sTemp
[MAX_PATH
];
618 szExt
= PathFindExtensionW(szFullPath
);
619 TRACE("szExt=%s\n", debugstr_w(szExt
));
621 HCR_MapTypeToValueW(szExt
, sTemp
, MAX_PATH
, TRUE
) &&
622 HCR_GetDefaultIconW(sTemp
, sTemp
, MAX_PATH
, &psfi
->iIcon
))
624 if (lstrcmpW(p1W
, sTemp
))
625 strcpyW(psfi
->szDisplayName
, sTemp
);
628 /* the icon is in the file */
629 strcpyW(psfi
->szDisplayName
, szFullPath
);
638 hr
= IShellFolder_GetUIObjectOf(psfParent
, 0, 1,
639 (LPCITEMIDLIST
*)&pidlLast
, &IID_IExtractIconW
,
640 &uDummy
, (LPVOID
*)&pei
);
643 hr
= IExtractIconW_GetIconLocation(pei
, uGilFlags
,
644 szLocation
, MAX_PATH
, &iIndex
, &uFlags
);
646 if (uFlags
& GIL_NOTFILENAME
)
650 lstrcpyW (psfi
->szDisplayName
, szLocation
);
651 psfi
->iIcon
= iIndex
;
653 IExtractIconW_Release(pei
);
658 /* get icon index (or load icon)*/
659 if (SUCCEEDED(hr
) && (flags
& (SHGFI_ICON
| SHGFI_SYSICONINDEX
)))
661 IImageList
*icon_list
;
662 SHGetImageList( (flags
& SHGFI_SMALLICON
) ? SHIL_SMALL
: SHIL_LARGE
, &IID_IImageList
, (void **)&icon_list
);
664 if (flags
& SHGFI_USEFILEATTRIBUTES
&& !(flags
& SHGFI_PIDL
))
666 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
667 psfi
->iIcon
= SIC_GetIconIndex(swShell32Name
, -IDI_SHELL_FOLDER
, 0);
670 static const WCHAR p1W
[] = {'%','1',0};
671 WCHAR sTemp
[MAX_PATH
];
675 lstrcpynW(sTemp
, szFullPath
, MAX_PATH
);
678 szExt
= PathFindExtensionW(sTemp
);
680 HCR_MapTypeToValueW(szExt
, sTemp
, MAX_PATH
, TRUE
) &&
681 HCR_GetDefaultIconW(sTemp
, sTemp
, MAX_PATH
, &icon_idx
))
683 if (!lstrcmpW(p1W
,sTemp
)) /* icon is in the file */
684 strcpyW(sTemp
, szFullPath
);
686 psfi
->iIcon
= SIC_GetIconIndex(sTemp
, icon_idx
, 0);
687 if (psfi
->iIcon
== -1)
694 if (!(PidlToSicIndex(psfParent
, pidlLast
, !(flags
& SHGFI_SMALLICON
),
695 uGilFlags
, &(psfi
->iIcon
))))
700 if (ret
&& (flags
& SHGFI_SYSICONINDEX
))
702 IImageList_AddRef( icon_list
);
703 ret
= (DWORD_PTR
)icon_list
;
705 if (ret
&& (flags
& SHGFI_ICON
))
707 if (flags
& SHGFI_SHELLICONSIZE
)
708 hr
= IImageList_GetIcon( icon_list
, psfi
->iIcon
, ILD_NORMAL
, &psfi
->hIcon
);
711 int width
= GetSystemMetrics( (flags
& SHGFI_SMALLICON
) ? SM_CXSMICON
: SM_CXICON
);
712 int height
= GetSystemMetrics( (flags
& SHGFI_SMALLICON
) ? SM_CYSMICON
: SM_CYICON
);
713 int list_width
, list_height
;
715 IImageList_GetIconSize( icon_list
, &list_width
, &list_height
);
716 if (list_width
== width
&& list_height
== height
)
717 hr
= IImageList_GetIcon( icon_list
, psfi
->iIcon
, ILD_NORMAL
, &psfi
->hIcon
);
718 else /* Use SHIL_SYSSMALL for SHFI_SMALLICONS when we implement it */
720 WCHAR buf
[MAX_PATH
], *file
= buf
;
721 DWORD size
= sizeof(buf
);
724 while ((hr
= SIC_get_location( psfi
->iIcon
, file
, &size
, &icon_idx
)) == E_NOT_SUFFICIENT_BUFFER
)
726 if (file
== buf
) file
= HeapAlloc( GetProcessHeap(), 0, size
);
727 else file
= HeapReAlloc( GetProcessHeap(), 0, file
, size
);
732 ret
= PrivateExtractIconsW( file
, icon_idx
, width
, height
, &psfi
->hIcon
, 0, 1, 0);
733 if (ret
== 0 || ret
== (UINT
)-1) hr
= E_FAIL
;
735 if (file
!= buf
) HeapFree( GetProcessHeap(), 0, file
);
739 IImageList_Release( icon_list
);
742 if (flags
& ~SHGFI_KNOWN_FLAGS
)
743 FIXME("unknown flags %08x\n", flags
& ~SHGFI_KNOWN_FLAGS
);
746 IShellFolder_Release(psfParent
);
753 TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
754 psfi
->hIcon
, psfi
->iIcon
, psfi
->dwAttributes
,
755 debugstr_w(psfi
->szDisplayName
), debugstr_w(psfi
->szTypeName
), ret
);
760 /*************************************************************************
761 * SHGetFileInfoA [SHELL32.@]
764 * MSVBVM60.__vbaNew2 expects this function to return a value in range
765 * 1 .. 0x7fff when the function succeeds and flags does not contain
766 * SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701)
768 DWORD_PTR WINAPI
SHGetFileInfoA(LPCSTR path
,DWORD dwFileAttributes
,
769 SHFILEINFOA
*psfi
, UINT sizeofpsfi
,
773 LPWSTR temppath
= NULL
;
776 SHFILEINFOW temppsfi
;
778 if (flags
& SHGFI_PIDL
)
780 /* path contains a pidl */
781 pathW
= (LPCWSTR
)path
;
785 len
= MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
786 temppath
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
787 MultiByteToWideChar(CP_ACP
, 0, path
, -1, temppath
, len
);
791 if (psfi
&& (flags
& SHGFI_ATTR_SPECIFIED
))
792 temppsfi
.dwAttributes
=psfi
->dwAttributes
;
795 ret
= SHGetFileInfoW(pathW
, dwFileAttributes
, NULL
, sizeof(temppsfi
), flags
);
797 ret
= SHGetFileInfoW(pathW
, dwFileAttributes
, &temppsfi
, sizeof(temppsfi
), flags
);
801 if(flags
& SHGFI_ICON
)
802 psfi
->hIcon
=temppsfi
.hIcon
;
803 if(flags
& (SHGFI_SYSICONINDEX
|SHGFI_ICON
|SHGFI_ICONLOCATION
))
804 psfi
->iIcon
=temppsfi
.iIcon
;
805 if(flags
& SHGFI_ATTRIBUTES
)
806 psfi
->dwAttributes
=temppsfi
.dwAttributes
;
807 if(flags
& (SHGFI_DISPLAYNAME
|SHGFI_ICONLOCATION
))
809 WideCharToMultiByte(CP_ACP
, 0, temppsfi
.szDisplayName
, -1,
810 psfi
->szDisplayName
, sizeof(psfi
->szDisplayName
), NULL
, NULL
);
812 if(flags
& SHGFI_TYPENAME
)
814 WideCharToMultiByte(CP_ACP
, 0, temppsfi
.szTypeName
, -1,
815 psfi
->szTypeName
, sizeof(psfi
->szTypeName
), NULL
, NULL
);
819 HeapFree(GetProcessHeap(), 0, temppath
);
824 /*************************************************************************
825 * DuplicateIcon [SHELL32.@]
827 HICON WINAPI
DuplicateIcon( HINSTANCE hInstance
, HICON hIcon
)
832 TRACE("%p %p\n", hInstance
, hIcon
);
834 if (GetIconInfo(hIcon
, &IconInfo
))
836 hDupIcon
= CreateIconIndirect(&IconInfo
);
838 /* clean up hbmMask and hbmColor */
839 DeleteObject(IconInfo
.hbmMask
);
840 DeleteObject(IconInfo
.hbmColor
);
846 /*************************************************************************
847 * ExtractIconA [SHELL32.@]
849 HICON WINAPI
ExtractIconA(HINSTANCE hInstance
, const char *file
, UINT nIconIndex
)
854 TRACE("%p %s %d\n", hInstance
, debugstr_a(file
), nIconIndex
);
856 fileW
= strdupAtoW(file
);
857 ret
= ExtractIconW(hInstance
, fileW
, nIconIndex
);
858 HeapFree(GetProcessHeap(), 0, fileW
);
863 /*************************************************************************
864 * ExtractIconW [SHELL32.@]
866 HICON WINAPI
ExtractIconW(HINSTANCE hInstance
, LPCWSTR lpszFile
, UINT nIconIndex
)
870 UINT cx
= GetSystemMetrics(SM_CXICON
), cy
= GetSystemMetrics(SM_CYICON
);
872 TRACE("%p %s %d\n", hInstance
, debugstr_w(lpszFile
), nIconIndex
);
874 if (nIconIndex
== (UINT
)-1)
876 ret
= PrivateExtractIconsW(lpszFile
, 0, cx
, cy
, NULL
, NULL
, 0, LR_DEFAULTCOLOR
);
877 if (ret
!= (UINT
)-1 && ret
)
878 return (HICON
)(UINT_PTR
)ret
;
882 ret
= PrivateExtractIconsW(lpszFile
, nIconIndex
, cx
, cy
, &hIcon
, NULL
, 1, LR_DEFAULTCOLOR
);
886 else if (ret
> 0 && hIcon
)
892 HRESULT WINAPI
SHCreateFileExtractIconW(LPCWSTR file
, DWORD attribs
, REFIID riid
, void **ppv
)
894 FIXME("%s, %x, %s, %p\n", debugstr_w(file
), attribs
, debugstr_guid(riid
), ppv
);
899 /*************************************************************************
900 * Printer_LoadIconsW [SHELL32.205]
902 VOID WINAPI
Printer_LoadIconsW(LPCWSTR wsPrinterName
, HICON
* pLargeIcon
, HICON
* pSmallIcon
)
904 INT iconindex
=IDI_SHELL_PRINTER
;
906 TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName
), pLargeIcon
, pSmallIcon
);
908 /* We should check if wsPrinterName is
909 1. the Default Printer or not
911 3. a Local Printer or a Network-Printer
912 and use different Icons
914 if((wsPrinterName
!= NULL
) && (wsPrinterName
[0] != 0))
916 FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName
));
919 if(pLargeIcon
!= NULL
)
920 *pLargeIcon
= LoadImageW(shell32_hInstance
,
921 (LPCWSTR
) MAKEINTRESOURCE(iconindex
), IMAGE_ICON
,
922 0, 0, LR_DEFAULTCOLOR
|LR_DEFAULTSIZE
);
924 if(pSmallIcon
!= NULL
)
925 *pSmallIcon
= LoadImageW(shell32_hInstance
,
926 (LPCWSTR
) MAKEINTRESOURCE(iconindex
), IMAGE_ICON
,
927 16, 16, LR_DEFAULTCOLOR
);
930 /*************************************************************************
931 * Printers_RegisterWindowW [SHELL32.213]
932 * used by "printui.dll":
933 * find the Window of the given Type for the specific Printer and
934 * return the already existent hwnd or open a new window
936 BOOL WINAPI
Printers_RegisterWindowW(LPCWSTR wsPrinter
, DWORD dwType
,
937 HANDLE
* phClassPidl
, HWND
* phwnd
)
939 FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter
), dwType
,
940 phClassPidl
, (phClassPidl
!= NULL
) ? *(phClassPidl
) : NULL
,
941 phwnd
, (phwnd
!= NULL
) ? *(phwnd
) : NULL
);
946 /*************************************************************************
947 * Printers_UnregisterWindow [SHELL32.214]
949 VOID WINAPI
Printers_UnregisterWindow(HANDLE hClassPidl
, HWND hwnd
)
951 FIXME("(%p, %p) stub!\n", hClassPidl
, hwnd
);
954 /*************************************************************************
955 * SHGetPropertyStoreForWindow [SHELL32.@]
957 HRESULT WINAPI
SHGetPropertyStoreForWindow(HWND hwnd
, REFIID riid
, void **ppv
)
959 FIXME("(%p %p %p) stub!\n", hwnd
, riid
, ppv
);
963 /*************************************************************************/
968 LPCWSTR szOtherStuff
;
973 #define DROP_FIELD_TOP (-12)
975 static void paint_dropline( HDC hdc
, HWND hWnd
)
977 HWND hWndCtl
= GetDlgItem(hWnd
, IDC_ABOUT_WINE_TEXT
);
980 if (!hWndCtl
) return;
981 GetWindowRect( hWndCtl
, &rect
);
982 MapWindowPoints( 0, hWnd
, (LPPOINT
)&rect
, 2 );
983 rect
.top
+= DROP_FIELD_TOP
;
984 rect
.bottom
= rect
.top
+ 2;
985 DrawEdge( hdc
, &rect
, BDR_SUNKENOUTER
, BF_RECT
);
988 /*************************************************************************
989 * SHHelpShortcuts_RunDLLA [SHELL32.@]
992 DWORD WINAPI
SHHelpShortcuts_RunDLLA(DWORD dwArg1
, DWORD dwArg2
, DWORD dwArg3
, DWORD dwArg4
)
994 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1
, dwArg2
, dwArg3
, dwArg4
);
998 /*************************************************************************
999 * SHHelpShortcuts_RunDLLA [SHELL32.@]
1002 DWORD WINAPI
SHHelpShortcuts_RunDLLW(DWORD dwArg1
, DWORD dwArg2
, DWORD dwArg3
, DWORD dwArg4
)
1004 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1
, dwArg2
, dwArg3
, dwArg4
);
1008 /*************************************************************************
1009 * SHLoadInProc [SHELL32.@]
1010 * Create an instance of specified object class from within
1011 * the shell process and release it immediately
1013 HRESULT WINAPI
SHLoadInProc (REFCLSID rclsid
)
1017 TRACE("%s\n", debugstr_guid(rclsid
));
1019 CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
,&ptr
);
1022 IUnknown
* pUnk
= ptr
;
1023 IUnknown_Release(pUnk
);
1026 return DISP_E_MEMBERNOTFOUND
;
1029 static void add_authors( HWND list
)
1031 static const WCHAR eol
[] = {'\r','\n',0};
1032 static const WCHAR authors
[] = {'A','U','T','H','O','R','S',0};
1033 WCHAR
*strW
, *start
, *end
;
1034 HRSRC rsrc
= FindResourceW( shell32_hInstance
, authors
, (LPCWSTR
)RT_RCDATA
);
1035 char *strA
= LockResource( LoadResource( shell32_hInstance
, rsrc
));
1036 DWORD sizeW
, sizeA
= SizeofResource( shell32_hInstance
, rsrc
);
1039 sizeW
= MultiByteToWideChar( CP_UTF8
, 0, strA
, sizeA
, NULL
, 0 ) + 1;
1040 if (!(strW
= HeapAlloc( GetProcessHeap(), 0, sizeW
* sizeof(WCHAR
) ))) return;
1041 MultiByteToWideChar( CP_UTF8
, 0, strA
, sizeA
, strW
, sizeW
);
1042 strW
[sizeW
- 1] = 0;
1044 start
= strpbrkW( strW
, eol
); /* skip the header line */
1047 while (*start
&& strchrW( eol
, *start
)) start
++;
1049 end
= strpbrkW( start
, eol
);
1050 if (end
) *end
++ = 0;
1051 SendMessageW( list
, LB_ADDSTRING
, -1, (LPARAM
)start
);
1054 HeapFree( GetProcessHeap(), 0, strW
);
1057 /*************************************************************************
1058 * AboutDlgProc (internal)
1060 static INT_PTR CALLBACK
AboutDlgProc( HWND hWnd
, UINT msg
, WPARAM wParam
,
1071 ABOUT_INFO
*info
= (ABOUT_INFO
*)lParam
;
1072 WCHAR
template[512], buffer
[512], version
[64];
1073 extern const char *wine_get_build_id(void);
1077 SendDlgItemMessageW(hWnd
, stc1
, STM_SETICON
,(WPARAM
)info
->hIcon
, 0);
1078 GetWindowTextW( hWnd
, template, sizeof(template)/sizeof(WCHAR
) );
1079 sprintfW( buffer
, template, info
->szApp
);
1080 SetWindowTextW( hWnd
, buffer
);
1081 SetWindowTextW( GetDlgItem(hWnd
, IDC_ABOUT_STATIC_TEXT1
), info
->szApp
);
1082 SetWindowTextW( GetDlgItem(hWnd
, IDC_ABOUT_STATIC_TEXT2
), info
->szOtherStuff
);
1083 GetWindowTextW( GetDlgItem(hWnd
, IDC_ABOUT_STATIC_TEXT3
),
1084 template, sizeof(template)/sizeof(WCHAR
) );
1085 MultiByteToWideChar( CP_UTF8
, 0, wine_get_build_id(), -1,
1086 version
, sizeof(version
)/sizeof(WCHAR
) );
1087 sprintfW( buffer
, template, version
);
1088 SetWindowTextW( GetDlgItem(hWnd
, IDC_ABOUT_STATIC_TEXT3
), buffer
);
1089 hWndCtl
= GetDlgItem(hWnd
, IDC_ABOUT_LISTBOX
);
1090 SendMessageW( hWndCtl
, WM_SETREDRAW
, 0, 0 );
1091 SendMessageW( hWndCtl
, WM_SETFONT
, (WPARAM
)info
->hFont
, 0 );
1092 add_authors( hWndCtl
);
1093 SendMessageW( hWndCtl
, WM_SETREDRAW
, 1, 0 );
1101 HDC hDC
= BeginPaint( hWnd
, &ps
);
1102 paint_dropline( hDC
, hWnd
);
1103 EndPaint( hWnd
, &ps
);
1108 if (wParam
== IDOK
|| wParam
== IDCANCEL
)
1110 EndDialog(hWnd
, TRUE
);
1113 if (wParam
== IDC_ABOUT_LICENSE
)
1115 MSGBOXPARAMSW params
;
1117 params
.cbSize
= sizeof(params
);
1118 params
.hwndOwner
= hWnd
;
1119 params
.hInstance
= shell32_hInstance
;
1120 params
.lpszText
= MAKEINTRESOURCEW(IDS_LICENSE
);
1121 params
.lpszCaption
= MAKEINTRESOURCEW(IDS_LICENSE_CAPTION
);
1122 params
.dwStyle
= MB_ICONINFORMATION
| MB_OK
;
1123 params
.lpszIcon
= 0;
1124 params
.dwContextHelpId
= 0;
1125 params
.lpfnMsgBoxCallback
= NULL
;
1126 params
.dwLanguageId
= LANG_NEUTRAL
;
1127 MessageBoxIndirectW( ¶ms
);
1131 EndDialog(hWnd
, TRUE
);
1139 /*************************************************************************
1140 * ShellAboutA [SHELL32.288]
1142 BOOL WINAPI
ShellAboutA( HWND hWnd
, LPCSTR szApp
, LPCSTR szOtherStuff
, HICON hIcon
)
1145 LPWSTR appW
= NULL
, otherW
= NULL
;
1150 len
= MultiByteToWideChar(CP_ACP
, 0, szApp
, -1, NULL
, 0);
1151 appW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1152 MultiByteToWideChar(CP_ACP
, 0, szApp
, -1, appW
, len
);
1156 len
= MultiByteToWideChar(CP_ACP
, 0, szOtherStuff
, -1, NULL
, 0);
1157 otherW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1158 MultiByteToWideChar(CP_ACP
, 0, szOtherStuff
, -1, otherW
, len
);
1161 ret
= ShellAboutW(hWnd
, appW
, otherW
, hIcon
);
1163 HeapFree(GetProcessHeap(), 0, otherW
);
1164 HeapFree(GetProcessHeap(), 0, appW
);
1169 /*************************************************************************
1170 * ShellAboutW [SHELL32.289]
1172 BOOL WINAPI
ShellAboutW( HWND hWnd
, LPCWSTR szApp
, LPCWSTR szOtherStuff
,
1178 static const WCHAR wszSHELL_ABOUT_MSGBOX
[] =
1179 {'S','H','E','L','L','_','A','B','O','U','T','_','M','S','G','B','O','X',0};
1183 if (!hIcon
) hIcon
= LoadImageW( 0, (LPWSTR
)IDI_WINLOGO
, IMAGE_ICON
, 48, 48, LR_SHARED
);
1185 info
.szOtherStuff
= szOtherStuff
;
1188 SystemParametersInfoW( SPI_GETICONTITLELOGFONT
, 0, &logFont
, 0 );
1189 info
.hFont
= CreateFontIndirectW( &logFont
);
1191 bRet
= DialogBoxParamW( shell32_hInstance
, wszSHELL_ABOUT_MSGBOX
, hWnd
, AboutDlgProc
, (LPARAM
)&info
);
1192 DeleteObject(info
.hFont
);
1196 /*************************************************************************
1197 * FreeIconList (SHELL32.@)
1199 void WINAPI
FreeIconList( DWORD dw
)
1201 FIXME("%x: stub\n",dw
);
1204 /*************************************************************************
1205 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
1207 HRESULT WINAPI
SHLoadNonloadedIconOverlayIdentifiers( VOID
)
1213 /***********************************************************************
1214 * DllGetVersion [SHELL32.@]
1216 * Retrieves version information of the 'SHELL32.DLL'
1219 * pdvi [O] pointer to version information structure.
1223 * Failure: E_INVALIDARG
1226 * Returns version of a shell32.dll from IE4.01 SP1.
1229 HRESULT WINAPI
DllGetVersion (DLLVERSIONINFO
*pdvi
)
1231 /* FIXME: shouldn't these values come from the version resource? */
1232 if (pdvi
->cbSize
== sizeof(DLLVERSIONINFO
) ||
1233 pdvi
->cbSize
== sizeof(DLLVERSIONINFO2
))
1235 pdvi
->dwMajorVersion
= WINE_FILEVERSION_MAJOR
;
1236 pdvi
->dwMinorVersion
= WINE_FILEVERSION_MINOR
;
1237 pdvi
->dwBuildNumber
= WINE_FILEVERSION_BUILD
;
1238 pdvi
->dwPlatformID
= WINE_FILEVERSION_PLATFORMID
;
1239 if (pdvi
->cbSize
== sizeof(DLLVERSIONINFO2
))
1241 DLLVERSIONINFO2
*pdvi2
= (DLLVERSIONINFO2
*)pdvi
;
1244 pdvi2
->ullVersion
= MAKEDLLVERULL(WINE_FILEVERSION_MAJOR
,
1245 WINE_FILEVERSION_MINOR
,
1246 WINE_FILEVERSION_BUILD
,
1247 WINE_FILEVERSION_PLATFORMID
);
1249 TRACE("%u.%u.%u.%u\n",
1250 pdvi
->dwMajorVersion
, pdvi
->dwMinorVersion
,
1251 pdvi
->dwBuildNumber
, pdvi
->dwPlatformID
);
1256 WARN("wrong DLLVERSIONINFO size from app\n");
1257 return E_INVALIDARG
;
1261 /*************************************************************************
1262 * global variables of the shell32.dll
1263 * all are once per process
1266 HINSTANCE shell32_hInstance
= 0;
1269 /*************************************************************************
1273 * calling oleinitialize here breaks some apps.
1275 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID fImpLoad
)
1277 TRACE("%p 0x%x %p\n", hinstDLL
, fdwReason
, fImpLoad
);
1281 case DLL_PROCESS_ATTACH
:
1282 shell32_hInstance
= hinstDLL
;
1283 DisableThreadLibraryCalls(shell32_hInstance
);
1285 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
1286 GetModuleFileNameW(hinstDLL
, swShell32Name
, MAX_PATH
);
1287 swShell32Name
[MAX_PATH
- 1] = '\0';
1289 InitChangeNotifications();
1292 case DLL_PROCESS_DETACH
:
1293 if (fImpLoad
) break;
1295 FreeChangeNotifications();
1296 release_desktop_folder();
1303 /*************************************************************************
1304 * DllInstall [SHELL32.@]
1308 * BOOL bInstall - TRUE for install, FALSE for uninstall
1309 * LPCWSTR pszCmdLine - command line (unused by shell32?)
1312 HRESULT WINAPI
DllInstall(BOOL bInstall
, LPCWSTR cmdline
)
1314 FIXME("%s %s: stub\n", bInstall
? "TRUE":"FALSE", debugstr_w(cmdline
));
1315 return S_OK
; /* indicate success */
1318 /***********************************************************************
1319 * DllCanUnloadNow (SHELL32.@)
1321 HRESULT WINAPI
DllCanUnloadNow(void)
1326 /***********************************************************************
1327 * DllRegisterServer (SHELL32.@)
1329 HRESULT WINAPI
DllRegisterServer(void)
1331 HRESULT hr
= __wine_register_resources( shell32_hInstance
);
1332 if (SUCCEEDED(hr
)) hr
= SHELL_RegisterShellFolders();
1336 /***********************************************************************
1337 * DllUnregisterServer (SHELL32.@)
1339 HRESULT WINAPI
DllUnregisterServer(void)
1341 return __wine_unregister_resources( shell32_hInstance
);
1344 /***********************************************************************
1345 * ExtractVersionResource16W (SHELL32.@)
1347 BOOL WINAPI
ExtractVersionResource16W(LPWSTR s
, DWORD d
)
1349 FIXME("(%s %x) stub!\n", debugstr_w(s
), d
);
1353 /***********************************************************************
1354 * InitNetworkAddressControl (SHELL32.@)
1356 BOOL WINAPI
InitNetworkAddressControl(void)
1362 /***********************************************************************
1363 * ShellHookProc (SHELL32.@)
1365 LRESULT CALLBACK
ShellHookProc(DWORD a
, DWORD b
, DWORD c
)
1371 /***********************************************************************
1372 * SHGetLocalizedName (SHELL32.@)
1374 HRESULT WINAPI
SHGetLocalizedName(LPCWSTR path
, LPWSTR module
, UINT size
, INT
*res
)
1376 FIXME("%s %p %u %p: stub\n", debugstr_w(path
), module
, size
, res
);
1380 /***********************************************************************
1381 * SetCurrentProcessExplicitAppUserModelID (SHELL32.@)
1383 HRESULT WINAPI
SetCurrentProcessExplicitAppUserModelID(PCWSTR appid
)
1385 FIXME("%s: stub\n", debugstr_w(appid
));
1389 /***********************************************************************
1390 * GetCurrentProcessExplicitAppUserModelID (SHELL32.@)
1392 HRESULT WINAPI
GetCurrentProcessExplicitAppUserModelID(PWSTR
*appid
)
1394 FIXME("%p: stub\n", appid
);
1399 /***********************************************************************
1400 * SHSetUnreadMailCountW (SHELL32.@)
1402 HRESULT WINAPI
SHSetUnreadMailCountW(LPCWSTR mailaddress
, DWORD count
, LPCWSTR executecommand
)
1404 FIXME("%s %x %s: stub\n", debugstr_w(mailaddress
), count
, debugstr_w(executecommand
));
1408 /***********************************************************************
1409 * SHEnumerateUnreadMailAccountsW (SHELL32.@)
1411 HRESULT WINAPI
SHEnumerateUnreadMailAccountsW(HKEY user
, DWORD idx
, LPWSTR mailaddress
, INT mailaddresslen
)
1413 FIXME("%p %d %p %d: stub\n", user
, idx
, mailaddress
, mailaddresslen
);
1417 /***********************************************************************
1418 * SHQueryUserNotificationState (SHELL32.@)
1420 HRESULT WINAPI
SHQueryUserNotificationState(QUERY_USER_NOTIFICATION_STATE
*state
)
1422 FIXME("%p: stub\n", state
);
1423 *state
= QUNS_ACCEPTS_NOTIFICATIONS
;