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