New functions to access attributes in HCR.
[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 #include "shlobj.h"
25 #include "shell32_main.h"
26
27 #include "shlguid.h"
28
29 DECLARE_DEBUG_CHANNEL(exec)
30 DECLARE_DEBUG_CHANNEL(shell)
31
32 /*************************************************************************
33  * CommandLineToArgvW                   [SHELL32.7]
34  */
35 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
36 {       LPWSTR  *argv,s,t;
37         int     i;
38         TRACE_(shell)("\n");
39
40         /* to get writeable copy */
41         cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
42         s=cmdline;i=0;
43         while (*s)
44         { /* space */
45           if (*s==0x0020) 
46           { i++;
47             s++;
48             while (*s && *s==0x0020)
49               s++;
50             continue;
51           }
52           s++;
53         }
54         argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
55         s=t=cmdline;
56         i=0;
57         while (*s)
58         { if (*s==0x0020)
59           { *s=0;
60             argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
61             *s=0x0020;
62             while (*s && *s==0x0020)
63               s++;
64             if (*s)
65               t=s+1;
66             else
67               t=s;
68             continue;
69           }
70           s++;
71         }
72         if (*t)
73           argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
74
75         HeapFree( GetProcessHeap(), 0, cmdline );
76         argv[i]=NULL;
77         *numargs=i;
78         return argv;
79 }
80
81 /*************************************************************************
82  * Control_RunDLL                       [SHELL32.12]
83  *
84  * Wild speculation in the following!
85  *
86  * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
87  */
88
89 void WINAPI Control_RunDLL( HWND hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4 )
90 {
91     FIXME_(shell)("(0x%08x, %p, %s, 0x%08lx): stub\n", hwnd, code,
92           debugstr_a(cmd), arg4);
93 }
94
95 /*************************************************************************
96  * SHGetFileInfoA                       [SHELL32.254]
97  */
98
99 DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
100                               SHFILEINFOA *psfi, UINT sizeofpsfi,
101                               UINT flags )
102 {       CHAR            szTemp[MAX_PATH];
103         LPPIDLDATA      pData;
104         LPITEMIDLIST    pPidlTemp = NULL;
105         DWORD           ret=0, dwfa = dwFileAttributes;
106
107         TRACE_(shell)("(%s,0x%lx,%p,0x%x,0x%x)\n",
108               path,dwFileAttributes,psfi,sizeofpsfi,flags);
109
110         /* translate the pidl to a path*/
111         if (flags & SHGFI_PIDL)
112         { pPidlTemp = (LPCITEMIDLIST)path;
113           SHGetPathFromIDListA (pPidlTemp, szTemp);
114           TRACE_(shell)("pidl=%p is %s\n", path, szTemp);
115         }
116         else
117         { strcpy(szTemp,path);
118           TRACE_(shell)("path=%s\n", szTemp);
119         }
120
121         if (flags & SHGFI_ATTRIBUTES)
122         { if (flags & SHGFI_PIDL)
123           {
124             /*
125              * We have to test for the desktop folder first because ILGetDataPointer returns
126              * NULL on the desktop folder.
127              */
128             if (_ILIsDesktop((LPCITEMIDLIST)path))
129             { psfi->dwAttributes = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANLINK;
130               ret = TRUE;
131             }
132             else
133             { pData = _ILGetDataPointer((LPCITEMIDLIST)path);
134                 
135               switch (pData->type)
136               { case PT_DESKTOP:
137                   psfi->dwAttributes = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANLINK;
138                 case PT_MYCOMP:
139                   psfi->dwAttributes = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
140                      SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANRENAME | SFGAO_CANLINK ;
141                 case PT_SPECIAL:
142                   psfi->dwAttributes = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_CAPABILITYMASK;
143                 case PT_DRIVE:
144                   psfi->dwAttributes = SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM  | SFGAO_FOLDER | SFGAO_FILESYSANCESTOR |
145                     SFGAO_DROPTARGET | SFGAO_HASPROPSHEET | SFGAO_CANLINK;
146                 case PT_FOLDER:
147                   psfi->dwAttributes = SFGAO_HASSUBFOLDER | SFGAO_FILESYSTEM | SFGAO_FOLDER | SFGAO_CAPABILITYMASK;
148                 case PT_VALUE:
149                   psfi->dwAttributes = SFGAO_FILESYSTEM | SFGAO_CAPABILITYMASK;
150               }
151               ret=TRUE;
152             }
153           }
154           else
155           { if (! (flags & SHGFI_USEFILEATTRIBUTES))
156               dwfa = GetFileAttributesA (szTemp);
157
158             psfi->dwAttributes = SFGAO_FILESYSTEM;
159             if (dwfa == FILE_ATTRIBUTE_DIRECTORY) 
160               psfi->dwAttributes |= SFGAO_FOLDER | SFGAO_HASSUBFOLDER;
161             ret=TRUE;
162           }
163           WARN_(shell)("file attributes, semi-stub\n");
164         }
165
166         if (flags & SHGFI_DISPLAYNAME)
167         { if (flags & SHGFI_PIDL)
168           { strcpy(psfi->szDisplayName,szTemp);
169           }
170           else
171           { strcpy(psfi->szDisplayName,path);
172           }
173           TRACE_(shell)("displayname=%s\n", psfi->szDisplayName);
174           ret=TRUE;
175         }
176
177         if (flags & SHGFI_TYPENAME)
178         { FIXME_(shell)("get the file type, stub\n");
179           strcpy(psfi->szTypeName,"FIXME: Type");
180           ret=TRUE;
181         }
182
183         if (flags & SHGFI_ICONLOCATION)
184         { FIXME_(shell)("location of icon, stub\n");
185           strcpy(psfi->szDisplayName,"");
186           ret=TRUE;
187         }
188
189         if (flags & SHGFI_EXETYPE)
190           FIXME_(shell)("type of executable, stub\n");
191
192         if (flags & SHGFI_LINKOVERLAY)
193           FIXME_(shell)("set icon to link, stub\n");
194
195         if (flags & SHGFI_OPENICON)
196           FIXME_(shell)("set to open icon, stub\n");
197
198         if (flags & SHGFI_SELECTED)
199           FIXME_(shell)("set icon to selected, stub\n");
200
201         if (flags & SHGFI_SHELLICONSIZE)
202           FIXME_(shell)("set icon to shell size, stub\n");
203
204         if (flags & SHGFI_USEFILEATTRIBUTES)
205           FIXME_(shell)("use the dwFileAttributes, stub\n");
206
207         if (flags & (SHGFI_UNKNOWN1 | SHGFI_UNKNOWN2 | SHGFI_UNKNOWN3))
208           FIXME_(shell)("unknown attribute!\n");
209         
210         if (flags & SHGFI_ICON)
211         { FIXME_(shell)("icon handle\n");
212           if (flags & SHGFI_SMALLICON)
213           { TRACE_(shell)("set to small icon\n"); 
214             psfi->hIcon=pImageList_GetIcon(ShellSmallIconList,32,ILD_NORMAL);
215             ret = (DWORD) ShellSmallIconList;
216           }
217           else
218           { TRACE_(shell)("set to big icon\n");
219             psfi->hIcon=pImageList_GetIcon(ShellBigIconList,32,ILD_NORMAL);
220             ret = (DWORD) ShellBigIconList;
221           }      
222         }
223
224         if (flags & SHGFI_SYSICONINDEX)
225         { IShellFolder * sf;
226           if (!pPidlTemp)
227           { pPidlTemp = ILCreateFromPathA (szTemp);
228           }
229           if (SUCCEEDED (SHGetDesktopFolder (&sf)))
230           { psfi->iIcon = SHMapPIDLToSystemImageListIndex (sf, pPidlTemp, 0);
231             IShellFolder_Release(sf);
232           }
233           TRACE_(shell)("-- SYSICONINDEX %i\n", psfi->iIcon);
234
235           if (flags & SHGFI_SMALLICON)
236           { TRACE_(shell)("set to small icon\n"); 
237             ret = (DWORD) ShellSmallIconList;
238           }
239           else        
240           { TRACE_(shell)("set to big icon\n");
241             ret = (DWORD) ShellBigIconList;
242           }
243         }
244
245         return ret;
246 }
247
248 /*************************************************************************
249  * SHGetFileInfoW                       [SHELL32.255]
250  */
251
252 DWORD WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
253                               SHFILEINFOW *psfi, UINT sizeofpsfi,
254                               UINT flags )
255 {       FIXME_(shell)("(%s,0x%lx,%p,0x%x,0x%x)\n",
256               debugstr_w(path),dwFileAttributes,psfi,sizeofpsfi,flags);
257         return 0;
258 }
259
260 /*************************************************************************
261  * ExtractIconA                         [SHELL32.133]
262  */
263 HICON WINAPI ExtractIconA( HINSTANCE hInstance, LPCSTR lpszExeFileName,
264         UINT nIconIndex )
265 {   HGLOBAL16 handle = InternalExtractIcon16(hInstance,lpszExeFileName,nIconIndex, 1);
266     TRACE_(shell)("\n");
267     if( handle )
268     {
269         HICON16* ptr = (HICON16*)GlobalLock16(handle);
270         HICON16  hIcon = *ptr;
271
272         GlobalFree16(handle);
273         return hIcon;
274     }
275     return 0;
276 }
277
278 /*************************************************************************
279  * ExtractIconW                         [SHELL32.180]
280  */
281 HICON WINAPI ExtractIconW( HINSTANCE hInstance, LPCWSTR lpszExeFileName,
282         UINT nIconIndex )
283 { LPSTR  exefn;
284   HICON  ret;
285   TRACE_(shell)("\n");
286
287   exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
288   ret = ExtractIconA(hInstance,exefn,nIconIndex);
289
290         HeapFree(GetProcessHeap(),0,exefn);
291         return ret;
292 }
293
294 /*************************************************************************
295  * FindExecutableA                      [SHELL32.184]
296  */
297 HINSTANCE WINAPI FindExecutableA( LPCSTR lpFile, LPCSTR lpDirectory,
298                                       LPSTR lpResult )
299 { HINSTANCE retval=31;    /* default - 'No association was found' */
300     char old_dir[1024];
301
302   TRACE_(shell)("File %s, Dir %s\n", 
303                  (lpFile != NULL?lpFile:"-"), 
304                  (lpDirectory != NULL?lpDirectory:"-"));
305
306     lpResult[0]='\0'; /* Start off with an empty return string */
307
308     /* trap NULL parameters on entry */
309     if (( lpFile == NULL ) || ( lpResult == NULL ))
310   { /* FIXME - should throw a warning, perhaps! */
311         return 2; /* File not found. Close enough, I guess. */
312     }
313
314     if (lpDirectory)
315   { GetCurrentDirectoryA( sizeof(old_dir), old_dir );
316         SetCurrentDirectoryA( lpDirectory );
317     }
318
319     retval = SHELL_FindExecutable( lpFile, "open", lpResult );
320
321   TRACE_(shell)("returning %s\n", lpResult);
322   if (lpDirectory)
323     SetCurrentDirectoryA( old_dir );
324     return retval;
325 }
326
327 /*************************************************************************
328  * FindExecutableW                      [SHELL32.219]
329  */
330 HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory,
331                                      LPWSTR lpResult)
332 {
333   FIXME_(shell)("(%p,%p,%p): stub\n", lpFile, lpDirectory, lpResult);
334   return 31;    /* default - 'No association was found' */
335 }
336
337 typedef struct
338 { LPCSTR  szApp;
339     LPCSTR  szOtherStuff;
340     HICON hIcon;
341 } ABOUT_INFO;
342
343 #define         IDC_STATIC_TEXT         100
344 #define         IDC_LISTBOX             99
345 #define         IDC_WINE_TEXT           98
346
347 #define         DROP_FIELD_TOP          (-15)
348 #define         DROP_FIELD_HEIGHT       15
349
350 extern HICON hIconTitleFont;
351
352 static BOOL __get_dropline( HWND hWnd, LPRECT lprect )
353 { HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT);
354     if( hWndCtl )
355   { GetWindowRect( hWndCtl, lprect );
356         MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 );
357         lprect->bottom = (lprect->top += DROP_FIELD_TOP);
358         return TRUE;
359     }
360     return FALSE;
361 }
362
363 /*************************************************************************
364  * SHAppBarMessage32                    [SHELL32.207]
365  */
366 UINT WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data)
367 {
368         FIXME_(shell)("(0x%08lx,%p hwnd=0x%08x): stub\n", msg, data, data->hWnd);
369
370         switch (msg)
371         { case ABM_GETSTATE:
372                 return ABS_ALWAYSONTOP | ABS_AUTOHIDE;
373           case ABM_GETTASKBARPOS:
374                 /* fake a taskbar on the bottom of the desktop */
375                 { RECT rec;
376                   GetWindowRect(GetDesktopWindow(), &rec);
377                   rec.left = 0;
378                   rec.top = rec.bottom - 2;
379                 }
380                 return TRUE;
381           case ABM_ACTIVATE:
382           case ABM_GETAUTOHIDEBAR:
383           case ABM_NEW:
384           case ABM_QUERYPOS:
385           case ABM_REMOVE:
386           case ABM_SETAUTOHIDEBAR:
387           case ABM_SETPOS:
388           case ABM_WINDOWPOSCHANGED:
389                 return FALSE;
390         }
391         return 0;
392 }
393
394
395 /*************************************************************************
396  * SHGetDesktopFolder                   [SHELL32.216]
397  * 
398  *  SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
399  *  CLSID_ShellDesktop
400  *  CoCreateInstance(CLSID_Desktop, NULL, CLSCTX_INPROC, IID_IShellFolder, &pshf);
401  *
402  * RETURNS
403  *   the interface to the shell desktop folder.
404  *
405  * FIXME
406  *   the pdesktopfolder has to be released at the end (at dll unloading???)
407  */
408 LPSHELLFOLDER pdesktopfolder=NULL;
409
410 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder)
411 {       HRESULT hres = E_OUTOFMEMORY;
412         LPCLASSFACTORY lpclf;
413         TRACE_(shell)("%p->(%p)\n",shellfolder,*shellfolder);
414
415         if (pdesktopfolder) 
416         { hres = NOERROR;
417         }
418         else 
419         { lpclf = IClassFactory_Constructor(&CLSID_ShellDesktop);
420           if(lpclf) 
421           { hres = IClassFactory_CreateInstance(lpclf,NULL,(REFIID)&IID_IShellFolder, (void*)&pdesktopfolder);
422             IClassFactory_Release(lpclf);
423           }  
424         }
425         
426         if (pdesktopfolder) 
427         { *shellfolder = pdesktopfolder;
428           IShellFolder_AddRef(pdesktopfolder);
429         } 
430         else 
431         { *shellfolder=NULL;
432         }
433
434         TRACE_(shell)("-- %p->(%p)\n",shellfolder, *shellfolder);
435         return hres;
436 }
437
438 /*************************************************************************
439  * SHGetSpecialFolderLocation           [SHELL32.223]
440  *
441  * gets the folder locations from the registry and creates a pidl
442  * creates missing reg keys and directorys
443  * 
444  * PARAMS
445  *   hwndOwner [I]
446  *   nFolder   [I] CSIDL_xxxxx
447  *   ppidl     [O] PIDL of a special folder
448  *
449  * RETURNS
450  *    HResult
451  *
452  * FIXME
453  *   - look for "User Shell Folder" first
454  *
455  */
456 HRESULT WINAPI SHGetSpecialFolderLocation(HWND hwndOwner, INT nFolder, LPITEMIDLIST * ppidl)
457 {       LPSHELLFOLDER shellfolder;
458         DWORD   pchEaten, tpathlen=MAX_PATH, type, dwdisp, res, dwLastError;
459         CHAR    pszTemp[256], buffer[256], tpath[MAX_PATH], npath[MAX_PATH];
460         LPWSTR  lpszDisplayName = (LPWSTR)&pszTemp[0];
461         HKEY    key;
462
463         enum 
464         { FT_UNKNOWN= 0x00000000,
465           FT_DIR=     0x00000001, 
466           FT_DESKTOP= 0x00000002,
467           FT_SPECIAL= 0x00000003
468         } tFolder; 
469
470         TRACE_(shell)("(%04x,0x%x,%p)\n", hwndOwner,nFolder,ppidl);
471
472         strcpy(buffer,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\");
473
474         res=RegCreateKeyExA(HKEY_CURRENT_USER,buffer,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&key,&dwdisp);
475         if (res)
476         { ERR_(shell)("Could not create key %s %08lx \n",buffer,res);
477           return E_OUTOFMEMORY;
478         }
479
480         tFolder=FT_DIR; 
481         switch (nFolder)
482         { case CSIDL_BITBUCKET:
483             strcpy (buffer,"xxx");                      /*not in the registry*/
484             TRACE_(shell)("looking for Recycler\n");
485             tFolder=FT_UNKNOWN;
486             break;
487           case CSIDL_CONTROLS:
488             strcpy (buffer,"xxx");                      /*virtual folder*/
489             TRACE_(shell)("looking for Control\n");
490             tFolder=FT_UNKNOWN;
491             break;
492           case CSIDL_DESKTOP:
493             strcpy (buffer,"xxx");                      /*virtual folder*/
494             TRACE_(shell)("looking for Desktop\n");
495             tFolder=FT_DESKTOP;                 
496             break;
497           case CSIDL_DESKTOPDIRECTORY:
498           case CSIDL_COMMON_DESKTOPDIRECTORY:
499             strcpy (buffer,"Desktop");
500             break;
501           case CSIDL_DRIVES:
502             strcpy (buffer,"xxx");                      /*virtual folder*/
503             TRACE_(shell)("looking for Drives\n");
504             tFolder=FT_SPECIAL;
505             break;
506           case CSIDL_FONTS:
507             strcpy (buffer,"Fonts");                    
508             break;
509           case CSIDL_NETHOOD:
510             strcpy (buffer,"NetHood");                  
511             break;
512           case CSIDL_PRINTHOOD:
513             strcpy (buffer,"PrintHood");                        
514             break;
515           case CSIDL_NETWORK:
516             strcpy (buffer,"xxx");                              /*virtual folder*/
517             TRACE_(shell)("looking for Network\n");
518             tFolder=FT_UNKNOWN;
519             break;
520           case CSIDL_APPDATA:
521             strcpy (buffer,"Appdata");                  
522             break;
523           case CSIDL_PERSONAL:
524             strcpy (buffer,"Personal");                 
525             break;
526           case CSIDL_FAVORITES:
527             strcpy (buffer,"Favorites");                        
528             break;
529           case CSIDL_PRINTERS:
530             strcpy (buffer,"PrintHood");
531             break;
532           case CSIDL_COMMON_PROGRAMS:
533           case CSIDL_PROGRAMS:
534             strcpy (buffer,"Programs");                 
535             break;
536           case CSIDL_RECENT:
537             strcpy (buffer,"Recent");
538             break;
539           case CSIDL_SENDTO:
540             strcpy (buffer,"SendTo");
541             break;
542           case CSIDL_COMMON_STARTMENU:
543           case CSIDL_STARTMENU:
544             strcpy (buffer,"Start Menu");
545             break;
546           case CSIDL_COMMON_STARTUP:  
547           case CSIDL_STARTUP:
548             strcpy (buffer,"Startup");                  
549             break;
550           case CSIDL_TEMPLATES:
551             strcpy (buffer,"Templates");                        
552             break;
553           case CSIDL_INTERNET_CACHE:
554             strcpy (buffer,"Cache");
555             break;
556           case CSIDL_HISTORY:
557             strcpy (buffer,"History");
558             break;
559           case CSIDL_COOKIES:
560             strcpy(buffer,"Cookies");
561             break;
562           default:
563             ERR_(shell)("unknown CSIDL 0x%08x\n", nFolder);
564             tFolder=FT_UNKNOWN;                 
565             break;
566         }
567
568         TRACE_(shell)("Key=%s\n",buffer);
569
570         type=REG_SZ;
571
572         switch (tFolder)
573         { case FT_DIR:
574             /* Directory: get the value from the registry, if its not there 
575                         create it and the directory*/
576             if (RegQueryValueExA(key,buffer,NULL,&type,(LPBYTE)tpath,&tpathlen))
577             { GetWindowsDirectoryA(npath,MAX_PATH);
578               PathAddBackslashA(npath);
579               switch (nFolder)
580               { case CSIDL_DESKTOPDIRECTORY:
581                 case CSIDL_COMMON_DESKTOPDIRECTORY:
582                   strcat (npath,"Desktop");
583                   break;
584                 case CSIDL_FONTS:
585                   strcat (npath,"Fonts");                       
586                   break;
587                 case CSIDL_NETHOOD:
588                   strcat (npath,"NetHood");                     
589                   break;
590                 case CSIDL_PRINTHOOD:
591                   strcat (npath,"PrintHood");                   
592                   break;
593                 case CSIDL_APPDATA:
594                   strcat (npath,"Appdata");                     
595                   break;
596                 case CSIDL_PERSONAL:
597                   strcpy (npath,"C:\\Personal");                        
598                   break;
599                 case CSIDL_FAVORITES:
600                   strcat (npath,"Favorites");                   
601                   break;
602                 case CSIDL_PRINTERS:
603                   strcat (npath,"PrintHood");                   
604                   break;
605                 case CSIDL_COMMON_PROGRAMS:
606                 case CSIDL_PROGRAMS:
607                   strcat (npath,"Start Menu");                  
608                   CreateDirectoryA(npath,NULL);
609                   strcat (npath,"\\Programs");                  
610                   break;
611                 case CSIDL_RECENT:
612                   strcat (npath,"Recent");
613                   break;
614                 case CSIDL_SENDTO:
615                   strcat (npath,"SendTo");
616                   break;
617                 case CSIDL_COMMON_STARTMENU:
618                 case CSIDL_STARTMENU:
619                   strcat (npath,"Start Menu");
620                   break;
621                 case CSIDL_COMMON_STARTUP:  
622                 case CSIDL_STARTUP:
623                   strcat (npath,"Start Menu");                  
624                   CreateDirectoryA(npath,NULL);
625                   strcat (npath,"\\Startup");                   
626                   break;
627                 case CSIDL_TEMPLATES:
628                   strcat (npath,"Templates");                   
629                   break;
630                 case CSIDL_INTERNET_CACHE:
631                   strcat(npath,"Temporary Internet Files");
632                   break;
633                 case CSIDL_HISTORY:
634                   strcat (npath,"History");
635                   break;
636                 case CSIDL_COOKIES:
637                   strcat (npath,"Cookies");
638                   break;
639                 default:
640                   RegCloseKey(key);
641                   return E_OUTOFMEMORY;
642               }
643               if (RegSetValueExA(key,buffer,0,REG_SZ,(LPBYTE)npath,sizeof(npath)+1))
644               { ERR_(shell)("could not create value %s\n",buffer);
645                 RegCloseKey(key);
646                 return E_OUTOFMEMORY;
647               }
648               TRACE_(shell)("value %s=%s created\n",buffer,npath);
649               dwLastError = GetLastError();
650               CreateDirectoryA(npath,NULL);
651               SetLastError (dwLastError);
652               strcpy(tpath,npath);
653             }
654             break;
655           case FT_DESKTOP:
656             strcpy (tpath,"Desktop");
657             break;
658           case FT_SPECIAL:
659             if (nFolder==CSIDL_DRIVES)
660             strcpy (tpath,"My Computer");
661             break;
662           default:
663             RegCloseKey(key);
664             return E_OUTOFMEMORY;
665         }
666
667         RegCloseKey(key);
668
669         TRACE_(shell)("Value=%s\n",tpath);
670         LocalToWideChar(lpszDisplayName, tpath, 256);
671   
672         if (SHGetDesktopFolder(&shellfolder)==S_OK)
673         { IShellFolder_ParseDisplayName(shellfolder,hwndOwner, NULL,lpszDisplayName,&pchEaten,ppidl,NULL);
674           IShellFolder_Release(shellfolder);
675         }
676
677         TRACE_(shell)("-- (new pidl %p)\n",*ppidl);
678         return NOERROR;
679 }
680 /*************************************************************************
681  * SHHelpShortcuts_RunDLL               [SHELL32.224]
682  *
683  */
684 DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
685 { FIXME_(exec)("(%lx, %lx, %lx, %lx) empty stub!\n",
686         dwArg1, dwArg2, dwArg3, dwArg4);
687
688   return 0;
689 }
690
691 /*************************************************************************
692  * SHLoadInProc                         [SHELL32.225]
693  *
694  */
695
696 DWORD WINAPI SHLoadInProc (DWORD dwArg1)
697 { FIXME_(shell)("(%lx) empty stub!\n", dwArg1);
698     return 0;
699 }
700
701 /*************************************************************************
702  * ShellExecuteA                        [SHELL32.245]
703  */
704 HINSTANCE WINAPI ShellExecuteA( HWND hWnd, LPCSTR lpOperation,
705                                     LPCSTR lpFile, LPCSTR lpParameters,
706                                     LPCSTR lpDirectory, INT iShowCmd )
707 {   TRACE_(shell)("\n");
708     return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
709                            lpDirectory, iShowCmd );
710 }
711
712 /*************************************************************************
713  * ShellExecuteW                        [SHELL32.294]
714  * from shellapi.h
715  * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation, 
716  * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);   
717  */
718 HINSTANCE WINAPI 
719 ShellExecuteW(
720        HWND hwnd, 
721        LPCWSTR lpOperation, 
722        LPCWSTR lpFile, 
723        LPCWSTR lpParameters, 
724        LPCWSTR lpDirectory, 
725        INT nShowCmd) {
726
727        FIXME_(shell)(": stub\n");
728        return 0;
729 }
730
731 /*************************************************************************
732  * AboutDlgProc32                       (internal)
733  */
734 BOOL WINAPI AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
735                               LPARAM lParam )
736 {   HWND hWndCtl;
737     char Template[512], AppTitle[512];
738
739     TRACE_(shell)("\n");
740
741     switch(msg)
742     { case WM_INITDIALOG:
743       { ABOUT_INFO *info = (ABOUT_INFO *)lParam;
744             if (info)
745         { const char* const *pstr = SHELL_People;
746                 SendDlgItemMessageA(hWnd, stc1, STM_SETICON,info->hIcon, 0);
747                 GetWindowTextA( hWnd, Template, sizeof(Template) );
748                 sprintf( AppTitle, Template, info->szApp );
749                 SetWindowTextA( hWnd, AppTitle );
750                 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT),
751                                   info->szOtherStuff );
752                 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
753                 SendMessageA( hWndCtl, WM_SETREDRAW, 0, 0 );
754                 SendMessageA( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
755                 while (*pstr)
756           { SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)*pstr );
757                     pstr++;
758                 }
759                 SendMessageA( hWndCtl, WM_SETREDRAW, 1, 0 );
760             }
761         }
762         return 1;
763
764     case WM_PAINT:
765       { RECT rect;
766             PAINTSTRUCT ps;
767             HDC hDC = BeginPaint( hWnd, &ps );
768
769             if( __get_dropline( hWnd, &rect ) ) {
770                 SelectObject( hDC, GetStockObject( BLACK_PEN ) );
771                 MoveToEx( hDC, rect.left, rect.top, NULL );
772                 LineTo( hDC, rect.right, rect.bottom );
773             }
774             EndPaint( hWnd, &ps );
775         }
776         break;
777
778     case WM_LBTRACKPOINT:
779         hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
780         if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
781       { if( DragDetect( hWndCtl, *((LPPOINT)&lParam) ) )
782         { INT idx = SendMessageA( hWndCtl, LB_GETCURSEL, 0, 0 );
783                 if( idx != -1 )
784           { INT length = SendMessageA( hWndCtl, LB_GETTEXTLEN, (WPARAM)idx, 0 );
785                     HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
786                     char* pstr = (char*)GlobalLock16( hMemObj );
787
788                     if( pstr )
789             { HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE16(OCR_DRAGOBJECT) );
790                         SendMessageA( hWndCtl, LB_GETTEXT, (WPARAM)idx, (LPARAM)pstr );
791                         SendMessageA( hWndCtl, LB_DELETESTRING, (WPARAM)idx, 0 );
792                         UpdateWindow( hWndCtl );
793                         if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
794                             SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)pstr );
795                     }
796             if( hMemObj )
797               GlobalFree16( hMemObj );
798                 }
799             }
800         }
801         break;
802
803     case WM_QUERYDROPOBJECT:
804         if( wParam == 0 )
805       { LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
806             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
807         { RECT rect;
808                 if( __get_dropline( hWnd, &rect ) )
809           { POINT pt;
810             pt.x=lpDragInfo->pt.x;
811             pt.x=lpDragInfo->pt.y;
812                     rect.bottom += DROP_FIELD_HEIGHT;
813                     if( PtInRect( &rect, pt ) )
814             { SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
815                         return TRUE;
816                     }
817                 }
818             }
819         }
820         break;
821
822     case WM_DROPOBJECT:
823         if( wParam == hWnd )
824       { LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
825             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
826         { char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
827                 if( pstr )
828           { static char __appendix_str[] = " with";
829
830                     hWndCtl = GetDlgItem( hWnd, IDC_WINE_TEXT );
831                     SendMessageA( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
832                     if( !lstrncmpA( Template, "WINE", 4 ) )
833                         SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT), Template );
834                     else
835           { char* pch = Template + strlen(Template) - strlen(__appendix_str);
836                         *pch = '\0';
837                         SendMessageA( GetDlgItem(hWnd, IDC_LISTBOX), LB_ADDSTRING, 
838                                         (WPARAM)-1, (LPARAM)Template );
839                     }
840
841                     lstrcpyA( Template, pstr );
842                     lstrcatA( Template, __appendix_str );
843                     SetWindowTextA( hWndCtl, Template );
844                     SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
845                     return TRUE;
846                 }
847             }
848         }
849         break;
850
851     case WM_COMMAND:
852         if (wParam == IDOK)
853     {  EndDialog(hWnd, TRUE);
854             return TRUE;
855         }
856         break;
857     }
858     return 0;
859 }
860
861
862 /*************************************************************************
863  * ShellAboutA                          [SHELL32.243]
864  */
865 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
866                              HICON hIcon )
867 {   ABOUT_INFO info;
868     HRSRC hRes;
869     LPVOID template;
870     TRACE_(shell)("\n");
871
872     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
873         return FALSE;
874     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
875         return FALSE;
876
877     info.szApp        = szApp;
878     info.szOtherStuff = szOtherStuff;
879     info.hIcon        = hIcon;
880     if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
881     return DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
882                                       template, hWnd, AboutDlgProc, (LPARAM)&info );
883 }
884
885
886 /*************************************************************************
887  * ShellAboutW                          [SHELL32.244]
888  */
889 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
890                              HICON hIcon )
891 {   BOOL ret;
892     ABOUT_INFO info;
893     HRSRC hRes;
894     LPVOID template;
895
896     TRACE_(shell)("\n");
897     
898     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
899         return FALSE;
900     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
901         return FALSE;
902
903     info.szApp        = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
904     info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
905     info.hIcon        = hIcon;
906     if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
907     ret = DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
908                                    template, hWnd, AboutDlgProc, (LPARAM)&info );
909     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
910     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
911     return ret;
912 }
913
914 /*************************************************************************
915  * Shell_NotifyIcon                     [SHELL32.296]
916  *      FIXME
917  *      This function is supposed to deal with the systray.
918  *      Any ideas on how this is to be implimented?
919  */
920 BOOL WINAPI Shell_NotifyIcon(   DWORD dwMessage, PNOTIFYICONDATAA pnid )
921 {   TRACE_(shell)("\n");
922     return FALSE;
923 }
924
925 /*************************************************************************
926  * Shell_NotifyIcon                     [SHELL32.297]
927  *      FIXME
928  *      This function is supposed to deal with the systray.
929  *      Any ideas on how this is to be implimented?
930  */
931 BOOL WINAPI Shell_NotifyIconA(DWORD dwMessage, PNOTIFYICONDATAA pnid )
932 {   TRACE_(shell)("\n");
933     return FALSE;
934 }
935
936 /*************************************************************************
937  * FreeIconList
938  */
939 void WINAPI FreeIconList( DWORD dw )
940 { FIXME_(shell)("(%lx): stub\n",dw);
941 }
942
943 /*************************************************************************
944  * SHGetPathFromIDListA         [SHELL32.261][NT 4.0: SHELL32.220]
945  *
946  * PARAMETERS
947  *  pidl,   [IN] pidl 
948  *  pszPath [OUT] path
949  *
950  * RETURNS 
951  *  path from a passed PIDL.
952  *
953  * NOTES
954  *     exported by name
955  *
956  * FIXME
957  *  fnGetDisplayNameOf can return different types of OLEString
958  */
959 DWORD WINAPI SHGetPathFromIDListA (LPCITEMIDLIST pidl,LPSTR pszPath)
960 {       STRRET lpName;
961         LPSHELLFOLDER shellfolder;
962         CHAR  buffer[MAX_PATH],tpath[MAX_PATH];
963         DWORD type,tpathlen=MAX_PATH,dwdisp;
964         HKEY  key;
965
966         TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
967
968         if (!pidl)
969         {  strcpy(buffer,"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders\\");
970
971           if (RegCreateKeyExA(HKEY_CURRENT_USER,buffer,0,NULL,REG_OPTION_NON_VOLATILE,KEY_WRITE,NULL,&key,&dwdisp))
972           { return E_OUTOFMEMORY;
973           }
974           type=REG_SZ;    
975           strcpy (buffer,"Desktop");                                    /*registry name*/
976           if ( RegQueryValueExA(key,buffer,NULL,&type,(LPBYTE)tpath,&tpathlen))
977           { GetWindowsDirectoryA(tpath,MAX_PATH);
978             PathAddBackslashA(tpath);
979             strcat (tpath,"Desktop");                           /*folder name*/
980             RegSetValueExA(key,buffer,0,REG_SZ,(LPBYTE)tpath,tpathlen);
981             CreateDirectoryA(tpath,NULL);
982           }
983           RegCloseKey(key);
984           strcpy(pszPath,tpath);
985         }
986         else
987         { if (SHGetDesktopFolder(&shellfolder)==S_OK)
988           { IShellFolder_GetDisplayNameOf(shellfolder,pidl,SHGDN_FORPARSING,&lpName);
989             IShellFolder_Release(shellfolder);
990           }
991           strcpy(pszPath,lpName.u.cStr);
992         }
993         TRACE_(shell)("-- (%s)\n",pszPath);
994
995         return TRUE;
996 }
997 /*************************************************************************
998  * SHGetPathFromIDListW                         [SHELL32.262]
999  */
1000 DWORD WINAPI SHGetPathFromIDListW (LPCITEMIDLIST pidl,LPWSTR pszPath)
1001 {       char sTemp[MAX_PATH];
1002
1003         TRACE_(shell)("(pidl=%p)\n", pidl);
1004
1005         SHGetPathFromIDListA (pidl, sTemp);
1006         lstrcpyAtoW(pszPath, sTemp);
1007
1008         TRACE_(shell)("-- (%s)\n",debugstr_w(pszPath));
1009
1010         return TRUE;
1011 }
1012
1013 /*************************************************************************
1014  * SHGetPathFromIDListAW                [SHELL32.221][NT 4.0: SHELL32.219]
1015  */
1016 BOOL WINAPI SHGetPathFromIDListAW(LPCITEMIDLIST pidl,LPVOID pszPath)     
1017 {
1018         TRACE_(shell)("(pidl=%p,%p)\n",pidl,pszPath);
1019
1020         if (VERSION_OsIsUnicode())
1021           return SHGetPathFromIDListW(pidl,pszPath);
1022         return SHGetPathFromIDListA(pidl,pszPath);
1023 }
1024
1025 /***********************************************************************
1026  * DllGetVersion [COMCTL32.25]
1027  *
1028  * Retrieves version information of the 'SHELL32.DLL'
1029  *
1030  * PARAMS
1031  *     pdvi [O] pointer to version information structure.
1032  *
1033  * RETURNS
1034  *     Success: S_OK
1035  *     Failure: E_INVALIDARG
1036  *
1037  * NOTES
1038  *     Returns version of a shell32.dll from IE4.01 SP1.
1039  */
1040
1041 HRESULT WINAPI SHELL32_DllGetVersion (DLLVERSIONINFO *pdvi)
1042 {
1043         if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) 
1044         { WARN_(shell)("wrong DLLVERSIONINFO size from app");
1045           return E_INVALIDARG;
1046         }
1047
1048         pdvi->dwMajorVersion = 4;
1049         pdvi->dwMinorVersion = 72;
1050         pdvi->dwBuildNumber = 3110;
1051         pdvi->dwPlatformID = 1;
1052
1053         TRACE_(shell)("%lu.%lu.%lu.%lu\n",
1054            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
1055            pdvi->dwBuildNumber, pdvi->dwPlatformID);
1056
1057         return S_OK;
1058 }
1059 /*************************************************************************
1060  * global variables of the shell32.dll
1061  * all are once per process
1062  *
1063  */
1064 void    (WINAPI* pDLLInitComctl)(LPVOID);
1065 INT     (WINAPI* pImageList_AddIcon) (HIMAGELIST himl, HICON hIcon);
1066 INT     (WINAPI* pImageList_ReplaceIcon) (HIMAGELIST, INT, HICON);
1067 HIMAGELIST (WINAPI * pImageList_Create) (INT,INT,UINT,INT,INT);
1068 BOOL    (WINAPI* pImageList_Draw) (HIMAGELIST himl, int i, HDC hdcDest, int x, int y, UINT fStyle);
1069 HICON   (WINAPI * pImageList_GetIcon) (HIMAGELIST, INT, UINT);
1070 INT     (WINAPI* pImageList_GetImageCount)(HIMAGELIST);
1071
1072 LPVOID  (WINAPI* pCOMCTL32_Alloc) (INT);  
1073 BOOL    (WINAPI* pCOMCTL32_Free) (LPVOID);  
1074
1075 HDPA    (WINAPI* pDPA_Create) (INT);  
1076 INT     (WINAPI* pDPA_InsertPtr) (const HDPA, INT, LPVOID); 
1077 BOOL    (WINAPI* pDPA_Sort) (const HDPA, PFNDPACOMPARE, LPARAM); 
1078 LPVOID  (WINAPI* pDPA_GetPtr) (const HDPA, INT);   
1079 BOOL    (WINAPI* pDPA_Destroy) (const HDPA); 
1080 INT     (WINAPI *pDPA_Search) (const HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
1081 LPVOID  (WINAPI *pDPA_DeletePtr) (const HDPA hdpa, INT i);
1082
1083 /* user32 */
1084 HICON (WINAPI *pLookupIconIdFromDirectoryEx)(LPBYTE dir, BOOL bIcon, INT width, INT height, UINT cFlag);
1085 HICON (WINAPI *pCreateIconFromResourceEx)(LPBYTE bits,UINT cbSize, BOOL bIcon, DWORD dwVersion, INT width, INT height,UINT cFlag);
1086
1087 static BOOL             bShell32IsInitialized = 0;
1088 static HINSTANCE        hComctl32;
1089 static INT              shell32_RefCount = 0;
1090
1091 INT             shell32_ObjCount = 0;
1092 HINSTANCE       shell32_hInstance; 
1093
1094 HIMAGELIST      ShellSmallIconList = 0;
1095 HIMAGELIST      ShellBigIconList = 0;
1096 HDPA            sic_hdpa = 0;
1097
1098 /*************************************************************************
1099  * SHELL32 LibMain
1100  *
1101  */
1102
1103 BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
1104 {       HMODULE hUser32;
1105
1106         TRACE_(shell)("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
1107
1108         shell32_hInstance = hinstDLL;
1109
1110         switch (fdwReason)
1111         {
1112           case DLL_PROCESS_ATTACH:
1113             if (!bShell32IsInitialized)
1114             {
1115               hComctl32 = LoadLibraryA("COMCTL32.DLL"); 
1116               hUser32 = GetModuleHandleA("USER32");
1117
1118               if (hComctl32 && hUser32)
1119               {
1120                 pDLLInitComctl=(void*)GetProcAddress(hComctl32,"InitCommonControlsEx");
1121                 if (pDLLInitComctl)
1122                 { pDLLInitComctl(NULL);
1123                 }
1124                 pImageList_Create=(void*)GetProcAddress(hComctl32,"ImageList_Create");
1125                 pImageList_AddIcon=(void*)GetProcAddress(hComctl32,"ImageList_AddIcon");
1126                 pImageList_ReplaceIcon=(void*)GetProcAddress(hComctl32,"ImageList_ReplaceIcon");
1127                 pImageList_GetIcon=(void*)GetProcAddress(hComctl32,"ImageList_GetIcon");
1128                 pImageList_GetImageCount=(void*)GetProcAddress(hComctl32,"ImageList_GetImageCount");
1129                 pImageList_Draw=(void*)GetProcAddress(hComctl32,"ImageList_Draw");
1130
1131                 /* imports by ordinal, pray that it works*/
1132                 pCOMCTL32_Alloc=(void*)GetProcAddress(hComctl32, (LPCSTR)71L);
1133                 pCOMCTL32_Free=(void*)GetProcAddress(hComctl32, (LPCSTR)73L);
1134                 pDPA_Create=(void*)GetProcAddress(hComctl32, (LPCSTR)328L);
1135                 pDPA_Destroy=(void*)GetProcAddress(hComctl32, (LPCSTR)329L);
1136                 pDPA_GetPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)332L);
1137                 pDPA_InsertPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)334L);
1138                 pDPA_DeletePtr=(void*)GetProcAddress(hComctl32, (LPCSTR)336L);
1139                 pDPA_Sort=(void*)GetProcAddress(hComctl32, (LPCSTR)338L);
1140                 pDPA_Search=(void*)GetProcAddress(hComctl32, (LPCSTR)339L);
1141                 /* user32 */
1142                 pLookupIconIdFromDirectoryEx=(void*)GetProcAddress(hUser32,"LookupIconIdFromDirectoryEx");
1143                 pCreateIconFromResourceEx=(void*)GetProcAddress(hUser32,"CreateIconFromResourceEx");
1144               }
1145               else
1146               { ERR_(shell)("P A N I C SHELL32 loading failed\n");
1147                 return FALSE;
1148               }
1149               SIC_Initialize();
1150               bShell32IsInitialized = TRUE;
1151             }
1152             shell32_RefCount++;
1153             break;
1154
1155           case DLL_THREAD_ATTACH:
1156             shell32_RefCount++;
1157             break;
1158
1159           case DLL_THREAD_DETACH:
1160             shell32_RefCount--;
1161             break;
1162
1163           case DLL_PROCESS_DETACH:
1164             shell32_RefCount--;
1165             if ( !shell32_RefCount )
1166             { 
1167               bShell32IsInitialized = FALSE;
1168
1169               if (pdesktopfolder) 
1170               { IShellFolder_Release(pdesktopfolder);
1171                 pdesktopfolder = NULL;
1172               }
1173
1174               SIC_Destroy();
1175               FreeLibrary(hComctl32);
1176
1177               /* this one is here to check if AddRef/Release is balanced */
1178               if (shell32_ObjCount)
1179               { WARN_(shell)("leaving with %u objects left (memory leak)\n", shell32_ObjCount);
1180               }
1181             }
1182             TRACE_(shell)("refcount=%u objcount=%u \n", shell32_RefCount, shell32_ObjCount);
1183             break;            
1184         }
1185
1186         return TRUE;
1187 }