Fixes for FreeBSD.
[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 <assert.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <ctype.h>
12 #include "windows.h"
13 #include "winerror.h"
14 #include "file.h"
15 #include "shell.h"
16 #include "heap.h"
17 #include "module.h"
18 #include "neexe.h"
19 #include "resource.h"
20 #include "dlgs.h"
21 #include "win.h"
22 #include "graphics.h"
23 #include "cursoricon.h"
24 #include "interfaces.h"
25 #include "sysmetrics.h"
26 #include "shlobj.h"
27 #include "debug.h"
28 #include "winreg.h"
29 #include "imagelist.h"
30 #include "commctrl.h"
31 #include "authors.h"
32
33 #include "pidl.h"
34 #include "shell32_main.h"
35
36 /*************************************************************************
37  *                              CommandLineToArgvW      [SHELL32.7]
38  */
39 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
40 { LPWSTR  *argv,s,t;
41         int     i;
42   TRACE(shell,"\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         HeapFree( GetProcessHeap(), 0, cmdline );
79         argv[i]=NULL;
80         *numargs=i;
81         return argv;
82 }
83
84 /*************************************************************************
85  *                              Control_RunDLL          [SHELL32.12]
86  *
87  * Wild speculation in the following!
88  *
89  * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
90  */
91
92 void WINAPI Control_RunDLL( HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4 )
93 {
94     FIXME(shell, "(0x%08x, %p, %s, 0x%08lx): stub\n", hwnd, code,
95           debugstr_a(cmd), arg4);
96 }
97
98 /*************************************************************************
99  * Shell_GetImageList [SHELL32.71]
100  *
101  * PARAMETERS
102  *  imglist[1|2] [OUT] pointer which recive imagelist handles
103  *
104  * NOTES
105  *  undocumented
106  *  I don't know, which pointer is which. They may have to be
107  *  exchanged. (jsch)
108  */
109 BOOL32 WINAPI Shell_GetImageList(HIMAGELIST * imglist1,HIMAGELIST * imglist2)
110 {       WARN(shell,"(%p,%p):semi-stub.\n",imglist1,imglist2);
111         if (imglist1)
112         { *imglist1=ShellSmallIconList;
113         }
114         if (imglist2)
115         { *imglist2=ShellBigIconList;
116         }
117
118         return TRUE;
119 }
120
121 HIMAGELIST ShellSmallIconList = 0;
122 HIMAGELIST ShellBigIconList = 0;
123
124 /*************************************************************************
125  *  SHGetFileInfoA              [SHELL32.254]
126  *
127  * FIXME
128  *   
129  */
130
131 DWORD WINAPI SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,
132                               SHFILEINFO32A *psfi, UINT32 sizeofpsfi,
133                               UINT32 flags )
134 {       CHAR szTemp[MAX_PATH];
135         LPPIDLDATA      pData;
136         DWORD ret=0;
137   
138         TRACE(shell,"(%s,0x%lx,%p,0x%x,0x%x)\n",
139               path,dwFileAttributes,psfi,sizeofpsfi,flags);
140
141         /* translate the pidl to a path*/
142         if (flags & SHGFI_PIDL)
143         { SHGetPathFromIDList32A ((LPCITEMIDLIST)path,szTemp);
144           TRACE(shell,"pidl=%p is %s\n",path,szTemp);
145         }
146         else
147         { TRACE(shell,"path=%p\n",path);
148         }
149
150         if (flags & SHGFI_ATTRIBUTES)
151         { if (flags & SHGFI_PIDL)
152           { pData = _ILGetDataPointer((LPCITEMIDLIST)path);
153             psfi->dwAttributes = pData->u.generic.dwSFGAO; /* fixme: no direct access*/
154             ret=TRUE;
155           }
156           else
157           { psfi->dwAttributes=SFGAO_FILESYSTEM;
158             ret=TRUE;
159           }
160           FIXME(shell,"file attributes, stub\n");           
161         }
162
163         if (flags & SHGFI_DISPLAYNAME)
164         { if (flags & SHGFI_PIDL)
165           { strcpy(psfi->szDisplayName,szTemp);
166           }
167           else
168           { strcpy(psfi->szDisplayName,path);
169           }
170           TRACE(shell,"displayname=%s\n", psfi->szDisplayName);   
171           ret=TRUE;
172         }
173   
174         if (flags & SHGFI_TYPENAME)
175         { FIXME(shell,"get the file type, stub\n");
176           strcpy(psfi->szTypeName,"FIXME: Type");
177           ret=TRUE;
178         }
179   
180   if (flags & SHGFI_ICONLOCATION)
181   { FIXME(shell,"location of icon, stub\n");
182     strcpy(psfi->szDisplayName,"");
183     ret=TRUE;
184   }
185
186   if (flags & SHGFI_EXETYPE)
187     FIXME(shell,"type of executable, stub\n");
188
189   if (flags & SHGFI_LINKOVERLAY)
190     FIXME(shell,"set icon to link, stub\n");
191
192   if (flags & SHGFI_OPENICON)
193     FIXME(shell,"set to open icon, stub\n");
194
195   if (flags & SHGFI_SELECTED)
196     FIXME(shell,"set icon to selected, stub\n");
197
198   if (flags & SHGFI_SHELLICONSIZE)
199     FIXME(shell,"set icon to shell size, stub\n");
200
201   if (flags & SHGFI_USEFILEATTRIBUTES)
202     FIXME(shell,"use the dwFileAttributes, stub\n");
203  
204   if (flags & SHGFI_ICON)
205   { FIXME(shell,"icon handle\n");
206     if (flags & SHGFI_SMALLICON)
207      { TRACE(shell,"set to small icon\n"); 
208        psfi->hIcon=pImageList_GetIcon(ShellSmallIconList,32,ILD_NORMAL);
209        ret = (DWORD) ShellSmallIconList;
210      }
211      else
212      { TRACE(shell,"set to big icon\n");
213        psfi->hIcon=pImageList_GetIcon(ShellBigIconList,32,ILD_NORMAL);
214        ret = (DWORD) ShellBigIconList;
215      }      
216   }
217
218   if (flags & SHGFI_SYSICONINDEX)
219   {  FIXME(shell,"get the SYSICONINDEX\n");
220      psfi->iIcon=32;
221      if (flags & SHGFI_SMALLICON)
222      { TRACE(shell,"set to small icon\n"); 
223        ret = (DWORD) ShellSmallIconList;
224      }
225      else        
226      { TRACE(shell,"set to big icon\n");
227        ret = (DWORD) ShellBigIconList;
228      }
229   }
230
231  
232   return ret;
233 }
234
235 /*************************************************************************
236  *  SHGetFileInfo32W            [SHELL32.255]
237  *
238  * FIXME
239  *   
240  */
241
242 DWORD WINAPI SHGetFileInfo32W(LPCWSTR path,DWORD dwFileAttributes,
243                               SHFILEINFO32W *psfi, UINT32 sizeofpsfi,
244                               UINT32 flags )
245 {       FIXME(shell,"(%s,0x%lx,%p,0x%x,0x%x)\n",
246               debugstr_w(path),dwFileAttributes,psfi,sizeofpsfi,flags);
247         return 0;
248 }
249
250 /*************************************************************************
251  *             ExtractIcon32A   (SHELL32.133)
252  */
253 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
254         UINT32 nIconIndex )
255 {   HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
256     TRACE(shell,"\n");
257     if( handle )
258     {
259         HICON16* ptr = (HICON16*)GlobalLock16(handle);
260         HICON16  hIcon = *ptr;
261
262         GlobalFree16(handle);
263         return hIcon;
264     }
265     return 0;
266 }
267
268 /*************************************************************************
269  *             ExtractIcon32W   (SHELL32.180)
270  */
271 HICON32 WINAPI ExtractIcon32W( HINSTANCE32 hInstance, LPCWSTR lpszExeFileName,
272         UINT32 nIconIndex )
273 { LPSTR  exefn;
274   HICON32  ret;
275   TRACE(shell,"\n");
276
277   exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
278   ret = ExtractIcon32A(hInstance,exefn,nIconIndex);
279
280         HeapFree(GetProcessHeap(),0,exefn);
281         return ret;
282 }
283
284 /*************************************************************************
285  *             FindExecutable32A   (SHELL32.184)
286  */
287 HINSTANCE32 WINAPI FindExecutable32A( LPCSTR lpFile, LPCSTR lpDirectory,
288                                       LPSTR lpResult )
289 { HINSTANCE32 retval=31;    /* default - 'No association was found' */
290     char old_dir[1024];
291
292   TRACE(shell, "File %s, Dir %s\n", 
293                  (lpFile != NULL?lpFile:"-"), 
294                  (lpDirectory != NULL?lpDirectory:"-"));
295
296     lpResult[0]='\0'; /* Start off with an empty return string */
297
298     /* trap NULL parameters on entry */
299     if (( lpFile == NULL ) || ( lpResult == NULL ))
300   { /* FIXME - should throw a warning, perhaps! */
301         return 2; /* File not found. Close enough, I guess. */
302     }
303
304     if (lpDirectory)
305   { GetCurrentDirectory32A( sizeof(old_dir), old_dir );
306         SetCurrentDirectory32A( lpDirectory );
307     }
308
309     retval = SHELL_FindExecutable( lpFile, "open", lpResult );
310
311   TRACE(shell, "returning %s\n", lpResult);
312   if (lpDirectory)
313     SetCurrentDirectory32A( old_dir );
314     return retval;
315 }
316
317 typedef struct
318 { LPCSTR  szApp;
319     LPCSTR  szOtherStuff;
320     HICON32 hIcon;
321 } ABOUT_INFO;
322
323 #define         IDC_STATIC_TEXT         100
324 #define         IDC_LISTBOX             99
325 #define         IDC_WINE_TEXT           98
326
327 #define         DROP_FIELD_TOP          (-15)
328 #define         DROP_FIELD_HEIGHT       15
329
330 extern HICON32 hIconTitleFont;
331
332 static BOOL32 __get_dropline( HWND32 hWnd, LPRECT32 lprect )
333 { HWND32 hWndCtl = GetDlgItem32(hWnd, IDC_WINE_TEXT);
334     if( hWndCtl )
335   { GetWindowRect32( hWndCtl, lprect );
336         MapWindowPoints32( 0, hWnd, (LPPOINT32)lprect, 2 );
337         lprect->bottom = (lprect->top += DROP_FIELD_TOP);
338         return TRUE;
339     }
340     return FALSE;
341 }
342
343 /*************************************************************************
344  *                              SHAppBarMessage32       [SHELL32.207]
345  */
346 UINT32 WINAPI SHAppBarMessage32(DWORD msg, PAPPBARDATA data)
347 { FIXME(shell,"(0x%08lx,%p): stub\n", msg, data);
348 #if 0
349   switch (msg)
350   { case ABM_ACTIVATE:
351         case ABM_GETAUTOHIDEBAR:
352         case ABM_GETSTATE:
353         case ABM_GETTASKBARPOS:
354         case ABM_NEW:
355         case ABM_QUERYPOS:
356         case ABM_REMOVE:
357         case ABM_SETAUTOHIDEBAR:
358         case ABM_SETPOS:
359         case ABM_WINDOWPOSCHANGED:
360             ;
361     }
362 #endif
363     return 0;
364 }
365
366 /*************************************************************************
367  * SHBrowseForFolderA [SHELL32.209]
368  *
369  */
370 LPITEMIDLIST WINAPI SHBrowseForFolder32A (LPBROWSEINFO32A lpbi)
371 { FIXME (shell, "(%lx,%s) empty stub!\n", (DWORD)lpbi, lpbi->lpszTitle);
372   return NULL;
373 }
374
375 /*************************************************************************
376  *  SHGetDesktopFolder          [SHELL32.216]
377  * 
378  *  SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
379  *  CLSID_ShellDesktop
380  *  CoCreateInstance(CLSID_Desktop, NULL, CLSCTX_INPROC, IID_IShellFolder, &pshf);
381  *
382  * RETURNS
383  *   the interface to the shell desktop folder.
384  *
385  * FIXME
386  *   the pdesktopfolder has to be released at the end (at dll unloading???)
387  */
388 LPSHELLFOLDER pdesktopfolder=NULL;
389
390 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder)
391 { HRESULT       hres = E_OUTOFMEMORY;
392   LPCLASSFACTORY lpclf;
393         TRACE(shell,"%p->(%p)\n",shellfolder,*shellfolder);
394
395   if (pdesktopfolder)
396         {       hres = NOERROR;
397         }
398         else
399   { lpclf = IClassFactory_Constructor();
400     /* fixme: the buildin IClassFactory_Constructor is at the moment only 
401                 for rclsid=CLSID_ShellDesktop, so we get the right Interface (jsch)*/
402     if(lpclf)
403     { hres = lpclf->lpvtbl->fnCreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
404                   lpclf->lpvtbl->fnRelease(lpclf);
405           }  
406   }
407         
408   if (pdesktopfolder)
409         { *shellfolder = pdesktopfolder;
410     pdesktopfolder->lpvtbl->fnAddRef(pdesktopfolder);
411         }
412   else
413         { *shellfolder=NULL;
414         }       
415
416   TRACE(shell,"-- %p->(%p)\n",shellfolder, *shellfolder);
417         return hres;
418 }
419 /*************************************************************************
420  *                       SHGetPathFromIDList            [SHELL32.221][NT 4.0: SHELL32.219]
421  */
422 BOOL32 WINAPI SHGetPathFromIDList32(LPCITEMIDLIST pidl,LPSTR pszPath)     
423 { TRACE(shell,"(pidl=%p,%p)\n",pidl,pszPath);
424   return SHGetPathFromIDList32A(pidl,pszPath);
425 }
426
427 /*************************************************************************
428  *                       SHGetSpecialFolderLocation     [SHELL32.223]
429  * gets the folder locations from the registry and creates a pidl
430  * creates missing reg keys and directorys
431  * 
432  * PARAMS
433  *   hwndOwner [I]
434  *   nFolder   [I] CSIDL_xxxxx
435  *   ppidl     [O] PIDL of a special folder
436  *
437  * RETURNS
438  *    HResult
439  *
440  * FIXME
441  *   - look for "User Shell Folder" first
442  *
443  */
444 HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl)
445 { LPSHELLFOLDER shellfolder;
446   DWORD pchEaten,tpathlen=MAX_PATH,type,dwdisp,res;
447   CHAR pszTemp[256],buffer[256],tpath[MAX_PATH],npath[MAX_PATH];
448   LPWSTR lpszDisplayName = (LPWSTR)&pszTemp[0];
449   HKEY key;
450
451         enum 
452         { FT_UNKNOWN= 0x00000000,
453           FT_DIR=     0x00000001, 
454           FT_DESKTOP= 0x00000002,
455           FT_SPECIAL= 0x00000003
456         } tFolder; 
457
458         TRACE(shell,"(%04x,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
459
460         strcpy(buffer,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\");
461
462         res=RegCreateKeyEx32A(HKEY_CURRENT_USER,buffer,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&key,&dwdisp);
463         if (res)
464         { ERR(shell,"Could not create key %s %08lx \n",buffer,res);
465           return E_OUTOFMEMORY;
466         }
467
468         tFolder=FT_DIR; 
469         switch (nFolder)
470         { case CSIDL_BITBUCKET:
471             strcpy (buffer,"xxx");                      /*not in the registry*/
472             TRACE (shell,"looking for Recycler\n");
473             tFolder=FT_UNKNOWN;
474             break;
475           case CSIDL_CONTROLS:
476             strcpy (buffer,"xxx");                      /*virtual folder*/
477             TRACE (shell,"looking for Control\n");
478             tFolder=FT_UNKNOWN;
479             break;
480           case CSIDL_DESKTOP:
481             strcpy (buffer,"xxx");                      /*virtual folder*/
482             TRACE (shell,"looking for Desktop\n");
483             tFolder=FT_DESKTOP;                 
484             break;
485           case CSIDL_DESKTOPDIRECTORY:
486             strcpy (buffer,"Desktop");
487             break;
488           case CSIDL_DRIVES:
489             strcpy (buffer,"xxx");                      /*virtual folder*/
490             TRACE (shell,"looking for Drives\n");
491             tFolder=FT_SPECIAL;
492             break;
493           case CSIDL_FONTS:
494             strcpy (buffer,"Fonts");                    
495             break;
496           case CSIDL_NETHOOD:
497             strcpy (buffer,"NetHood");                  
498             break;
499           case CSIDL_NETWORK:
500             strcpy (buffer,"xxx");                              /*virtual folder*/
501             TRACE (shell,"looking for Network\n");
502             tFolder=FT_UNKNOWN;
503             break;
504           case CSIDL_PERSONAL:
505             strcpy (buffer,"Personal");                 
506             break;
507           case CSIDL_FAVORITES:
508             strcpy (buffer,"Favorites");                        
509             break;
510           case CSIDL_PRINTERS:
511             strcpy (buffer,"PrintHood");
512             break;
513           case CSIDL_PROGRAMS:
514             strcpy (buffer,"Programs");                 
515             break;
516           case CSIDL_RECENT:
517             strcpy (buffer,"Recent");
518             break;
519           case CSIDL_SENDTO:
520             strcpy (buffer,"SendTo");
521             break;
522           case CSIDL_STARTMENU:
523             strcpy (buffer,"Start Menu");
524             break;
525           case CSIDL_STARTUP:
526             strcpy (buffer,"Startup");                  
527             break;
528           case CSIDL_TEMPLATES:
529             strcpy (buffer,"Templates");                        
530             break;
531           default:
532             ERR (shell,"unknown CSIDL\n");
533             tFolder=FT_UNKNOWN;                 
534             break;
535         }
536
537         TRACE(shell,"Key=%s\n",buffer);
538
539         type=REG_SZ;
540
541         switch (tFolder)
542         { case FT_DIR:
543             /* Directory: get the value from the registry, if its not there 
544                         create it and the directory*/
545             if (RegQueryValueEx32A(key,buffer,NULL,&type,tpath,&tpathlen))
546             { GetWindowsDirectory32A(npath,MAX_PATH);
547               PathAddBackslash(npath);
548               switch (nFolder)
549               { case CSIDL_DESKTOPDIRECTORY:
550                   strcat (npath,"Desktop");
551                   break;
552                 case CSIDL_FONTS:
553                   strcat (npath,"Fonts");                       
554                   break;
555                 case CSIDL_NETHOOD:
556                   strcat (npath,"NetHood");                     
557                   break;
558                 case CSIDL_PERSONAL:
559                   strcpy (npath,"C:\\Personal");                        
560                   break;
561                 case CSIDL_FAVORITES:
562                   strcat (npath,"Favorites");                   
563                   break;
564                 case CSIDL_PRINTERS:
565                   strcat (npath,"PrintHood");                   
566                   break;
567                 case CSIDL_PROGRAMS:
568                   strcat (npath,"Start Menu");                  
569                   CreateDirectory32A(npath,NULL);
570                   strcat (npath,"\\Programs");                  
571                   break;
572                 case CSIDL_RECENT:
573                   strcat (npath,"Recent");
574                   break;
575                 case CSIDL_SENDTO:
576                   strcat (npath,"SendTo");
577                   break;
578                 case CSIDL_STARTMENU:
579                   strcat (npath,"Start Menu");
580                   break;
581                 case CSIDL_STARTUP:
582                   strcat (npath,"Start Menu");                  
583                   CreateDirectory32A(npath,NULL);
584                   strcat (npath,"\\Startup");                   
585                   break;
586                 case CSIDL_TEMPLATES:
587                   strcat (npath,"Templates");                   
588                   break;
589                 default:
590                   RegCloseKey(key);
591                   return E_OUTOFMEMORY;
592               }
593               if (RegSetValueEx32A(key,buffer,0,REG_SZ,npath,sizeof(npath)+1))
594               { ERR(shell,"could not create value %s\n",buffer);
595                 RegCloseKey(key);
596                 return E_OUTOFMEMORY;
597               }
598               TRACE(shell,"value %s=%s created\n",buffer,npath);
599               CreateDirectory32A(npath,NULL);
600               strcpy(tpath,npath);
601             }
602             break;
603           case FT_DESKTOP:
604             strcpy (tpath,"Desktop");
605             break;
606           case FT_SPECIAL:
607             if (nFolder==CSIDL_DRIVES)
608             strcpy (tpath,"My Computer");
609             break;
610           default:
611             RegCloseKey(key);
612             return E_OUTOFMEMORY;
613         }
614
615         RegCloseKey(key);
616
617         TRACE(shell,"Value=%s\n",tpath);
618         LocalToWideChar32(lpszDisplayName, tpath, 256);
619   
620         if (SHGetDesktopFolder(&shellfolder)==S_OK)
621         { shellfolder->lpvtbl->fnParseDisplayName(shellfolder,hwndOwner, NULL,lpszDisplayName,&pchEaten,ppidl,NULL);
622           shellfolder->lpvtbl->fnRelease(shellfolder);
623         }
624
625         TRACE(shell, "-- (new pidl %p)\n",*ppidl);
626         return NOERROR;
627 }
628 /*************************************************************************
629  * SHHelpShortcuts_RunDLL [SHELL32.224]
630  *
631  */
632 DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
633 { FIXME (exec, "(%lx, %lx, %lx, %lx) empty stub!\n",
634         dwArg1, dwArg2, dwArg3, dwArg4);
635
636   return 0;
637 }
638
639 /*************************************************************************
640  * SHLoadInProc [SHELL32.225]
641  *
642  */
643
644 DWORD WINAPI SHLoadInProc (DWORD dwArg1)
645 { FIXME (shell, "(%lx) empty stub!\n", dwArg1);
646     return 0;
647 }
648
649 /*************************************************************************
650  *             ShellExecute32A   (SHELL32.245)
651  */
652 HINSTANCE32 WINAPI ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation,
653                                     LPCSTR lpFile, LPCSTR lpParameters,
654                                     LPCSTR lpDirectory, INT32 iShowCmd )
655 {   TRACE(shell,"\n");
656     return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
657                            lpDirectory, iShowCmd );
658 }
659
660
661 /*************************************************************************
662  *             AboutDlgProc32  (not an exported API function)
663  */
664 LRESULT WINAPI AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
665                                LPARAM lParam )
666 {   HWND32 hWndCtl;
667     char Template[512], AppTitle[512];
668
669     TRACE(shell,"\n");
670
671     switch(msg)
672     { case WM_INITDIALOG:
673       { ABOUT_INFO *info = (ABOUT_INFO *)lParam;
674             if (info)
675         { const char* const *pstr = SHELL_People;
676                 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON32,info->hIcon, 0);
677                 GetWindowText32A( hWnd, Template, sizeof(Template) );
678                 sprintf( AppTitle, Template, info->szApp );
679                 SetWindowText32A( hWnd, AppTitle );
680                 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT),
681                                   info->szOtherStuff );
682                 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
683                 SendMessage32A( hWndCtl, WM_SETREDRAW, 0, 0 );
684                 SendMessage32A( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
685                 while (*pstr)
686           { SendMessage32A( hWndCtl, LB_ADDSTRING32, (WPARAM32)-1, (LPARAM)*pstr );
687                     pstr++;
688                 }
689                 SendMessage32A( hWndCtl, WM_SETREDRAW, 1, 0 );
690             }
691         }
692         return 1;
693
694     case WM_PAINT:
695       { RECT32 rect;
696             PAINTSTRUCT32 ps;
697             HDC32 hDC = BeginPaint32( hWnd, &ps );
698
699             if( __get_dropline( hWnd, &rect ) )
700                 GRAPH_DrawLines( hDC, (LPPOINT32)&rect, 1, GetStockObject32( BLACK_PEN ) );
701             EndPaint32( hWnd, &ps );
702         }
703         break;
704
705     case WM_LBTRACKPOINT:
706         hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
707         if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
708       { if( DragDetect32( hWndCtl, *((LPPOINT32)&lParam) ) )
709         { INT32 idx = SendMessage32A( hWndCtl, LB_GETCURSEL32, 0, 0 );
710                 if( idx != -1 )
711           { INT32 length = SendMessage32A( hWndCtl, LB_GETTEXTLEN32, (WPARAM32)idx, 0 );
712                     HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
713                     char* pstr = (char*)GlobalLock16( hMemObj );
714
715                     if( pstr )
716             { HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE16(OCR_DRAGOBJECT) );
717                         SendMessage32A( hWndCtl, LB_GETTEXT32, (WPARAM32)idx, (LPARAM)pstr );
718                         SendMessage32A( hWndCtl, LB_DELETESTRING32, (WPARAM32)idx, 0 );
719                         UpdateWindow32( hWndCtl );
720                         if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
721                             SendMessage32A( hWndCtl, LB_ADDSTRING32, (WPARAM32)-1, (LPARAM)pstr );
722                     }
723             if( hMemObj )
724               GlobalFree16( hMemObj );
725                 }
726             }
727         }
728         break;
729
730     case WM_QUERYDROPOBJECT:
731         if( wParam == 0 )
732       { LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
733             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
734         { RECT32 rect;
735                 if( __get_dropline( hWnd, &rect ) )
736           { POINT32 pt = { lpDragInfo->pt.x, lpDragInfo->pt.y };
737                     rect.bottom += DROP_FIELD_HEIGHT;
738                     if( PtInRect32( &rect, pt ) )
739             { SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
740                         return TRUE;
741                     }
742                 }
743             }
744         }
745         break;
746
747     case WM_DROPOBJECT:
748         if( wParam == hWnd )
749       { LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
750             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
751         { char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
752                 if( pstr )
753           { static char __appendix_str[] = " with";
754
755                     hWndCtl = GetDlgItem32( hWnd, IDC_WINE_TEXT );
756                     SendMessage32A( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
757                     if( !lstrncmp32A( Template, "WINE", 4 ) )
758                         SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT), Template );
759                     else
760           { char* pch = Template + strlen(Template) - strlen(__appendix_str);
761                         *pch = '\0';
762                         SendMessage32A( GetDlgItem32(hWnd, IDC_LISTBOX), LB_ADDSTRING32, 
763                                         (WPARAM32)-1, (LPARAM)Template );
764                     }
765
766                     lstrcpy32A( Template, pstr );
767                     lstrcat32A( Template, __appendix_str );
768                     SetWindowText32A( hWndCtl, Template );
769                     SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
770                     return TRUE;
771                 }
772             }
773         }
774         break;
775
776     case WM_COMMAND:
777         if (wParam == IDOK)
778     {  EndDialog32(hWnd, TRUE);
779             return TRUE;
780         }
781         break;
782     }
783     return 0;
784 }
785
786
787 /*************************************************************************
788  *             ShellAbout32A   (SHELL32.243)
789  */
790 BOOL32 WINAPI ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
791                              HICON32 hIcon )
792 {   ABOUT_INFO info;
793     TRACE(shell,"\n");
794     info.szApp        = szApp;
795     info.szOtherStuff = szOtherStuff;
796     info.hIcon        = hIcon;
797     if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
798     return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
799                          SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
800                                       hWnd, AboutDlgProc32, (LPARAM)&info );
801 }
802
803
804 /*************************************************************************
805  *             ShellAbout32W   (SHELL32.244)
806  */
807 BOOL32 WINAPI ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
808                              HICON32 hIcon )
809 {   BOOL32 ret;
810     ABOUT_INFO info;
811
812     TRACE(shell,"\n");
813     
814     info.szApp        = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
815     info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
816     info.hIcon        = hIcon;
817     if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
818     ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
819                          SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
820                                       hWnd, AboutDlgProc32, (LPARAM)&info );
821     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
822     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
823     return ret;
824 }
825
826 /*************************************************************************
827  *                              Shell_NotifyIcon        [SHELL32.296]
828  *      FIXME
829  *      This function is supposed to deal with the systray.
830  *      Any ideas on how this is to be implimented?
831  */
832 BOOL32 WINAPI Shell_NotifyIcon( DWORD dwMessage, PNOTIFYICONDATA pnid )
833 {   TRACE(shell,"\n");
834     return FALSE;
835 }
836
837 /*************************************************************************
838  *                              Shell_NotifyIcon        [SHELL32.297]
839  *      FIXME
840  *      This function is supposed to deal with the systray.
841  *      Any ideas on how this is to be implimented?
842  */
843 BOOL32 WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATA pnid )
844 {   TRACE(shell,"\n");
845     return FALSE;
846 }
847
848 /*************************************************************************
849  * FreeIconList
850  */
851 void WINAPI FreeIconList( DWORD dw )
852 { FIXME(shell, "(%lx): stub\n",dw);
853 }
854
855 /*************************************************************************
856  * SHGetPathFromIDList32A        [SHELL32.261][NT 4.0: SHELL32.220]
857  *
858  * PARAMETERS
859  *  pidl,   [IN] pidl 
860  *  pszPath [OUT] path
861  *
862  * RETURNS 
863  *  path from a passed PIDL.
864  *
865  * NOTES
866  *     exported by name
867  *
868  * FIXME
869  *  fnGetDisplayNameOf can return different types of OLEString
870  */
871 DWORD WINAPI SHGetPathFromIDList32A (LPCITEMIDLIST pidl,LPSTR pszPath)
872 {       STRRET lpName;
873         LPSHELLFOLDER shellfolder;
874   CHAR  buffer[MAX_PATH],tpath[MAX_PATH];
875   DWORD type,tpathlen=MAX_PATH,dwdisp;
876   HKEY  key;
877
878         TRACE(shell,"(pidl=%p,%p)\n",pidl,pszPath);
879
880   if (!pidl)
881   {  strcpy(buffer,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\");
882
883      if (RegCreateKeyEx32A(HKEY_CURRENT_USER,buffer,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&key,&dwdisp))
884      { return E_OUTOFMEMORY;
885      }
886      type=REG_SZ;    
887      strcpy (buffer,"Desktop");                                 /*registry name*/
888      if ( RegQueryValueEx32A(key,buffer,NULL,&type,tpath,&tpathlen))
889      { GetWindowsDirectory32A(tpath,MAX_PATH);
890        PathAddBackslash(tpath);
891        strcat (tpath,"Desktop");                                /*folder name*/
892        RegSetValueEx32A(key,buffer,0,REG_SZ,tpath,tpathlen);
893        CreateDirectory32A(tpath,NULL);
894      }
895      RegCloseKey(key);
896      strcpy(pszPath,tpath);
897   }
898   else
899   { if (SHGetDesktopFolder(&shellfolder)==S_OK)
900         { shellfolder->lpvtbl->fnGetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&lpName);
901           shellfolder->lpvtbl->fnRelease(shellfolder);
902         }
903   /*WideCharToLocal32(pszPath, lpName.u.pOleStr, MAX_PATH);*/
904         strcpy(pszPath,lpName.u.cStr);
905         /* fixme free the olestring*/
906   }
907         TRACE(shell,"-- (%s)\n",pszPath);
908         return NOERROR;
909 }
910 /*************************************************************************
911  * SHGetPathFromIDList32W [SHELL32.262]
912  */
913 DWORD WINAPI SHGetPathFromIDList32W (LPCITEMIDLIST pidl,LPWSTR pszPath)
914 {       char sTemp[MAX_PATH];
915
916         FIXME (shell,"(pidl=%p)\n", pidl);
917
918         SHGetPathFromIDList32A (pidl, sTemp);
919         lstrcpyAtoW(pszPath, sTemp);
920         TRACE(shell,"-- (%s)\n",debugstr_w(pszPath));
921         return NOERROR;
922 }
923
924
925 void (CALLBACK* pDLLInitComctl)();
926 INT32 (CALLBACK* pImageList_AddIcon) (HIMAGELIST himl, HICON32 hIcon);
927 INT32(CALLBACK* pImageList_ReplaceIcon) (HIMAGELIST, INT32, HICON32);
928 HIMAGELIST (CALLBACK * pImageList_Create) (INT32,INT32,UINT32,INT32,INT32);
929 HICON32 (CALLBACK * pImageList_GetIcon) (HIMAGELIST, INT32, UINT32);
930
931 /*************************************************************************
932  * SHELL32 LibMain
933  *
934  * FIXME
935  *  at the moment the icons are extracted from shell32.dll
936  *  free the imagelists
937  */
938 HINSTANCE32 shell32_hInstance; 
939
940 BOOL32 WINAPI Shell32LibMain(HINSTANCE32 hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
941 { HICON32 htmpIcon;
942   UINT32 iiconindex;
943   UINT32 index;
944   CHAR   szShellPath[MAX_PATH];
945   HINSTANCE32 hComctl32;
946   
947
948   TRACE(shell,"0x%x 0x%lx %p\n", hinstDLL, fdwReason, lpvReserved);
949
950   shell32_hInstance = hinstDLL;
951   
952   GetWindowsDirectory32A(szShellPath,MAX_PATH);
953   PathAddBackslash(szShellPath);
954   strcat(szShellPath,"system\\shell32.dll");
955        
956   if (fdwReason==DLL_PROCESS_ATTACH)
957   { hComctl32 = LoadLibrary32A("COMCTL32.DLL"); 
958     if (hComctl32)
959     { pDLLInitComctl=GetProcAddress32(hComctl32,"InitCommonControlsEx");
960       if (pDLLInitComctl)
961       { pDLLInitComctl();
962       }
963       pImageList_Create=GetProcAddress32(hComctl32,"ImageList_Create");
964       pImageList_AddIcon=GetProcAddress32(hComctl32,"ImageList_AddIcon");
965       pImageList_ReplaceIcon=GetProcAddress32(hComctl32,"ImageList_ReplaceIcon");
966       pImageList_GetIcon=GetProcAddress32(hComctl32,"ImageList_GetIcon");
967       FreeLibrary32(hComctl32);
968     }
969     else
970     { /* panic, imediately exit wine*/
971       ERR(shell,"P A N I C error getting functionpointers\n");
972       exit (1);
973     }
974     if ( ! ShellSmallIconList )
975     { if ( (ShellSmallIconList = pImageList_Create(sysMetrics[SM_CXSMICON],sysMetrics[SM_CYSMICON],ILC_COLORDDB | ILC_MASK,0,0x20)) )
976       { for (index=0;index < 40; index++)
977         { if ( ! ( htmpIcon = ExtractIcon32A(hinstDLL, szShellPath, index))
978           || ( -1 == (iiconindex = pImageList_AddIcon (ShellSmallIconList, htmpIcon))) )
979           { ERR(shell,"could not initialize iconlist (is shell32.dll in the system directory?)\n");
980             break;
981           }
982         }
983       }
984     }
985     if ( ! ShellBigIconList )
986     { if ( (ShellBigIconList = pImageList_Create(SYSMETRICS_CXSMICON, SYSMETRICS_CYSMICON,ILC_COLORDDB | ILC_MASK,0,0x20)) )
987       { for (index=0;index < 40; index++)
988         { if ( ! (htmpIcon = ExtractIcon32A( hinstDLL, szShellPath, index)) 
989            || (-1 == (iiconindex = pImageList_AddIcon (ShellBigIconList, htmpIcon))) )
990           { ERR(shell,"could not initialize iconlist (is shell32.dll in the system directory?)\n");
991             break;
992           }
993         }
994       }
995     }
996     TRACE(shell,"hIconSmall=%p hIconBig=%p\n",ShellSmallIconList, ShellBigIconList);
997   }
998   return TRUE;
999 }