ntdll: Add a helper for platform-specific threading initialization.
[wine.git] / dlls / shell32 / shell32_main.c
blobafbf5164c9a1722714e5a26e01c96b96744f404d
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 static DWORD shgfi_get_exe_type(LPCWSTR szFullPath)
60 BOOL status = FALSE;
61 HANDLE hfile;
62 DWORD BinaryType;
63 IMAGE_DOS_HEADER mz_header;
64 IMAGE_NT_HEADERS nt;
65 DWORD len;
66 char magic[4];
68 status = GetBinaryTypeW (szFullPath, &BinaryType);
69 if (!status)
70 return 0;
71 if (BinaryType == SCS_DOS_BINARY || BinaryType == SCS_PIF_BINARY)
72 return 0x4d5a;
74 hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ,
75 NULL, OPEN_EXISTING, 0, 0 );
76 if ( hfile == INVALID_HANDLE_VALUE )
77 return 0;
80 * The next section is adapted from MODULE_GetBinaryType, as we need
81 * to examine the image header to get OS and version information. We
82 * know from calling GetBinaryTypeA that the image is valid and either
83 * an NE or PE, so much error handling can be omitted.
84 * Seek to the start of the file and read the header information.
87 SetFilePointer( hfile, 0, NULL, SEEK_SET );
88 ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL );
90 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
91 ReadFile( hfile, magic, sizeof(magic), &len, NULL );
92 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
94 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
95 ReadFile( hfile, &nt, sizeof(nt), &len, NULL );
96 CloseHandle( hfile );
97 /* DLL files are not executable and should return 0 */
98 if (nt.FileHeader.Characteristics & IMAGE_FILE_DLL)
99 return 0;
100 if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)
102 return IMAGE_NT_SIGNATURE |
103 (nt.OptionalHeader.MajorSubsystemVersion << 24) |
104 (nt.OptionalHeader.MinorSubsystemVersion << 16);
106 return IMAGE_NT_SIGNATURE;
108 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
110 IMAGE_OS2_HEADER ne;
111 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
112 ReadFile( hfile, &ne, sizeof(ne), &len, NULL );
113 CloseHandle( hfile );
114 if (ne.ne_exetyp == 2)
115 return IMAGE_OS2_SIGNATURE | (ne.ne_expver << 16);
116 return 0;
118 CloseHandle( hfile );
119 return 0;
122 /*************************************************************************
123 * SHELL_IsShortcut [internal]
125 * Decide if an item id list points to a shell shortcut
127 BOOL SHELL_IsShortcut(LPCITEMIDLIST pidlLast)
129 char szTemp[MAX_PATH];
130 HKEY keyCls;
131 BOOL ret = FALSE;
133 if (_ILGetExtension(pidlLast, szTemp, MAX_PATH) &&
134 HCR_MapTypeToValueA(szTemp, szTemp, MAX_PATH, TRUE))
136 if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls))
138 if (ERROR_SUCCESS == RegQueryValueExA(keyCls, "IsShortcut", NULL, NULL, NULL, NULL))
139 ret = TRUE;
141 RegCloseKey(keyCls);
145 return ret;
148 #define SHGFI_KNOWN_FLAGS \
149 (SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \
150 SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \
151 SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ATTRIBUTES | \
152 SHGFI_ICONLOCATION | SHGFI_EXETYPE | SHGFI_SYSICONINDEX | \
153 SHGFI_LINKOVERLAY | SHGFI_SELECTED | SHGFI_ATTR_SPECIFIED)
155 /*************************************************************************
156 * SHGetFileInfoW [SHELL32.@]
159 DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
160 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags )
162 WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH];
163 int iIndex;
164 DWORD_PTR ret = TRUE;
165 DWORD dwAttributes = 0;
166 IShellFolder * psfParent = NULL;
167 IExtractIconW * pei = NULL;
168 LPITEMIDLIST pidlLast = NULL, pidl = NULL;
169 HRESULT hr = S_OK;
170 UINT uGilFlags = 0;
172 TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n",
173 (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes,
174 psfi, psfi ? psfi->dwAttributes : 0, sizeofpsfi, flags);
176 if (!path)
177 return FALSE;
179 /* windows initializes these values regardless of the flags */
180 if (psfi != NULL)
182 psfi->szDisplayName[0] = '\0';
183 psfi->szTypeName[0] = '\0';
184 psfi->iIcon = 0;
187 if (!(flags & SHGFI_PIDL))
189 /* SHGetFileInfo should work with absolute and relative paths */
190 if (PathIsRelativeW(path))
192 GetCurrentDirectoryW(MAX_PATH, szLocation);
193 PathCombineW(szFullPath, szLocation, path);
195 else
197 lstrcpynW(szFullPath, path, MAX_PATH);
201 if (flags & SHGFI_EXETYPE)
203 if (flags != SHGFI_EXETYPE)
204 return 0;
205 return shgfi_get_exe_type(szFullPath);
209 * psfi is NULL normally to query EXE type. If it is NULL, none of the
210 * below makes sense anyway. Windows allows this and just returns FALSE
212 if (psfi == NULL)
213 return FALSE;
216 * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES
217 * is not specified.
218 * The pidl functions fail on not existing file names
221 if (flags & SHGFI_PIDL)
223 pidl = ILClone((LPCITEMIDLIST)path);
225 else if (!(flags & SHGFI_USEFILEATTRIBUTES))
227 hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes);
230 if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES))
232 /* get the parent shellfolder */
233 if (pidl)
235 hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent,
236 (LPCITEMIDLIST*)&pidlLast );
237 if (SUCCEEDED(hr))
238 pidlLast = ILClone(pidlLast);
239 ILFree(pidl);
241 else
243 ERR("pidl is null!\n");
244 return FALSE;
248 /* get the attributes of the child */
249 if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
251 if (!(flags & SHGFI_ATTR_SPECIFIED))
253 psfi->dwAttributes = 0xffffffff;
255 if (psfParent)
256 IShellFolder_GetAttributesOf( psfParent, 1, (LPCITEMIDLIST*)&pidlLast,
257 &(psfi->dwAttributes) );
260 /* get the displayname */
261 if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
263 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
265 lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath));
267 else
269 STRRET str;
270 hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast,
271 SHGDN_INFOLDER, &str);
272 StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
276 /* get the type name */
277 if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
279 static const WCHAR szFolder[] = { 'F','o','l','d','e','r',0 };
280 static const WCHAR szFile[] = { 'F','i','l','e',0 };
281 static const WCHAR szSpaceFile[] = { ' ','f','i','l','e',0 };
283 if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL))
285 char ftype[80];
287 _ILGetFileType(pidlLast, ftype, 80);
288 MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 );
290 else
292 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
293 strcatW (psfi->szTypeName, szFolder);
294 else
296 WCHAR sTemp[64];
298 lstrcpyW(sTemp,PathFindExtensionW(szFullPath));
299 if (sTemp[0] == 0 || (sTemp[0] == '.' && sTemp[1] == 0))
301 /* "name" or "name." => "File" */
302 lstrcpynW (psfi->szTypeName, szFile, 64);
304 else if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) &&
305 HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE )))
307 if (sTemp[0])
309 lstrcpynW (psfi->szTypeName, sTemp, 64);
310 strcatW (psfi->szTypeName, szSpaceFile);
312 else
314 lstrcpynW (psfi->szTypeName, szFile, 64);
321 /* ### icons ###*/
322 if (flags & SHGFI_OPENICON)
323 uGilFlags |= GIL_OPENICON;
325 if (flags & SHGFI_LINKOVERLAY)
326 uGilFlags |= GIL_FORSHORTCUT;
327 else if ((flags&SHGFI_ADDOVERLAYS) ||
328 (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON)
330 if (SHELL_IsShortcut(pidlLast))
331 uGilFlags |= GIL_FORSHORTCUT;
334 if (flags & SHGFI_OVERLAYINDEX)
335 FIXME("SHGFI_OVERLAYINDEX unhandled\n");
337 if (flags & SHGFI_SELECTED)
338 FIXME("set icon to selected, stub\n");
340 /* get the iconlocation */
341 if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
343 UINT uDummy,uFlags;
345 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
347 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
349 lstrcpyW(psfi->szDisplayName, swShell32Name);
350 psfi->iIcon = -IDI_SHELL_FOLDER;
352 else
354 WCHAR* szExt;
355 static const WCHAR p1W[] = {'%','1',0};
356 WCHAR sTemp [MAX_PATH];
358 szExt = PathFindExtensionW(szFullPath);
359 TRACE("szExt=%s\n", debugstr_w(szExt));
360 if ( szExt &&
361 HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
362 HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &psfi->iIcon))
364 if (lstrcmpW(p1W, sTemp))
365 strcpyW(psfi->szDisplayName, sTemp);
366 else
368 /* the icon is in the file */
369 strcpyW(psfi->szDisplayName, szFullPath);
372 else
373 ret = FALSE;
376 else
378 hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1,
379 (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW,
380 &uDummy, (LPVOID*)&pei);
381 if (SUCCEEDED(hr))
383 hr = IExtractIconW_GetIconLocation(pei, uGilFlags,
384 szLocation, MAX_PATH, &iIndex, &uFlags);
386 if (uFlags & GIL_NOTFILENAME)
387 ret = FALSE;
388 else
390 lstrcpyW (psfi->szDisplayName, szLocation);
391 psfi->iIcon = iIndex;
393 IExtractIconW_Release(pei);
398 /* get icon index (or load icon)*/
399 if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
401 IImageList *icon_list;
402 SHGetImageList( (flags & SHGFI_SMALLICON) ? SHIL_SMALL : SHIL_LARGE, &IID_IImageList, (void **)&icon_list );
404 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL))
406 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
407 psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0);
408 else
410 static const WCHAR p1W[] = {'%','1',0};
411 WCHAR sTemp[MAX_PATH];
412 WCHAR *szExt;
413 int icon_idx = 0;
415 lstrcpynW(sTemp, szFullPath, MAX_PATH);
417 psfi->iIcon = 0;
418 szExt = PathFindExtensionW(sTemp);
419 if ( szExt &&
420 HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) &&
421 HCR_GetDefaultIconW(sTemp, sTemp, MAX_PATH, &icon_idx))
423 if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */
424 strcpyW(sTemp, szFullPath);
426 psfi->iIcon = SIC_GetIconIndex(sTemp, icon_idx, 0);
427 if (psfi->iIcon == -1)
428 psfi->iIcon = 0;
432 else
434 if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON),
435 uGilFlags, &(psfi->iIcon))))
437 ret = FALSE;
440 if (ret && (flags & SHGFI_SYSICONINDEX))
442 IImageList_AddRef( icon_list );
443 ret = (DWORD_PTR)icon_list;
445 if (ret && (flags & SHGFI_ICON))
447 if (flags & SHGFI_SHELLICONSIZE)
448 hr = IImageList_GetIcon( icon_list, psfi->iIcon, ILD_NORMAL, &psfi->hIcon );
449 else
451 int width = GetSystemMetrics( (flags & SHGFI_SMALLICON) ? SM_CXSMICON : SM_CXICON );
452 int height = GetSystemMetrics( (flags & SHGFI_SMALLICON) ? SM_CYSMICON : SM_CYICON );
453 int list_width, list_height;
455 IImageList_GetIconSize( icon_list, &list_width, &list_height );
456 if (list_width == width && list_height == height)
457 hr = IImageList_GetIcon( icon_list, psfi->iIcon, ILD_NORMAL, &psfi->hIcon );
458 else /* Use SHIL_SYSSMALL for SHFI_SMALLICONS when we implement it */
460 WCHAR buf[MAX_PATH], *file = buf;
461 DWORD size = sizeof(buf);
462 int icon_idx;
464 while ((hr = SIC_get_location( psfi->iIcon, file, &size, &icon_idx )) == E_NOT_SUFFICIENT_BUFFER)
466 if (file == buf) file = heap_alloc( size );
467 else file = heap_realloc( file, size );
468 if (!file) break;
470 if (SUCCEEDED(hr))
472 ret = PrivateExtractIconsW( file, icon_idx, width, height, &psfi->hIcon, 0, 1, 0);
473 if (ret == 0 || ret == (UINT)-1) hr = E_FAIL;
475 if (file != buf) heap_free( file );
479 IImageList_Release( icon_list );
482 if (flags & ~SHGFI_KNOWN_FLAGS)
483 FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS);
485 if (psfParent)
486 IShellFolder_Release(psfParent);
488 if (hr != S_OK)
489 ret = FALSE;
491 SHFree(pidlLast);
493 TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n",
494 psfi->hIcon, psfi->iIcon, psfi->dwAttributes,
495 debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret);
497 return ret;
500 /*************************************************************************
501 * SHGetFileInfoA [SHELL32.@]
503 * Note:
504 * MSVBVM60.__vbaNew2 expects this function to return a value in range
505 * 1 .. 0x7fff when the function succeeds and flags does not contain
506 * SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701)
508 DWORD_PTR WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
509 SHFILEINFOA *psfi, UINT sizeofpsfi,
510 UINT flags )
512 INT len;
513 LPWSTR temppath = NULL;
514 LPCWSTR pathW;
515 DWORD_PTR ret;
516 SHFILEINFOW temppsfi;
518 if (flags & SHGFI_PIDL)
520 /* path contains a pidl */
521 pathW = (LPCWSTR)path;
523 else
525 len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
526 temppath = heap_alloc(len*sizeof(WCHAR));
527 MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len);
528 pathW = temppath;
531 if (psfi && (flags & SHGFI_ATTR_SPECIFIED))
532 temppsfi.dwAttributes=psfi->dwAttributes;
534 if (psfi == NULL)
535 ret = SHGetFileInfoW(pathW, dwFileAttributes, NULL, sizeof(temppsfi), flags);
536 else
537 ret = SHGetFileInfoW(pathW, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
539 if (psfi)
541 if(flags & SHGFI_ICON)
542 psfi->hIcon=temppsfi.hIcon;
543 if(flags & (SHGFI_SYSICONINDEX|SHGFI_ICON|SHGFI_ICONLOCATION))
544 psfi->iIcon=temppsfi.iIcon;
545 if(flags & SHGFI_ATTRIBUTES)
546 psfi->dwAttributes=temppsfi.dwAttributes;
547 if(flags & (SHGFI_DISPLAYNAME|SHGFI_ICONLOCATION))
549 WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1,
550 psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL);
552 if(flags & SHGFI_TYPENAME)
554 WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1,
555 psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL);
559 heap_free(temppath);
561 return ret;
564 /*************************************************************************
565 * DuplicateIcon [SHELL32.@]
567 HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
569 ICONINFO IconInfo;
570 HICON hDupIcon = 0;
572 TRACE("%p %p\n", hInstance, hIcon);
574 if (GetIconInfo(hIcon, &IconInfo))
576 hDupIcon = CreateIconIndirect(&IconInfo);
578 /* clean up hbmMask and hbmColor */
579 DeleteObject(IconInfo.hbmMask);
580 DeleteObject(IconInfo.hbmColor);
583 return hDupIcon;
586 /*************************************************************************
587 * ExtractIconA [SHELL32.@]
589 HICON WINAPI ExtractIconA(HINSTANCE hInstance, const char *file, UINT nIconIndex)
591 WCHAR *fileW;
592 HICON ret;
594 TRACE("%p %s %d\n", hInstance, debugstr_a(file), nIconIndex);
596 fileW = strdupAtoW(file);
597 ret = ExtractIconW(hInstance, fileW, nIconIndex);
598 heap_free(fileW);
600 return ret;
603 /*************************************************************************
604 * ExtractIconW [SHELL32.@]
606 HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex)
608 HICON hIcon = NULL;
609 UINT ret;
610 UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON);
612 TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex);
614 if (nIconIndex == (UINT)-1)
616 ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR);
617 if (ret != (UINT)-1 && ret)
618 return (HICON)(UINT_PTR)ret;
619 return NULL;
621 else
622 ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR);
624 if (ret == (UINT)-1)
625 return (HICON)1;
626 else if (ret > 0 && hIcon)
627 return hIcon;
629 return NULL;
632 HRESULT WINAPI SHCreateFileExtractIconW(LPCWSTR file, DWORD attribs, REFIID riid, void **ppv)
634 FIXME("%s, %x, %s, %p\n", debugstr_w(file), attribs, debugstr_guid(riid), ppv);
635 *ppv = NULL;
636 return E_NOTIMPL;
639 /*************************************************************************
640 * Printer_LoadIconsW [SHELL32.205]
642 VOID WINAPI Printer_LoadIconsW(LPCWSTR wsPrinterName, HICON * pLargeIcon, HICON * pSmallIcon)
644 INT iconindex=IDI_SHELL_PRINTER;
646 TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName), pLargeIcon, pSmallIcon);
648 /* We should check if wsPrinterName is
649 1. the Default Printer or not
650 2. connected or not
651 3. a Local Printer or a Network-Printer
652 and use different Icons
654 if((wsPrinterName != NULL) && (wsPrinterName[0] != 0))
656 FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName));
659 if(pLargeIcon != NULL)
660 *pLargeIcon = LoadImageW(shell32_hInstance,
661 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
662 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE);
664 if(pSmallIcon != NULL)
665 *pSmallIcon = LoadImageW(shell32_hInstance,
666 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON,
667 16, 16, LR_DEFAULTCOLOR);
670 /*************************************************************************
671 * Printers_RegisterWindowW [SHELL32.213]
672 * used by "printui.dll":
673 * find the Window of the given Type for the specific Printer and
674 * return the already existent hwnd or open a new window
676 BOOL WINAPI Printers_RegisterWindowW(LPCWSTR wsPrinter, DWORD dwType,
677 HANDLE * phClassPidl, HWND * phwnd)
679 FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType,
680 phClassPidl, (phClassPidl != NULL) ? *(phClassPidl) : NULL,
681 phwnd, (phwnd != NULL) ? *(phwnd) : NULL);
683 return FALSE;
686 /*************************************************************************
687 * Printers_UnregisterWindow [SHELL32.214]
689 VOID WINAPI Printers_UnregisterWindow(HANDLE hClassPidl, HWND hwnd)
691 FIXME("(%p, %p) stub!\n", hClassPidl, hwnd);
694 struct window_prop_store
696 IPropertyStore IPropertyStore_iface;
697 LONG ref;
700 static inline struct window_prop_store *impl_from_IPropertyStore(IPropertyStore *iface)
702 return CONTAINING_RECORD(iface, struct window_prop_store, IPropertyStore_iface);
705 static ULONG WINAPI window_prop_store_AddRef(IPropertyStore *iface)
707 struct window_prop_store *store = impl_from_IPropertyStore(iface);
708 LONG ref = InterlockedIncrement(&store->ref);
709 TRACE("returning %d\n", ref);
710 return ref;
713 static ULONG WINAPI window_prop_store_Release(IPropertyStore *iface)
715 struct window_prop_store *store = impl_from_IPropertyStore(iface);
716 LONG ref = InterlockedDecrement(&store->ref);
717 if (!ref) heap_free(store);
718 TRACE("returning %d\n", ref);
719 return ref;
722 static HRESULT WINAPI window_prop_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **obj)
724 struct window_prop_store *store = impl_from_IPropertyStore(iface);
725 TRACE("%p, %s, %p\n", iface, debugstr_guid(iid), obj);
727 if (!obj) return E_POINTER;
728 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IPropertyStore))
730 *obj = &store->IPropertyStore_iface;
732 else
734 FIXME("no interface for %s\n", debugstr_guid(iid));
735 *obj = NULL;
736 return E_NOINTERFACE;
739 IUnknown_AddRef((IUnknown *)*obj);
740 return S_OK;
743 static HRESULT WINAPI window_prop_store_GetCount(IPropertyStore *iface, DWORD *count)
745 FIXME("%p, %p\n", iface, count);
746 return E_NOTIMPL;
749 static HRESULT WINAPI window_prop_store_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
751 FIXME("%p, %u,%p\n", iface, prop, key);
752 return E_NOTIMPL;
755 static HRESULT WINAPI window_prop_store_GetValue(IPropertyStore *iface, const PROPERTYKEY *key, PROPVARIANT *var)
757 FIXME("%p, {%s,%u}, %p\n", iface, debugstr_guid(&key->fmtid), key->pid, var);
758 return E_NOTIMPL;
761 static HRESULT WINAPI window_prop_store_SetValue(IPropertyStore *iface, const PROPERTYKEY *key, const PROPVARIANT *var)
763 FIXME("%p, {%s,%u}, %p\n", iface, debugstr_guid(&key->fmtid), key->pid, var);
764 return S_OK;
767 static HRESULT WINAPI window_prop_store_Commit(IPropertyStore *iface)
769 FIXME("%p\n", iface);
770 return S_OK;
773 static const IPropertyStoreVtbl window_prop_store_vtbl =
775 window_prop_store_QueryInterface,
776 window_prop_store_AddRef,
777 window_prop_store_Release,
778 window_prop_store_GetCount,
779 window_prop_store_GetAt,
780 window_prop_store_GetValue,
781 window_prop_store_SetValue,
782 window_prop_store_Commit
785 static HRESULT create_window_prop_store(IPropertyStore **obj)
787 struct window_prop_store *store;
789 if (!(store = heap_alloc(sizeof(*store)))) return E_OUTOFMEMORY;
790 store->IPropertyStore_iface.lpVtbl = &window_prop_store_vtbl;
791 store->ref = 1;
793 *obj = &store->IPropertyStore_iface;
794 return S_OK;
797 /*************************************************************************
798 * SHGetPropertyStoreForWindow [SHELL32.@]
800 HRESULT WINAPI SHGetPropertyStoreForWindow(HWND hwnd, REFIID riid, void **ppv)
802 IPropertyStore *store;
803 HRESULT hr;
805 FIXME("(%p %p %p) stub!\n", hwnd, riid, ppv);
807 if ((hr = create_window_prop_store( &store )) != S_OK) return hr;
808 hr = IPropertyStore_QueryInterface( store, riid, ppv );
809 IPropertyStore_Release( store );
810 return hr;
813 /*************************************************************************/
815 typedef struct
817 LPCWSTR szApp;
818 LPCWSTR szOtherStuff;
819 HICON hIcon;
820 HFONT hFont;
821 } ABOUT_INFO;
823 #define DROP_FIELD_TOP (-12)
825 static void paint_dropline( HDC hdc, HWND hWnd )
827 HWND hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_WINE_TEXT);
828 RECT rect;
830 if (!hWndCtl) return;
831 GetWindowRect( hWndCtl, &rect );
832 MapWindowPoints( 0, hWnd, (LPPOINT)&rect, 2 );
833 rect.top += DROP_FIELD_TOP;
834 rect.bottom = rect.top + 2;
835 DrawEdge( hdc, &rect, BDR_SUNKENOUTER, BF_RECT );
838 /*************************************************************************
839 * SHHelpShortcuts_RunDLLA [SHELL32.@]
842 DWORD WINAPI SHHelpShortcuts_RunDLLA(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
844 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
845 return 0;
848 /*************************************************************************
849 * SHHelpShortcuts_RunDLLA [SHELL32.@]
852 DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
854 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4);
855 return 0;
858 /*************************************************************************
859 * SHLoadInProc [SHELL32.@]
860 * Create an instance of specified object class from within
861 * the shell process and release it immediately
863 HRESULT WINAPI SHLoadInProc (REFCLSID rclsid)
865 void *ptr = NULL;
867 TRACE("%s\n", debugstr_guid(rclsid));
869 CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr);
870 if(ptr)
872 IUnknown * pUnk = ptr;
873 IUnknown_Release(pUnk);
874 return S_OK;
876 return DISP_E_MEMBERNOTFOUND;
879 static void add_authors( HWND list )
881 static const WCHAR eol[] = {'\r','\n',0};
882 static const WCHAR authors[] = {'A','U','T','H','O','R','S',0};
883 WCHAR *strW, *start, *end;
884 HRSRC rsrc = FindResourceW( shell32_hInstance, authors, (LPCWSTR)RT_RCDATA );
885 char *strA = LockResource( LoadResource( shell32_hInstance, rsrc ));
886 DWORD sizeW, sizeA = SizeofResource( shell32_hInstance, rsrc );
888 if (!strA) return;
889 sizeW = MultiByteToWideChar( CP_UTF8, 0, strA, sizeA, NULL, 0 ) + 1;
890 if (!(strW = heap_alloc( sizeW * sizeof(WCHAR) ))) return;
891 MultiByteToWideChar( CP_UTF8, 0, strA, sizeA, strW, sizeW );
892 strW[sizeW - 1] = 0;
894 start = strpbrkW( strW, eol ); /* skip the header line */
895 while (start)
897 while (*start && strchrW( eol, *start )) start++;
898 if (!*start) break;
899 end = strpbrkW( start, eol );
900 if (end) *end++ = 0;
901 SendMessageW( list, LB_ADDSTRING, -1, (LPARAM)start );
902 start = end;
904 heap_free( strW );
907 /*************************************************************************
908 * AboutDlgProc (internal)
910 static INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
911 LPARAM lParam )
913 HWND hWndCtl;
915 TRACE("\n");
917 switch(msg)
919 case WM_INITDIALOG:
921 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
922 WCHAR template[512], buffer[512], version[64];
923 const char *(CDECL *wine_get_build_id)(void);
925 if (info)
927 wine_get_build_id = (void *)GetProcAddress( GetModuleHandleA("ntdll.dll"),
928 "wine_get_build_id");
929 SendDlgItemMessageW(hWnd, stc1, STM_SETICON,(WPARAM)info->hIcon, 0);
930 GetWindowTextW( hWnd, template, ARRAY_SIZE(template) );
931 sprintfW( buffer, template, info->szApp );
932 SetWindowTextW( hWnd, buffer );
933 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT1), info->szApp );
934 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT2), info->szOtherStuff );
935 GetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3),
936 template, ARRAY_SIZE(template) );
937 if (wine_get_build_id)
939 MultiByteToWideChar( CP_UTF8, 0, wine_get_build_id(), -1, version, ARRAY_SIZE(version) );
940 sprintfW( buffer, template, version );
941 SetWindowTextW( GetDlgItem(hWnd, IDC_ABOUT_STATIC_TEXT3), buffer );
943 hWndCtl = GetDlgItem(hWnd, IDC_ABOUT_LISTBOX);
944 SendMessageW( hWndCtl, WM_SETREDRAW, 0, 0 );
945 SendMessageW( hWndCtl, WM_SETFONT, (WPARAM)info->hFont, 0 );
946 add_authors( hWndCtl );
947 SendMessageW( hWndCtl, WM_SETREDRAW, 1, 0 );
950 return 1;
952 case WM_PAINT:
954 PAINTSTRUCT ps;
955 HDC hDC = BeginPaint( hWnd, &ps );
956 paint_dropline( hDC, hWnd );
957 EndPaint( hWnd, &ps );
959 break;
961 case WM_COMMAND:
962 if (wParam == IDOK || wParam == IDCANCEL)
964 EndDialog(hWnd, TRUE);
965 return TRUE;
967 if (wParam == IDC_ABOUT_LICENSE)
969 MSGBOXPARAMSW params;
971 params.cbSize = sizeof(params);
972 params.hwndOwner = hWnd;
973 params.hInstance = shell32_hInstance;
974 params.lpszText = MAKEINTRESOURCEW(IDS_LICENSE);
975 params.lpszCaption = MAKEINTRESOURCEW(IDS_LICENSE_CAPTION);
976 params.dwStyle = MB_ICONINFORMATION | MB_OK;
977 params.lpszIcon = 0;
978 params.dwContextHelpId = 0;
979 params.lpfnMsgBoxCallback = NULL;
980 params.dwLanguageId = LANG_NEUTRAL;
981 MessageBoxIndirectW( &params );
983 break;
984 case WM_CLOSE:
985 EndDialog(hWnd, TRUE);
986 break;
989 return 0;
993 /*************************************************************************
994 * ShellAboutA [SHELL32.288]
996 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon )
998 BOOL ret;
999 LPWSTR appW = NULL, otherW = NULL;
1000 int len;
1002 if (szApp)
1004 len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0);
1005 appW = heap_alloc( len * sizeof(WCHAR));
1006 MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len);
1008 if (szOtherStuff)
1010 len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0);
1011 otherW = heap_alloc( len * sizeof(WCHAR));
1012 MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len);
1015 ret = ShellAboutW(hWnd, appW, otherW, hIcon);
1017 heap_free(otherW);
1018 heap_free(appW);
1019 return ret;
1023 /*************************************************************************
1024 * ShellAboutW [SHELL32.289]
1026 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
1027 HICON hIcon )
1029 ABOUT_INFO info;
1030 LOGFONTW logFont;
1031 BOOL bRet;
1032 static const WCHAR wszSHELL_ABOUT_MSGBOX[] =
1033 {'S','H','E','L','L','_','A','B','O','U','T','_','M','S','G','B','O','X',0};
1035 TRACE("\n");
1037 if (!hIcon) hIcon = LoadImageW( 0, (LPWSTR)IDI_WINLOGO, IMAGE_ICON, 48, 48, LR_SHARED );
1038 info.szApp = szApp;
1039 info.szOtherStuff = szOtherStuff;
1040 info.hIcon = hIcon;
1042 SystemParametersInfoW( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
1043 info.hFont = CreateFontIndirectW( &logFont );
1045 bRet = DialogBoxParamW( shell32_hInstance, wszSHELL_ABOUT_MSGBOX, hWnd, AboutDlgProc, (LPARAM)&info );
1046 DeleteObject(info.hFont);
1047 return bRet;
1050 /*************************************************************************
1051 * FreeIconList (SHELL32.@)
1053 void WINAPI FreeIconList( DWORD dw )
1055 FIXME("%x: stub\n",dw);
1058 /*************************************************************************
1059 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@)
1061 HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID )
1063 FIXME("stub\n");
1064 return S_OK;
1067 /***********************************************************************
1068 * DllGetVersion [SHELL32.@]
1070 * Retrieves version information of the 'SHELL32.DLL'
1072 * PARAMS
1073 * pdvi [O] pointer to version information structure.
1075 * RETURNS
1076 * Success: S_OK
1077 * Failure: E_INVALIDARG
1079 * NOTES
1080 * Returns version of a shell32.dll from IE4.01 SP1.
1083 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
1085 /* FIXME: shouldn't these values come from the version resource? */
1086 if (pdvi->cbSize == sizeof(DLLVERSIONINFO) ||
1087 pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1089 pdvi->dwMajorVersion = WINE_FILEVERSION_MAJOR;
1090 pdvi->dwMinorVersion = WINE_FILEVERSION_MINOR;
1091 pdvi->dwBuildNumber = WINE_FILEVERSION_BUILD;
1092 pdvi->dwPlatformID = WINE_FILEVERSION_PLATFORMID;
1093 if (pdvi->cbSize == sizeof(DLLVERSIONINFO2))
1095 DLLVERSIONINFO2 *pdvi2 = (DLLVERSIONINFO2 *)pdvi;
1097 pdvi2->dwFlags = 0;
1098 pdvi2->ullVersion = MAKEDLLVERULL(WINE_FILEVERSION_MAJOR,
1099 WINE_FILEVERSION_MINOR,
1100 WINE_FILEVERSION_BUILD,
1101 WINE_FILEVERSION_PLATFORMID);
1103 TRACE("%u.%u.%u.%u\n",
1104 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
1105 pdvi->dwBuildNumber, pdvi->dwPlatformID);
1106 return S_OK;
1108 else
1110 WARN("wrong DLLVERSIONINFO size from app\n");
1111 return E_INVALIDARG;
1115 /*************************************************************************
1116 * global variables of the shell32.dll
1117 * all are once per process
1120 HINSTANCE shell32_hInstance = 0;
1123 /*************************************************************************
1124 * SHELL32 DllMain
1126 * NOTES
1127 * calling oleinitialize here breaks some apps.
1129 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1131 TRACE("%p 0x%x %p\n", hinstDLL, fdwReason, fImpLoad);
1133 switch (fdwReason)
1135 case DLL_PROCESS_ATTACH:
1136 shell32_hInstance = hinstDLL;
1137 DisableThreadLibraryCalls(shell32_hInstance);
1139 /* get full path to this DLL for IExtractIconW_fnGetIconLocation() */
1140 GetModuleFileNameW(hinstDLL, swShell32Name, MAX_PATH);
1141 swShell32Name[MAX_PATH - 1] = '\0';
1143 InitChangeNotifications();
1144 break;
1146 case DLL_PROCESS_DETACH:
1147 if (fImpLoad) break;
1148 SIC_Destroy();
1149 FreeChangeNotifications();
1150 release_desktop_folder();
1151 release_typelib();
1152 break;
1154 return TRUE;
1157 /*************************************************************************
1158 * DllInstall [SHELL32.@]
1160 * PARAMETERS
1162 * BOOL bInstall - TRUE for install, FALSE for uninstall
1163 * LPCWSTR pszCmdLine - command line (unused by shell32?)
1166 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1168 FIXME("%s %s: stub\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
1169 return S_OK; /* indicate success */
1172 /***********************************************************************
1173 * DllCanUnloadNow (SHELL32.@)
1175 HRESULT WINAPI DllCanUnloadNow(void)
1177 return S_FALSE;
1180 /***********************************************************************
1181 * DllRegisterServer (SHELL32.@)
1183 HRESULT WINAPI DllRegisterServer(void)
1185 HRESULT hr = __wine_register_resources( shell32_hInstance );
1186 if (SUCCEEDED(hr)) hr = SHELL_RegisterShellFolders();
1187 return hr;
1190 /***********************************************************************
1191 * DllUnregisterServer (SHELL32.@)
1193 HRESULT WINAPI DllUnregisterServer(void)
1195 return __wine_unregister_resources( shell32_hInstance );
1198 /***********************************************************************
1199 * ExtractVersionResource16W (SHELL32.@)
1201 BOOL WINAPI ExtractVersionResource16W(LPWSTR s, DWORD d)
1203 FIXME("(%s %x) stub!\n", debugstr_w(s), d);
1204 return FALSE;
1207 /***********************************************************************
1208 * InitNetworkAddressControl (SHELL32.@)
1210 BOOL WINAPI InitNetworkAddressControl(void)
1212 FIXME("stub\n");
1213 return FALSE;
1216 /***********************************************************************
1217 * ShellHookProc (SHELL32.@)
1219 LRESULT CALLBACK ShellHookProc(DWORD a, DWORD b, DWORD c)
1221 FIXME("Stub\n");
1222 return 0;
1225 /***********************************************************************
1226 * SHGetLocalizedName (SHELL32.@)
1228 HRESULT WINAPI SHGetLocalizedName(LPCWSTR path, LPWSTR module, UINT size, INT *res)
1230 FIXME("%s %p %u %p: stub\n", debugstr_w(path), module, size, res);
1231 return E_NOTIMPL;
1234 /***********************************************************************
1235 * SHSetUnreadMailCountW (SHELL32.@)
1237 HRESULT WINAPI SHSetUnreadMailCountW(LPCWSTR mailaddress, DWORD count, LPCWSTR executecommand)
1239 FIXME("%s %x %s: stub\n", debugstr_w(mailaddress), count, debugstr_w(executecommand));
1240 return E_NOTIMPL;
1243 /***********************************************************************
1244 * SHEnumerateUnreadMailAccountsW (SHELL32.@)
1246 HRESULT WINAPI SHEnumerateUnreadMailAccountsW(HKEY user, DWORD idx, LPWSTR mailaddress, INT mailaddresslen)
1248 FIXME("%p %d %p %d: stub\n", user, idx, mailaddress, mailaddresslen);
1249 return E_NOTIMPL;
1252 /***********************************************************************
1253 * SHQueryUserNotificationState (SHELL32.@)
1255 HRESULT WINAPI SHQueryUserNotificationState(QUERY_USER_NOTIFICATION_STATE *state)
1257 FIXME("%p: stub\n", state);
1258 *state = QUNS_ACCEPTS_NOTIFICATIONS;
1259 return S_OK;
1262 /***********************************************************************
1263 * SHCreateDataObject (SHELL32.@)
1265 HRESULT WINAPI SHCreateDataObject(PCIDLIST_ABSOLUTE pidl_folder, UINT count, PCUITEMID_CHILD_ARRAY pidl_array,
1266 IDataObject *object, REFIID riid, void **ppv)
1268 FIXME("%p %d %p %p %s %p: stub\n", pidl_folder, count, pidl_array, object, debugstr_guid(riid), ppv);
1269 return E_NOTIMPL;