4 * Copyright 1998 Marcus Meissner
5 * Copyright 1998 Juergen Schmied (jsch) * <juergen.schmied@metronet.de>
6 * Copyright 2017 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <wine/config.h>
25 #define WIN32_NO_STATUS
35 #include "undocshell.h"
37 #include "shell32_main.h"
40 #include <wine/debug.h>
41 #include <wine/unicode.h>
43 #include <reactos/version.h>
45 WINE_DEFAULT_DEBUG_CHANNEL(shell
);
47 const char * const SHELL_Authors
[] = { "Copyright 1993-"COPYRIGHT_YEAR
" WINE team", "Copyright 1998-"COPYRIGHT_YEAR
" ReactOS Team", 0 };
49 /*************************************************************************
50 * CommandLineToArgvW [SHELL32.@]
52 * We must interpret the quotes in the command line to rebuild the argv
54 * - arguments are separated by spaces or tabs
55 * - quotes serve as optional argument delimiters
57 * - escaped quotes must be converted back to '"'
59 * - consecutive backslashes preceding a quote see their number halved with
60 * the remainder escaping the quote:
61 * 2n backslashes + quote -> n backslashes + quote as an argument delimiter
62 * 2n+1 backslashes + quote -> n backslashes + literal quote
63 * - backslashes that are not followed by a quote are copied literally:
66 * - in quoted strings, consecutive quotes see their number divided by three
67 * with the remainder modulo 3 deciding whether to close the string or not.
68 * Note that the opening quote must be counted in the consecutive quotes,
69 * that's the (1+) below:
70 * (1+) 3n quotes -> n quotes
71 * (1+) 3n+1 quotes -> n quotes plus closes the quoted string
72 * (1+) 3n+2 quotes -> n+1 quotes plus closes the quoted string
73 * - in unquoted strings, the first quote opens the quoted string and the
74 * remaining consecutive quotes follow the above rule.
76 LPWSTR
* WINAPI
CommandLineToArgvW(LPCWSTR lpCmdline
, int* numargs
)
87 SetLastError(ERROR_INVALID_PARAMETER
);
93 /* Return the path to the executable */
94 DWORD len
, deslen
=MAX_PATH
, size
;
96 size
= sizeof(LPWSTR
)*2 + deslen
*sizeof(WCHAR
);
99 if (!(argv
= LocalAlloc(LMEM_FIXED
, size
))) return NULL
;
100 len
= GetModuleFileNameW(0, (LPWSTR
)(argv
+2), deslen
);
106 if (len
< deslen
) break;
108 size
= sizeof(LPWSTR
)*2 + deslen
*sizeof(WCHAR
);
111 argv
[0]=(LPWSTR
)(argv
+2);
118 /* --- First count the arguments */
121 /* The first argument, the executable path, follows special rules */
124 /* The executable path ends at the next quote, no matter what */
132 /* The executable path ends at the next space, no matter what */
133 while (*s
&& *s
!=' ' && *s
!='\t')
136 /* skip to the first argument, if any */
137 while (*s
==' ' || *s
=='\t')
142 /* Analyze the remaining arguments */
146 if ((*s
==' ' || *s
=='\t') && qcount
==0)
148 /* skip to the next argument and count it if any */
149 while (*s
==' ' || *s
=='\t')
157 /* '\', count them */
165 qcount
++; /* unescaped '"' */
168 /* consecutive quotes, see comment in copying code below */
180 /* a regular character */
186 /* Allocate in a single lump, the string array, and the strings that go
187 * with it. This way the caller can make a single LocalFree() call to free
190 argv
=LocalAlloc(LMEM_FIXED
, (argc
+1)*sizeof(LPWSTR
)+(strlenW(lpCmdline
)+1)*sizeof(WCHAR
));
193 cmdline
=(LPWSTR
)(argv
+argc
+1);
194 strcpyW(cmdline
, lpCmdline
);
196 /* --- Then split and copy the arguments */
199 /* The first argument, the executable path, follows special rules */
202 /* The executable path ends at the next quote, no matter what */
216 /* The executable path ends at the next space, no matter what */
217 while (*d
&& *d
!=' ' && *d
!='\t')
223 /* close the executable path */
225 /* skip to the first argument and initialize it if any */
226 while (*s
==' ' || *s
=='\t')
230 /* There are no parameters so we are all done */
236 /* Split and copy the remaining arguments */
241 if ((*s
==' ' || *s
=='\t') && qcount
==0)
243 /* close the argument */
247 /* skip to the next one and initialize it if any */
250 } while (*s
==' ' || *s
=='\t');
263 /* Preceded by an even number of '\', this is half that
264 * number of '\', plus a quote which we erase.
271 /* Preceded by an odd number of '\', this is half that
272 * number of '\' followed by a '"'
279 /* Now count the number of consecutive quotes. Note that qcount
280 * already takes into account the opening quote if any, as well as
281 * the quote that lead us here.
297 /* a regular character */
309 static DWORD
shgfi_get_exe_type(LPCWSTR szFullPath
)
314 IMAGE_DOS_HEADER mz_header
;
319 status
= GetBinaryTypeW (szFullPath
, &BinaryType
);
322 if (BinaryType
== SCS_DOS_BINARY
|| BinaryType
== SCS_PIF_BINARY
)
325 hfile
= CreateFileW( szFullPath
, GENERIC_READ
, FILE_SHARE_READ
,
326 NULL
, OPEN_EXISTING
, 0, 0 );
327 if ( hfile
== INVALID_HANDLE_VALUE
)
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.
338 SetFilePointer( hfile
, 0, NULL
, SEEK_SET
);
339 ReadFile( hfile
, &mz_header
, sizeof(mz_header
), &len
, NULL
);
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
)
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
)
351 if (nt
.OptionalHeader
.Subsystem
== IMAGE_SUBSYSTEM_WINDOWS_GUI
)
353 return IMAGE_NT_SIGNATURE
|
354 (nt
.OptionalHeader
.MajorSubsystemVersion
<< 24) |
355 (nt
.OptionalHeader
.MinorSubsystemVersion
<< 16);
357 return IMAGE_NT_SIGNATURE
;
359 else if ( *(WORD
*)magic
== IMAGE_OS2_SIGNATURE
)
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);
369 CloseHandle( hfile
);
373 /*************************************************************************
374 * SHELL_IsShortcut [internal]
376 * Decide if an item id list points to a shell shortcut
378 BOOL
SHELL_IsShortcut(LPCITEMIDLIST pidlLast
)
380 char szTemp
[MAX_PATH
];
384 if (_ILGetExtension(pidlLast
, szTemp
, MAX_PATH
) &&
385 HCR_MapTypeToValueA(szTemp
, szTemp
, MAX_PATH
, TRUE
))
387 if (ERROR_SUCCESS
== RegOpenKeyExA(HKEY_CLASSES_ROOT
, szTemp
, 0, KEY_QUERY_VALUE
, &keyCls
))
389 if (ERROR_SUCCESS
== RegQueryValueExA(keyCls
, "IsShortcut", NULL
, NULL
, NULL
, NULL
))
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)
406 /*************************************************************************
407 * SHGetFileInfoW [SHELL32.@]
410 DWORD_PTR WINAPI
SHGetFileInfoW(LPCWSTR path
,DWORD dwFileAttributes
,
411 SHFILEINFOW
*psfi
, UINT sizeofpsfi
, UINT flags
)
413 WCHAR szLocation
[MAX_PATH
], szFullPath
[MAX_PATH
];
415 DWORD_PTR ret
= TRUE
;
416 DWORD dwAttributes
= 0;
417 IShellFolder
* psfParent
= NULL
;
418 IExtractIconW
* pei
= NULL
;
419 LPITEMIDLIST pidlLast
= NULL
, pidl
= NULL
;
421 BOOL IconNotYetLoaded
=TRUE
;
423 HIMAGELIST big_icons
, small_icons
;
425 TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
426 (flags
& SHGFI_PIDL
)? "pidl" : debugstr_w(path
), dwFileAttributes
,
427 psfi
, psfi
? psfi
->dwAttributes
: 0, sizeofpsfi
, flags
);
432 /* windows initializes these values regardless of the flags */
435 psfi
->szDisplayName
[0] = '\0';
436 psfi
->szTypeName
[0] = '\0';
440 if (!(flags
& SHGFI_PIDL
))
442 /* SHGetFileInfo should work with absolute and relative paths */
443 if (PathIsRelativeW(path
))
445 GetCurrentDirectoryW(MAX_PATH
, szLocation
);
446 PathCombineW(szFullPath
, szLocation
, path
);
450 lstrcpynW(szFullPath
, path
, MAX_PATH
);
455 SHGetPathFromIDListW((LPITEMIDLIST
)path
, szFullPath
);
458 if (flags
& SHGFI_EXETYPE
)
460 if (!(flags
& SHGFI_SYSICONINDEX
))
462 if (flags
& SHGFI_USEFILEATTRIBUTES
)
466 else if (GetFileAttributesW(szFullPath
) != INVALID_FILE_ATTRIBUTES
)
468 return shgfi_get_exe_type(szFullPath
);
474 * psfi is NULL normally to query EXE type. If it is NULL, none of the
475 * below makes sense anyway. Windows allows this and just returns FALSE
481 * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES
483 * The pidl functions fail on not existing file names
486 if (flags
& SHGFI_PIDL
)
488 pidl
= ILClone((LPCITEMIDLIST
)path
);
490 else if (!(flags
& SHGFI_USEFILEATTRIBUTES
))
492 hr
= SHILCreateFromPathW(szFullPath
, &pidl
, &dwAttributes
);
495 if ((flags
& SHGFI_PIDL
) || !(flags
& SHGFI_USEFILEATTRIBUTES
))
497 /* get the parent shellfolder */
500 hr
= SHBindToParent( pidl
, &IID_IShellFolder
, (LPVOID
*)&psfParent
,
501 (LPCITEMIDLIST
*)&pidlLast
);
503 pidlLast
= ILClone(pidlLast
);
510 ERR("pidl is null!\n");
515 /* get the attributes of the child */
516 if (SUCCEEDED(hr
) && (flags
& SHGFI_ATTRIBUTES
))
518 if (!(flags
& SHGFI_ATTR_SPECIFIED
))
520 psfi
->dwAttributes
= 0xffffffff;
524 IShellFolder_GetAttributesOf(psfParent
, 1, (LPCITEMIDLIST
*)&pidlLast
,
525 &(psfi
->dwAttributes
));
529 if (flags
& SHGFI_USEFILEATTRIBUTES
)
531 if (flags
& SHGFI_ICON
)
533 psfi
->dwAttributes
= 0;
537 /* get the displayname */
538 if (SUCCEEDED(hr
) && (flags
& SHGFI_DISPLAYNAME
))
540 if (flags
& SHGFI_USEFILEATTRIBUTES
&& !(flags
& SHGFI_PIDL
))
542 lstrcpyW (psfi
->szDisplayName
, PathFindFileNameW(szFullPath
));
547 hr
= IShellFolder_GetDisplayNameOf( psfParent
, pidlLast
,
548 SHGDN_INFOLDER
, &str
);
549 StrRetToStrNW (psfi
->szDisplayName
, MAX_PATH
, &str
, pidlLast
);
553 /* get the type name */
554 if (SUCCEEDED(hr
) && (flags
& SHGFI_TYPENAME
))
556 static const WCHAR szFolder
[] = { 'F','o','l','d','e','r',0 };
557 static const WCHAR szFile
[] = { 'F','i','l','e',0 };
558 static const WCHAR szSpaceFile
[] = { ' ','f','i','l','e',0 };
560 if (!(flags
& SHGFI_USEFILEATTRIBUTES
) || (flags
& SHGFI_PIDL
))
564 _ILGetFileType(pidlLast
, ftype
, 80);
565 MultiByteToWideChar(CP_ACP
, 0, ftype
, -1, psfi
->szTypeName
, 80 );
569 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
570 strcatW (psfi
->szTypeName
, szFolder
);
575 lstrcpyW(sTemp
,PathFindExtensionW(szFullPath
));
576 if (sTemp
[0] == 0 || (sTemp
[0] == '.' && sTemp
[1] == 0))
578 /* "name" or "name." => "File" */
579 lstrcpynW (psfi
->szTypeName
, szFile
, 64);
581 else if (!( HCR_MapTypeToValueW(sTemp
, sTemp
, 64, TRUE
) &&
582 HCR_MapTypeToValueW(sTemp
, psfi
->szTypeName
, 80, FALSE
)))
586 lstrcpynW (psfi
->szTypeName
, sTemp
, 64);
587 strcatW (psfi
->szTypeName
, szSpaceFile
);
591 lstrcpynW (psfi
->szTypeName
, szFile
, 64);
600 Shell_GetImageLists( &big_icons
, &small_icons
);
602 if (flags
& SHGFI_OPENICON
)
603 uGilFlags
|= GIL_OPENICON
;
605 if (flags
& SHGFI_LINKOVERLAY
)
606 uGilFlags
|= GIL_FORSHORTCUT
;
607 else if ((flags
&SHGFI_ADDOVERLAYS
) ||
608 (flags
&(SHGFI_ICON
|SHGFI_SMALLICON
))==SHGFI_ICON
)
610 if (SHELL_IsShortcut(pidlLast
))
611 uGilFlags
|= GIL_FORSHORTCUT
;
614 if (flags
& SHGFI_OVERLAYINDEX
)
615 FIXME("SHGFI_OVERLAYINDEX unhandled\n");
617 if (flags
& SHGFI_SELECTED
)
618 FIXME("set icon to selected, stub\n");
620 if (flags
& SHGFI_SHELLICONSIZE
)
621 FIXME("set icon to shell size, stub\n");
623 /* get the iconlocation */
624 if (SUCCEEDED(hr
) && (flags
& SHGFI_ICONLOCATION
))
628 if (flags
& SHGFI_USEFILEATTRIBUTES
&& !(flags
& SHGFI_PIDL
))
630 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
632 lstrcpyW(psfi
->szDisplayName
, swShell32Name
);
633 psfi
->iIcon
= -IDI_SHELL_FOLDER
;
638 static const WCHAR p1W
[] = {'%','1',0};
639 WCHAR sTemp
[MAX_PATH
];
641 szExt
= PathFindExtensionW(szFullPath
);
642 TRACE("szExt=%s\n", debugstr_w(szExt
));
644 HCR_MapTypeToValueW(szExt
, sTemp
, MAX_PATH
, TRUE
) &&
645 HCR_GetIconW(sTemp
, sTemp
, NULL
, MAX_PATH
, &psfi
->iIcon
))
647 if (lstrcmpW(p1W
, sTemp
))
648 strcpyW(psfi
->szDisplayName
, sTemp
);
651 /* the icon is in the file */
652 strcpyW(psfi
->szDisplayName
, szFullPath
);
661 hr
= IShellFolder_GetUIObjectOf(psfParent
, 0, 1,
662 (LPCITEMIDLIST
*)&pidlLast
, &IID_IExtractIconW
,
663 &uDummy
, (LPVOID
*)&pei
);
666 hr
= IExtractIconW_GetIconLocation(pei
, uGilFlags
,
667 szLocation
, MAX_PATH
, &iIndex
, &uFlags
);
669 if (uFlags
& GIL_NOTFILENAME
)
673 lstrcpyW (psfi
->szDisplayName
, szLocation
);
674 psfi
->iIcon
= iIndex
;
676 IExtractIconW_Release(pei
);
681 /* get icon index (or load icon)*/
682 if (SUCCEEDED(hr
) && (flags
& (SHGFI_ICON
| SHGFI_SYSICONINDEX
)))
684 if (flags
& SHGFI_USEFILEATTRIBUTES
&& !(flags
& SHGFI_PIDL
))
686 WCHAR sTemp
[MAX_PATH
];
690 lstrcpynW(sTemp
, szFullPath
, MAX_PATH
);
692 if (dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
)
693 psfi
->iIcon
= SIC_GetIconIndex(swShell32Name
, -IDI_SHELL_FOLDER
, 0);
696 static const WCHAR p1W
[] = {'%','1',0};
699 szExt
= PathFindExtensionW(sTemp
);
701 HCR_MapTypeToValueW(szExt
, sTemp
, MAX_PATH
, TRUE
) &&
702 HCR_GetIconW(sTemp
, sTemp
, NULL
, MAX_PATH
, &icon_idx
))
704 if (!lstrcmpW(p1W
,sTemp
)) /* icon is in the file */
705 strcpyW(sTemp
, szFullPath
);
707 if (flags
& SHGFI_SYSICONINDEX
)
709 psfi
->iIcon
= SIC_GetIconIndex(sTemp
,icon_idx
,0);
710 if (psfi
->iIcon
== -1)
716 if (flags
& SHGFI_SMALLICON
)
717 ret
= PrivateExtractIconsW( sTemp
,icon_idx
,
718 GetSystemMetrics( SM_CXSMICON
),
719 GetSystemMetrics( SM_CYSMICON
),
720 &psfi
->hIcon
, 0, 1, 0);
722 ret
= PrivateExtractIconsW( sTemp
, icon_idx
,
723 GetSystemMetrics( SM_CXICON
),
724 GetSystemMetrics( SM_CYICON
),
725 &psfi
->hIcon
, 0, 1, 0);
726 if (ret
!= 0 && ret
!= (UINT
)-1)
728 IconNotYetLoaded
=FALSE
;
729 psfi
->iIcon
= icon_idx
;
737 if (!(PidlToSicIndex(psfParent
, pidlLast
, !(flags
& SHGFI_SMALLICON
),
738 uGilFlags
, &(psfi
->iIcon
))))
743 if (ret
&& (flags
& SHGFI_SYSICONINDEX
))
745 if (flags
& SHGFI_SMALLICON
)
746 ret
= (DWORD_PTR
)small_icons
;
748 ret
= (DWORD_PTR
)big_icons
;
753 if (SUCCEEDED(hr
) && (flags
& SHGFI_ICON
) && IconNotYetLoaded
)
755 if (flags
& SHGFI_SMALLICON
)
756 psfi
->hIcon
= ImageList_GetIcon( small_icons
, psfi
->iIcon
, ILD_NORMAL
);
758 psfi
->hIcon
= ImageList_GetIcon( big_icons
, psfi
->iIcon
, ILD_NORMAL
);
761 if (flags
& ~SHGFI_KNOWN_FLAGS
)
762 FIXME("unknown flags %08x\n", flags
& ~SHGFI_KNOWN_FLAGS
);
765 IShellFolder_Release(psfParent
);
772 TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
773 psfi
->hIcon
, psfi
->iIcon
, psfi
->dwAttributes
,
774 debugstr_w(psfi
->szDisplayName
), debugstr_w(psfi
->szTypeName
), ret
);
779 /*************************************************************************
780 * SHGetFileInfoA [SHELL32.@]
783 * MSVBVM60.__vbaNew2 expects this function to return a value in range
784 * 1 .. 0x7fff when the function succeeds and flags does not contain
785 * SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701)
787 DWORD_PTR WINAPI
SHGetFileInfoA(LPCSTR path
,DWORD dwFileAttributes
,
788 SHFILEINFOA
*psfi
, UINT sizeofpsfi
,
792 LPWSTR temppath
= NULL
;
795 SHFILEINFOW temppsfi
;
797 if (flags
& SHGFI_PIDL
)
799 /* path contains a pidl */
800 pathW
= (LPCWSTR
)path
;
804 len
= MultiByteToWideChar(CP_ACP
, 0, path
, -1, NULL
, 0);
805 temppath
= HeapAlloc(GetProcessHeap(), 0, len
*sizeof(WCHAR
));
806 MultiByteToWideChar(CP_ACP
, 0, path
, -1, temppath
, len
);
812 temppsfi
.hIcon
= psfi
->hIcon
;
813 temppsfi
.iIcon
= psfi
->iIcon
;
814 temppsfi
.dwAttributes
= psfi
->dwAttributes
;
816 ret
= SHGetFileInfoW(pathW
, dwFileAttributes
, &temppsfi
, sizeof(temppsfi
), flags
);
817 psfi
->hIcon
= temppsfi
.hIcon
;
818 psfi
->iIcon
= temppsfi
.iIcon
;
819 psfi
->dwAttributes
= temppsfi
.dwAttributes
;
821 WideCharToMultiByte(CP_ACP
, 0, temppsfi
.szDisplayName
, -1,
822 psfi
->szDisplayName
, sizeof(psfi
->szDisplayName
), NULL
, NULL
);
824 WideCharToMultiByte(CP_ACP
, 0, temppsfi
.szTypeName
, -1,
825 psfi
->szTypeName
, sizeof(psfi
->szTypeName
), NULL
, NULL
);
828 ret
= SHGetFileInfoW(pathW
, dwFileAttributes
, NULL
, 0, flags
);
830 HeapFree(GetProcessHeap(), 0, temppath
);
835 /*************************************************************************
836 * DuplicateIcon [SHELL32.@]
838 HICON WINAPI
DuplicateIcon( HINSTANCE hInstance
, HICON hIcon
)
843 TRACE("%p %p\n", hInstance
, hIcon
);
845 if (GetIconInfo(hIcon
, &IconInfo
))
847 hDupIcon
= CreateIconIndirect(&IconInfo
);
849 /* clean up hbmMask and hbmColor */
850 DeleteObject(IconInfo
.hbmMask
);
851 DeleteObject(IconInfo
.hbmColor
);
857 /*************************************************************************
858 * ExtractIconA [SHELL32.@]
860 HICON WINAPI
ExtractIconA(HINSTANCE hInstance
, LPCSTR lpszFile
, UINT nIconIndex
)
863 INT len
= MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, NULL
, 0);
864 LPWSTR lpwstrFile
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
866 TRACE("%p %s %d\n", hInstance
, lpszFile
, nIconIndex
);
868 MultiByteToWideChar(CP_ACP
, 0, lpszFile
, -1, lpwstrFile
, len
);
869 ret
= ExtractIconW(hInstance
, lpwstrFile
, nIconIndex
);
870 HeapFree(GetProcessHeap(), 0, lpwstrFile
);
875 /*************************************************************************
876 * ExtractIconW [SHELL32.@]
878 HICON WINAPI
ExtractIconW(HINSTANCE hInstance
, LPCWSTR lpszFile
, UINT nIconIndex
)
882 UINT cx
= GetSystemMetrics(SM_CXICON
), cy
= GetSystemMetrics(SM_CYICON
);
884 TRACE("%p %s %d\n", hInstance
, debugstr_w(lpszFile
), nIconIndex
);
886 if (nIconIndex
== (UINT
)-1)
888 ret
= PrivateExtractIconsW(lpszFile
, 0, cx
, cy
, NULL
, NULL
, 0, LR_DEFAULTCOLOR
);
889 if (ret
!= (UINT
)-1 && ret
)
890 return (HICON
)(UINT_PTR
)ret
;
894 ret
= PrivateExtractIconsW(lpszFile
, nIconIndex
, cx
, cy
, &hIcon
, NULL
, 1, LR_DEFAULTCOLOR
);
898 else if (ret
> 0 && hIcon
)
904 /*************************************************************************
905 * Printer_LoadIconsW [SHELL32.205]
907 VOID WINAPI
Printer_LoadIconsW(LPCWSTR wsPrinterName
, HICON
* pLargeIcon
, HICON
* pSmallIcon
)
909 INT iconindex
=IDI_SHELL_PRINTERS_FOLDER
;
911 TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName
), pLargeIcon
, pSmallIcon
);
913 /* We should check if wsPrinterName is
914 1. the Default Printer or not
916 3. a Local Printer or a Network-Printer
917 and use different Icons
919 if((wsPrinterName
!= NULL
) && (wsPrinterName
[0] != 0))
921 FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName
));
924 if(pLargeIcon
!= NULL
)
925 *pLargeIcon
= LoadImageW(shell32_hInstance
,
926 (LPCWSTR
) MAKEINTRESOURCE(iconindex
), IMAGE_ICON
,
927 0, 0, LR_DEFAULTCOLOR
|LR_DEFAULTSIZE
);
929 if(pSmallIcon
!= NULL
)
930 *pSmallIcon
= LoadImageW(shell32_hInstance
,
931 (LPCWSTR
) MAKEINTRESOURCE(iconindex
), IMAGE_ICON
,
932 16, 16, LR_DEFAULTCOLOR
);
935 /*************************************************************************
936 * Printers_RegisterWindowW [SHELL32.213]
937 * used by "printui.dll":
938 * find the Window of the given Type for the specific Printer and
939 * return the already existent hwnd or open a new window
941 BOOL WINAPI
Printers_RegisterWindowW(LPCWSTR wsPrinter
, DWORD dwType
,
942 HANDLE
* phClassPidl
, HWND
* phwnd
)
944 FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter
), dwType
,
945 phClassPidl
, (phClassPidl
!= NULL
) ? *(phClassPidl
) : NULL
,
946 phwnd
, (phwnd
!= NULL
) ? *(phwnd
) : NULL
);
951 /*************************************************************************
952 * Printers_UnregisterWindow [SHELL32.214]
954 VOID WINAPI
Printers_UnregisterWindow(HANDLE hClassPidl
, HWND hwnd
)
956 FIXME("(%p, %p) stub!\n", hClassPidl
, hwnd
);
959 /*************************************************************************/
964 LPCWSTR szOtherStuff
;
968 #define DROP_FIELD_TOP (-15)
969 #define DROP_FIELD_HEIGHT 15
971 /*************************************************************************
972 * SHAppBarMessage [SHELL32.@]
974 UINT_PTR WINAPI
SHAppBarMessage(DWORD msg
, PAPPBARDATA data
)
976 int width
=data
->rc
.right
- data
->rc
.left
;
977 int height
=data
->rc
.bottom
- data
->rc
.top
;
980 TRACE("msg=%d, data={cb=%d, hwnd=%p, callback=%x, edge=%d, rc=%s, lparam=%lx}\n",
981 msg
, data
->cbSize
, data
->hWnd
, data
->uCallbackMessage
, data
->uEdge
,
982 wine_dbgstr_rect(&data
->rc
), data
->lParam
);
987 return ABS_ALWAYSONTOP
| ABS_AUTOHIDE
;
989 case ABM_GETTASKBARPOS
:
990 GetWindowRect(data
->hWnd
, &rec
);
995 SetActiveWindow(data
->hWnd
);
998 case ABM_GETAUTOHIDEBAR
:
999 return 0; /* pretend there is no autohide bar */
1002 /* cbSize, hWnd, and uCallbackMessage are used. All other ignored */
1003 SetWindowPos(data
->hWnd
,HWND_TOP
,0,0,0,0,SWP_SHOWWINDOW
|SWP_NOMOVE
|SWP_NOSIZE
);
1007 GetWindowRect(data
->hWnd
, &(data
->rc
));
1011 FIXME("ABM_REMOVE broken\n");
1012 /* FIXME: this is wrong; should it be DestroyWindow instead? */
1013 /*CloseHandle(data->hWnd);*/
1016 case ABM_SETAUTOHIDEBAR
:
1017 SetWindowPos(data
->hWnd
,HWND_TOP
,rec
.left
+1000,rec
.top
,
1018 width
,height
,SWP_SHOWWINDOW
);
1022 data
->uEdge
=(ABE_RIGHT
| ABE_LEFT
);
1023 SetWindowPos(data
->hWnd
,HWND_TOP
,data
->rc
.left
,data
->rc
.top
,
1024 width
,height
,SWP_SHOWWINDOW
);
1027 case ABM_WINDOWPOSCHANGED
:
1034 /*************************************************************************
1035 * SHHelpShortcuts_RunDLLA [SHELL32.@]
1038 DWORD WINAPI
SHHelpShortcuts_RunDLLA(DWORD dwArg1
, DWORD dwArg2
, DWORD dwArg3
, DWORD dwArg4
)
1040 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1
, dwArg2
, dwArg3
, dwArg4
);
1044 /*************************************************************************
1045 * SHHelpShortcuts_RunDLLA [SHELL32.@]
1048 DWORD WINAPI
SHHelpShortcuts_RunDLLW(DWORD dwArg1
, DWORD dwArg2
, DWORD dwArg3
, DWORD dwArg4
)
1050 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1
, dwArg2
, dwArg3
, dwArg4
);
1054 /*************************************************************************
1055 * SHLoadInProc [SHELL32.@]
1056 * Create an instance of specified object class from within
1057 * the shell process and release it immediately
1059 HRESULT WINAPI
SHLoadInProc (REFCLSID rclsid
)
1063 TRACE("%s\n", debugstr_guid(rclsid
));
1065 CoCreateInstance(rclsid
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
,&ptr
);
1068 IUnknown
* pUnk
= ptr
;
1069 IUnknown_Release(pUnk
);
1072 return DISP_E_MEMBERNOTFOUND
;
1075 static VOID
SetRegTextData(HWND hWnd
, HKEY hKey
, LPCWSTR Value
, UINT uID
)
1081 if( RegQueryValueExW(hKey
, Value
, NULL
, &dwType
, NULL
, &dwBufferSize
) == ERROR_SUCCESS
)
1083 if(dwType
== REG_SZ
)
1085 lpBuffer
= (LPWSTR
)HeapAlloc(GetProcessHeap(), 0, dwBufferSize
);
1089 if( RegQueryValueExW(hKey
, Value
, NULL
, &dwType
, (LPBYTE
)lpBuffer
, &dwBufferSize
) == ERROR_SUCCESS
)
1091 SetDlgItemTextW(hWnd
, uID
, lpBuffer
);
1094 HeapFree(GetProcessHeap(), 0, lpBuffer
);
1100 INT_PTR CALLBACK
AboutAuthorsDlgProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1106 const char* const *pstr
= SHELL_Authors
;
1108 // Add the authors to the list
1109 SendDlgItemMessageW( hWnd
, IDC_ABOUT_AUTHORS_LISTBOX
, WM_SETREDRAW
, FALSE
, 0 );
1115 /* authors list is in utf-8 format */
1116 MultiByteToWideChar( CP_UTF8
, 0, *pstr
, -1, name
, sizeof(name
)/sizeof(WCHAR
) );
1117 SendDlgItemMessageW( hWnd
, IDC_ABOUT_AUTHORS_LISTBOX
, LB_ADDSTRING
, (WPARAM
)-1, (LPARAM
)name
);
1121 SendDlgItemMessageW( hWnd
, IDC_ABOUT_AUTHORS_LISTBOX
, WM_SETREDRAW
, TRUE
, 0 );
1129 /*************************************************************************
1130 * AboutDlgProc (internal)
1132 static INT_PTR CALLBACK
AboutDlgProc( HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
1134 static DWORD cxLogoBmp
;
1135 static DWORD cyLogoBmp
;
1136 static HBITMAP hLogoBmp
;
1137 static HWND hWndAuthors
;
1143 ABOUT_INFO
*info
= (ABOUT_INFO
*)lParam
;
1147 const WCHAR szRegKey
[] = L
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
1149 MEMORYSTATUSEX MemStat
;
1150 WCHAR szAppTitle
[512];
1151 WCHAR szAppTitleTemplate
[512];
1152 WCHAR szAuthorsText
[20];
1154 // Preload the ROS bitmap
1155 hLogoBmp
= (HBITMAP
)LoadImage(shell32_hInstance
, MAKEINTRESOURCE(IDB_REACTOS
), IMAGE_BITMAP
, 0, 0, LR_DEFAULTCOLOR
);
1161 GetObject( hLogoBmp
, sizeof(BITMAP
), &bmpLogo
);
1163 cxLogoBmp
= bmpLogo
.bmWidth
;
1164 cyLogoBmp
= bmpLogo
.bmHeight
;
1167 // Set App-specific stuff (icon, app name, szOtherStuff string)
1168 SendDlgItemMessageW(hWnd
, IDC_ABOUT_ICON
, STM_SETICON
, (WPARAM
)info
->hIcon
, 0);
1170 GetWindowTextW( hWnd
, szAppTitleTemplate
, sizeof(szAppTitleTemplate
) / sizeof(WCHAR
) );
1171 swprintf( szAppTitle
, szAppTitleTemplate
, info
->szApp
);
1172 SetWindowTextW( hWnd
, szAppTitle
);
1174 SetDlgItemTextW( hWnd
, IDC_ABOUT_APPNAME
, info
->szApp
);
1175 SetDlgItemTextW( hWnd
, IDC_ABOUT_OTHERSTUFF
, info
->szOtherStuff
);
1177 // Set the registered user and organization name
1178 if(RegOpenKeyExW( HKEY_LOCAL_MACHINE
, szRegKey
, 0, KEY_QUERY_VALUE
, &hRegKey
) == ERROR_SUCCESS
)
1180 SetRegTextData( hWnd
, hRegKey
, L
"RegisteredOwner", IDC_ABOUT_REG_USERNAME
);
1181 SetRegTextData( hWnd
, hRegKey
, L
"RegisteredOrganization", IDC_ABOUT_REG_ORGNAME
);
1183 RegCloseKey( hRegKey
);
1186 // Set the value for the installed physical memory
1187 MemStat
.dwLength
= sizeof(MemStat
);
1188 if( GlobalMemoryStatusEx(&MemStat
) )
1192 if (MemStat
.ullTotalPhys
> 1024 * 1024 * 1024)
1195 WCHAR szDecimalSeparator
[4];
1198 // We're dealing with GBs or more
1199 MemStat
.ullTotalPhys
/= 1024 * 1024;
1201 if (MemStat
.ullTotalPhys
> 1024 * 1024)
1203 // We're dealing with TBs or more
1204 MemStat
.ullTotalPhys
/= 1024;
1206 if (MemStat
.ullTotalPhys
> 1024 * 1024)
1208 // We're dealing with PBs or more
1209 MemStat
.ullTotalPhys
/= 1024;
1211 dTotalPhys
= (double)MemStat
.ullTotalPhys
/ 1024;
1212 wcscpy( szUnits
, L
"PB" );
1216 dTotalPhys
= (double)MemStat
.ullTotalPhys
/ 1024;
1217 wcscpy( szUnits
, L
"TB" );
1222 dTotalPhys
= (double)MemStat
.ullTotalPhys
/ 1024;
1223 wcscpy( szUnits
, L
"GB" );
1226 // We need the decimal point of the current locale to display the RAM size correctly
1227 if (GetLocaleInfoW(LOCALE_USER_DEFAULT
, LOCALE_SDECIMAL
,
1229 sizeof(szDecimalSeparator
) / sizeof(WCHAR
)) > 0)
1234 uIntegral
= (UINT
)dTotalPhys
;
1235 uDecimals
= (UCHAR
)((UINT
)(dTotalPhys
* 100) - uIntegral
* 100);
1237 // Display the RAM size with 2 decimals
1238 swprintf(szBuf
, L
"%u%s%02u %s", uIntegral
, szDecimalSeparator
, uDecimals
, szUnits
);
1243 // We're dealing with MBs, don't show any decimals
1244 swprintf( szBuf
, L
"%u MB", (UINT
)MemStat
.ullTotalPhys
/ 1024 / 1024 );
1247 SetDlgItemTextW( hWnd
, IDC_ABOUT_PHYSMEM
, szBuf
);
1250 // Add the Authors dialog
1251 hWndAuthors
= CreateDialogW( shell32_hInstance
, MAKEINTRESOURCEW(IDD_ABOUT_AUTHORS
), hWnd
, AboutAuthorsDlgProc
);
1252 LoadStringW( shell32_hInstance
, IDS_SHELL_ABOUT_AUTHORS
, szAuthorsText
, sizeof(szAuthorsText
) / sizeof(WCHAR
) );
1253 SetDlgItemTextW( hWnd
, IDC_ABOUT_AUTHORS
, szAuthorsText
);
1267 hdc
= BeginPaint(hWnd
, &ps
);
1268 hdcMem
= CreateCompatibleDC(hdc
);
1272 SelectObject(hdcMem
, hLogoBmp
);
1273 BitBlt(hdc
, 0, 0, cxLogoBmp
, cyLogoBmp
, hdcMem
, 0, 0, SRCCOPY
);
1278 EndPaint(hWnd
, &ps
);
1288 EndDialog(hWnd
, TRUE
);
1291 case IDC_ABOUT_AUTHORS
:
1293 static BOOL bShowingAuthors
= FALSE
;
1294 WCHAR szAuthorsText
[20];
1298 LoadStringW( shell32_hInstance
, IDS_SHELL_ABOUT_AUTHORS
, szAuthorsText
, sizeof(szAuthorsText
) / sizeof(WCHAR
) );
1299 ShowWindow( hWndAuthors
, SW_HIDE
);
1303 LoadStringW( shell32_hInstance
, IDS_SHELL_ABOUT_BACK
, szAuthorsText
, sizeof(szAuthorsText
) / sizeof(WCHAR
) );
1304 ShowWindow( hWndAuthors
, SW_SHOW
);
1307 SetDlgItemTextW( hWnd
, IDC_ABOUT_AUTHORS
, szAuthorsText
);
1308 bShowingAuthors
= !bShowingAuthors
;
1315 EndDialog(hWnd
, TRUE
);
1323 /*************************************************************************
1324 * ShellAboutA [SHELL32.288]
1326 BOOL WINAPI
ShellAboutA( HWND hWnd
, LPCSTR szApp
, LPCSTR szOtherStuff
, HICON hIcon
)
1329 LPWSTR appW
= NULL
, otherW
= NULL
;
1334 len
= MultiByteToWideChar(CP_ACP
, 0, szApp
, -1, NULL
, 0);
1335 appW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1336 MultiByteToWideChar(CP_ACP
, 0, szApp
, -1, appW
, len
);
1340 len
= MultiByteToWideChar(CP_ACP
, 0, szOtherStuff
, -1, NULL
, 0);
1341 otherW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
1342 MultiByteToWideChar(CP_ACP
, 0, szOtherStuff
, -1, otherW
, len
);
1345 ret
= ShellAboutW(hWnd
, appW
, otherW
, hIcon
);
1347 HeapFree(GetProcessHeap(), 0, otherW
);
1348 HeapFree(GetProcessHeap(), 0, appW
);
1353 /*************************************************************************
1354 * ShellAboutW [SHELL32.289]
1356 BOOL WINAPI
ShellAboutW( HWND hWnd
, LPCWSTR szApp
, LPCWSTR szOtherStuff
,
1361 DLGTEMPLATE
*DlgTemplate
;
1366 // DialogBoxIndirectParamW will be called with the hInstance of the calling application, so we have to preload the dialog template
1367 hRes
= FindResourceW(shell32_hInstance
, MAKEINTRESOURCEW(IDD_ABOUT
), (LPWSTR
)RT_DIALOG
);
1371 DlgTemplate
= (DLGTEMPLATE
*)LoadResource(shell32_hInstance
, hRes
);
1376 info
.szOtherStuff
= szOtherStuff
;
1377 info
.hIcon
= hIcon
? hIcon
: LoadIconW( 0, (LPWSTR
)IDI_WINLOGO
);
1379 bRet
= DialogBoxIndirectParamW((HINSTANCE
)GetWindowLongPtrW( hWnd
, GWLP_HINSTANCE
),
1380 DlgTemplate
, hWnd
, AboutDlgProc
, (LPARAM
)&info
);
1384 /*************************************************************************
1385 * FreeIconList (SHELL32.@)
1387 void WINAPI
FreeIconList( DWORD dw
)
1389 FIXME("%x: stub\n",dw
);
1392 /*************************************************************************
1393 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
1395 HRESULT WINAPI
SHLoadNonloadedIconOverlayIdentifiers( VOID
)