shell32: Take a reference on the imagelist returned with SHGFI_SYSICONINDEX.
[wine.git] / dlls / shell32 / shell32_main.c
blob0ccde93223a9c0842ab2957aac9321ee7fd75cca
1 /*
2 * Shell basics
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
22 #include "config.h"
24 #include <stdlib.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <stdio.h>
29 #define COBJMACROS
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 #include "commoncontrols.h"
45 #include "undocshell.h"
46 #include "pidl.h"
47 #include "shell32_main.h"
48 #include "version.h"
49 #include "shresdef.h"
50 #include "initguid.h"
51 #include "shfldr.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
62 * array correctly:
63 * - arguments are separated by spaces or tabs
64 * - quotes serve as optional argument delimiters
65 * '"a b"' -> 'a b'
66 * - escaped quotes must be converted back to '"'
67 * '\"' -> '"'
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:
73 * 'a\b' -> 'a\b'
74 * 'a\\b' -> 'a\\b'
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)
87 DWORD argc;
88 LPWSTR *argv;
89 LPCWSTR s;
90 LPWSTR d;
91 LPWSTR cmdline;
92 int qcount,bcount;
94 if(!numargs)
96 SetLastError(ERROR_INVALID_PARAMETER);
97 return NULL;
100 if (*lpCmdline==0)
102 /* Return the path to the executable */
103 DWORD len, deslen=MAX_PATH, size;
105 size = sizeof(LPWSTR)*2 + deslen*sizeof(WCHAR);
106 for (;;)
108 if (!(argv = LocalAlloc(LMEM_FIXED, size))) return NULL;
109 len = GetModuleFileNameW(0, (LPWSTR)(argv+2), deslen);
110 if (!len)
112 LocalFree(argv);
113 return NULL;
115 if (len < deslen) break;
116 deslen*=2;
117 size = sizeof(LPWSTR)*2 + deslen*sizeof(WCHAR);
118 LocalFree( argv );
120 argv[0]=(LPWSTR)(argv+2);
121 argv[1]=NULL;
122 *numargs=1;
124 return argv;
127 /* --- First count the arguments */
128 argc=1;
129 s=lpCmdline;
130 /* The first argument, the executable path, follows special rules */
131 if (*s=='"')
133 /* The executable path ends at the next quote, no matter what */
134 s++;
135 while (*s)
136 if (*s++=='"')
137 break;
139 else
141 /* The executable path ends at the next space, no matter what */
142 while (*s && *s!=' ' && *s!='\t')
143 s++;
145 /* skip to the first argument, if any */
146 while (*s==' ' || *s=='\t')
147 s++;
148 if (*s)
149 argc++;
151 /* Analyze the remaining arguments */
152 qcount=bcount=0;
153 while (*s)
155 if ((*s==' ' || *s=='\t') && qcount==0)
157 /* skip to the next argument and count it if any */
158 while (*s==' ' || *s=='\t')
159 s++;
160 if (*s)
161 argc++;
162 bcount=0;
164 else if (*s=='\\')
166 /* '\', count them */
167 bcount++;
168 s++;
170 else if (*s=='"')
172 /* '"' */
173 if ((bcount & 1)==0)
174 qcount++; /* unescaped '"' */
175 s++;
176 bcount=0;
177 /* consecutive quotes, see comment in copying code below */
178 while (*s=='"')
180 qcount++;
181 s++;
183 qcount=qcount % 3;
184 if (qcount==2)
185 qcount=0;
187 else
189 /* a regular character */
190 bcount=0;
191 s++;
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
197 * both, as per MSDN.
199 argv=LocalAlloc(LMEM_FIXED, (argc+1)*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR));
200 if (!argv)
201 return NULL;
202 cmdline=(LPWSTR)(argv+argc+1);
203 strcpyW(cmdline, lpCmdline);
205 /* --- Then split and copy the arguments */
206 argv[0]=d=cmdline;
207 argc=1;
208 /* The first argument, the executable path, follows special rules */
209 if (*d=='"')
211 /* The executable path ends at the next quote, no matter what */
212 s=d+1;
213 while (*s)
215 if (*s=='"')
217 s++;
218 break;
220 *d++=*s++;
223 else
225 /* The executable path ends at the next space, no matter what */
226 while (*d && *d!=' ' && *d!='\t')
227 d++;
228 s=d;
229 if (*s)
230 s++;
232 /* close the executable path */
233 *d++=0;
234 /* skip to the first argument and initialize it if any */
235 while (*s==' ' || *s=='\t')
236 s++;
237 if (!*s)
239 /* There are no parameters so we are all done */
240 argv[argc]=NULL;
241 *numargs=argc;
242 return argv;
245 /* Split and copy the remaining arguments */
246 argv[argc++]=d;
247 qcount=bcount=0;
248 while (*s)
250 if ((*s==' ' || *s=='\t') && qcount==0)
252 /* close the argument */
253 *d++=0;
254 bcount=0;
256 /* skip to the next one and initialize it if any */
257 do {
258 s++;
259 } while (*s==' ' || *s=='\t');
260 if (*s)
261 argv[argc++]=d;
263 else if (*s=='\\')
265 *d++=*s++;
266 bcount++;
268 else if (*s=='"')
270 if ((bcount & 1)==0)
272 /* Preceded by an even number of '\', this is half that
273 * number of '\', plus a quote which we erase.
275 d-=bcount/2;
276 qcount++;
278 else
280 /* Preceded by an odd number of '\', this is half that
281 * number of '\' followed by a '"'
283 d=d-bcount/2-1;
284 *d++='"';
286 s++;
287 bcount=0;
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.
292 while (*s=='"')
294 if (++qcount==3)
296 *d++='"';
297 qcount=0;
299 s++;
301 if (qcount==2)
302 qcount=0;
304 else
306 /* a regular character */
307 *d++=*s++;
308 bcount=0;
311 *d='\0';
312 argv[argc]=NULL;
313 *numargs=argc;
315 return argv;
318 static DWORD shgfi_get_exe_type(LPCWSTR szFullPath)
320 BOOL status = FALSE;
321 HANDLE hfile;
322 DWORD BinaryType;
323 IMAGE_DOS_HEADER mz_header;
324 IMAGE_NT_HEADERS nt;
325 DWORD len;
326 char magic[4];
328 status = GetBinaryTypeW (szFullPath, &BinaryType);
329 if (!status)
330 return 0;
331 if (BinaryType == SCS_DOS_BINARY || BinaryType == SCS_PIF_BINARY)
332 return 0x4d5a;
334 hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ,
335 NULL, OPEN_EXISTING, 0, 0 );
336 if ( hfile == INVALID_HANDLE_VALUE )
337 return 0;
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)
359 return 0;
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 )
370 IMAGE_OS2_HEADER ne;
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);
376 return 0;
378 CloseHandle( hfile );
379 return 0;
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];
390 HKEY keyCls;
391 BOOL ret = FALSE;
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))
399 ret = TRUE;
401 RegCloseKey(keyCls);
405 return ret;
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];
423 int iIndex;
424 DWORD_PTR ret = TRUE;
425 DWORD dwAttributes = 0;
426 IShellFolder * psfParent = NULL;
427 IExtractIconW * pei = NULL;
428 LPITEMIDLIST pidlLast = NULL, pidl = NULL;
429 HRESULT hr = S_OK;
430 BOOL IconNotYetLoaded=TRUE;
431 UINT uGilFlags = 0;
432 HIMAGELIST big_icons, small_icons;
434 TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
435 (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes,
436 psfi, psfi->dwAttributes, sizeofpsfi, flags);
438 if (!path)
439 return FALSE;
441 /* windows initializes these values regardless of the flags */
442 if (psfi != NULL)
444 psfi->szDisplayName[0] = '\0';
445 psfi->szTypeName[0] = '\0';
446 psfi->iIcon = 0;
449 if (!(flags & SHGFI_PIDL))
451 /* SHGetFileInfo should work with absolute and relative paths */
452 if (PathIsRelativeW(path))
454 GetCurrentDirectoryW(MAX_PATH, szLocation);
455 PathCombineW(szFullPath, szLocation, path);
457 else
459 lstrcpynW(szFullPath, path, MAX_PATH);
463 if (flags & SHGFI_EXETYPE)
465 if (flags != SHGFI_EXETYPE)
466 return 0;
467 return shgfi_get_exe_type(szFullPath);
471 * psfi is NULL normally to query EXE type. If it is NULL, none of the
472 * below makes sense anyway. Windows allows this and just returns FALSE
474 if (psfi == NULL)
475 return FALSE;
478 * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES
479 * is not specified.
480 * The pidl functions fail on not existing file names
483 if (flags & SHGFI_PIDL)
485 pidl = ILClone((LPCITEMIDLIST)path);
487 else if (!(flags & SHGFI_USEFILEATTRIBUTES))
489 hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes);
492 if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES))
494 /* get the parent shellfolder */
495 if (pidl)
497 hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent,
498 (LPCITEMIDLIST*)&pidlLast );
499 if (SUCCEEDED(hr))
500 pidlLast = ILClone(pidlLast);
501 ILFree(pidl);
503 else
505 ERR("pidl is null!\n");
506 return FALSE;
510 /* get the attributes of the child */
511 if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
513 if (!(flags & SHGFI_ATTR_SPECIFIED))
515 psfi->dwAttributes = 0xffffffff;
517 if (psfParent)
518 IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
519 &(psfi->dwAttributes) );
522 /* get the displayname */
523 if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
525 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
527 lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath));
529 else
531 STRRET str;
532 hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast,
533 SHGDN_INFOLDER, &str);
534 StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
538 /* get the type name */
539 if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
541 static const WCHAR szFolder[] = { 'F','o','l','d','e','r',0 };
542 static const WCHAR szFile[] = { 'F','i','l','e',0 };
543 static const WCHAR szSpaceFile[] = { ' ','f','i','l','e',0 };
545 if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL))
547 char ftype[80];
549 _ILGetFileType(pidlLast, ftype, 80);
550 MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 );
552 else
554 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
555 strcatW (psfi->szTypeName, szFolder);
556 else
558 WCHAR sTemp[64];
560 lstrcpyW(sTemp,PathFindExtensionW(szFullPath));
561 if (sTemp[0] == 0 || (sTemp[0] == '.' && sTemp[1] == 0))
563 /* "name" or "name." => "File" */
564 lstrcpynW (psfi->szTypeName, szFile, 64);
566 else if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) &&
567 HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE )))
569 if (sTemp[0])
571 lstrcpynW (psfi->szTypeName, sTemp, 64);
572 strcatW (psfi->szTypeName, szSpaceFile);
574 else
576 lstrcpynW (psfi->szTypeName, szFile, 64);
583 /* ### icons ###*/
585 Shell_GetImageLists( &big_icons, &small_icons );
587 if (flags & SHGFI_OPENICON)
588 uGilFlags |= GIL_OPENICON;
590 if (flags & SHGFI_LINKOVERLAY)
591 uGilFlags |= GIL_FORSHORTCUT;
592 else if ((flags&SHGFI_ADDOVERLAYS) ||
593 (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON)
595 if (SHELL_IsShortcut(pidlLast))
596 uGilFlags |= GIL_FORSHORTCUT;
599 if (flags & SHGFI_OVERLAYINDEX)
600 FIXME("SHGFI_OVERLAYINDEX unhandled\n");
602 if (flags & SHGFI_SELECTED)
603 FIXME("set icon to selected, stub\n");
605 if (flags & SHGFI_SHELLICONSIZE)
606 FIXME("set icon to shell size, stub\n");
608 /* get the iconlocation */
609 if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
611 UINT uDummy,uFlags;
613 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
615 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
617 lstrcpyW(psfi->szDisplayName, swShell32Name);
618 psfi->iIcon = -IDI_SHELL_FOLDER;
620 else
622 WCHAR* szExt;
623 static const WCHAR p1W[] = {'%','1',0};
624 WCHAR sTemp [MAX_PATH];
626 szExt = PathFindExtensionW(szFullPath);
627 TRACE("szExt=%s\n", debugstr_w(szExt));
628 if ( szExt &&
629 HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
630 HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &psfi->iIcon))
632 if (lstrcmpW(p1W, sTemp))
633 strcpyW(psfi->szDisplayName, sTemp);
634 else
636 /* the icon is in the file */
637 strcpyW(psfi->szDisplayName, szFullPath);
640 else
641 ret = FALSE;
644 else
646 hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1,
647 (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW,
648 &uDummy, (LPVOID*)&pei);
649 if (SUCCEEDED(hr))
651 hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
652 szLocation, MAX_PATH, &iIndex, &uFlags);
654 if (uFlags & GIL_NOTFILENAME)
655 ret = FALSE;
656 else
658 lstrcpyW (psfi->szDisplayName, szLocation);
659 psfi->iIcon = iIndex;
661 IExtractIconW_Release(pei);
666 /* get icon index (or load icon)*/
667 if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
669 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
671 WCHAR sTemp [MAX_PATH];
672 WCHAR * szExt;
673 int icon_idx=0;
675 lstrcpynW(sTemp, szFullPath, MAX_PATH);
677 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
678 psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0);
679 else
681 static const WCHAR p1W[] = {'%','1',0};
683 psfi->iIcon = 0;
684 szExt = PathFindExtensionW(sTemp);
685 if ( szExt &&
686 HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
687 HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &icon_idx))
689 if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */
690 strcpyW(sTemp, szFullPath);
692 if (flags & SHGFI_SYSICONINDEX)
694 psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0);
695 if (psfi->iIcon == -1)
696 psfi->iIcon = 0;
698 else
700 UINT ret;
701 if (flags & SHGFI_SMALLICON)
702 ret = PrivateExtractIconsW( sTemp,icon_idx,
703 GetSystemMetrics( SM_CXSMICON ),
704 GetSystemMetrics( SM_CYSMICON ),
705 &psfi->hIcon, 0, 1, 0);
706 else
707 ret = PrivateExtractIconsW( sTemp, icon_idx,
708 GetSystemMetrics( SM_CXICON),
709 GetSystemMetrics( SM_CYICON),
710 &psfi->hIcon, 0, 1, 0);
711 if (ret != 0 && ret != (UINT)-1)
713 IconNotYetLoaded=FALSE;
714 psfi->iIcon = icon_idx;
720 else
722 if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
723 uGilFlags, &(psfi->iIcon))))
725 ret = FALSE;
728 if (ret && (flags & SHGFI_SYSICONINDEX))
730 if (flags & SHGFI_SMALLICON)
731 ret = (DWORD_PTR)small_icons;
732 else
733 ret = (DWORD_PTR)big_icons;
734 IImageList_AddRef((IImageList*)ret);
738 /* icon handle */
739 if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded)
741 if (flags & SHGFI_SMALLICON)
742 psfi->hIcon = ImageList_GetIcon( small_icons, psfi->iIcon, ILD_NORMAL);
743 else
744 psfi->hIcon = ImageList_GetIcon( big_icons, psfi->iIcon, ILD_NORMAL);
747 if (flags & ~SHGFI_KNOWN_FLAGS)
748 FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS);
750 if (psfParent)
751 IShellFolder_Release(psfParent);
753 if (hr != S_OK)
754 ret = FALSE;
756 SHFree(pidlLast);
758 TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
759 psfi->hIcon, psfi->iIcon, psfi->dwAttributes,
760 debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret);
762 return ret;
765 /*************************************************************************
766 * SHGetFileInfoA [SHELL32.@]
768 * Note:
769 * MSVBVM60.__vbaNew2 expects this function to return a value in range
770 * 1 .. 0x7fff when the function succeeds and flags does not contain
771 * SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701)
773 DWORD_PTR WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
774 SHFILEINFOA *psfi, UINT sizeofpsfi,
775 UINT flags )
777 INT len;
778 LPWSTR temppath = NULL;
779 LPCWSTR pathW;
780 DWORD_PTR ret;
781 SHFILEINFOW temppsfi;
783 if (flags & SHGFI_PIDL)
785 /* path contains a pidl */
786 pathW = (LPCWSTR)path;
788 else
790 len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
791 temppath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
792 MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len);
793 pathW = temppath;
796 if (psfi && (flags & SHGFI_ATTR_SPECIFIED))
797 temppsfi.dwAttributes=psfi->dwAttributes;
799 if (psfi == NULL)
800 ret = SHGetFileInfoW(pathW, dwFileAttributes, NULL, sizeof(temppsfi), flags);
801 else
802 ret = SHGetFileInfoW(pathW, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
804 if (psfi)
806 if(flags & SHGFI_ICON)
807 psfi->hIcon=temppsfi.hIcon;
808 if(flags & (SHGFI_SYSICONINDEX|SHGFI_ICON|SHGFI_ICONLOCATION))
809 psfi->iIcon=temppsfi.iIcon;
810 if(flags & SHGFI_ATTRIBUTES)
811 psfi->dwAttributes=temppsfi.dwAttributes;
812 if(flags & (SHGFI_DISPLAYNAME|SHGFI_ICONLOCATION))
814 WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1,
815 psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL);
817 if(flags & SHGFI_TYPENAME)
819 WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1,
820 psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL);
824 HeapFree(GetProcessHeap(), 0, temppath);
826 return ret;
829 /*************************************************************************
830 * DuplicateIcon [SHELL32.@]
832 HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
834 ICONINFO IconInfo;
835 HICON hDupIcon = 0;
837 TRACE("%p %p\n", hInstance, hIcon);
839 if (GetIconInfo(hIcon, &IconInfo))
841 hDupIcon = CreateIconIndirect(&IconInfo);
843 /* clean up hbmMask and hbmColor */
844 DeleteObject(IconInfo.hbmMask);
845 DeleteObject(IconInfo.hbmColor);
848 return hDupIcon;
851 /*************************************************************************
852 * ExtractIconA [SHELL32.@]
854 HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex)
856 HICON ret;
857 INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0);
858 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
860 TRACE("%p %s %d\n", hInstance, lpszFile, nIconIndex);
862 MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len);
863 ret = ExtractIconW(hInstance, lpwstrFile, nIconIndex);
864 HeapFree(GetProcessHeap(), 0, lpwstrFile);
866 return ret;
869 /*************************************************************************
870 * ExtractIconW [SHELL32.@]
872 HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
874 HICON hIcon = NULL;
875 UINT ret;
876 UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON);
878 TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex);
880 if (nIconIndex == (UINT)-1)
882 ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR);
883 if (ret != (UINT)-1 && ret)
884 return (HICON)(UINT_PTR)ret;
885 return NULL;
887 else
888 ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR);
890 if (ret == (UINT)-1)
891 return (HICON)1;
892 else if (ret > 0 && hIcon)
893 return hIcon;
895 return NULL;
898 HRESULT WINAPI SHCreateFileExtractIconW(LPCWSTR file, DWORD attribs, REFIID riid, void **ppv)
900 FIXME("%s, %x, %s, %p\n", debugstr_w(file), attribs, debugstr_guid(riid), ppv);
901 *ppv = NULL;
902 return E_NOTIMPL;
905 /*************************************************************************
906 * Printer_LoadIconsW [SHELL32.205]
908 VOID WINAPI Printer_LoadIconsW(LPCWSTR wsPrinterName, HICON * pLargeIcon, HICON * pSmallIcon)
910 INT iconindex=IDI_SHELL_PRINTER;
912 TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName), pLargeIcon, pSmallIcon);
914 /* We should check if wsPrinterName is
915 1. the Default Printer or not
916 2. connected or not
917 3. a Local Printer or a Network-Printer
918 and use different Icons
920 if((wsPrinterName != NULL) && (wsPrinterName[0] != 0))
922 FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName));
925 if(pLargeIcon != NULL)
926 *pLargeIcon = LoadImageW(shell32_hInstance,
927 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
928 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
930 if(pSmallIcon != NULL)
931 *pSmallIcon = LoadImageW(shell32_hInstance,
932 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
933 16, 16, LR_DEFAULTCOLOR);
936 /*************************************************************************
937 * Printers_RegisterWindowW [SHELL32.213]
938 * used by "printui.dll":
939 * find the Window of the given Type for the specific Printer and
940 * return the already existent hwnd or open a new window
942 BOOL WINAPI Printers_RegisterWindowW(LPCWSTR wsPrinter, DWORD dwType,
943 HANDLE * phClassPidl, HWND * phwnd)
945 FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType,
946 phClassPidl, (phClassPidl != NULL) ? *(phClassPidl) : NULL,
947 phwnd, (phwnd != NULL) ? *(phwnd) : NULL);
949 return FALSE;
952 /*************************************************************************
953 * Printers_UnregisterWindow [SHELL32.214]
955 VOID WINAPI Printers_UnregisterWindow(HANDLE hClassPidl, HWND hwnd)
957 FIXME("(%p, %p) stub!\n", hClassPidl, hwnd);
960 /*************************************************************************
961 * SHGetPropertyStoreForWindow [SHELL32.@]
963 HRESULT WINAPI SHGetPropertyStoreForWindow(HWND hwnd, REFIID riid, void **ppv)
965 FIXME("(%p %p %p) stub!\n", hwnd, riid, ppv);
966 return E_NOTIMPL;
969 /*************************************************************************/
971 typedef struct
973 LPCWSTR szApp;
974 LPCWSTR szOtherStuff;
975 HICON hIcon;
976 HFONT hFont;
977 } ABOUT_INFO;
979 #define DROP_FIELD_TOP (-12)
981 static void paint_dropline( HDC hdc, HWND hWnd )
983 HWND hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_WINE_TEXT);
984 RECT rect;
986 if (!hWndCtl) return;
987 GetWindowRect( hWndCtl, &rect );
988 MapWindowPoints( 0, hWnd, (LPPOINT)&rect, 2 );
989 rect.top += DROP_FIELD_TOP;
990 rect.bottom = rect.top + 2;
991 DrawEdge( hdc, &rect, BDR_SUNKENOUTER, BF_RECT );
994 /*************************************************************************
995 * SHHelpShortcuts_RunDLLA [SHELL32.@]
998 DWORD WINAPI SHHelpShortcuts_RunDLLA(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
1000 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
1001 return 0;
1004 /*************************************************************************
1005 * SHHelpShortcuts_RunDLLA [SHELL32.@]
1008 DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
1010 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
1011 return 0;
1014 /*************************************************************************
1015 * SHLoadInProc [SHELL32.@]
1016 * Create an instance of specified object class from within
1017 * the shell process and release it immediately
1019 HRESULT WINAPI SHLoadInProc (REFCLSID rclsid)
1021 void *ptr = NULL;
1023 TRACE("%s\n", debugstr_guid(rclsid));
1025 CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr);
1026 if(ptr)
1028 IUnknown * pUnk = ptr;
1029 IUnknown_Release(pUnk);
1030 return S_OK;
1032 return DISP_E_MEMBERNOTFOUND;
1035 static void add_authors( HWND list )
1037 static const WCHAR eol[] = {'\r','\n',0};
1038 static const WCHAR authors[] = {'A','U','T','H','O','R','S',0};
1039 WCHAR *strW, *start, *end;
1040 HRSRC rsrc = FindResourceW( shell32_hInstance, authors, (LPCWSTR)RT_RCDATA );
1041 char *strA = LockResource( LoadResource( shell32_hInstance, rsrc ));
1042 DWORD sizeW, sizeA = SizeofResource( shell32_hInstance, rsrc );
1044 if (!strA) return;
1045 sizeW = MultiByteToWideChar( CP_UTF8, 0, strA, sizeA, NULL, 0 ) + 1;
1046 if (!(strW = HeapAlloc( GetProcessHeap(), 0, sizeW * sizeof(WCHAR) ))) return;
1047 MultiByteToWideChar( CP_UTF8, 0, strA, sizeA, strW, sizeW );
1048 strW[sizeW - 1] = 0;
1050 start = strpbrkW( strW, eol ); /* skip the header line */
1051 while (start)
1053 while (*start && strchrW( eol, *start )) start++;
1054 if (!*start) break;
1055 end = strpbrkW( start, eol );
1056 if (end) *end++ = 0;
1057 SendMessageW( list, LB_ADDSTRING, -1, (LPARAM)start );
1058 start = end;
1060 HeapFree( GetProcessHeap(), 0, strW );
1063 /*************************************************************************
1064 * AboutDlgProc (internal)
1066 static INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
1067 LPARAM lParam )
1069 HWND hWndCtl;
1071 TRACE("\n");
1073 switch(msg)
1075 case WM_INITDIALOG:
1077 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
1078 WCHAR template[512], buffer[512], version[64];
1079 extern const char *wine_get_build_id(void);
1081 if (info)
1083 SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0);
1084 GetWindowTextW( hWnd, template, sizeof(template)/sizeof(WCHAR) );
1085 sprintfW( buffer, template, info->szApp );
1086 SetWindowTextW( hWnd, buffer );
1087 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT1), info->szApp );
1088 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT2), info->szOtherStuff );
1089 GetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3),
1090 template, sizeof(template)/sizeof(WCHAR) );
1091 MultiByteToWideChar( CP_UTF8, 0, wine_get_build_id(), -1,
1092 version, sizeof(version)/sizeof(WCHAR) );
1093 sprintfW( buffer, template, version );
1094 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3), buffer );
1095 hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_LISTBOX);
1096 SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 );
1097 SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 );
1098 add_authors( hWndCtl );
1099 SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 );
1102 return 1;
1104 case WM_PAINT:
1106 PAINTSTRUCT ps;
1107 HDC hDC = BeginPaint( hWnd, &ps );
1108 paint_dropline( hDC, hWnd );
1109 EndPaint( hWnd, &ps );
1111 break;
1113 case WM_COMMAND:
1114 if (wParam == IDOK || wParam == IDCANCEL)
1116 EndDialog(hWnd, TRUE);
1117 return TRUE;
1119 if (wParam == IDC_ABOUT_LICENSE)
1121 MSGBOXPARAMSW params;
1123 params.cbSize = sizeof(params);
1124 params.hwndOwner = hWnd;
1125 params.hInstance = shell32_hInstance;
1126 params.lpszText = MAKEINTRESOURCEW(IDS_LICENSE);
1127 params.lpszCaption = MAKEINTRESOURCEW(IDS_LICENSE_CAPTION);
1128 params.dwStyle = MB_ICONINFORMATION | MB_OK;
1129 params.lpszIcon = 0;
1130 params.dwContextHelpId = 0;
1131 params.lpfnMsgBoxCallback = NULL;
1132 params.dwLanguageId = LANG_NEUTRAL;
1133 MessageBoxIndirectW( &params );
1135 break;
1136 case WM_CLOSE:
1137 EndDialog(hWnd, TRUE);
1138 break;
1141 return 0;
1145 /*************************************************************************
1146 * ShellAboutA [SHELL32.288]
1148 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon )
1150 BOOL ret;
1151 LPWSTR appW = NULL, otherW = NULL;
1152 int len;
1154 if (szApp)
1156 len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0);
1157 appW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1158 MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len);
1160 if (szOtherStuff)
1162 len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0);
1163 otherW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
1164 MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len);
1167 ret = ShellAboutW(hWnd, appW, otherW, hIcon);
1169 HeapFree(GetProcessHeap(), 0, otherW);
1170 HeapFree(GetProcessHeap(), 0, appW);
1171 return ret;
1175 /*************************************************************************
1176 * ShellAboutW [SHELL32.289]
1178 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
1179 HICON hIcon )
1181 ABOUT_INFO info;
1182 LOGFONTW logFont;
1183 BOOL bRet;
1184 static const WCHAR wszSHELL_ABOUT_MSGBOX[] =
1185 {'S','H','E','L','L','_','A','B','O','U','T','_','M','S','G','B','O','X',0};
1187 TRACE("\n");
1189 if (!hIcon) hIcon = LoadImageW( 0, (LPWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED );
1190 info.szApp = szApp;
1191 info.szOtherStuff = szOtherStuff;
1192 info.hIcon = hIcon;
1194 SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
1195 info.hFont = CreateFontIndirectW( &logFont );
1197 bRet = DialogBoxParamW( shell32_hInstance, wszSHELL_ABOUT_MSGBOX, hWnd, AboutDlgProc, (LPARAM)&info );
1198 DeleteObject(info.hFont);
1199 return bRet;
1202 /*************************************************************************
1203 * FreeIconList (SHELL32.@)
1205 void WINAPI FreeIconList( DWORD dw )
1207 FIXME("%x: stub\n",dw);
1210 /*************************************************************************
1211 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
1213 HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID )
1215 FIXME("stub\n");
1216 return S_OK;
1219 /***********************************************************************
1220 * DllGetVersion [SHELL32.@]
1222 * Retrieves version information of the 'SHELL32.DLL'
1224 * PARAMS
1225 * pdvi [O] pointer to version information structure.
1227 * RETURNS
1228 * Success: S_OK
1229 * Failure: E_INVALIDARG
1231 * NOTES
1232 * Returns version of a shell32.dll from IE4.01 SP1.
1235 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
1237 /* FIXME: shouldn't these values come from the version resource? */
1238 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
1239 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1241 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
1242 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
1243 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
1244 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
1245 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1247 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
1249 pdvi2->dwFlags = 0;
1250 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
1251 WINE_FILEVERSION_MINOR,
1252 WINE_FILEVERSION_BUILD,
1253 WINE_FILEVERSION_PLATFORMID);
1255 TRACE("%u.%u.%u.%u\n",
1256 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
1257 pdvi->dwBuildNumber, pdvi->dwPlatformID);
1258 return S_OK;
1260 else
1262 WARN("wrong DLLVERSIONINFO size from app\n");
1263 return E_INVALIDARG;
1267 /*************************************************************************
1268 * global variables of the shell32.dll
1269 * all are once per process
1272 HINSTANCE shell32_hInstance = 0;
1275 /*************************************************************************
1276 * SHELL32 DllMain
1278 * NOTES
1279 * calling oleinitialize here breaks some apps.
1281 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1283 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
1285 switch (fdwReason)
1287 case DLL_PROCESS_ATTACH:
1288 shell32_hInstance = hinstDLL;
1289 DisableThreadLibraryCalls(shell32_hInstance);
1291 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
1292 GetModuleFileNameW(hinstDLL, swShell32Name, MAX_PATH);
1293 swShell32Name[MAX_PATH - 1] = '\0';
1295 InitChangeNotifications();
1296 break;
1298 case DLL_PROCESS_DETACH:
1299 if (fImpLoad) break;
1300 SIC_Destroy();
1301 FreeChangeNotifications();
1302 release_desktop_folder();
1303 release_typelib();
1304 break;
1306 return TRUE;
1309 /*************************************************************************
1310 * DllInstall [SHELL32.@]
1312 * PARAMETERS
1314 * BOOL bInstall - TRUE for install, FALSE for uninstall
1315 * LPCWSTR pszCmdLine - command line (unused by shell32?)
1318 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1320 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
1321 return S_OK; /* indicate success */
1324 /***********************************************************************
1325 * DllCanUnloadNow (SHELL32.@)
1327 HRESULT WINAPI DllCanUnloadNow(void)
1329 return S_FALSE;
1332 /***********************************************************************
1333 * DllRegisterServer (SHELL32.@)
1335 HRESULT WINAPI DllRegisterServer(void)
1337 HRESULT hr = __wine_register_resources( shell32_hInstance );
1338 if (SUCCEEDED(hr)) hr = SHELL_RegisterShellFolders();
1339 return hr;
1342 /***********************************************************************
1343 * DllUnregisterServer (SHELL32.@)
1345 HRESULT WINAPI DllUnregisterServer(void)
1347 return __wine_unregister_resources( shell32_hInstance );
1350 /***********************************************************************
1351 * ExtractVersionResource16W (SHELL32.@)
1353 BOOL WINAPI ExtractVersionResource16W(LPWSTR s, DWORD d)
1355 FIXME("(%s %x) stub!\n", debugstr_w(s), d);
1356 return FALSE;
1359 /***********************************************************************
1360 * InitNetworkAddressControl (SHELL32.@)
1362 BOOL WINAPI InitNetworkAddressControl(void)
1364 FIXME("stub\n");
1365 return FALSE;
1368 /***********************************************************************
1369 * ShellHookProc (SHELL32.@)
1371 LRESULT CALLBACK ShellHookProc(DWORD a, DWORD b, DWORD c)
1373 FIXME("Stub\n");
1374 return 0;
1377 /***********************************************************************
1378 * SHGetLocalizedName (SHELL32.@)
1380 HRESULT WINAPI SHGetLocalizedName(LPCWSTR path, LPWSTR module, UINT size, INT *res)
1382 FIXME("%s %p %u %p: stub\n", debugstr_w(path), module, size, res);
1383 return E_NOTIMPL;
1386 /***********************************************************************
1387 * SetCurrentProcessExplicitAppUserModelID (SHELL32.@)
1389 HRESULT WINAPI SetCurrentProcessExplicitAppUserModelID(PCWSTR appid)
1391 FIXME("%s: stub\n", debugstr_w(appid));
1392 return E_NOTIMPL;
1395 /***********************************************************************
1396 * GetCurrentProcessExplicitAppUserModelID (SHELL32.@)
1398 HRESULT WINAPI GetCurrentProcessExplicitAppUserModelID(PWSTR *appid)
1400 FIXME("%p: stub\n", appid);
1401 *appid = NULL;
1402 return E_NOTIMPL;
1405 /***********************************************************************
1406 * SHSetUnreadMailCountW (SHELL32.@)
1408 HRESULT WINAPI SHSetUnreadMailCountW(LPCWSTR mailaddress, DWORD count, LPCWSTR executecommand)
1410 FIXME("%s %x %s: stub\n", debugstr_w(mailaddress), count, debugstr_w(executecommand));
1411 return E_NOTIMPL;
1414 /***********************************************************************
1415 * SHEnumerateUnreadMailAccountsW (SHELL32.@)
1417 HRESULT WINAPI SHEnumerateUnreadMailAccountsW(HKEY user, DWORD idx, LPWSTR mailaddress, INT mailaddresslen)
1419 FIXME("%p %d %p %d: stub\n", user, idx, mailaddress, mailaddresslen);
1420 return E_NOTIMPL;
1423 /***********************************************************************
1424 * SHQueryUserNotificationState (SHELL32.@)
1426 HRESULT WINAPI SHQueryUserNotificationState(QUERY_USER_NOTIFICATION_STATE *state)
1428 FIXME("%p: stub\n", state);
1429 *state = QUNS_ACCEPTS_NOTIFICATIONS;
1430 return S_OK;