New XP debugging APIs: implemented DebugActiveProcessStop,
[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
8 #include "config.h"
9
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
13
14 #include "windef.h"
15 #include "winerror.h"
16 #include "winreg.h"
17 #include "dlgs.h"
18 #include "shellapi.h"
19 #include "shlobj.h"
20 #include "shlguid.h"
21 #include "shlwapi.h"
22
23 #include "undocshell.h"
24 #include "wine/winuser16.h"
25 #include "authors.h"
26 #include "heap.h"
27 #include "pidl.h"
28 #include "shell32_main.h"
29
30 #include "debugtools.h"
31
32 DEFAULT_DEBUG_CHANNEL(shell);
33
34 #define MORE_DEBUG 1
35 /*************************************************************************
36  * CommandLineToArgvW                   [SHELL32.@]
37  *
38  * We must interpret the quotes in the command line to rebuild the argv 
39  * array correctly:
40  * - arguments are separated by spaces or tabs
41  * - quotes serve as optional argument delimiters
42  *   '"a b"'   -> 'a b'
43  * - escaped quotes must be converted back to '"'
44  *   '\"'      -> '"'
45  * - an odd number of '\'s followed by '"' correspond to half that number 
46  *   of '\' followed by a '"' (extension of the above)
47  *   '\\\"'    -> '\"'
48  *   '\\\\\"'  -> '\\"'
49  * - an even number of '\'s followed by a '"' correspond to half that number
50  *   of '\', plus a regular quote serving as an argument delimiter (which 
51  *   means it does not appear in the result)
52  *   'a\\"b c"'   -> 'a\b c'
53  *   'a\\\\"b c"' -> 'a\\b c'
54  * - '\' that are not followed by a '"' are copied literally
55  *   'a\b'     -> 'a\b'
56  *   'a\\b'    -> 'a\\b'
57  *
58  * Note:
59  * '\t' == 0x0009
60  * ' '  == 0x0020
61  * '"'  == 0x0022
62  * '\\' == 0x005c
63  */
64 LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
65 {
66     DWORD argc;
67     HGLOBAL hargv;
68     LPWSTR  *argv;
69     LPCWSTR cs;
70     LPWSTR arg,s,d;
71     LPWSTR cmdline;
72     int in_quotes,bcount;
73
74     if (*lpCmdline==0) {
75         /* Return the path to the executable */
76         DWORD size;
77
78         hargv=0;
79         size=16;
80         do {
81             size*=2;
82             hargv=GlobalReAlloc(hargv, size, 0);
83             argv=GlobalLock(hargv);
84         } while (GetModuleFileNameW((HMODULE)0, (LPWSTR)(argv+1), size-sizeof(LPWSTR)) == 0);
85         argv[0]=(LPWSTR)(argv+1);
86         if (numargs)
87             *numargs=2;
88
89         return argv;
90     }
91
92     /* to get a writeable copy */
93     argc=0;
94     bcount=0;
95     in_quotes=0;
96     cs=lpCmdline;
97     while (1) {
98         if (*cs==0 || ((*cs==0x0009 || *cs==0x0020) && !in_quotes)) {
99             /* space */
100             argc++;
101             /* skip the remaining spaces */
102             while (*cs==0x0009 || *cs==0x0020) {
103                 cs++;
104             }
105             if (*cs==0)
106                 break;
107             bcount=0;
108             continue;
109         } else if (*cs==0x005c) {
110             /* '\', count them */
111             bcount++;
112         } else if ((*cs==0x0022) && ((bcount & 1)==0)) {
113             /* unescaped '"' */
114             in_quotes=!in_quotes;
115             bcount=0;
116         } else {
117             /* a regular character */
118             bcount=0;
119         }
120         cs++;
121     }
122     /* Allocate in a single lump, the string array, and the strings that go with it.
123      * This way the caller can make a single GlobalFree call to free both, as per MSDN.
124      */
125     hargv=GlobalAlloc(0, argc*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR));
126     argv=GlobalLock(hargv);
127     if (!argv)
128         return NULL;
129     cmdline=(LPWSTR)(argv+argc);
130     strcpyW(cmdline, lpCmdline);
131
132     argc=0;
133     bcount=0;
134     in_quotes=0;
135     arg=d=s=cmdline;
136     while (*s) {
137         if ((*s==0x0009 || *s==0x0020) && !in_quotes) {
138             /* Close the argument and copy it */
139             *d=0;
140             argv[argc++]=arg;
141
142             /* skip the remaining spaces */
143             do {
144                 s++;
145             } while (*s==0x0009 || *s==0x0020);
146
147             /* Start with a new argument */
148             arg=d=s;
149             bcount=0;
150         } else if (*s==0x005c) {
151             /* '\\' */
152             *d++=*s++;
153             bcount++;
154         } else if (*s==0x0022) {
155             /* '"' */
156             if ((bcount & 1)==0) {
157                 /* Preceeded by an even number of '\', this is half that 
158                  * number of '\', plus a quote which we erase.
159                  */
160                 d-=bcount/2;
161                 in_quotes=!in_quotes;
162                 s++;
163             } else {
164                 /* Preceeded by an odd number of '\', this is half that 
165                  * number of '\' followed by a '"'
166                  */
167                 d=d-bcount/2-1;
168                 *d++='"';
169                 s++;
170             }
171             bcount=0;
172         } else {
173             /* a regular character */
174             *d++=*s++;
175             bcount=0;
176         }
177     }
178     if (*arg) {
179         *d='\0';
180         argv[argc]=arg;
181     }
182     if (numargs)
183         *numargs=argc;
184
185     return argv;
186 }
187
188 /*************************************************************************
189  * SHGetFileInfoA                       [SHELL32.@]
190  *
191  */
192
193 DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
194                               SHFILEINFOA *psfi, UINT sizeofpsfi,
195                               UINT flags )
196 {
197         char szLoaction[MAX_PATH];
198         int iIndex;
199         DWORD ret = TRUE, dwAttributes = 0;
200         IShellFolder * psfParent = NULL;
201         IExtractIconA * pei = NULL;
202         LPITEMIDLIST    pidlLast = NULL, pidl = NULL;
203         HRESULT hr = S_OK;
204     BOOL IconNotYetLoaded=TRUE;
205
206         TRACE("(%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x)\n", 
207           (flags & SHGFI_PIDL)? "pidl" : path, dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags);
208
209         if ((flags & SHGFI_USEFILEATTRIBUTES) && (flags & (SHGFI_ATTRIBUTES|SHGFI_EXETYPE|SHGFI_PIDL)))
210           return FALSE;
211         
212         /* windows initializes this values regardless of the flags */
213         psfi->szDisplayName[0] = '\0';
214         psfi->szTypeName[0] = '\0';
215         psfi->iIcon = 0;
216
217         if (flags & SHGFI_EXETYPE) {
218           BOOL status = FALSE;
219           HANDLE hfile;
220           DWORD BinaryType;
221           IMAGE_DOS_HEADER mz_header;
222           IMAGE_NT_HEADERS nt;
223           DWORD len;
224           char magic[4];
225
226           if (flags != SHGFI_EXETYPE) return 0;
227
228           status = GetBinaryTypeA (path, &BinaryType);
229           if (!status) return 0;
230           if ((BinaryType == SCS_DOS_BINARY)
231                 || (BinaryType == SCS_PIF_BINARY)) return 0x4d5a;
232
233           hfile = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ,
234                 NULL, OPEN_EXISTING, 0, 0 );
235           if ( hfile == INVALID_HANDLE_VALUE ) return 0;
236
237         /* The next section is adapted from MODULE_GetBinaryType, as we need
238          * to examine the image header to get OS and version information. We
239          * know from calling GetBinaryTypeA that the image is valid and either
240          * an NE or PE, so much error handling can be omitted.
241          * Seek to the start of the file and read the header information.
242          */
243
244           SetFilePointer( hfile, 0, NULL, SEEK_SET );  
245           ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL );
246
247          SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
248          ReadFile( hfile, magic, sizeof(magic), &len, NULL );
249          if ( *(DWORD*)magic      == IMAGE_NT_SIGNATURE )
250          {
251              SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); 
252              ReadFile( hfile, &nt, sizeof(nt), &len, NULL );
253               CloseHandle( hfile );
254               if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
255                  return IMAGE_NT_SIGNATURE
256                         | (nt.OptionalHeader.MajorSubsystemVersion << 24)
257                         | (nt.OptionalHeader.MinorSubsystemVersion << 16);
258               }
259               return IMAGE_NT_SIGNATURE;
260           }
261          else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
262          {
263              IMAGE_OS2_HEADER ne;
264              SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); 
265              ReadFile( hfile, &ne, sizeof(ne), &len, NULL );
266               CloseHandle( hfile );
267              if (ne.ne_exetyp == 2) return IMAGE_OS2_SIGNATURE
268                         | (ne.ne_expver << 16);
269               return 0;
270           }
271           CloseHandle( hfile );
272           return 0;
273       }
274
275         
276         /* translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES in not specified 
277            the pidl functions fail on not existing file names */
278         if (flags & SHGFI_PIDL)
279         {
280           pidl = (LPCITEMIDLIST) path;
281           if (!pidl )
282           {
283             ERR("pidl is null!\n");
284             return FALSE;
285           }
286         }
287         else if (!(flags & SHGFI_USEFILEATTRIBUTES))
288         {
289           hr = SHILCreateFromPathA ( path, &pidl, &dwAttributes);
290           /* note: the attributes in ISF::ParseDisplayName are not implemented */
291         }
292         
293         /* get the parent shellfolder */
294         if (pidl)
295         {
296           hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidlLast);
297         }
298         
299         /* get the attributes of the child */
300         if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
301         {
302           if (!(flags & SHGFI_ATTR_SPECIFIED))
303           {
304             psfi->dwAttributes = 0xffffffff;
305           }
306           IShellFolder_GetAttributesOf(psfParent, 1 , &pidlLast, &(psfi->dwAttributes));
307         }
308
309         /* get the displayname */
310         if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
311         { 
312           if (flags & SHGFI_USEFILEATTRIBUTES)
313           {
314             strcpy (psfi->szDisplayName, PathFindFileNameA(path));
315           }
316           else
317           {
318             STRRET str;
319             hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_INFOLDER, &str);
320             StrRetToStrNA (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
321           }
322         }
323
324         /* get the type name */
325         if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
326         {
327             if (!(flags & SHGFI_USEFILEATTRIBUTES))
328                 _ILGetFileType(pidlLast, psfi->szTypeName, 80);
329             else
330             {
331                 char sTemp[64];
332                 strcpy(sTemp,PathFindExtensionA(path));
333                 if (!( HCR_MapTypeToValue(sTemp, sTemp, 64, TRUE)
334                        && HCR_MapTypeToValue(sTemp, psfi->szTypeName, 80, FALSE )))
335                 {
336                     lstrcpynA (psfi->szTypeName, sTemp, 80 - 6);
337                     strcat (psfi->szTypeName, "-file");
338                 }
339             }
340         }
341
342         /* ### icons ###*/
343         if (flags & SHGFI_LINKOVERLAY)
344           FIXME("set icon to link, stub\n");
345
346         if (flags & SHGFI_SELECTED)
347           FIXME("set icon to selected, stub\n");
348
349         if (flags & SHGFI_SHELLICONSIZE)
350           FIXME("set icon to shell size, stub\n");
351
352         /* get the iconlocation */
353         if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
354         {
355           UINT uDummy,uFlags;
356           hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, &pidlLast, &IID_IExtractIconA, &uDummy, (LPVOID*)&pei);
357
358           if (SUCCEEDED(hr))
359           {
360             hr = IExtractIconA_GetIconLocation(pei, (flags & SHGFI_OPENICON)? GIL_OPENICON : 0,szLoaction, MAX_PATH, &iIndex, &uFlags);
361             /* FIXME what to do with the index? */
362
363             if(uFlags != GIL_NOTFILENAME)
364               strcpy (psfi->szDisplayName, szLoaction);
365             else
366               ret = FALSE;
367               
368             IExtractIconA_Release(pei);
369           }
370         }
371
372         /* get icon index (or load icon)*/
373         if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
374         {
375
376           if (flags & SHGFI_USEFILEATTRIBUTES)
377           {
378             char sTemp [MAX_PATH];
379             char * szExt;
380             DWORD dwNr=0;
381
382             lstrcpynA(sTemp, path, MAX_PATH);
383             szExt = (LPSTR) PathFindExtensionA(sTemp);
384             if( szExt && HCR_MapTypeToValue(szExt, sTemp, MAX_PATH, TRUE)
385               && HCR_GetDefaultIcon(sTemp, sTemp, MAX_PATH, &dwNr))
386             {
387               if (!strcmp("%1",sTemp))            /* icon is in the file */
388               {
389                 strcpy(sTemp, path);
390               }
391               IconNotYetLoaded=FALSE;
392               psfi->iIcon = 0;
393               if (SHGFI_LARGEICON)
394                 PrivateExtractIconsA(sTemp,dwNr,GetSystemMetrics(SM_CXICON),
395                                      GetSystemMetrics(SM_CYICON),
396                                      &psfi->hIcon,0,1,0);
397               else
398                 PrivateExtractIconsA(sTemp,dwNr,GetSystemMetrics(SM_CXSMICON),
399                                      GetSystemMetrics(SM_CYSMICON),
400                                      &psfi->hIcon,0,1,0);
401             }
402             else                                  /* default icon */
403             {
404               psfi->iIcon = 0;
405             }          
406           }
407           else
408           {
409             if (!(PidlToSicIndex(psfParent, pidlLast, (flags & SHGFI_LARGEICON), 
410               (flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon))))
411             {
412               ret = FALSE;
413             }
414           }
415           if (ret) 
416           {
417             ret = (DWORD) ((flags & SHGFI_LARGEICON) ? ShellBigIconList : ShellSmallIconList);
418           }
419         }
420
421         /* icon handle */
422         if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded)
423           psfi->hIcon = ImageList_GetIcon((flags & SHGFI_LARGEICON) ? ShellBigIconList:ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
424
425         if (flags & (SHGFI_UNKNOWN1 | SHGFI_UNKNOWN2 | SHGFI_UNKNOWN3))
426           FIXME("unknown attribute!\n");
427
428         if (psfParent)
429           IShellFolder_Release(psfParent);
430
431         if (hr != S_OK)
432           ret = FALSE;
433
434         if(pidlLast) SHFree(pidlLast);
435 #ifdef MORE_DEBUG
436         TRACE ("icon=0x%08x index=0x%08x attr=0x%08lx name=%s type=%s ret=0x%08lx\n", 
437                 psfi->hIcon, psfi->iIcon, psfi->dwAttributes, psfi->szDisplayName, psfi->szTypeName, ret);
438 #endif
439         return ret;
440 }
441
442 /*************************************************************************
443  * SHGetFileInfoW                       [SHELL32.@]
444  */
445
446 DWORD WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
447                               SHFILEINFOW *psfi, UINT sizeofpsfi,
448                               UINT flags )
449 {
450         INT len;
451         LPSTR temppath;
452         DWORD ret;
453         SHFILEINFOA temppsfi;
454
455         len = WideCharToMultiByte(CP_ACP, 0, path, -1, NULL, 0, NULL, NULL);
456         temppath = HeapAlloc(GetProcessHeap(), 0, len);
457         WideCharToMultiByte(CP_ACP, 0, path, -1, temppath, len, NULL, NULL);
458
459         WideCharToMultiByte(CP_ACP, 0, psfi->szDisplayName, -1, temppsfi.szDisplayName,
460                             sizeof(temppsfi.szDisplayName), NULL, NULL);
461         WideCharToMultiByte(CP_ACP, 0, psfi->szTypeName, -1, temppsfi.szTypeName,
462                             sizeof(temppsfi.szTypeName), NULL, NULL);
463
464         ret = SHGetFileInfoA(temppath, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
465
466         HeapFree(GetProcessHeap(), 0, temppath);
467         
468         return ret;
469 }
470
471 /*************************************************************************
472  * SHGetFileInfo                        [SHELL32.@]
473  */
474 DWORD WINAPI SHGetFileInfoAW(
475         LPCVOID path,
476         DWORD dwFileAttributes,
477         LPVOID psfi,
478         UINT sizeofpsfi,
479         UINT flags)
480 {
481         if(SHELL_OsIsUnicode())
482           return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags );
483         return SHGetFileInfoA(path, dwFileAttributes, psfi, sizeofpsfi, flags );
484 }
485
486 /*************************************************************************
487  * DuplicateIcon                        [SHELL32.@]
488  */
489 HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
490 {
491     ICONINFO IconInfo;
492     HICON hDupIcon = 0;
493
494     TRACE("(%04x, %04x)\n", hInstance, hIcon);
495
496     if(GetIconInfo(hIcon, &IconInfo))
497     {
498         hDupIcon = CreateIconIndirect(&IconInfo);
499
500         /* clean up hbmMask and hbmColor */
501         DeleteObject(IconInfo.hbmMask);        
502         DeleteObject(IconInfo.hbmColor);        
503     }
504  
505     return hDupIcon;
506 }
507     
508
509 /*************************************************************************
510  * ExtractIconA                         [SHELL32.@]
511  *
512  * FIXME
513  *  if the filename is not a file return 1
514  */
515 HICON WINAPI ExtractIconA( HINSTANCE hInstance, LPCSTR lpszExeFileName,
516         UINT nIconIndex )
517 {   HGLOBAL16 handle = InternalExtractIcon16(hInstance,lpszExeFileName,nIconIndex, 1);
518     TRACE("\n");
519     if( handle )
520     {
521         HICON16* ptr = (HICON16*)GlobalLock16(handle);
522         HICON16  hIcon = *ptr;
523
524         GlobalFree16(handle);
525         return hIcon;
526     }
527     return 0;
528 }
529
530 /*************************************************************************
531  * ExtractIconW                         [SHELL32.@]
532  *
533  * FIXME: if the filename is not a file return 1
534  */
535 HICON WINAPI ExtractIconW( HINSTANCE hInstance, LPCWSTR lpszExeFileName,
536         UINT nIconIndex )
537 { LPSTR  exefn;
538   HICON  ret;
539   TRACE("\n");
540
541   exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
542   ret = ExtractIconA(hInstance,exefn,nIconIndex);
543
544         HeapFree(GetProcessHeap(),0,exefn);
545         return ret;
546 }
547
548 typedef struct
549 { LPCSTR  szApp;
550     LPCSTR  szOtherStuff;
551     HICON hIcon;
552 } ABOUT_INFO;
553
554 #define         IDC_STATIC_TEXT         100
555 #define         IDC_LISTBOX             99
556 #define         IDC_WINE_TEXT           98
557
558 #define         DROP_FIELD_TOP          (-15)
559 #define         DROP_FIELD_HEIGHT       15
560
561 static HICON hIconTitleFont;
562
563 static BOOL __get_dropline( HWND hWnd, LPRECT lprect )
564 { HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT);
565     if( hWndCtl )
566   { GetWindowRect( hWndCtl, lprect );
567         MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 );
568         lprect->bottom = (lprect->top += DROP_FIELD_TOP);
569         return TRUE;
570     }
571     return FALSE;
572 }
573
574 /*************************************************************************
575  * SHAppBarMessage                      [SHELL32.@]
576  */
577 UINT WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data)
578 {
579         int width=data->rc.right - data->rc.left;
580         int height=data->rc.bottom - data->rc.top;
581         RECT rec=data->rc;
582         switch (msg)
583         { case ABM_GETSTATE:
584                return ABS_ALWAYSONTOP | ABS_AUTOHIDE;
585           case ABM_GETTASKBARPOS:
586                GetWindowRect(data->hWnd, &rec);
587                data->rc=rec;
588                return TRUE;
589           case ABM_ACTIVATE:
590                SetActiveWindow(data->hWnd);
591                return TRUE;
592           case ABM_GETAUTOHIDEBAR:
593                data->hWnd=GetActiveWindow();
594                return TRUE;
595           case ABM_NEW:
596                SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top,
597                                         width,height,SWP_SHOWWINDOW);
598                return TRUE;
599           case ABM_QUERYPOS:
600                GetWindowRect(data->hWnd, &(data->rc));
601                return TRUE;
602           case ABM_REMOVE:
603                FIXME("ABM_REMOVE broken\n");
604                /* FIXME: this is wrong; should it be DestroyWindow instead? */
605                /*CloseHandle(data->hWnd);*/
606                return TRUE;
607           case ABM_SETAUTOHIDEBAR:
608                SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top,
609                                        width,height,SWP_SHOWWINDOW);          
610                return TRUE;
611           case ABM_SETPOS:
612                data->uEdge=(ABE_RIGHT | ABE_LEFT);
613                SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top,
614                                   width,height,SWP_SHOWWINDOW);
615                return TRUE;
616           case ABM_WINDOWPOSCHANGED:
617                SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top,
618                                         width,height,SWP_SHOWWINDOW);
619                return TRUE;
620           }
621       return FALSE;
622 }
623
624 /*************************************************************************
625  * SHHelpShortcuts_RunDLL               [SHELL32.@]
626  *
627  */
628 DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
629 { FIXME("(%lx, %lx, %lx, %lx) empty stub!\n",
630         dwArg1, dwArg2, dwArg3, dwArg4);
631
632   return 0;
633 }
634
635 /*************************************************************************
636  * SHLoadInProc                         [SHELL32.@]
637  * Create an instance of specified object class from within 
638  * the shell process and release it immediately
639  */
640
641 DWORD WINAPI SHLoadInProc (REFCLSID rclsid)
642 {
643         IUnknown * pUnk = NULL;
644         TRACE("%s\n", debugstr_guid(rclsid));
645
646         CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,(LPVOID*)pUnk);
647         if(pUnk)
648         {
649           IUnknown_Release(pUnk);
650           return NOERROR;
651         }
652         return DISP_E_MEMBERNOTFOUND;
653 }
654
655 /*************************************************************************
656  * AboutDlgProc                 (internal)
657  */
658 BOOL WINAPI AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
659                               LPARAM lParam )
660 {   HWND hWndCtl;
661     char Template[512], AppTitle[512];
662
663     TRACE("\n");
664
665     switch(msg)
666     { case WM_INITDIALOG:
667       { ABOUT_INFO *info = (ABOUT_INFO *)lParam;
668             if (info)
669         { const char* const *pstr = SHELL_People;
670                 SendDlgItemMessageA(hWnd, stc1, STM_SETICON,info->hIcon, 0);
671                 GetWindowTextA( hWnd, Template, sizeof(Template) );
672                 sprintf( AppTitle, Template, info->szApp );
673                 SetWindowTextA( hWnd, AppTitle );
674                 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT),
675                                   info->szOtherStuff );
676                 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
677                 SendMessageA( hWndCtl, WM_SETREDRAW, 0, 0 );
678                 if (!hIconTitleFont)
679                 {
680                     LOGFONTA logFont;
681                     SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
682                     hIconTitleFont = CreateFontIndirectA( &logFont );
683                 }
684                 SendMessageA( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
685                 while (*pstr)
686           { SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)*pstr );
687                     pstr++;
688                 }
689                 SendMessageA( hWndCtl, WM_SETREDRAW, 1, 0 );
690             }
691         }
692         return 1;
693
694     case WM_PAINT:
695       { RECT rect;
696             PAINTSTRUCT ps;
697             HDC hDC = BeginPaint( hWnd, &ps );
698
699             if( __get_dropline( hWnd, &rect ) ) {
700                 SelectObject( hDC, GetStockObject( BLACK_PEN ) );
701                 MoveToEx( hDC, rect.left, rect.top, NULL );
702                 LineTo( hDC, rect.right, rect.bottom );
703             }
704             EndPaint( hWnd, &ps );
705         }
706         break;
707
708 #if 0  /* FIXME: should use DoDragDrop */
709     case WM_LBTRACKPOINT:
710         hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
711         if( (INT16)GetKeyState( VK_CONTROL ) < 0 )
712       { if( DragDetect( hWndCtl, *((LPPOINT)&lParam) ) )
713         { INT idx = SendMessageA( hWndCtl, LB_GETCURSEL, 0, 0 );
714                 if( idx != -1 )
715           { INT length = SendMessageA( hWndCtl, LB_GETTEXTLEN, (WPARAM)idx, 0 );
716                     HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
717                     char* pstr = (char*)GlobalLock16( hMemObj );
718
719                     if( pstr )
720             { HCURSOR hCursor = LoadCursorA( 0, MAKEINTRESOURCEA(OCR_DRAGOBJECT) );
721                         SendMessageA( hWndCtl, LB_GETTEXT, (WPARAM)idx, (LPARAM)pstr );
722                         SendMessageA( hWndCtl, LB_DELETESTRING, (WPARAM)idx, 0 );
723                         UpdateWindow( hWndCtl );
724                         if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
725                             SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)pstr );
726                     }
727             if( hMemObj )
728               GlobalFree16( hMemObj );
729                 }
730             }
731         }
732         break;
733 #endif
734
735     case WM_QUERYDROPOBJECT:
736         if( wParam == 0 )
737       { LPDRAGINFO16 lpDragInfo = MapSL((SEGPTR)lParam);
738             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
739         { RECT rect;
740                 if( __get_dropline( hWnd, &rect ) )
741           { POINT pt;
742             pt.x=lpDragInfo->pt.x;
743             pt.x=lpDragInfo->pt.y;
744                     rect.bottom += DROP_FIELD_HEIGHT;
745                     if( PtInRect( &rect, pt ) )
746             { SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
747                         return TRUE;
748                     }
749                 }
750             }
751         }
752         break;
753
754     case WM_DROPOBJECT:
755         if( wParam == hWnd )
756       { LPDRAGINFO16 lpDragInfo = MapSL((SEGPTR)lParam);
757             if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
758         { char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
759                 if( pstr )
760           { static char __appendix_str[] = " with";
761
762                     hWndCtl = GetDlgItem( hWnd, IDC_WINE_TEXT );
763                     SendMessageA( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
764                     if( !strncmp( Template, "WINE", 4 ) )
765                         SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT), Template );
766                     else
767           { char* pch = Template + strlen(Template) - strlen(__appendix_str);
768                         *pch = '\0';
769                         SendMessageA( GetDlgItem(hWnd, IDC_LISTBOX), LB_ADDSTRING, 
770                                         (WPARAM)-1, (LPARAM)Template );
771                     }
772
773                     strcpy( Template, pstr );
774                     strcat( Template, __appendix_str );
775                     SetWindowTextA( hWndCtl, Template );
776                     SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
777                     return TRUE;
778                 }
779             }
780         }
781         break;
782
783     case WM_COMMAND:
784         if (wParam == IDOK)
785     {  EndDialog(hWnd, TRUE);
786             return TRUE;
787         }
788         break;
789     case WM_CLOSE:
790       EndDialog(hWnd, TRUE);
791       break;
792     }
793
794     return 0;
795 }
796
797
798 /*************************************************************************
799  * ShellAboutA                          [SHELL32.288]
800  */
801 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
802                              HICON hIcon )
803 {   ABOUT_INFO info;
804     HRSRC hRes;
805     LPVOID template;
806     TRACE("\n");
807
808     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
809         return FALSE;
810     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
811         return FALSE;
812
813     info.szApp        = szApp;
814     info.szOtherStuff = szOtherStuff;
815     info.hIcon        = hIcon;
816     if (!hIcon) info.hIcon = LoadIconA( 0, IDI_WINLOGOA );
817     return DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
818                                       template, hWnd, AboutDlgProc, (LPARAM)&info );
819 }
820
821
822 /*************************************************************************
823  * ShellAboutW                          [SHELL32.289]
824  */
825 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
826                              HICON hIcon )
827 {   BOOL ret;
828     ABOUT_INFO info;
829     HRSRC hRes;
830     LPVOID template;
831
832     TRACE("\n");
833     
834     if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
835         return FALSE;
836     if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
837         return FALSE;
838
839     info.szApp        = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
840     info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
841     info.hIcon        = hIcon;
842     if (!hIcon) info.hIcon = LoadIconA( 0, IDI_WINLOGOA );
843     ret = DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
844                                    template, hWnd, AboutDlgProc, (LPARAM)&info );
845     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
846     HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
847     return ret;
848 }
849
850 /*************************************************************************
851  * FreeIconList (SHELL32.@)
852  */
853 void WINAPI FreeIconList( DWORD dw )
854 { FIXME("(%lx): stub\n",dw);
855 }
856
857 /***********************************************************************
858  * DllGetVersion [SHELL32.@]
859  *
860  * Retrieves version information of the 'SHELL32.DLL'
861  *
862  * PARAMS
863  *     pdvi [O] pointer to version information structure.
864  *
865  * RETURNS
866  *     Success: S_OK
867  *     Failure: E_INVALIDARG
868  *
869  * NOTES
870  *     Returns version of a shell32.dll from IE4.01 SP1.
871  */
872
873 HRESULT WINAPI SHELL32_DllGetVersion (DLLVERSIONINFO *pdvi)
874 {
875         if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
876         {
877           WARN("wrong DLLVERSIONINFO size from app\n");
878           return E_INVALIDARG;
879         }
880
881         pdvi->dwMajorVersion = 4;
882         pdvi->dwMinorVersion = 72;
883         pdvi->dwBuildNumber = 3110;
884         pdvi->dwPlatformID = 1;
885
886         TRACE("%lu.%lu.%lu.%lu\n",
887            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
888            pdvi->dwBuildNumber, pdvi->dwPlatformID);
889
890         return S_OK;
891 }
892 /*************************************************************************
893  * global variables of the shell32.dll
894  * all are once per process
895  *
896  */
897 void    (WINAPI *pDLLInitComctl)(LPVOID);
898
899 LPVOID  (WINAPI *pCOMCTL32_Alloc) (INT);  
900 BOOL    (WINAPI *pCOMCTL32_Free) (LPVOID);  
901
902 HDPA    (WINAPI *pDPA_Create) (INT);  
903 INT     (WINAPI *pDPA_InsertPtr) (const HDPA, INT, LPVOID); 
904 BOOL    (WINAPI *pDPA_Sort) (const HDPA, PFNDPACOMPARE, LPARAM); 
905 LPVOID  (WINAPI *pDPA_GetPtr) (const HDPA, INT);   
906 BOOL    (WINAPI *pDPA_Destroy) (const HDPA); 
907 INT     (WINAPI *pDPA_Search) (const HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
908 LPVOID  (WINAPI *pDPA_DeletePtr) (const HDPA hdpa, INT i);
909 HANDLE  (WINAPI *pCreateMRUListA) (LPVOID lpcml);
910 DWORD   (WINAPI *pFreeMRUListA) (HANDLE hMRUList);
911 INT     (WINAPI *pAddMRUData) (HANDLE hList, LPCVOID lpData, DWORD cbData);
912 INT     (WINAPI *pFindMRUData) (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum);
913 INT     (WINAPI *pEnumMRUListA) (HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize);
914
915 static HINSTANCE        hComctl32;
916
917 LONG            shell32_ObjCount = 0;
918 HINSTANCE       shell32_hInstance = 0; 
919 HIMAGELIST      ShellSmallIconList = 0;
920 HIMAGELIST      ShellBigIconList = 0;
921
922
923 /*************************************************************************
924  * SHELL32 LibMain
925  *
926  * NOTES
927  *  calling oleinitialize here breaks sone apps.
928  */
929
930 BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
931 {
932         TRACE("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
933
934         switch (fdwReason)
935         {
936           case DLL_PROCESS_ATTACH:
937             shell32_hInstance = hinstDLL;
938             hComctl32 = GetModuleHandleA("COMCTL32.DLL");       
939             DisableThreadLibraryCalls(shell32_hInstance);
940
941             if (!hComctl32)
942             {
943               ERR("P A N I C SHELL32 loading failed\n");
944               return FALSE;
945             }
946
947             /* comctl32 */
948             pDLLInitComctl=(void*)GetProcAddress(hComctl32,"InitCommonControlsEx");
949             pCOMCTL32_Alloc=(void*)GetProcAddress(hComctl32, (LPCSTR)71L);
950             pCOMCTL32_Free=(void*)GetProcAddress(hComctl32, (LPCSTR)73L);
951             pDPA_Create=(void*)GetProcAddress(hComctl32, (LPCSTR)328L);
952             pDPA_Destroy=(void*)GetProcAddress(hComctl32, (LPCSTR)329L);
953             pDPA_GetPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)332L);
954             pDPA_InsertPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)334L);
955             pDPA_DeletePtr=(void*)GetProcAddress(hComctl32, (LPCSTR)336L);
956             pDPA_Sort=(void*)GetProcAddress(hComctl32, (LPCSTR)338L);
957             pDPA_Search=(void*)GetProcAddress(hComctl32, (LPCSTR)339L);
958             pCreateMRUListA=(void*)GetProcAddress(hComctl32, (LPCSTR)151L /*"CreateMRUListA"*/);
959             pFreeMRUListA=(void*)GetProcAddress(hComctl32, (LPCSTR)152L /*"FreeMRUList"*/);
960             pAddMRUData=(void*)GetProcAddress(hComctl32, (LPCSTR)167L /*"AddMRUData"*/);
961             pFindMRUData=(void*)GetProcAddress(hComctl32, (LPCSTR)169L /*"FindMRUData"*/);
962             pEnumMRUListA=(void*)GetProcAddress(hComctl32, (LPCSTR)154L /*"EnumMRUListA"*/);
963
964             /* initialize the common controls */
965             if (pDLLInitComctl)
966             {
967               pDLLInitComctl(NULL);
968             }
969
970             SIC_Initialize();
971             SYSTRAY_Init();
972             InitChangeNotifications();
973             SHInitRestricted(NULL, NULL);
974             break;
975
976           case DLL_THREAD_ATTACH:
977             break;
978
979           case DLL_THREAD_DETACH:
980             break;
981
982           case DLL_PROCESS_DETACH:
983               shell32_hInstance = 0;
984
985               if (pdesktopfolder) 
986               {
987                 IShellFolder_Release(pdesktopfolder);
988                 pdesktopfolder = NULL;
989               }
990
991               SIC_Destroy();
992               FreeChangeNotifications();
993               
994               /* this one is here to check if AddRef/Release is balanced */
995               if (shell32_ObjCount)
996               {
997                 WARN("leaving with %lu objects left (memory leak)\n", shell32_ObjCount);
998               }
999               break;
1000         }
1001         return TRUE;
1002 }
1003
1004 /*************************************************************************
1005  * DllInstall         [SHELL32.@]
1006  *
1007  * PARAMETERS
1008  *   
1009  *    BOOL bInstall - TRUE for install, FALSE for uninstall
1010  *    LPCWSTR pszCmdLine - command line (unused by shell32?)
1011  */
1012
1013 HRESULT WINAPI SHELL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
1014 {
1015    FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
1016
1017    return S_OK;         /* indicate success */
1018 }
1019
1020 /***********************************************************************
1021  *              DllCanUnloadNow (SHELL32.@)
1022  */
1023 HRESULT WINAPI SHELL32_DllCanUnloadNow(void)
1024 {
1025     FIXME("(void): stub\n");
1026
1027     return S_FALSE;
1028 }