Release 980329
[wine/multimedia.git] / misc / shell.c
blob545ecdc5a2007243a738edd8467ef09f5ef75726
1 /*
2 * Shell Library Functions
3 */
4 #include <assert.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <ctype.h>
10 #include "windows.h"
11 #include "winerror.h"
12 #include "file.h"
13 #include "shell.h"
14 #include "heap.h"
15 #include "module.h"
16 #include "neexe.h"
17 #include "resource.h"
18 #include "dlgs.h"
19 #include "win.h"
20 #include "graphics.h"
21 #include "cursoricon.h"
22 #include "interfaces.h"
23 #include "sysmetrics.h"
24 #include "shlobj.h"
25 #include "debug.h"
26 #include "winreg.h"
28 static const char * const SHELL_People[] =
30 "Bob Amstadt",
31 "Dag Asheim",
32 "Martin Ayotte",
33 "Karl Backstr\366m",
34 "Peter Bajusz",
35 "Marcel Baur",
36 "Georg Beyerle",
37 "Ross Biro",
38 "Martin Boehme",
39 "Uwe Bonnes",
40 "Erik Bos",
41 "Fons Botman",
42 "John Brezak",
43 "Andrew Bulhak",
44 "John Burton",
45 "Niels de Carpentier",
46 "Gordon Chaffee",
47 "Jimen Ching",
48 "David A. Cuthbert",
49 "Huw D. M. Davies",
50 "Roman Dolejsi",
51 "Frans van Dorsselaer",
52 "Chris Faherty",
53 "Carsten Fallesen",
54 "Paul Falstad",
55 "David Faure",
56 "Claus Fischer",
57 "Olaf Flebbe",
58 "Chad Fraleigh",
59 "Peter Galbavy",
60 "Ramon Garcia",
61 "Matthew Ghio",
62 "Jody Goldberg",
63 "Hans de Graaff",
64 "Charles M. Hannum",
65 "Adrian Harvey",
66 "John Harvey",
67 "Cameron Heide",
68 "Jochen Hoenicke",
69 "Onno Hovers",
70 "Jeffrey Hsu",
71 "Miguel de Icaza",
72 "Jukka Iivonen",
73 "Lee Jaekil",
74 "Alexandre Julliard",
75 "Bang Jun-Young",
76 "Pavel Kankovsky",
77 "Jochen Karrer",
78 "Andreas Kirschbaum",
79 "Albrecht Kleine",
80 "Eric Kohl",
81 "Jon Konrath",
82 "Alex Korobka",
83 "Greg Kreider",
84 "Anand Kumria",
85 "Scott A. Laird",
86 "David Lee Lambert",
87 "Andrew Lewycky",
88 "Martin von Loewis",
89 "Michiel van Loon",
90 "Kenneth MacDonald",
91 "Peter MacDonald",
92 "William Magro",
93 "Juergen Marquardt",
94 "Ricardo Massaro",
95 "Marcus Meissner",
96 "Graham Menhennitt",
97 "David Metcalfe",
98 "Bruce Milner",
99 "Steffen Moeller",
100 "Andreas Mohr",
101 "James Moody",
102 "Philippe De Muyter",
103 "Itai Nahshon",
104 "Kristian Nielsen",
105 "Henrik Olsen",
106 "Michael Patra",
107 "Dimitrie O. Paun",
108 "Jim Peterson",
109 "Robert Pouliot",
110 "Keith Reynolds",
111 "Slaven Rezic",
112 "John Richardson",
113 "Rick Richardson",
114 "Doug Ridgway",
115 "Bernhard Rosenkraenzer",
116 "Johannes Ruscheinski",
117 "Thomas Sandford",
118 "Constantine Sapuntzakis",
119 "Pablo Saratxaga",
120 "Daniel Schepler",
121 "Peter Schlaile",
122 "Ulrich Schmid",
123 "Bernd Schmidt",
124 "Ingo Schneider",
125 "Victor Schneider",
126 "Yngvi Sigurjonsson",
127 "Stephen Simmons",
128 "Rick Sladkey",
129 "William Smith",
130 "Dominik Strasser",
131 "Vadim Strizhevsky",
132 "Bertho Stultiens",
133 "Erik Svendsen",
134 "Tristan Tarrant",
135 "Andrew Taylor",
136 "Duncan C Thomson",
137 "Goran Thyni",
138 "Jimmy Tirtawangsa",
139 "Jon Tombs",
140 "Linus Torvalds",
141 "Gregory Trubetskoy",
142 "Petri Tuomola",
143 "Michael Veksler",
144 "Sven Verdoolaege",
145 "Ronan Waide",
146 "Eric Warnke",
147 "Manfred Weichel",
148 "Morten Welinder",
149 "Len White",
150 "Lawson Whitney",
151 "Jan Willamowius",
152 "Carl Williams",
153 "Karl Guenter Wuensch",
154 "Eric Youngdale",
155 "James Youngman",
156 "Nikita V. Youshchenko",
157 "Mikolaj Zalewski",
158 "John Zero",
159 "Luiz Otavio L. Zorzella",
160 NULL
164 /* .ICO file ICONDIR definitions */
166 #pragma pack(1)
168 typedef struct
170 BYTE bWidth; /* Width, in pixels, of the image */
171 BYTE bHeight; /* Height, in pixels, of the image */
172 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
173 BYTE bReserved; /* Reserved ( must be 0) */
174 WORD wPlanes; /* Color Planes */
175 WORD wBitCount; /* Bits per pixel */
176 DWORD dwBytesInRes; /* How many bytes in this resource? */
177 DWORD dwImageOffset; /* Where in the file is this image? */
178 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
180 typedef struct
182 WORD idReserved; /* Reserved (must be 0) */
183 WORD idType; /* Resource Type (1 for icons) */
184 WORD idCount; /* How many images? */
185 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
186 } icoICONDIR, *LPicoICONDIR;
188 #pragma pack(4)
190 static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
191 static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
192 static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
194 static HWND16 SHELL_hWnd = 0;
195 static HHOOK SHELL_hHook = 0;
196 static UINT16 uMsgWndCreated = 0;
197 static UINT16 uMsgWndDestroyed = 0;
198 static UINT16 uMsgShellActivate = 0;
200 /*************************************************************************
201 * DragAcceptFiles [SHELL.9]
203 void WINAPI DragAcceptFiles(HWND16 hWnd, BOOL16 b)
205 WND* wnd = WIN_FindWndPtr(hWnd);
207 if( wnd )
208 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
209 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
213 /*************************************************************************
214 * DragQueryFile [SHELL.11]
216 UINT16 WINAPI DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile,
217 WORD wLength)
219 /* hDrop is a global memory block allocated with GMEM_SHARE
220 * with DROPFILESTRUCT as a header and filenames following
221 * it, zero length filename is in the end */
223 LPDROPFILESTRUCT lpDropFileStruct;
224 LPSTR lpCurrent;
225 WORD i;
227 TRACE(reg,"(%04x, %i, %p, %u)\n",
228 hDrop,wFile,lpszFile,wLength);
230 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
231 if(!lpDropFileStruct) return 0;
233 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
235 i = 0;
236 while (i++ < wFile)
238 while (*lpCurrent++); /* skip filename */
239 if (!*lpCurrent)
240 return (wFile == 0xFFFF) ? i : 0;
243 i = strlen(lpCurrent);
244 if (!lpszFile) return i+1; /* needed buffer size */
246 i = (wLength > i) ? i : wLength-1;
247 strncpy(lpszFile, lpCurrent, i);
248 lpszFile[i] = '\0';
250 GlobalUnlock16(hDrop);
251 return i;
255 /*************************************************************************
256 * DragFinish [SHELL.12]
258 void WINAPI DragFinish(HDROP16 h)
260 GlobalFree16((HGLOBAL16)h);
264 /*************************************************************************
265 * DragQueryPoint [SHELL.13]
267 BOOL16 WINAPI DragQueryPoint(HDROP16 hDrop, POINT16 *p)
269 LPDROPFILESTRUCT lpDropFileStruct;
270 BOOL16 bRet;
272 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
274 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
275 bRet = lpDropFileStruct->fInNonClientArea;
277 GlobalUnlock16(hDrop);
278 return bRet;
281 /*************************************************************************
282 * SHELL_FindExecutable
283 * Utility for code sharing between FindExecutable and ShellExecute
285 static HINSTANCE32 SHELL_FindExecutable( LPCSTR lpFile,
286 LPCSTR lpOperation,
287 LPSTR lpResult)
289 char *extension = NULL; /* pointer to file extension */
290 char tmpext[5]; /* local copy to mung as we please */
291 char filetype[256]; /* registry name for this filetype */
292 LONG filetypelen=256; /* length of above */
293 char command[256]; /* command from registry */
294 LONG commandlen=256; /* This is the most DOS can handle :) */
295 char buffer[256]; /* Used to GetProfileString */
296 HINSTANCE32 retval=31; /* default - 'No association was found' */
297 char *tok; /* token pointer */
298 int i; /* random counter */
299 char xlpFile[256]; /* result of SearchPath */
301 TRACE(exec, "%s\n",
302 (lpFile != NULL?lpFile:"-") );
303 lpResult[0]='\0'; /* Start off with an empty return string */
305 /* trap NULL parameters on entry */
306 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
308 /* FIXME - should throw a warning, perhaps! */
309 return 2; /* File not found. Close enough, I guess. */
312 if (SearchPath32A( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
313 lpFile = xlpFile;
315 /* First thing we need is the file's extension */
316 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
317 /* File->Run in progman uses */
318 /* .\FILE.EXE :( */
319 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
321 return 31; /* no association */
324 /* Make local copy & lowercase it for reg & 'programs=' lookup */
325 lstrcpyn32A( tmpext, extension, 5 );
326 CharLower32A( tmpext );
327 TRACE(exec, "%s file\n", tmpext);
329 /* Three places to check: */
330 /* 1. win.ini, [windows], programs (NB no leading '.') */
331 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
332 /* 3. win.ini, [extensions], extension (NB no leading '.' */
333 /* All I know of the order is that registry is checked before */
334 /* extensions; however, it'd make sense to check the programs */
335 /* section first, so that's what happens here. */
337 /* See if it's a program - if GetProfileString fails, we skip this
338 * section. Actually, if GetProfileString fails, we've probably
339 * got a lot more to worry about than running a program... */
340 if ( GetProfileString32A("windows", "programs", "exe pif bat com",
341 buffer, sizeof(buffer)) > 0 )
343 for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
345 tok = strtok(buffer, " \t"); /* ? */
346 while( tok!= NULL)
348 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
350 strcpy(lpResult, xlpFile);
351 /* Need to perhaps check that the file has a path
352 * attached */
353 TRACE(exec, "found %s\n",
354 lpResult);
355 return 33;
357 /* Greater than 32 to indicate success FIXME According to the
358 * docs, I should be returning a handle for the
359 * executable. Does this mean I'm supposed to open the
360 * executable file or something? More RTFM, I guess... */
362 tok=strtok(NULL, " \t");
366 /* Check registry */
367 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
368 &filetypelen ) == SHELL_ERROR_SUCCESS )
370 filetype[filetypelen]='\0';
371 TRACE(exec, "File type: %s\n",
372 filetype);
374 /* Looking for ...buffer\shell\lpOperation\command */
375 strcat( filetype, "\\shell\\" );
376 strcat( filetype, lpOperation );
377 strcat( filetype, "\\command" );
379 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
380 &commandlen ) == SHELL_ERROR_SUCCESS )
382 /* Is there a replace() function anywhere? */
383 command[commandlen]='\0';
384 strcpy( lpResult, command );
385 tok=strstr( lpResult, "%1" );
386 if (tok != NULL)
388 tok[0]='\0'; /* truncate string at the percent */
389 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
390 tok=strstr( command, "%1" );
391 if ((tok!=NULL) && (strlen(tok)>2))
393 strcat( lpResult, &tok[2] );
396 retval=33; /* FIXME see above */
399 else /* Check win.ini */
401 /* Toss the leading dot */
402 extension++;
403 if ( GetProfileString32A( "extensions", extension, "", command,
404 sizeof(command)) > 0)
406 if (strlen(command)!=0)
408 strcpy( lpResult, command );
409 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
410 if (tok != NULL)
412 tok[0]='\0';
413 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
414 tok=strstr( command, "^" ); /* see above */
415 if ((tok != NULL) && (strlen(tok)>5))
417 strcat( lpResult, &tok[5]);
420 retval=33; /* FIXME - see above */
425 TRACE(exec, "returning %s\n", lpResult);
426 return retval;
429 /*************************************************************************
430 * ShellExecute16 [SHELL.20]
432 HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
433 LPCSTR lpFile, LPCSTR lpParameters,
434 LPCSTR lpDirectory, INT16 iShowCmd )
436 HINSTANCE16 retval=31;
437 char old_dir[1024];
438 char cmd[256];
440 TRACE(exec, "(%04x,'%s','%s','%s','%s',%x)\n",
441 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
442 lpParameters ? lpParameters : "<null>",
443 lpDirectory ? lpDirectory : "<null>", iShowCmd);
445 if (lpFile==NULL) return 0; /* should not happen */
446 if (lpOperation==NULL) /* default is open */
447 lpOperation="open";
449 if (lpDirectory)
451 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
452 SetCurrentDirectory32A( lpDirectory );
455 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
457 if (retval > 32) /* Found */
459 if (lpParameters)
461 strcat(cmd," ");
462 strcat(cmd,lpParameters);
465 TRACE(exec,"starting %s\n",cmd);
466 retval = WinExec32( cmd, iShowCmd );
468 if (lpDirectory) SetCurrentDirectory32A( old_dir );
469 return retval;
473 /*************************************************************************
474 * ShellExecute32A (SHELL32.245)
476 HINSTANCE32 WINAPI ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation,
477 LPCSTR lpFile, LPCSTR lpParameters,
478 LPCSTR lpDirectory, INT32 iShowCmd )
480 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
481 lpDirectory, iShowCmd );
485 /*************************************************************************
486 * FindExecutable16 (SHELL.21)
488 HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
489 LPSTR lpResult )
491 return (HINSTANCE16)FindExecutable32A( lpFile, lpDirectory, lpResult );
494 /*************************************************************************
495 * FindExecutable32A (SHELL32.184)
497 HINSTANCE32 WINAPI FindExecutable32A( LPCSTR lpFile, LPCSTR lpDirectory,
498 LPSTR lpResult )
500 HINSTANCE32 retval=31; /* default - 'No association was found' */
501 char old_dir[1024];
503 TRACE(exec, "File %s, Dir %s\n",
504 (lpFile != NULL?lpFile:"-"),
505 (lpDirectory != NULL?lpDirectory:"-"));
507 lpResult[0]='\0'; /* Start off with an empty return string */
509 /* trap NULL parameters on entry */
510 if (( lpFile == NULL ) || ( lpResult == NULL ))
512 /* FIXME - should throw a warning, perhaps! */
513 return 2; /* File not found. Close enough, I guess. */
516 if (lpDirectory)
518 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
519 SetCurrentDirectory32A( lpDirectory );
522 retval = SHELL_FindExecutable( lpFile, "open", lpResult );
524 TRACE(exec, "returning %s\n", lpResult);
525 if (lpDirectory) SetCurrentDirectory32A( old_dir );
526 return retval;
529 typedef struct
531 LPCSTR szApp;
532 LPCSTR szOtherStuff;
533 HICON32 hIcon;
534 } ABOUT_INFO;
536 #define IDC_STATIC_TEXT 100
537 #define IDC_LISTBOX 99
538 #define IDC_WINE_TEXT 98
540 #define DROP_FIELD_TOP (-15)
541 #define DROP_FIELD_HEIGHT 15
543 extern HICON32 hIconTitleFont;
545 static BOOL32 __get_dropline( HWND32 hWnd, LPRECT32 lprect )
547 HWND32 hWndCtl = GetDlgItem32(hWnd, IDC_WINE_TEXT);
548 if( hWndCtl )
550 GetWindowRect32( hWndCtl, lprect );
551 MapWindowPoints32( 0, hWnd, (LPPOINT32)lprect, 2 );
552 lprect->bottom = (lprect->top += DROP_FIELD_TOP);
553 return TRUE;
555 return FALSE;
558 /*************************************************************************
559 * AboutDlgProc32 (not an exported API function)
561 LRESULT WINAPI AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
562 LPARAM lParam )
564 HWND32 hWndCtl;
565 char Template[512], AppTitle[512];
567 switch(msg)
569 case WM_INITDIALOG:
571 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
572 if (info)
574 const char* const *pstr = SHELL_People;
575 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON32,info->hIcon, 0);
576 GetWindowText32A( hWnd, Template, sizeof(Template) );
577 sprintf( AppTitle, Template, info->szApp );
578 SetWindowText32A( hWnd, AppTitle );
579 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT),
580 info->szOtherStuff );
581 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
582 SendMessage32A( hWndCtl, WM_SETREDRAW, 0, 0 );
583 SendMessage32A( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
584 while (*pstr)
586 SendMessage32A( hWndCtl, LB_ADDSTRING32,
587 (WPARAM32)-1, (LPARAM)*pstr );
588 pstr++;
590 SendMessage32A( hWndCtl, WM_SETREDRAW, 1, 0 );
593 return 1;
595 case WM_PAINT:
597 RECT32 rect;
598 PAINTSTRUCT32 ps;
599 HDC32 hDC = BeginPaint32( hWnd, &ps );
601 if( __get_dropline( hWnd, &rect ) )
602 GRAPH_DrawLines( hDC, (LPPOINT32)&rect, 1, GetStockObject32( BLACK_PEN ) );
603 EndPaint32( hWnd, &ps );
605 break;
607 case WM_LBTRACKPOINT:
609 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
610 if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
612 if( DragDetect32( hWndCtl, *((LPPOINT32)&lParam) ) )
614 INT32 idx = SendMessage32A( hWndCtl, LB_GETCURSEL32, 0, 0 );
615 if( idx != -1 )
617 INT32 length = SendMessage32A( hWndCtl, LB_GETTEXTLEN32, (WPARAM32)idx, 0 );
618 HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
619 char* pstr = (char*)GlobalLock16( hMemObj );
621 if( pstr )
623 HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE(OCR_DRAGOBJECT) );
624 SendMessage32A( hWndCtl, LB_GETTEXT32, (WPARAM32)idx, (LPARAM)pstr );
625 SendMessage32A( hWndCtl, LB_DELETESTRING32, (WPARAM32)idx, 0 );
626 UpdateWindow32( hWndCtl );
627 if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
628 SendMessage32A( hWndCtl, LB_ADDSTRING32, (WPARAM32)-1, (LPARAM)pstr );
630 if( hMemObj ) GlobalFree16( hMemObj );
634 break;
636 case WM_QUERYDROPOBJECT:
637 if( wParam == 0 )
639 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
640 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
642 RECT32 rect;
643 if( __get_dropline( hWnd, &rect ) )
645 POINT32 pt = { lpDragInfo->pt.x, lpDragInfo->pt.y };
646 rect.bottom += DROP_FIELD_HEIGHT;
647 if( PtInRect32( &rect, pt ) )
649 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
650 return TRUE;
655 break;
657 case WM_DROPOBJECT:
658 if( wParam == hWnd )
660 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
661 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
663 char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
664 if( pstr )
666 static char __appendix_str[] = " with";
668 hWndCtl = GetDlgItem32( hWnd, IDC_WINE_TEXT );
669 SendMessage32A( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
670 if( !lstrncmp32A( Template, "WINE", 4 ) )
671 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT), Template );
672 else
674 char* pch = Template + strlen(Template) - strlen(__appendix_str);
675 *pch = '\0';
676 SendMessage32A( GetDlgItem32(hWnd, IDC_LISTBOX), LB_ADDSTRING32,
677 (WPARAM32)-1, (LPARAM)Template );
680 lstrcpy32A( Template, pstr );
681 lstrcat32A( Template, __appendix_str );
682 SetWindowText32A( hWndCtl, Template );
684 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
685 return TRUE;
689 break;
691 case WM_COMMAND:
692 if (wParam == IDOK)
694 EndDialog32(hWnd, TRUE);
695 return TRUE;
697 break;
699 return 0;
703 /*************************************************************************
704 * AboutDlgProc16 (SHELL.33)
706 LRESULT WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
707 LPARAM lParam )
709 return AboutDlgProc32( hWnd, msg, wParam, lParam );
713 /*************************************************************************
714 * ShellAbout16 (SHELL.22)
716 BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
717 HICON16 hIcon )
719 return ShellAbout32A( hWnd, szApp, szOtherStuff, hIcon );
722 /*************************************************************************
723 * ShellAbout32A (SHELL32.243)
725 BOOL32 WINAPI ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
726 HICON32 hIcon )
728 ABOUT_INFO info;
729 info.szApp = szApp;
730 info.szOtherStuff = szOtherStuff;
731 info.hIcon = hIcon;
732 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
733 return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
734 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
735 hWnd, AboutDlgProc32, (LPARAM)&info );
739 /*************************************************************************
740 * ShellAbout32W (SHELL32.244)
742 BOOL32 WINAPI ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
743 HICON32 hIcon )
745 BOOL32 ret;
746 ABOUT_INFO info;
748 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
749 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
750 info.hIcon = hIcon;
751 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
752 ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
753 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
754 hWnd, AboutDlgProc32, (LPARAM)&info );
755 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
756 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
757 return ret;
760 /*************************************************************************
761 * Shell_NotifyIcon [SHELL32.249]
762 * FIXME
763 * This function is supposed to deal with the systray.
764 * Any ideas on how this is to be implimented?
766 BOOL32 WINAPI Shell_NotifyIcon( DWORD dwMessage,
767 PNOTIFYICONDATA pnid )
769 return FALSE;
772 /*************************************************************************
773 * Shell_NotifyIcon [SHELL32.240]
774 * FIXME
775 * This function is supposed to deal with the systray.
776 * Any ideas on how this is to be implimented?
778 BOOL32 WINAPI Shell_NotifyIconA(DWORD dwMessage,
779 PNOTIFYICONDATA pnid )
781 return FALSE;
784 /*************************************************************************
785 * SHELL_GetResourceTable
787 static DWORD SHELL_GetResourceTable(HFILE32 hFile,LPBYTE *retptr)
789 IMAGE_DOS_HEADER mz_header;
790 char magic[4];
791 int size;
793 *retptr = NULL;
794 _llseek32( hFile, 0, SEEK_SET );
795 if ( (_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
796 (mz_header.e_magic != IMAGE_DOS_SIGNATURE)
798 return 0;
800 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
801 if (_lread32( hFile, magic, sizeof(magic) ) != sizeof(magic))
802 return 0;
803 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET);
805 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
806 return IMAGE_NT_SIGNATURE;
807 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE) {
808 IMAGE_OS2_HEADER ne_header;
809 LPBYTE pTypeInfo = (LPBYTE)-1;
811 if (_lread32(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
812 return 0;
814 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return 0;
815 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
816 if( size > sizeof(NE_TYPEINFO) )
818 pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
819 if( pTypeInfo ) {
820 _llseek32(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
821 if( _lread32( hFile, (char*)pTypeInfo, size) != size ) {
822 HeapFree( GetProcessHeap(), 0, pTypeInfo);
823 pTypeInfo = NULL;
827 *retptr = pTypeInfo;
828 } else
829 *retptr = (LPBYTE)-1;
830 return IMAGE_OS2_SIGNATURE; /* handles .ICO too */
834 /*************************************************************************
835 * SHELL_LoadResource
837 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
839 BYTE* ptr;
840 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
842 if( (ptr = (BYTE*)GlobalLock16( handle )) )
844 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
845 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
846 return handle;
848 return 0;
851 /*************************************************************************
852 * ICO_LoadIcon
854 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
856 BYTE* ptr;
857 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
859 if( (ptr = (BYTE*)GlobalLock16( handle )) )
861 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
862 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
863 return handle;
865 return 0;
868 /*************************************************************************
869 * ICO_GetIconDirectory
871 * Read .ico file and build phony ICONDIR struct for GetIconID
873 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
875 WORD id[3]; /* idReserved, idType, idCount */
876 LPicoICONDIR lpiID;
877 int i;
879 _llseek32( hFile, 0, SEEK_SET );
880 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
882 /* check .ICO header
884 * - see http://www.microsoft.com/win32dev/ui/icons.htm
887 if( id[0] || id[1] != 1 || !id[2] ) return 0;
889 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
891 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
893 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
895 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
896 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
897 if( handle )
899 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
900 lpID->idReserved = lpiID->idReserved = id[0];
901 lpID->idType = lpiID->idType = id[1];
902 lpID->idCount = lpiID->idCount = id[2];
903 for( i=0; i < lpiID->idCount; i++ )
905 memcpy((void*)(lpID->idEntries + i),
906 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
907 lpID->idEntries[i].icon.wResId = i;
909 *lplpiID = lpiID;
910 return handle;
913 /* fail */
915 HeapFree( GetProcessHeap(), 0, lpiID);
916 return 0;
919 /*************************************************************************
920 * InternalExtractIcon [SHELL.39]
922 * This abortion is called directly by Progman
924 HGLOBAL16 WINAPI InternalExtractIcon(HINSTANCE16 hInstance,
925 LPCSTR lpszExeFileName, UINT16 nIconIndex,
926 WORD n )
928 HGLOBAL16 hRet = 0;
929 HGLOBAL16* RetPtr = NULL;
930 LPBYTE pData;
931 OFSTRUCT ofs;
932 DWORD sig;
933 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
934 UINT16 iconDirCount = 0,iconCount = 0;
936 TRACE(reg,"(%04x,file %s,start %d,extract %d\n",
937 hInstance, lpszExeFileName, nIconIndex, n);
939 if( hFile == HFILE_ERROR32 || !n ) return 0;
941 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
942 RetPtr = (HICON16*)GlobalLock16(hRet);
944 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
946 sig = SHELL_GetResourceTable(hFile,&pData);
948 if(sig == IMAGE_OS2_SIGNATURE)
950 HICON16 hIcon = 0;
951 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
952 NE_NAMEINFO* pIconStorage = NULL;
953 NE_NAMEINFO* pIconDir = NULL;
954 LPicoICONDIR lpiID = NULL;
956 if( pData == (BYTE*)-1 )
958 /* check for .ICO file */
960 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
961 if( hIcon ) { iconDirCount = 1; iconCount = lpiID->idCount; }
963 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
965 /* find icon directory and icon repository */
967 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
969 iconDirCount = pTInfo->count;
970 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
971 TRACE(reg,"\tfound directory - %i icon families\n", iconDirCount);
973 if( pTInfo->type_id == NE_RSCTYPE_ICON )
975 iconCount = pTInfo->count;
976 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
977 TRACE(reg,"\ttotal icons - %i\n", iconCount);
979 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
982 /* load resources and create icons */
984 if( (pIconStorage && pIconDir) || lpiID )
985 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
986 else if( nIconIndex < iconDirCount )
988 UINT16 i, icon;
990 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
992 for( i = nIconIndex; i < nIconIndex + n; i++ )
994 /* .ICO files have only one icon directory */
996 if( lpiID == NULL )
997 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
998 *(WORD*)pData );
999 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
1000 GlobalFree16(hIcon);
1003 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
1005 hIcon = 0;
1006 if( lpiID )
1007 hIcon = ICO_LoadIcon( hInstance, hFile,
1008 lpiID->idEntries + RetPtr[icon-nIconIndex]);
1009 else
1010 for( i = 0; i < iconCount; i++ )
1011 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
1012 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
1013 *(WORD*)pData );
1014 if( hIcon )
1016 RetPtr[icon-nIconIndex] = LoadIconHandler( hIcon, TRUE );
1017 FarSetOwner( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
1019 else
1020 RetPtr[icon-nIconIndex] = 0;
1023 if( lpiID ) HeapFree( GetProcessHeap(), 0, lpiID);
1024 else HeapFree( GetProcessHeap(), 0, pData);
1026 if( sig == IMAGE_NT_SIGNATURE)
1028 LPBYTE peimage,idata,igdata;
1029 LPIMAGE_DOS_HEADER dheader;
1030 LPIMAGE_NT_HEADERS pe_header;
1031 LPIMAGE_SECTION_HEADER pe_sections;
1032 LPIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
1033 LPIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
1034 HANDLE32 fmapping;
1035 int i,j;
1036 LPIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
1037 CURSORICONDIR **cids;
1039 fmapping = CreateFileMapping32A(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
1040 if (fmapping == 0) { /* FIXME, INVALID_HANDLE_VALUE? */
1041 WARN(reg,"failed to create filemap.\n");
1042 _lclose32( hFile);
1043 return 0;
1045 peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
1046 if (!peimage) {
1047 WARN(reg,"failed to mmap filemap.\n");
1048 CloseHandle(fmapping);
1049 _lclose32( hFile);
1050 return 0;
1052 dheader = (LPIMAGE_DOS_HEADER)peimage;
1053 /* it is a pe header, SHELL_GetResourceTable checked that */
1054 pe_header = (LPIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
1055 /* probably makes problems with short PE headers... but I haven't seen
1056 * one yet...
1058 pe_sections = (LPIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
1059 rootresdir = NULL;
1060 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) {
1061 if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
1062 continue;
1063 /* FIXME: doesn't work when the resources are not in a seperate section */
1064 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) {
1065 rootresdir = (LPIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
1066 break;
1070 if (!rootresdir) {
1071 WARN(reg,"haven't found section for resource directory.\n");
1072 UnmapViewOfFile(peimage);
1073 CloseHandle(fmapping);
1074 _lclose32( hFile);
1075 return 0;
1077 icongroupresdir = GetResDirEntryW(rootresdir,(LPWSTR)RT_GROUP_ICON,(DWORD)rootresdir,FALSE);
1078 if (!icongroupresdir) {
1079 WARN(reg,"No Icongroupresourcedirectory!\n");
1080 UnmapViewOfFile(peimage);
1081 CloseHandle(fmapping);
1082 _lclose32( hFile);
1083 return 0;
1086 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
1087 if( nIconIndex == (UINT16)-1 ) {
1088 RetPtr[0] = iconDirCount;
1089 UnmapViewOfFile(peimage);
1090 CloseHandle(fmapping);
1091 _lclose32( hFile);
1092 return hRet;
1095 if (nIconIndex >= iconDirCount) {
1096 WARN(reg,"nIconIndex %d is larger than iconDirCount %d\n",
1097 nIconIndex,iconDirCount);
1098 UnmapViewOfFile(peimage);
1099 CloseHandle(fmapping);
1100 _lclose32( hFile);
1101 GlobalFree16(hRet);
1102 return 0;
1104 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
1106 /* caller just wanted the number of entries */
1108 xresent = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
1109 /* assure we don't get too much ... */
1110 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
1112 /* starting from specified index ... */
1113 xresent = xresent+nIconIndex;
1115 for (i=0;i<n;i++,xresent++) {
1116 CURSORICONDIR *cid;
1117 LPIMAGE_RESOURCE_DIRECTORY resdir;
1119 /* go down this resource entry, name */
1120 resdir = (LPIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
1121 /* default language (0) */
1122 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1123 igdataent = (LPIMAGE_RESOURCE_DATA_ENTRY)resdir;
1125 /* lookup address in mapped image for virtual address */
1126 igdata = NULL;
1127 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1128 if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
1129 continue;
1130 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1131 continue;
1132 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1134 if (!igdata) {
1135 WARN(reg,"no matching real address for icongroup!\n");
1136 UnmapViewOfFile(peimage);
1137 CloseHandle(fmapping);
1138 _lclose32( hFile);
1139 return 0;
1141 /* found */
1142 cid = (CURSORICONDIR*)igdata;
1143 cids[i] = cid;
1144 RetPtr[i] = LookupIconIdFromDirectoryEx32(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1146 iconresdir=GetResDirEntryW(rootresdir,(LPWSTR)RT_ICON,(DWORD)rootresdir,FALSE);
1147 if (!iconresdir) {
1148 WARN(reg,"No Iconresourcedirectory!\n");
1149 UnmapViewOfFile(peimage);
1150 CloseHandle(fmapping);
1151 _lclose32( hFile);
1152 return 0;
1154 for (i=0;i<n;i++) {
1155 LPIMAGE_RESOURCE_DIRECTORY xresdir;
1157 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir,FALSE);
1158 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1160 idataent = (LPIMAGE_RESOURCE_DATA_ENTRY)xresdir;
1162 idata = NULL;
1163 /* map virtual to address in image */
1164 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1165 if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
1166 continue;
1167 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1168 continue;
1169 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1171 if (!idata) {
1172 WARN(reg,"no matching real address found for icondata!\n");
1173 RetPtr[i]=0;
1174 continue;
1176 RetPtr[i] = CreateIconFromResourceEx32(idata,idataent->Size,TRUE,0x00030000,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1178 UnmapViewOfFile(peimage);
1179 CloseHandle(fmapping);
1180 _lclose32( hFile);
1181 return hRet;
1183 _lclose32( hFile );
1184 /* return array with icon handles */
1185 return hRet;
1189 /*************************************************************************
1190 * ExtractIcon16 (SHELL.34)
1192 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
1193 UINT16 nIconIndex )
1195 return ExtractIcon32A( hInstance, lpszExeFileName, nIconIndex );
1199 /*************************************************************************
1200 * ExtractIcon32A (SHELL32.133)
1202 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
1203 UINT32 nIconIndex )
1205 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
1207 if( handle )
1209 HICON16* ptr = (HICON16*)GlobalLock16(handle);
1210 HICON16 hIcon = *ptr;
1212 GlobalFree16(handle);
1213 return hIcon;
1215 return 0;
1218 /*************************************************************************
1219 * ExtractIcon32W (SHELL32.180)
1221 HICON32 WINAPI ExtractIcon32W( HINSTANCE32 hInstance, LPCWSTR lpszExeFileName,
1222 UINT32 nIconIndex )
1224 LPSTR exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
1225 HICON32 ret = ExtractIcon32A(hInstance,exefn,nIconIndex);
1227 HeapFree(GetProcessHeap(),0,exefn);
1228 return ret;
1232 /*************************************************************************
1233 * ExtractAssociatedIcon [SHELL.36]
1235 * Return icon for given file (either from file itself or from associated
1236 * executable) and patch parameters if needed.
1238 HICON32 WINAPI ExtractAssociatedIcon32A(HINSTANCE32 hInst,LPSTR lpIconPath,
1239 LPWORD lpiIcon)
1241 return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
1244 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst,LPSTR lpIconPath,
1245 LPWORD lpiIcon)
1247 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1249 if( hIcon < 2 )
1252 if( hIcon == 1 ) /* no icons found in given file */
1254 char tempPath[0x80];
1255 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
1257 if( uRet > 32 && tempPath[0] )
1259 strcpy(lpIconPath,tempPath);
1260 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1262 if( hIcon > 2 ) return hIcon;
1264 else hIcon = 0;
1267 if( hIcon == 1 )
1268 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
1269 else
1270 *lpiIcon = 6; /* generic icon - found nothing */
1272 GetModuleFileName16(hInst, lpIconPath, 0x80);
1273 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
1276 return hIcon;
1279 /*************************************************************************
1280 * FindEnvironmentString [SHELL.38]
1282 * Returns a pointer into the DOS environment... Ugh.
1284 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
1286 UINT16 l = strlen(entry);
1287 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
1289 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
1291 if( !*(lpEnv+l) )
1292 return (lpEnv + l); /* empty entry */
1293 else if ( *(lpEnv+l)== '=' )
1294 return (lpEnv + l + 1);
1296 return NULL;
1299 SEGPTR WINAPI FindEnvironmentString(LPSTR str)
1301 SEGPTR spEnv = GetDOSEnvironment();
1302 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
1304 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
1306 if( lpString ) /* offset should be small enough */
1307 return spEnv + (lpString - lpEnv);
1309 return (SEGPTR)NULL;
1312 /*************************************************************************
1313 * DoEnvironmentSubst [SHELL.37]
1315 * Replace %KEYWORD% in the str with the value of variable KEYWORD
1316 * from "DOS" environment.
1318 DWORD WINAPI DoEnvironmentSubst(LPSTR str,WORD length)
1320 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
1321 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
1322 LPSTR lpstr = str;
1323 LPSTR lpbstr = lpBuffer;
1325 CharToOem32A(str,str);
1327 TRACE(reg,"accept %s\n", str);
1329 while( *lpstr && lpbstr - lpBuffer < length )
1331 LPSTR lpend = lpstr;
1333 if( *lpstr == '%' )
1335 do { lpend++; } while( *lpend && *lpend != '%' );
1336 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
1338 LPSTR lpKey;
1339 *lpend = '\0';
1340 lpKey = SHELL_FindString(lpEnv, lpstr+1);
1341 if( lpKey ) /* found key value */
1343 int l = strlen(lpKey);
1345 if( l > length - (lpbstr - lpBuffer) - 1 )
1347 WARN(reg,"Env subst aborted - string too short\n");
1348 *lpend = '%';
1349 break;
1351 strcpy(lpbstr, lpKey);
1352 lpbstr += l;
1354 else break;
1355 *lpend = '%';
1356 lpstr = lpend + 1;
1358 else break; /* back off and whine */
1360 continue;
1363 *lpbstr++ = *lpstr++;
1366 *lpbstr = '\0';
1367 if( lpstr - str == strlen(str) )
1369 strncpy(str, lpBuffer, length);
1370 length = 1;
1372 else
1373 length = 0;
1375 TRACE(reg," return %s\n", str);
1377 OemToChar32A(str,str);
1378 HeapFree( GetProcessHeap(), 0, lpBuffer);
1380 /* Return str length in the LOWORD
1381 * and 1 in HIWORD if subst was successful.
1383 return (DWORD)MAKELONG(strlen(str), length);
1386 /*************************************************************************
1387 * ShellHookProc [SHELL.103]
1388 * System-wide WH_SHELL hook.
1390 LRESULT WINAPI ShellHookProc(INT16 code, WPARAM16 wParam, LPARAM lParam)
1392 TRACE(reg,"%i, %04x, %08x\n", code, wParam,
1393 (unsigned)lParam );
1394 if( SHELL_hHook && SHELL_hWnd )
1396 UINT16 uMsg = 0;
1397 switch( code )
1399 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
1400 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
1401 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
1403 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
1405 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
1408 /*************************************************************************
1409 * RegisterShellHook [SHELL.102]
1411 BOOL32 WINAPI RegisterShellHook(HWND16 hWnd, UINT16 uAction)
1413 TRACE(reg,"%04x [%u]\n", hWnd, uAction );
1415 switch( uAction )
1417 case 2: /* register hWnd as a shell window */
1419 if( !SHELL_hHook )
1421 HMODULE16 hShell = GetModuleHandle16( "SHELL" );
1423 SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc,
1424 hShell, 0 );
1425 if( SHELL_hHook )
1427 uMsgWndCreated = RegisterWindowMessage32A( lpstrMsgWndCreated );
1428 uMsgWndDestroyed = RegisterWindowMessage32A( lpstrMsgWndDestroyed );
1429 uMsgShellActivate = RegisterWindowMessage32A( lpstrMsgShellActivate );
1431 else WARN(reg, "unable to install ShellHookProc()!\n");
1434 if( SHELL_hHook ) return ((SHELL_hWnd = hWnd) != 0);
1435 break;
1437 default:
1439 WARN(reg, "unknown code %i\n", uAction );
1441 /* just in case */
1443 SHELL_hWnd = 0;
1445 return FALSE;
1449 /*************************************************************************
1450 * SHGetFileInfoA [SHELL32.218]
1452 DWORD WINAPI SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,
1453 SHFILEINFO32A *psfi, UINT32 sizeofpsfi,
1454 UINT32 flags )
1456 FIXME(shell,"(%s,0x%08lx,%p,%d,0x%08x): stub\n",
1457 path,dwFileAttributes,psfi,sizeofpsfi,flags);
1458 return TRUE;
1461 /*************************************************************************
1462 * SHAppBarMessage32 [SHELL32.207]
1464 UINT32 WINAPI SHAppBarMessage32(DWORD msg, PAPPBARDATA data)
1466 FIXME(shell,"(0x%08lx,%p): stub\n", msg, data);
1467 #if 0
1468 switch (msg) {
1469 case ABM_ACTIVATE:
1470 case ABM_GETAUTOHIDEBAR:
1471 case ABM_GETSTATE:
1472 case ABM_GETTASKBARPOS:
1473 case ABM_NEW:
1474 case ABM_QUERYPOS:
1475 case ABM_REMOVE:
1476 case ABM_SETAUTOHIDEBAR:
1477 case ABM_SETPOS:
1478 case ABM_WINDOWPOSCHANGED:
1481 #endif
1482 return 0;
1485 /*************************************************************************
1486 * CommandLineToArgvW [SHELL32.7]
1488 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
1490 LPWSTR *argv,s,t;
1491 int i;
1493 /* to get writeable copy */
1494 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
1495 s=cmdline;i=0;
1496 while (*s) {
1497 /* space */
1498 if (*s==0x0020) {
1499 i++;
1500 s++;
1501 while (*s && *s==0x0020)
1502 s++;
1503 continue;
1505 s++;
1507 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
1508 s=t=cmdline;
1509 i=0;
1510 while (*s) {
1511 if (*s==0x0020) {
1512 *s=0;
1513 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
1514 *s=0x0020;
1515 while (*s && *s==0x0020)
1516 s++;
1517 if (*s)
1518 t=s+1;
1519 else
1520 t=s;
1521 continue;
1523 s++;
1525 if (*t)
1526 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
1527 HeapFree( GetProcessHeap(), 0, cmdline );
1528 argv[i]=NULL;
1529 *numargs=i;
1530 return argv;
1533 /*************************************************************************
1534 * Control_RunDLL [SHELL32.12]
1536 * Wild speculation in the following!
1538 * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
1541 void WINAPI Control_RunDLL (HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4)
1543 TRACE(exec, "(%08x, %p, \"%s\", %08lx)\n",
1544 hwnd, code ? code : "(null)", cmd ? cmd : "(null)", arg4);
1547 /*************************************************************************
1550 void WINAPI FreeIconList( DWORD dw )
1552 FIXME(reg, "empty stub\n" );
1555 /*************************************************************************
1556 * SHELL32_DllGetClassObject [SHELL32.14]
1558 * http://premium.microsoft.com/msdn/library/sdkdoc/api2_48fo.htm
1560 DWORD WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID *ppv)
1562 char xclsid[50],xiid[50];
1563 HRESULT hres = E_OUTOFMEMORY;
1566 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1567 WINE_StringFromCLSID((LPCLSID)iid,xiid);
1568 TRACE(shell,"(%s,%s,%p)\n",xclsid,xiid,ppv);
1570 *ppv = NULL;
1571 /* SDK example code looks like this:
1573 HRESULT hres = E_OUTOFMEMORY;
1575 *ppv = NULL;
1576 CClassFactory *pClassFactory = new CClassFactory(rclsid);
1578 if (pClassFactory) {
1579 hRes = pClassFactory->QueryInterface(riid,ppv);
1580 pClassFactory->Release();
1582 return hRes;
1584 * The magic of the whole stuff is still unclear to me, so just hack together
1585 * something.
1588 if (!memcmp(rclsid,&CLSID_ShellDesktop,sizeof(CLSID_ShellDesktop))) {
1589 TRACE(shell," requested CLSID_ShellDesktop, creating it.\n");
1590 *ppv = IShellFolder_Constructor();
1591 FIXME(shell,"Initialize this folder to be the shell desktop folder\n");
1592 return 0;
1595 FIXME(shell, " -> clsid not found. returning E_OUTOFMEMORY.\n");
1596 return hres;
1599 /*************************************************************************
1600 * SHGetDesktopFolder [SHELL32.216]
1601 * returns the interface to the shell desktop folder.
1603 * [SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
1604 * CLSID_ShellDesktop.
1606 * CoCreateInstance(CLSID_Desktop, NULL,
1607 * CLSCTX_INPROC, IID_IShellFolder, &pshf);
1609 * So what we are doing is currently wrong....
1611 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
1612 *shellfolder = IShellFolder_Constructor();
1613 return NOERROR;
1616 /*************************************************************************
1617 * SHGetMalloc [SHELL32.220]
1618 * returns the interface to shell malloc.
1620 * [SDK header win95/shlobj.h:
1621 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
1623 * What we are currently doing is not very wrong, since we always use the same
1624 * heap (ProcessHeap).
1626 DWORD WINAPI SHGetMalloc(LPMALLOC32 *lpmal) {
1627 TRACE(shell,"(%p)\n", lpmal);
1628 return CoGetMalloc32(0,lpmal);
1631 /*************************************************************************
1632 * SHGetSpecialFolderLocation [SHELL32.223]
1633 * returns the PIDL of a special folder
1635 * nFolder is a CSIDL_xxxxx.
1637 HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl) {
1638 FIXME(shell,"(%04x,%d,%p),stub!\n", hwndOwner,nFolder,ppidl);
1639 *ppidl = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2*sizeof(ITEMIDLIST));
1640 FIXME(shell, "we return only the empty ITEMIDLIST currently.\n");
1641 (*ppidl)->mkid.cb = 0;
1642 return NOERROR;
1645 /*************************************************************************
1646 * SHGetPathFromIDList [SHELL32.221]
1647 * returns the path from a passed PIDL.
1649 BOOL32 WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath) {
1650 FIXME(shell,"(%p,%p),stub!\n",pidl,pszPath);
1651 lstrcpy32A(pszPath,"E:\\"); /* FIXME */
1652 return NOERROR;