Like the AUTORADIOBUTTON, the parent of a RADIOBUTTON style button
[wine] / dlls / shell32 / shell32_main.c
1 /*
2  *                              Shell basics
3  *
4  *  1998 Marcus Meissner
5  *  1998 Juergen Schmied (jsch)  *  <juergen.schmied@metronet.de>
6  */
7 #include <stdlib.h>
8 #include <string.h>
9 #include <stdio.h>
10
11 #include "windef.h"
12 #include "wingdi.h"
13 #include "wine/winuser16.h"
14 #include "winerror.h"
15 #include "heap.h"
16 #include "dlgs.h"
17 #include "ldt.h"
18 #include "sysmetrics.h"
19 #include "debugtools.h"
20 #include "winreg.h"
21 #include "authors.h"
22 #include "winversion.h"
23
24 #include "shellapi.h"
25 #include "pidl.h"
26
27 #include "shell32_main.h"
28 #include "wine/undocshell.h"
29 #include "shlobj.h"
30 #include "shlguid.h"
31 #include "shlwapi.h"
32
33 DEFAULT_DEBUG_CHANNEL(shell);
34
35 #define MORE_DEBUG 1
36 /*************************************************************************
37  * CommandLineToArgvW                   [SHELL32.7]
38  */
39 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
40 {       LPWSTR  *argv,s,t;
41         int     i;
42         TRACE("\n");
43
44         /* to get writeable copy */
45         cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
46         s=cmdline;i=0;
47         while (*s)
48         { /* space */
49           if (*s==0x0020) 
50           { i++;
51             s++;
52             while (*s && *s==0x0020)
53               s++;
54             continue;
55           }
56           s++;
57         }
58         argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
59         s=t=cmdline;
60         i=0;
61         while (*s)
62         { if (*s==0x0020)
63           { *s=0;
64             argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
65             *s=0x0020;
66             while (*s && *s==0x0020)
67               s++;
68             if (*s)
69               t=s+1;
70             else
71               t=s;
72             continue;
73           }
74           s++;
75         }
76         if (*t)
77           argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
78
79         HeapFree( GetProcessHeap(), 0, cmdline );
80         argv[i]=NULL;
81         *numargs=i;
82         return argv;
83 }
84
85 /*************************************************************************
86  * Control_RunDLL                       [SHELL32.12]
87  *
88  * Wild speculation in the following!
89  *
90  * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
91  */
92
93 void WINAPI Control_RunDLL( HWND hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4 )
94 {
95     FIXME("(0x%08x, %p, %s, 0x%08lx): stub\n", hwnd, code,
96           debugstr_a(cmd), arg4);
97 }
98
99 /*************************************************************************
100  * SHGetFileInfoA                       [SHELL32.@]
101  */
102
103 DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
104                               SHFILEINFOA *psfi, UINT sizeofpsfi,
105                               UINT flags )
106 {
107         char szLoaction[MAX_PATH];
108         int iIndex;
109         DWORD ret = TRUE, dwAttributes = 0;
110         IShellFolder * psfParent = NULL;
111         IExtractIconA * pei = NULL;
112         LPITEMIDLIST    pidlLast = NULL, pidl = NULL;
113         HRESULT hr = S_OK;
114
115         TRACE("(%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x)\n", 
116           (flags & SHGFI_PIDL)? "pidl" : path, dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags);
117
118         if ((flags & SHGFI_USEFILEATTRIBUTES) && (flags & (SHGFI_ATTRIBUTES|SHGFI_EXETYPE|SHGFI_PIDL)))
119           return FALSE;
120         
121         /* translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES in not specified 
122            the pidl functions fail on not existing file names */
123         if (flags & SHGFI_PIDL)
124         {
125           pidl = (LPCITEMIDLIST) path;
126           if (!pidl )
127           {
128             ERR("pidl is null!\n");
129             return FALSE;
130           }
131         }
132         else if (!(flags & SHGFI_USEFILEATTRIBUTES))
133         {
134           hr = SHILCreateFromPathA ( path, &pidl, &dwAttributes);
135           /* note: the attributes in ISF::ParseDisplayName are not implemented */
136         }
137         
138         /* get the parent shellfolder */
139         if (pidl)
140         {
141           hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidlLast);
142         }
143         
144         /* get the attributes of the child */
145         if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
146         {
147           if (!(flags & SHGFI_ATTR_SPECIFIED))
148           {
149             psfi->dwAttributes = 0xffffffff;
150           }
151           IShellFolder_GetAttributesOf(psfParent, 1 , &pidlLast, &(psfi->dwAttributes));
152         }
153
154         /* get the displayname */
155         if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
156         { 
157           if (flags & SHGFI_USEFILEATTRIBUTES)
158           {
159             strcpy (psfi->szDisplayName, PathFindFileNameA(path));
160           }
161           else
162           {
163             STRRET str;
164             hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_INFOLDER, &str);
165             StrRetToStrNA (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
166           }
167         }
168
169         /* get the type name */
170         if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
171         {
172           _ILGetFileType(pidlLast, psfi->szTypeName, 80);
173         }
174
175         /* ### icons ###*/
176         if (flags & SHGFI_LINKOVERLAY)
177           FIXME("set icon to link, stub\n");
178
179         if (flags & SHGFI_SELECTED)
180           FIXME("set icon to selected, stub\n");
181
182         if (flags & SHGFI_SHELLICONSIZE)
183           FIXME("set icon to shell size, stub\n");
184
185         /* get the iconlocation */
186         if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
187         {
188           UINT uDummy,uFlags;
189           hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, &pidlLast, &IID_IExtractIconA, &uDummy, (LPVOID*)&pei);
190
191           if (SUCCEEDED(hr))
192           {
193             hr = IExtractIconA_GetIconLocation(pei, (flags & SHGFI_OPENICON)? GIL_OPENICON : 0,szLoaction, MAX_PATH, &iIndex, &uFlags);
194             /* fixme what to do with the index? */
195
196             if(uFlags != GIL_NOTFILENAME)
197               strcpy (psfi->szDisplayName, szLoaction);
198             else
199               ret = FALSE;
200               
201             IExtractIconA_Release(pei);
202           }
203         }
204
205         /* get icon index (or load icon)*/
206         if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
207         {
208           if (flags & SHGFI_USEFILEATTRIBUTES)
209           {
210             char sTemp [MAX_PATH];
211             char * szExt;
212             DWORD dwNr=0;
213
214             lstrcpynA(sTemp, path, MAX_PATH);
215             szExt = (LPSTR) PathFindExtensionA(sTemp);
216             if( szExt && HCR_MapTypeToValue(szExt, sTemp, MAX_PATH, TRUE)
217               && HCR_GetDefaultIcon(sTemp, sTemp, MAX_PATH, &dwNr))
218             {
219               if (!strcmp("%1",sTemp))            /* icon is in the file */
220               {
221                 strcpy(sTemp, path);
222               }
223               /* FIXME: if sTemp contains a valid filename, get the icon 
224                  from there, index is in dwNr
225               */
226               psfi->iIcon = 2;
227             }
228             else                                  /* default icon */
229             {
230               psfi->iIcon = 0;
231             }          
232           }
233           else
234           {
235             if (!(PidlToSicIndex(psfParent, pidlLast, (flags & SHGFI_LARGEICON), 
236               (flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon))))
237             {
238               ret = FALSE;
239             }
240           }
241           if (ret) 
242           {
243             ret = (DWORD) ((flags & SHGFI_LARGEICON) ? ShellBigIconList : ShellSmallIconList);
244           }
245         }
246
247         /* icon handle */
248         if (SUCCEEDED(hr) && (flags & SHGFI_ICON))
249           psfi->hIcon = pImageList_GetIcon((flags & SHGFI_LARGEICON) ? ShellBigIconList:ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
250
251
252         if (flags & SHGFI_EXETYPE)
253           FIXME("type of executable, stub\n");
254
255         if (flags & (SHGFI_UNKNOWN1 | SHGFI_UNKNOWN2 | SHGFI_UNKNOWN3))
256           FIXME("unknown attribute!\n");
257
258         if (psfParent)
259           IShellFolder_Release(psfParent);
260
261         if (hr != S_OK)
262           ret = FALSE;
263
264         if(pidlLast) SHFree(pidlLast);
265 #ifdef MORE_DEBUG
266         TRACE ("icon=0x%08x index=0x%08x attr=0x%08lx name=%s type=%s ret=0x%08lx\n", 
267                 psfi->hIcon, psfi->iIcon, psfi->dwAttributes, psfi->szDisplayName, psfi->szTypeName, ret);
268 #endif
269         return ret;
270 }
271
272 /*************************************************************************
273  * SHGetFileInfoW                       [SHELL32.@]
274  */
275
276 DWORD WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
277                               SHFILEINFOW *psfi, UINT sizeofpsfi,
278                               UINT flags )
279 {       FIXME("(%s,0x%lx,%p,0x%x,0x%x)\n",
280               debugstr_w(path),dwFileAttributes,psfi,sizeofpsfi,flags);
281         return 0;
282 }
283
284 /*************************************************************************
285  * SHGetFileInfoAW                      [SHELL32.@]
286  */
287 DWORD WINAPI SHGetFileInfoAW(
288         LPCVOID path,
289         DWORD dwFileAttributes,
290         LPVOID psfi,
291         UINT sizeofpsfi,
292         UINT flags)
293 {
294         if(VERSION_OsIsUnicode())
295           return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags );
296         return SHGetFileInfoA(path, dwFileAttributes, psfi, sizeofpsfi, flags );
297 }
298
299 /*************************************************************************
300  * ExtractIconA                         [SHELL32.133]
301  */
302 HICON WINAPI ExtractIconA( HINSTANCE hInstance, LPCSTR lpszExeFileName,
303         UINT nIconIndex )
304 {   HGLOBAL16 handle = InternalExtractIcon16(hInstance,lpszExeFileName,nIconIndex, 1);
305     TRACE("\n");
306     if( handle )
307     {
308         HICON16* ptr = (HICON16*)GlobalLock16(handle);
309         HICON16  hIcon = *ptr;
310
311         GlobalFree16(handle);
312         return hIcon;
313     }
314     return 0;
315 }
316
317 /*************************************************************************
318  * ExtractIconW                         [SHELL32.180]
319  */
320 HICON WINAPI ExtractIconW( HINSTANCE hInstance, LPCWSTR lpszExeFileName,
321         UINT nIconIndex )
322 { LPSTR  exefn;
323   HICON  ret;
324   TRACE("\n");
325
326   exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
327   ret = ExtractIconA(hInstance,exefn,nIconIndex);
328
329         HeapFree(GetProcessHeap(),0,exefn);
330         return ret;
331 }
332
333 /*************************************************************************
334  * FindExecutableA                      [SHELL32.184]
335  */
336 HINSTANCE WINAPI FindExecutableA( LPCSTR lpFile, LPCSTR lpDirectory,
337                                       LPSTR lpResult )
338 { HINSTANCE retval=31;    /* default - 'No association was found' */
339     char old_dir[1024];
340
341   TRACE("File %s, Dir %s\n", 
342                  (lpFile != NULL?lpFile:"-"), 
343                  (lpDirectory != NULL?lpDirectory:"-"));
344
345     lpResult[0]='\0'; /* Start off with an empty return string */
346
347     /* trap NULL parameters on entry */
348     if (( lpFile == NULL ) || ( lpResult == NULL ))
349   { /* FIXME - should throw a warning, perhaps! */
350         return 2; /* File not found. Close enough, I guess. */
351     }
352
353     if (lpDirectory)
354   { GetCurrentDirectoryA( sizeof(old_dir), old_dir );
355         SetCurrentDirectoryA( lpDirectory );
356     }
357
358     retval = SHELL_FindExecutable( lpFile, "open", lpResult );
359
360   TRACE("returning %s\n", lpResult);
361   if (lpDirectory)
362     SetCurrentDirectoryA( old_dir );
363     return retval;
364 }
365
366 /*************************************************************************
367  * FindExecutableW                      [SHELL32.219]
368  */
369 HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory,
370                                      LPWSTR lpResult)
371 {
372   FIXME("(%p,%p,%p): stub\n", lpFile, lpDirectory, lpResult);
373   return 31;    /* default - 'No association was found' */
374 }
375
376 typedef struct
377 { LPCSTR  szApp;
378     LPCSTR  szOtherStuff;
379     HICON hIcon;
380 } ABOUT_INFO;
381
382 #define         IDC_STATIC_TEXT         100
383 #define         IDC_LISTBOX             99
384 #define         IDC_WINE_TEXT           98
385
386 #define         DROP_FIELD_TOP          (-15)
387 #define         DROP_FIELD_HEIGHT       15
388
389 extern HICON hIconTitleFont;
390
391 static BOOL __get_dropline( HWND hWnd, LPRECT lprect )
392 { HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT);
393     if( hWndCtl )
394   { GetWindowRect( hWndCtl, lprect );
395         MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 );
396         lprect->bottom = (lprect->top += DROP_FIELD_TOP);
397         return TRUE;
398     }
399     return FALSE;
400 }
401
402 /*************************************************************************
403  * SHAppBarMessage                      [SHELL32.207]
404  */
405 UINT WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data)
406 {
407         int width=data->rc.right - data->rc.left;
408         int height=data->rc.bottom - data->rc.top;
409         RECT rec=data->rc;
410         switch (msg)
411         { case ABM_GETSTATE:
412                return ABS_ALWAYSONTOP | ABS_AUTOHIDE;
413           case ABM_GETTASKBARPOS:
414                GetWindowRect(data->hWnd, &rec);
415                data->rc=rec;
416                return TRUE;
417           case ABM_ACTIVATE:
418                SetActiveWindow(data->hWnd);
419                return TRUE;
420           case ABM_GETAUTOHIDEBAR:
421                data->hWnd=GetActiveWindow();
422                return TRUE;
423           case ABM_NEW:
424                SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top,
425                                         width,height,SWP_SHOWWINDOW);
426                return TRUE;
427           case ABM_QUERYPOS:
428                GetWindowRect(data->hWnd, &(data->rc));
429                return TRUE;
430           case ABM_REMOVE:
431                CloseHandle(data->hWnd);
432                return TRUE;
433           case ABM_SETAUTOHIDEBAR:
434                SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top,
435                                        width,height,SWP_SHOWWINDOW);          
436                return TRUE;
437           case ABM_SETPOS:
438                data->uEdge=(ABE_RIGHT | ABE_LEFT);
439                SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top,
440                                   width,height,SWP_SHOWWINDOW);
441                return TRUE;
442           case ABM_WINDOWPOSCHANGED:
443                SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top,
444                                         width,height,SWP_SHOWWINDOW);
445                return TRUE;
446           }
447       return FALSE;
448 }
449
450 /*************************************************************************
451  * SHHelpShortcuts_RunDLL               [SHELL32.224]
452  *
453  */
454 DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
455 { FIXME("(%lx, %lx, %lx, %lx) empty stub!\n",
456         dwArg1, dwArg2, dwArg3, dwArg4);
457
458   return 0;
459 }
460
461 /*************************************************************************
462  * SHLoadInProc                         [SHELL32.225]
463  * Create an instance of specified object class from within 
464  * the shell process and release it immediately
465  */
466
467 DWORD WINAPI SHLoadInProc (REFCLSID rclsid)
468 {
469         IUnknown * pUnk = NULL;
470         TRACE("%s\n", debugstr_guid(rclsid));
471
472         CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,(LPVOID*)pUnk);
473         if(pUnk)
474         {
475           IUnknown_Release(pUnk);
476           return NOERROR;
477         }
478         return DISP_E_MEMBERNOTFOUND;
479 }
480
481 /*************************************************************************
482  * ShellExecuteA                        [SHELL32.245]
483  */
484 HINSTANCE WINAPI ShellExecuteA( HWND hWnd, LPCSTR lpOperation,
485                                     LPCSTR lpFile, LPCSTR lpParameters,
486                                     LPCSTR lpDirectory, INT iShowCmd )
487 {   TRACE("\n");
488     return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
489                            lpDirectory, iShowCmd );
490 }
491
492 /*************************************************************************
493  * ShellExecuteW                        [SHELL32.294]
494  * from shellapi.h
495  * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, 
496  * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);   
497  */
498 HINSTANCE WINAPI 
499 ShellExecuteW(
500        HWND hwnd, 
501        LPCWSTR lpOperation, 
502        LPCWSTR lpFile, 
503        LPCWSTR lpParameters, 
504        LPCWSTR lpDirectory, 
505        INT nShowCmd) {
506
507        FIXME(": stub\n");
508        return 0;
509 }
510
511 /*************************************************************************
512  * AboutDlgProc                 (internal)
513  */
514 BOOL WINAPI AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
515                               LPARAM lParam )
516 {   HWND hWndCtl;
517     char Template[512], AppTitle[512];
518
519     TRACE("\n");
520
521     switch(msg)
522     { case WM_INITDIALOG:
523       { ABOUT_INFO *info = (ABOUT_INFO *)lParam;
524             if (info)
525         { const char* const *pstr = SHELL_People;
526                 SendDlgItemMessageA(hWnd, stc1, STM_SETICON,info->hIcon, 0);
527                 GetWindowTextA( hWnd, Template, sizeof(Template) );
528                 sprintf( AppTitle, Template, info->szApp );
529                 SetWindowTextA( hWnd, AppTitle );
530                 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT),
531                                   info->szOtherStuff );
532                 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
533                 SendMessageA( hWndCtl, WM_SETREDRAW, 0, 0 );
534                 SendMessageA( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
535                 while (*pstr)
536           { SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)*pstr );
537                     pstr++;
538                 }
539                 SendMessageA( hWndCtl, WM_SETREDRAW, 1, 0 );
540             }
541         }
542         return 1;
543
544     case WM_PAINT:
545       { RECT rect;
546             PAINTSTRUCT ps;
547             HDC hDC = BeginPaint( hWnd, &ps );
548
549             if( __get_dropline( hWnd, &rect ) ) {
550                 SelectObject( hDC, GetStockObject( BLACK_PEN ) );
551                 MoveToEx( hDC, rect.left, rect.top, NULL );
552                 LineTo( hDC, rect.right, rect.bottom );
553             }
554             EndPaint( hWnd, &ps );
555         }
556         break;
557
558     case WM_LBTRACKPOINT:
559         hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
560         if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
561       { if( DragDetect( hWndCtl, *((LPPOINT)&lParam) ) )
562         { INT idx = SendMessageA( hWndCtl, LB_GETCURSEL, 0, 0 );
563                 if( idx != -1 )
564           { INT length = SendMessageA( hWndCtl, LB_GETTEXTLEN, (WPARAM)idx, 0 );
565                     HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
566                     char* pstr = (char*)GlobalLock16( hMemObj );
567
568                     if( pstr )
569             { HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE16(OCR_DRAGOBJECT) );
570                         SendMessageA( hWndCtl, LB_GETTEXT, (WPARAM)idx, (LPARAM)pstr );
571                         SendMessageA( hWndCtl, LB_DELETESTRING, (WPARAM)idx, 0 );
572                         UpdateWindow( hWndCtl );
573                         if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
574                             SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)pstr );
575                     }
576             if( hMemObj )
577               GlobalFree16( hMemObj );
578                 }
579             }
580         }
581         break;
582
583     case WM_QUERYDROPOBJECT:
584         if( wParam == 0 )
585       { LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
586             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
587         { RECT rect;
588                 if( __get_dropline( hWnd, &rect ) )
589           { POINT pt;
590             pt.x=lpDragInfo->pt.x;
591             pt.x=lpDragInfo->pt.y;
592                     rect.bottom += DROP_FIELD_HEIGHT;
593                     if( PtInRect( &rect, pt ) )
594             { SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
595                         return TRUE;
596                     }
597                 }
598             }
599         }
600         break;
601
602     case WM_DROPOBJECT:
603         if( wParam == hWnd )
604       { LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
605             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
606         { char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
607                 if( pstr )
608           { static char __appendix_str[] = " with";
609
610                     hWndCtl = GetDlgItem( hWnd, IDC_WINE_TEXT );
611                     SendMessageA( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
612                     if( !strncmp( Template, "WINE", 4 ) )
613                         SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT), Template );
614                     else
615           { char* pch = Template + strlen(Template) - strlen(__appendix_str);
616                         *pch = '\0';
617                         SendMessageA( GetDlgItem(hWnd, IDC_LISTBOX), LB_ADDSTRING, 
618                                         (WPARAM)-1, (LPARAM)Template );
619                     }
620
621                     strcpy( Template, pstr );
622                     strcat( Template, __appendix_str );
623                     SetWindowTextA( hWndCtl, Template );
624                     SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
625                     return TRUE;
626                 }
627             }
628         }
629         break;
630
631     case WM_COMMAND:
632         if (wParam == IDOK)
633     {  EndDialog(hWnd, TRUE);
634             return TRUE;
635         }
636         break;
637     case WM_CLOSE:
638       EndDialog(hWnd, TRUE);
639       break;
640     }
641
642     return 0;
643 }
644
645
646 /*************************************************************************
647  * ShellAboutA                          [SHELL32.243]
648  */
649 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
650                              HICON hIcon )
651 {   ABOUT_INFO info;
652     HRSRC hRes;
653     LPVOID template;
654     TRACE("\n");
655
656     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
657         return FALSE;
658     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
659         return FALSE;
660
661     info.szApp        = szApp;
662     info.szOtherStuff = szOtherStuff;
663     info.hIcon        = hIcon;
664     if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
665     return DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
666                                       template, hWnd, AboutDlgProc, (LPARAM)&info );
667 }
668
669
670 /*************************************************************************
671  * ShellAboutW                          [SHELL32.244]
672  */
673 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
674                              HICON hIcon )
675 {   BOOL ret;
676     ABOUT_INFO info;
677     HRSRC hRes;
678     LPVOID template;
679
680     TRACE("\n");
681     
682     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
683         return FALSE;
684     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
685         return FALSE;
686
687     info.szApp        = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
688     info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
689     info.hIcon        = hIcon;
690     if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
691     ret = DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
692                                    template, hWnd, AboutDlgProc, (LPARAM)&info );
693     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
694     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
695     return ret;
696 }
697
698 /*************************************************************************
699  * FreeIconList
700  */
701 void WINAPI FreeIconList( DWORD dw )
702 { FIXME("(%lx): stub\n",dw);
703 }
704
705 /***********************************************************************
706  * DllGetVersion [COMCTL32.25]
707  *
708  * Retrieves version information of the 'SHELL32.DLL'
709  *
710  * PARAMS
711  *     pdvi [O] pointer to version information structure.
712  *
713  * RETURNS
714  *     Success: S_OK
715  *     Failure: E_INVALIDARG
716  *
717  * NOTES
718  *     Returns version of a shell32.dll from IE4.01 SP1.
719  */
720
721 HRESULT WINAPI SHELL32_DllGetVersion (DLLVERSIONINFO *pdvi)
722 {
723         if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) 
724         { WARN("wrong DLLVERSIONINFO size from app");
725           return E_INVALIDARG;
726         }
727
728         pdvi->dwMajorVersion = 4;
729         pdvi->dwMinorVersion = 72;
730         pdvi->dwBuildNumber = 3110;
731         pdvi->dwPlatformID = 1;
732
733         TRACE("%lu.%lu.%lu.%lu\n",
734            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
735            pdvi->dwBuildNumber, pdvi->dwPlatformID);
736
737         return S_OK;
738 }
739 /*************************************************************************
740  * global variables of the shell32.dll
741  * all are once per process
742  *
743  */
744 void    (WINAPI* pDLLInitComctl)(LPVOID);
745 INT     (WINAPI* pImageList_AddIcon) (HIMAGELIST himl, HICON hIcon);
746 INT     (WINAPI* pImageList_ReplaceIcon) (HIMAGELIST, INT, HICON);
747 HIMAGELIST (WINAPI * pImageList_Create) (INT,INT,UINT,INT,INT);
748 BOOL    (WINAPI* pImageList_Draw) (HIMAGELIST himl, int i, HDC hdcDest, int x, int y, UINT fStyle);
749 HICON   (WINAPI * pImageList_GetIcon) (HIMAGELIST, INT, UINT);
750 INT     (WINAPI* pImageList_GetImageCount)(HIMAGELIST);
751 COLORREF (WINAPI *pImageList_SetBkColor)(HIMAGELIST, COLORREF);
752
753 LPVOID  (WINAPI* pCOMCTL32_Alloc) (INT);  
754 BOOL    (WINAPI* pCOMCTL32_Free) (LPVOID);  
755
756 HDPA    (WINAPI* pDPA_Create) (INT);  
757 INT     (WINAPI* pDPA_InsertPtr) (const HDPA, INT, LPVOID); 
758 BOOL    (WINAPI* pDPA_Sort) (const HDPA, PFNDPACOMPARE, LPARAM); 
759 LPVOID  (WINAPI* pDPA_GetPtr) (const HDPA, INT);   
760 BOOL    (WINAPI* pDPA_Destroy) (const HDPA); 
761 INT     (WINAPI *pDPA_Search) (const HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
762 LPVOID  (WINAPI *pDPA_DeletePtr) (const HDPA hdpa, INT i);
763
764 /* user32 */
765 HICON (WINAPI *pLookupIconIdFromDirectoryEx)(LPBYTE dir, BOOL bIcon, INT width, INT height, UINT cFlag);
766 HICON (WINAPI *pCreateIconFromResourceEx)(LPBYTE bits,UINT cbSize, BOOL bIcon, DWORD dwVersion, INT width, INT height,UINT cFlag);
767
768 static HINSTANCE        hComctl32;
769 static INT              shell32_RefCount = 0;
770
771 LONG            shell32_ObjCount = 0;
772 HINSTANCE       shell32_hInstance; 
773 HIMAGELIST      ShellSmallIconList = 0;
774 HIMAGELIST      ShellBigIconList = 0;
775
776 /*************************************************************************
777  * SHELL32 LibMain
778  *
779  * NOTES
780  *  calling oleinitialize here breaks sone apps.
781  */
782
783 BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
784 {
785         HMODULE hUser32;
786
787         TRACE("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
788
789         switch (fdwReason)
790         {
791           case DLL_PROCESS_ATTACH:
792             shell32_RefCount++;
793             if (shell32_hInstance) return TRUE;
794
795             shell32_hInstance = hinstDLL;
796             hComctl32 = GetModuleHandleA("COMCTL32.DLL");       
797             hUser32 = GetModuleHandleA("USER32");
798             DisableThreadLibraryCalls(shell32_hInstance);
799
800             if (!hComctl32 || !hUser32)
801             {
802               ERR("P A N I C SHELL32 loading failed\n");
803               return FALSE;
804             }
805
806             /* comctl32 */
807             pDLLInitComctl=(void*)GetProcAddress(hComctl32,"InitCommonControlsEx");
808             pImageList_Create=(void*)GetProcAddress(hComctl32,"ImageList_Create");
809             pImageList_AddIcon=(void*)GetProcAddress(hComctl32,"ImageList_AddIcon");
810             pImageList_ReplaceIcon=(void*)GetProcAddress(hComctl32,"ImageList_ReplaceIcon");
811             pImageList_GetIcon=(void*)GetProcAddress(hComctl32,"ImageList_GetIcon");
812             pImageList_GetImageCount=(void*)GetProcAddress(hComctl32,"ImageList_GetImageCount");
813             pImageList_Draw=(void*)GetProcAddress(hComctl32,"ImageList_Draw");
814             pImageList_SetBkColor=(void*)GetProcAddress(hComctl32,"ImageList_SetBkColor");
815             pCOMCTL32_Alloc=(void*)GetProcAddress(hComctl32, (LPCSTR)71L);
816             pCOMCTL32_Free=(void*)GetProcAddress(hComctl32, (LPCSTR)73L);
817             pDPA_Create=(void*)GetProcAddress(hComctl32, (LPCSTR)328L);
818             pDPA_Destroy=(void*)GetProcAddress(hComctl32, (LPCSTR)329L);
819             pDPA_GetPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)332L);
820             pDPA_InsertPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)334L);
821             pDPA_DeletePtr=(void*)GetProcAddress(hComctl32, (LPCSTR)336L);
822             pDPA_Sort=(void*)GetProcAddress(hComctl32, (LPCSTR)338L);
823             pDPA_Search=(void*)GetProcAddress(hComctl32, (LPCSTR)339L);
824             /* user32 */
825             pLookupIconIdFromDirectoryEx=(void*)GetProcAddress(hUser32,"LookupIconIdFromDirectoryEx");
826             pCreateIconFromResourceEx=(void*)GetProcAddress(hUser32,"CreateIconFromResourceEx");
827
828             /* initialize the common controls */
829             if (pDLLInitComctl)
830             {
831               pDLLInitComctl(NULL);
832             }
833
834             SIC_Initialize();
835             SYSTRAY_Init();
836             InitChangeNotifications();
837             SHInitRestricted(NULL, NULL);
838             break;
839
840           case DLL_THREAD_ATTACH:
841             shell32_RefCount++;
842             break;
843
844           case DLL_THREAD_DETACH:
845             shell32_RefCount--;
846             break;
847
848           case DLL_PROCESS_DETACH:
849             shell32_RefCount--;
850
851             if ( !shell32_RefCount )
852             { 
853               shell32_hInstance = 0;
854
855               if (pdesktopfolder) 
856               {
857                 IShellFolder_Release(pdesktopfolder);
858                 pdesktopfolder = NULL;
859               }
860
861               SIC_Destroy();
862               FreeChangeNotifications();
863               
864               /* this one is here to check if AddRef/Release is balanced */
865               if (shell32_ObjCount)
866               {
867                 WARN("leaving with %lu objects left (memory leak)\n", shell32_ObjCount);
868               }
869             }
870
871             TRACE("refcount=%u objcount=%lu \n", shell32_RefCount, shell32_ObjCount);
872             break;
873         }
874         return TRUE;
875 }
876
877 /*************************************************************************
878  * DllInstall         [SHELL32.202]
879  *
880  * PARAMETERS
881  *   
882  *    BOOL bInstall - TRUE for install, FALSE for uninstall
883  *    LPCWSTR pszCmdLine - command line (unused by shell32?)
884  */
885
886 HRESULT WINAPI SHELL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
887 {
888    FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
889
890    return S_OK;         /* indicate success */
891 }