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