Allocate the array and strings in one lump (bug found by Malte
[wine.git] / dlls / shell32 / shell32_main.c
blob4b9bb4c80d848dbc65ed7437688e475e8fd049f8
1 /*
2 * Shell basics
4 * 1998 Marcus Meissner
5 * 1998 Juergen Schmied (jsch) * <juergen.schmied@metronet.de>
6 */
8 #include "config.h"
10 #include <stdlib.h>
11 #include <string.h>
12 #include <stdio.h>
14 #include "dlgs.h"
15 #include "shellapi.h"
16 #include "shlobj.h"
17 #include "shlguid.h"
18 #include "shlwapi.h"
19 #include "windef.h"
20 #include "winerror.h"
21 #include "winreg.h"
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"
30 #include "debugtools.h"
32 DEFAULT_DEBUG_CHANNEL(shell);
34 #define MORE_DEBUG 1
35 /*************************************************************************
36 * CommandLineToArgvW [SHELL32.@]
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'
58 * Note:
59 * '\t' == 0x0009
60 * ' ' == 0x0020
61 * '"' == 0x0022
62 * '\\' == 0x005c
64 LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs)
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;
74 if (*lpCmdline==0) {
75 /* Return the path to the executable */
76 DWORD size;
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;
89 return argv;
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++;
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;
120 cs++;
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.
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);
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;
142 /* skip the remaining spaces */
143 do {
144 s++;
145 } while (*s==0x0009 || *s==0x0020);
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.
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 '"'
167 d=d-bcount/2-1;
168 *d++='"';
169 s++;
171 bcount=0;
172 } else {
173 /* a regular character */
174 *d++=*s++;
175 bcount=0;
178 if (*arg) {
179 *d='\0';
180 argv[argc]=arg;
182 if (numargs)
183 *numargs=argc;
185 return argv;
188 /*************************************************************************
189 * SHGetFileInfoA [SHELL32.@]
193 DWORD WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes,
194 SHFILEINFOA *psfi, UINT sizeofpsfi,
195 UINT flags )
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;
205 TRACE("(%s fattr=0x%lx sfi=%p(attr=0x%08lx) size=0x%x flags=0x%x)\n",
206 (flags & SHGFI_PIDL)? "pidl" : path, dwFileAttributes, psfi, psfi->dwAttributes, sizeofpsfi, flags);
208 if ((flags & SHGFI_USEFILEATTRIBUTES) && (flags & (SHGFI_ATTRIBUTES|SHGFI_EXETYPE|SHGFI_PIDL)))
209 return FALSE;
211 /* windows initializes this values regardless of the flags */
212 psfi->szDisplayName[0] = '\0';
213 psfi->szTypeName[0] = '\0';
214 psfi->iIcon = 0;
216 if (flags & SHGFI_EXETYPE) {
217 BOOL status = FALSE;
218 HANDLE hfile;
219 DWORD BinaryType;
220 IMAGE_DOS_HEADER mz_header;
221 IMAGE_NT_HEADERS nt;
222 DWORD len;
223 char magic[4];
225 if (flags != SHGFI_EXETYPE) return 0;
227 status = GetBinaryTypeA (path, &BinaryType);
228 if (!status) return 0;
229 if ((BinaryType == SCS_DOS_BINARY)
230 || (BinaryType == SCS_PIF_BINARY)) return 0x4d5a;
232 hfile = CreateFileA( path, GENERIC_READ, FILE_SHARE_READ,
233 NULL, OPEN_EXISTING, 0, 0 );
234 if ( hfile == INVALID_HANDLE_VALUE ) return 0;
236 /* The next section is adapted from MODULE_GetBinaryType, as we need
237 * to examine the image header to get OS and version information. We
238 * know from calling GetBinaryTypeA that the image is valid and either
239 * an NE or PE, so much error handling can be omitted.
240 * Seek to the start of the file and read the header information.
243 SetFilePointer( hfile, 0, NULL, SEEK_SET );
244 ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL );
246 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
247 ReadFile( hfile, magic, sizeof(magic), &len, NULL );
248 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
250 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
251 ReadFile( hfile, &nt, sizeof(nt), &len, NULL );
252 CloseHandle( hfile );
253 if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
254 return IMAGE_NT_SIGNATURE
255 | (nt.OptionalHeader.MajorSubsystemVersion << 24)
256 | (nt.OptionalHeader.MinorSubsystemVersion << 16);
258 return IMAGE_NT_SIGNATURE;
260 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
262 IMAGE_OS2_HEADER ne;
263 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET );
264 ReadFile( hfile, &ne, sizeof(ne), &len, NULL );
265 CloseHandle( hfile );
266 if (ne.ne_exetyp == 2) return IMAGE_OS2_SIGNATURE
267 | (ne.ne_expver << 16);
268 return 0;
270 CloseHandle( hfile );
271 return 0;
275 /* translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES in not specified
276 the pidl functions fail on not existing file names */
277 if (flags & SHGFI_PIDL)
279 pidl = (LPCITEMIDLIST) path;
280 if (!pidl )
282 ERR("pidl is null!\n");
283 return FALSE;
286 else if (!(flags & SHGFI_USEFILEATTRIBUTES))
288 hr = SHILCreateFromPathA ( path, &pidl, &dwAttributes);
289 /* note: the attributes in ISF::ParseDisplayName are not implemented */
292 /* get the parent shellfolder */
293 if (pidl)
295 hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, &pidlLast);
298 /* get the attributes of the child */
299 if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES))
301 if (!(flags & SHGFI_ATTR_SPECIFIED))
303 psfi->dwAttributes = 0xffffffff;
305 IShellFolder_GetAttributesOf(psfParent, 1 , &pidlLast, &(psfi->dwAttributes));
308 /* get the displayname */
309 if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME))
311 if (flags & SHGFI_USEFILEATTRIBUTES)
313 strcpy (psfi->szDisplayName, PathFindFileNameA(path));
315 else
317 STRRET str;
318 hr = IShellFolder_GetDisplayNameOf(psfParent, pidlLast, SHGDN_INFOLDER, &str);
319 StrRetToStrNA (psfi->szDisplayName, MAX_PATH, &str, pidlLast);
323 /* get the type name */
324 if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME))
326 _ILGetFileType(pidlLast, psfi->szTypeName, 80);
329 /* ### icons ###*/
330 if (flags & SHGFI_LINKOVERLAY)
331 FIXME("set icon to link, stub\n");
333 if (flags & SHGFI_SELECTED)
334 FIXME("set icon to selected, stub\n");
336 if (flags & SHGFI_SHELLICONSIZE)
337 FIXME("set icon to shell size, stub\n");
339 /* get the iconlocation */
340 if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION ))
342 UINT uDummy,uFlags;
343 hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, &pidlLast, &IID_IExtractIconA, &uDummy, (LPVOID*)&pei);
345 if (SUCCEEDED(hr))
347 hr = IExtractIconA_GetIconLocation(pei, (flags & SHGFI_OPENICON)? GIL_OPENICON : 0,szLoaction, MAX_PATH, &iIndex, &uFlags);
348 /* fixme what to do with the index? */
350 if(uFlags != GIL_NOTFILENAME)
351 strcpy (psfi->szDisplayName, szLoaction);
352 else
353 ret = FALSE;
355 IExtractIconA_Release(pei);
359 /* get icon index (or load icon)*/
360 if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX)))
362 if (flags & SHGFI_USEFILEATTRIBUTES)
364 char sTemp [MAX_PATH];
365 char * szExt;
366 DWORD dwNr=0;
368 lstrcpynA(sTemp, path, MAX_PATH);
369 szExt = (LPSTR) PathFindExtensionA(sTemp);
370 if( szExt && HCR_MapTypeToValue(szExt, sTemp, MAX_PATH, TRUE)
371 && HCR_GetDefaultIcon(sTemp, sTemp, MAX_PATH, &dwNr))
373 if (!strcmp("%1",sTemp)) /* icon is in the file */
375 strcpy(sTemp, path);
377 /* FIXME: if sTemp contains a valid filename, get the icon
378 from there, index is in dwNr
380 psfi->iIcon = 2;
382 else /* default icon */
384 psfi->iIcon = 0;
387 else
389 if (!(PidlToSicIndex(psfParent, pidlLast, (flags & SHGFI_LARGEICON),
390 (flags & SHGFI_OPENICON)? GIL_OPENICON : 0, &(psfi->iIcon))))
392 ret = FALSE;
395 if (ret)
397 ret = (DWORD) ((flags & SHGFI_LARGEICON) ? ShellBigIconList : ShellSmallIconList);
401 /* icon handle */
402 if (SUCCEEDED(hr) && (flags & SHGFI_ICON))
403 psfi->hIcon = ImageList_GetIcon((flags & SHGFI_LARGEICON) ? ShellBigIconList:ShellSmallIconList, psfi->iIcon, ILD_NORMAL);
405 if (flags & (SHGFI_UNKNOWN1 | SHGFI_UNKNOWN2 | SHGFI_UNKNOWN3))
406 FIXME("unknown attribute!\n");
408 if (psfParent)
409 IShellFolder_Release(psfParent);
411 if (hr != S_OK)
412 ret = FALSE;
414 if(pidlLast) SHFree(pidlLast);
415 #ifdef MORE_DEBUG
416 TRACE ("icon=0x%08x index=0x%08x attr=0x%08lx name=%s type=%s ret=0x%08lx\n",
417 psfi->hIcon, psfi->iIcon, psfi->dwAttributes, psfi->szDisplayName, psfi->szTypeName, ret);
418 #endif
419 return ret;
422 /*************************************************************************
423 * SHGetFileInfoW [SHELL32.@]
426 DWORD WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes,
427 SHFILEINFOW *psfi, UINT sizeofpsfi,
428 UINT flags )
430 INT len;
431 LPSTR temppath;
432 DWORD ret;
433 SHFILEINFOA temppsfi;
435 len = WideCharToMultiByte(CP_ACP, 0, path, -1, NULL, 0, NULL, NULL);
436 temppath = HeapAlloc(GetProcessHeap(), 0, len);
437 WideCharToMultiByte(CP_ACP, 0, path, -1, temppath, len, NULL, NULL);
439 WideCharToMultiByte(CP_ACP, 0, psfi->szDisplayName, -1, temppsfi.szDisplayName,
440 sizeof(temppsfi.szDisplayName), NULL, NULL);
441 WideCharToMultiByte(CP_ACP, 0, psfi->szTypeName, -1, temppsfi.szTypeName,
442 sizeof(temppsfi.szTypeName), NULL, NULL);
444 ret = SHGetFileInfoA(temppath, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags);
446 HeapFree(GetProcessHeap(), 0, temppath);
448 return ret;
451 /*************************************************************************
452 * SHGetFileInfo [SHELL32.@]
454 DWORD WINAPI SHGetFileInfoAW(
455 LPCVOID path,
456 DWORD dwFileAttributes,
457 LPVOID psfi,
458 UINT sizeofpsfi,
459 UINT flags)
461 if(SHELL_OsIsUnicode())
462 return SHGetFileInfoW(path, dwFileAttributes, psfi, sizeofpsfi, flags );
463 return SHGetFileInfoA(path, dwFileAttributes, psfi, sizeofpsfi, flags );
466 /*************************************************************************
467 * DuplicateIcon [SHELL32.@]
469 HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon)
471 ICONINFO IconInfo;
472 HICON hDupIcon = 0;
474 TRACE("(%04x, %04x)\n", hInstance, hIcon);
476 if(GetIconInfo(hIcon, &IconInfo))
478 hDupIcon = CreateIconIndirect(&IconInfo);
480 /* clean up hbmMask and hbmColor */
481 DeleteObject(IconInfo.hbmMask);
482 DeleteObject(IconInfo.hbmColor);
485 return hDupIcon;
489 /*************************************************************************
490 * ExtractIconA [SHELL32.@]
492 * FIXME
493 * if the filename is not a file return 1
495 HICON WINAPI ExtractIconA( HINSTANCE hInstance, LPCSTR lpszExeFileName,
496 UINT nIconIndex )
497 { HGLOBAL16 handle = InternalExtractIcon16(hInstance,lpszExeFileName,nIconIndex, 1);
498 TRACE("\n");
499 if( handle )
501 HICON16* ptr = (HICON16*)GlobalLock16(handle);
502 HICON16 hIcon = *ptr;
504 GlobalFree16(handle);
505 return hIcon;
507 return 0;
510 /*************************************************************************
511 * ExtractIconW [SHELL32.@]
513 * fixme
514 * is the filename is not a file return 1
516 HICON WINAPI ExtractIconW( HINSTANCE hInstance, LPCWSTR lpszExeFileName,
517 UINT nIconIndex )
518 { LPSTR exefn;
519 HICON ret;
520 TRACE("\n");
522 exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
523 ret = ExtractIconA(hInstance,exefn,nIconIndex);
525 HeapFree(GetProcessHeap(),0,exefn);
526 return ret;
529 /*************************************************************************
530 * FindExecutableA [SHELL32.@]
532 HINSTANCE WINAPI FindExecutableA( LPCSTR lpFile, LPCSTR lpDirectory,
533 LPSTR lpResult )
535 HINSTANCE retval=31; /* default - 'No association was found' */
536 char old_dir[1024];
538 TRACE("File %s, Dir %s\n",
539 (lpFile != NULL?lpFile:"-"),
540 (lpDirectory != NULL?lpDirectory:"-"));
542 lpResult[0]='\0'; /* Start off with an empty return string */
544 /* trap NULL parameters on entry */
545 if (( lpFile == NULL ) || ( lpResult == NULL ))
546 { /* FIXME - should throw a warning, perhaps! */
547 return 2; /* File not found. Close enough, I guess. */
550 if (lpDirectory)
551 { GetCurrentDirectoryA( sizeof(old_dir), old_dir );
552 SetCurrentDirectoryA( lpDirectory );
555 retval = SHELL_FindExecutable( lpFile, "open", lpResult );
557 TRACE("returning %s\n", lpResult);
558 if (lpDirectory)
559 SetCurrentDirectoryA( old_dir );
560 return retval;
563 /*************************************************************************
564 * FindExecutableW [SHELL32.@]
566 HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory,
567 LPWSTR lpResult)
569 FIXME("(%p,%p,%p): stub\n", lpFile, lpDirectory, lpResult);
570 return 31; /* default - 'No association was found' */
573 typedef struct
574 { LPCSTR szApp;
575 LPCSTR szOtherStuff;
576 HICON hIcon;
577 } ABOUT_INFO;
579 #define IDC_STATIC_TEXT 100
580 #define IDC_LISTBOX 99
581 #define IDC_WINE_TEXT 98
583 #define DROP_FIELD_TOP (-15)
584 #define DROP_FIELD_HEIGHT 15
586 static HICON hIconTitleFont;
588 static BOOL __get_dropline( HWND hWnd, LPRECT lprect )
589 { HWND hWndCtl = GetDlgItem(hWnd, IDC_WINE_TEXT);
590 if( hWndCtl )
591 { GetWindowRect( hWndCtl, lprect );
592 MapWindowPoints( 0, hWnd, (LPPOINT)lprect, 2 );
593 lprect->bottom = (lprect->top += DROP_FIELD_TOP);
594 return TRUE;
596 return FALSE;
599 /*************************************************************************
600 * SHAppBarMessage [SHELL32.@]
602 UINT WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data)
604 int width=data->rc.right - data->rc.left;
605 int height=data->rc.bottom - data->rc.top;
606 RECT rec=data->rc;
607 switch (msg)
608 { case ABM_GETSTATE:
609 return ABS_ALWAYSONTOP | ABS_AUTOHIDE;
610 case ABM_GETTASKBARPOS:
611 GetWindowRect(data->hWnd, &rec);
612 data->rc=rec;
613 return TRUE;
614 case ABM_ACTIVATE:
615 SetActiveWindow(data->hWnd);
616 return TRUE;
617 case ABM_GETAUTOHIDEBAR:
618 data->hWnd=GetActiveWindow();
619 return TRUE;
620 case ABM_NEW:
621 SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top,
622 width,height,SWP_SHOWWINDOW);
623 return TRUE;
624 case ABM_QUERYPOS:
625 GetWindowRect(data->hWnd, &(data->rc));
626 return TRUE;
627 case ABM_REMOVE:
628 FIXME("ABM_REMOVE broken\n");
629 /* FIXME: this is wrong; should it be DestroyWindow instead? */
630 /*CloseHandle(data->hWnd);*/
631 return TRUE;
632 case ABM_SETAUTOHIDEBAR:
633 SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top,
634 width,height,SWP_SHOWWINDOW);
635 return TRUE;
636 case ABM_SETPOS:
637 data->uEdge=(ABE_RIGHT | ABE_LEFT);
638 SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top,
639 width,height,SWP_SHOWWINDOW);
640 return TRUE;
641 case ABM_WINDOWPOSCHANGED:
642 SetWindowPos(data->hWnd,HWND_TOP,rec.left,rec.top,
643 width,height,SWP_SHOWWINDOW);
644 return TRUE;
646 return FALSE;
649 /*************************************************************************
650 * SHHelpShortcuts_RunDLL [SHELL32.@]
653 DWORD WINAPI SHHelpShortcuts_RunDLL (DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4)
654 { FIXME("(%lx, %lx, %lx, %lx) empty stub!\n",
655 dwArg1, dwArg2, dwArg3, dwArg4);
657 return 0;
660 /*************************************************************************
661 * SHLoadInProc [SHELL32.@]
662 * Create an instance of specified object class from within
663 * the shell process and release it immediately
666 DWORD WINAPI SHLoadInProc (REFCLSID rclsid)
668 IUnknown * pUnk = NULL;
669 TRACE("%s\n", debugstr_guid(rclsid));
671 CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,(LPVOID*)pUnk);
672 if(pUnk)
674 IUnknown_Release(pUnk);
675 return NOERROR;
677 return DISP_E_MEMBERNOTFOUND;
680 /*************************************************************************
681 * ShellExecuteA [SHELL32.290]
683 HINSTANCE WINAPI ShellExecuteA( HWND hWnd, LPCSTR lpOperation,
684 LPCSTR lpFile, LPCSTR lpParameters,
685 LPCSTR lpDirectory, INT iShowCmd )
686 { TRACE("\n");
687 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
688 lpDirectory, iShowCmd );
691 /*************************************************************************
692 * ShellExecuteW [SHELL32.294]
693 * from shellapi.h
694 * WINSHELLAPI HINSTANCE APIENTRY ShellExecuteW(HWND hwnd, LPCWSTR lpOperation,
695 * LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd);
697 HINSTANCE WINAPI
698 ShellExecuteW(
699 HWND hwnd,
700 LPCWSTR lpOperation,
701 LPCWSTR lpFile,
702 LPCWSTR lpParameters,
703 LPCWSTR lpDirectory,
704 INT nShowCmd) {
706 FIXME(": stub\n");
707 return 0;
710 /*************************************************************************
711 * AboutDlgProc (internal)
713 BOOL WINAPI AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam,
714 LPARAM lParam )
715 { HWND hWndCtl;
716 char Template[512], AppTitle[512];
718 TRACE("\n");
720 switch(msg)
721 { case WM_INITDIALOG:
722 { ABOUT_INFO *info = (ABOUT_INFO *)lParam;
723 if (info)
724 { const char* const *pstr = SHELL_People;
725 SendDlgItemMessageA(hWnd, stc1, STM_SETICON,info->hIcon, 0);
726 GetWindowTextA( hWnd, Template, sizeof(Template) );
727 sprintf( AppTitle, Template, info->szApp );
728 SetWindowTextA( hWnd, AppTitle );
729 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT),
730 info->szOtherStuff );
731 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
732 SendMessageA( hWndCtl, WM_SETREDRAW, 0, 0 );
733 if (!hIconTitleFont)
735 LOGFONTA logFont;
736 SystemParametersInfoA( SPI_GETICONTITLELOGFONT, 0, &logFont, 0 );
737 hIconTitleFont = CreateFontIndirectA( &logFont );
739 SendMessageA( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
740 while (*pstr)
741 { SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)*pstr );
742 pstr++;
744 SendMessageA( hWndCtl, WM_SETREDRAW, 1, 0 );
747 return 1;
749 case WM_PAINT:
750 { RECT rect;
751 PAINTSTRUCT ps;
752 HDC hDC = BeginPaint( hWnd, &ps );
754 if( __get_dropline( hWnd, &rect ) ) {
755 SelectObject( hDC, GetStockObject( BLACK_PEN ) );
756 MoveToEx( hDC, rect.left, rect.top, NULL );
757 LineTo( hDC, rect.right, rect.bottom );
759 EndPaint( hWnd, &ps );
761 break;
763 #if 0 /* FIXME: should use DoDragDrop */
764 case WM_LBTRACKPOINT:
765 hWndCtl = GetDlgItem(hWnd, IDC_LISTBOX);
766 if( (INT16)GetKeyState( VK_CONTROL ) < 0 )
767 { if( DragDetect( hWndCtl, *((LPPOINT)&lParam) ) )
768 { INT idx = SendMessageA( hWndCtl, LB_GETCURSEL, 0, 0 );
769 if( idx != -1 )
770 { INT length = SendMessageA( hWndCtl, LB_GETTEXTLEN, (WPARAM)idx, 0 );
771 HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
772 char* pstr = (char*)GlobalLock16( hMemObj );
774 if( pstr )
775 { HCURSOR hCursor = LoadCursorA( 0, MAKEINTRESOURCEA(OCR_DRAGOBJECT) );
776 SendMessageA( hWndCtl, LB_GETTEXT, (WPARAM)idx, (LPARAM)pstr );
777 SendMessageA( hWndCtl, LB_DELETESTRING, (WPARAM)idx, 0 );
778 UpdateWindow( hWndCtl );
779 if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
780 SendMessageA( hWndCtl, LB_ADDSTRING, (WPARAM)-1, (LPARAM)pstr );
782 if( hMemObj )
783 GlobalFree16( hMemObj );
787 break;
788 #endif
790 case WM_QUERYDROPOBJECT:
791 if( wParam == 0 )
792 { LPDRAGINFO16 lpDragInfo = MapSL((SEGPTR)lParam);
793 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
794 { RECT rect;
795 if( __get_dropline( hWnd, &rect ) )
796 { POINT pt;
797 pt.x=lpDragInfo->pt.x;
798 pt.x=lpDragInfo->pt.y;
799 rect.bottom += DROP_FIELD_HEIGHT;
800 if( PtInRect( &rect, pt ) )
801 { SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
802 return TRUE;
807 break;
809 case WM_DROPOBJECT:
810 if( wParam == hWnd )
811 { LPDRAGINFO16 lpDragInfo = MapSL((SEGPTR)lParam);
812 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
813 { char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
814 if( pstr )
815 { static char __appendix_str[] = " with";
817 hWndCtl = GetDlgItem( hWnd, IDC_WINE_TEXT );
818 SendMessageA( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
819 if( !strncmp( Template, "WINE", 4 ) )
820 SetWindowTextA( GetDlgItem(hWnd, IDC_STATIC_TEXT), Template );
821 else
822 { char* pch = Template + strlen(Template) - strlen(__appendix_str);
823 *pch = '\0';
824 SendMessageA( GetDlgItem(hWnd, IDC_LISTBOX), LB_ADDSTRING,
825 (WPARAM)-1, (LPARAM)Template );
828 strcpy( Template, pstr );
829 strcat( Template, __appendix_str );
830 SetWindowTextA( hWndCtl, Template );
831 SetWindowLongA( hWnd, DWL_MSGRESULT, 1 );
832 return TRUE;
836 break;
838 case WM_COMMAND:
839 if (wParam == IDOK)
840 { EndDialog(hWnd, TRUE);
841 return TRUE;
843 break;
844 case WM_CLOSE:
845 EndDialog(hWnd, TRUE);
846 break;
849 return 0;
853 /*************************************************************************
854 * ShellAboutA [SHELL32.288]
856 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
857 HICON hIcon )
858 { ABOUT_INFO info;
859 HRSRC hRes;
860 LPVOID template;
861 TRACE("\n");
863 if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
864 return FALSE;
865 if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
866 return FALSE;
868 info.szApp = szApp;
869 info.szOtherStuff = szOtherStuff;
870 info.hIcon = hIcon;
871 if (!hIcon) info.hIcon = LoadIconA( 0, IDI_WINLOGOA );
872 return DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
873 template, hWnd, AboutDlgProc, (LPARAM)&info );
877 /*************************************************************************
878 * ShellAboutW [SHELL32.289]
880 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
881 HICON hIcon )
882 { BOOL ret;
883 ABOUT_INFO info;
884 HRSRC hRes;
885 LPVOID template;
887 TRACE("\n");
889 if(!(hRes = FindResourceA(shell32_hInstance, "SHELL_ABOUT_MSGBOX", RT_DIALOGA)))
890 return FALSE;
891 if(!(template = (LPVOID)LoadResource(shell32_hInstance, hRes)))
892 return FALSE;
894 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
895 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
896 info.hIcon = hIcon;
897 if (!hIcon) info.hIcon = LoadIconA( 0, IDI_WINLOGOA );
898 ret = DialogBoxIndirectParamA( GetWindowLongA( hWnd, GWL_HINSTANCE ),
899 template, hWnd, AboutDlgProc, (LPARAM)&info );
900 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
901 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
902 return ret;
905 /*************************************************************************
906 * FreeIconList (SHELL32.@)
908 void WINAPI FreeIconList( DWORD dw )
909 { FIXME("(%lx): stub\n",dw);
912 /***********************************************************************
913 * DllGetVersion [SHELL32.@]
915 * Retrieves version information of the 'SHELL32.DLL'
917 * PARAMS
918 * pdvi [O] pointer to version information structure.
920 * RETURNS
921 * Success: S_OK
922 * Failure: E_INVALIDARG
924 * NOTES
925 * Returns version of a shell32.dll from IE4.01 SP1.
928 HRESULT WINAPI SHELL32_DllGetVersion (DLLVERSIONINFO *pdvi)
930 if (pdvi->cbSize != sizeof(DLLVERSIONINFO))
932 WARN("wrong DLLVERSIONINFO size from app\n");
933 return E_INVALIDARG;
936 pdvi->dwMajorVersion = 4;
937 pdvi->dwMinorVersion = 72;
938 pdvi->dwBuildNumber = 3110;
939 pdvi->dwPlatformID = 1;
941 TRACE("%lu.%lu.%lu.%lu\n",
942 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
943 pdvi->dwBuildNumber, pdvi->dwPlatformID);
945 return S_OK;
947 /*************************************************************************
948 * global variables of the shell32.dll
949 * all are once per process
952 void WINAPI (*pDLLInitComctl)(LPVOID);
954 LPVOID WINAPI (*pCOMCTL32_Alloc) (INT);
955 BOOL WINAPI (*pCOMCTL32_Free) (LPVOID);
957 HDPA WINAPI (*pDPA_Create) (INT);
958 INT WINAPI (*pDPA_InsertPtr) (const HDPA, INT, LPVOID);
959 BOOL WINAPI (*pDPA_Sort) (const HDPA, PFNDPACOMPARE, LPARAM);
960 LPVOID WINAPI (*pDPA_GetPtr) (const HDPA, INT);
961 BOOL WINAPI (*pDPA_Destroy) (const HDPA);
962 INT WINAPI (*pDPA_Search) (const HDPA, LPVOID, INT, PFNDPACOMPARE, LPARAM, UINT);
963 LPVOID WINAPI (*pDPA_DeletePtr) (const HDPA hdpa, INT i);
964 HANDLE WINAPI (*pCreateMRUListA) (LPVOID lpcml);
965 DWORD WINAPI (*pFreeMRUListA) (HANDLE hMRUList);
966 INT WINAPI (*pAddMRUData) (HANDLE hList, LPCVOID lpData, DWORD cbData);
967 INT WINAPI (*pFindMRUData) (HANDLE hList, LPCVOID lpData, DWORD cbData, LPINT lpRegNum);
968 INT WINAPI (*pEnumMRUListA) (HANDLE hList, INT nItemPos, LPVOID lpBuffer, DWORD nBufferSize);
970 static HINSTANCE hComctl32;
972 LONG shell32_ObjCount = 0;
973 HINSTANCE shell32_hInstance = 0;
974 HIMAGELIST ShellSmallIconList = 0;
975 HIMAGELIST ShellBigIconList = 0;
978 /*************************************************************************
979 * SHELL32 LibMain
981 * NOTES
982 * calling oleinitialize here breaks sone apps.
985 BOOL WINAPI Shell32LibMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
987 TRACE("0x%x 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
989 switch (fdwReason)
991 case DLL_PROCESS_ATTACH:
992 shell32_hInstance = hinstDLL;
993 hComctl32 = GetModuleHandleA("COMCTL32.DLL");
994 DisableThreadLibraryCalls(shell32_hInstance);
996 if (!hComctl32)
998 ERR("P A N I C SHELL32 loading failed\n");
999 return FALSE;
1002 /* comctl32 */
1003 pDLLInitComctl=(void*)GetProcAddress(hComctl32,"InitCommonControlsEx");
1004 pCOMCTL32_Alloc=(void*)GetProcAddress(hComctl32, (LPCSTR)71L);
1005 pCOMCTL32_Free=(void*)GetProcAddress(hComctl32, (LPCSTR)73L);
1006 pDPA_Create=(void*)GetProcAddress(hComctl32, (LPCSTR)328L);
1007 pDPA_Destroy=(void*)GetProcAddress(hComctl32, (LPCSTR)329L);
1008 pDPA_GetPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)332L);
1009 pDPA_InsertPtr=(void*)GetProcAddress(hComctl32, (LPCSTR)334L);
1010 pDPA_DeletePtr=(void*)GetProcAddress(hComctl32, (LPCSTR)336L);
1011 pDPA_Sort=(void*)GetProcAddress(hComctl32, (LPCSTR)338L);
1012 pDPA_Search=(void*)GetProcAddress(hComctl32, (LPCSTR)339L);
1013 pCreateMRUListA=(void*)GetProcAddress(hComctl32, (LPCSTR)151L /*"CreateMRUListA"*/);
1014 pFreeMRUListA=(void*)GetProcAddress(hComctl32, (LPCSTR)152L /*"FreeMRUList"*/);
1015 pAddMRUData=(void*)GetProcAddress(hComctl32, (LPCSTR)167L /*"AddMRUData"*/);
1016 pFindMRUData=(void*)GetProcAddress(hComctl32, (LPCSTR)169L /*"FindMRUData"*/);
1017 pEnumMRUListA=(void*)GetProcAddress(hComctl32, (LPCSTR)154L /*"EnumMRUListA"*/);
1019 /* initialize the common controls */
1020 if (pDLLInitComctl)
1022 pDLLInitComctl(NULL);
1025 SIC_Initialize();
1026 SYSTRAY_Init();
1027 InitChangeNotifications();
1028 SHInitRestricted(NULL, NULL);
1029 break;
1031 case DLL_THREAD_ATTACH:
1032 break;
1034 case DLL_THREAD_DETACH:
1035 break;
1037 case DLL_PROCESS_DETACH:
1038 shell32_hInstance = 0;
1040 if (pdesktopfolder)
1042 IShellFolder_Release(pdesktopfolder);
1043 pdesktopfolder = NULL;
1046 SIC_Destroy();
1047 FreeChangeNotifications();
1049 /* this one is here to check if AddRef/Release is balanced */
1050 if (shell32_ObjCount)
1052 WARN("leaving with %lu objects left (memory leak)\n", shell32_ObjCount);
1054 break;
1056 return TRUE;
1059 /*************************************************************************
1060 * DllInstall [SHELL32.@]
1062 * PARAMETERS
1064 * BOOL bInstall - TRUE for install, FALSE for uninstall
1065 * LPCWSTR pszCmdLine - command line (unused by shell32?)
1068 HRESULT WINAPI SHELL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
1070 FIXME("(%s, %s): stub!\n", bInstall ? "TRUE":"FALSE", debugstr_w(cmdline));
1072 return S_OK; /* indicate success */
1075 /***********************************************************************
1076 * DllCanUnloadNow (SHELL32.@)
1078 HRESULT WINAPI SHELL32_DllCanUnloadNow(void)
1080 FIXME("(void): stub\n");
1082 return S_FALSE;