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