Release 980517
[wine/multimedia.git] / misc / shell.c
blob0520d695e0c31bf62bd6935c80b998f744fdcf29
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, MAKEINTRESOURCE16(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, MAKEINTRESOURCE16(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, MAKEINTRESOURCE16(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)
797 ) { /* .ICO file ? */
798 if (mz_header.e_cblp == 1) { /* ICONHEADER.idType, must be 1 */
799 *retptr = (LPBYTE)-1;
800 return 1;
802 else
803 return 0; /* failed */
805 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
806 if (_lread32( hFile, magic, sizeof(magic) ) != sizeof(magic))
807 return 0;
808 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET);
810 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
811 return IMAGE_NT_SIGNATURE;
812 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE) {
813 IMAGE_OS2_HEADER ne_header;
814 LPBYTE pTypeInfo = (LPBYTE)-1;
816 if (_lread32(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
817 return 0;
819 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return 0;
820 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
821 if( size > sizeof(NE_TYPEINFO) )
823 pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
824 if( pTypeInfo ) {
825 _llseek32(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
826 if( _lread32( hFile, (char*)pTypeInfo, size) != size ) {
827 HeapFree( GetProcessHeap(), 0, pTypeInfo);
828 pTypeInfo = NULL;
832 *retptr = pTypeInfo;
833 return IMAGE_OS2_SIGNATURE;
834 } else
835 return 0; /* failed */
838 /*************************************************************************
839 * SHELL_LoadResource
841 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
843 BYTE* ptr;
844 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
846 if( (ptr = (BYTE*)GlobalLock16( handle )) )
848 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
849 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
850 return handle;
852 return 0;
855 /*************************************************************************
856 * ICO_LoadIcon
858 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
860 BYTE* ptr;
861 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
863 if( (ptr = (BYTE*)GlobalLock16( handle )) )
865 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
866 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
867 return handle;
869 return 0;
872 /*************************************************************************
873 * ICO_GetIconDirectory
875 * Read .ico file and build phony ICONDIR struct for GetIconID
877 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
879 WORD id[3]; /* idReserved, idType, idCount */
880 LPicoICONDIR lpiID;
881 int i;
883 _llseek32( hFile, 0, SEEK_SET );
884 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
886 /* check .ICO header
888 * - see http://www.microsoft.com/win32dev/ui/icons.htm
891 if( id[0] || id[1] != 1 || !id[2] ) return 0;
893 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
895 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
897 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
899 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
900 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
901 if( handle )
903 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
904 lpID->idReserved = lpiID->idReserved = id[0];
905 lpID->idType = lpiID->idType = id[1];
906 lpID->idCount = lpiID->idCount = id[2];
907 for( i=0; i < lpiID->idCount; i++ )
909 memcpy((void*)(lpID->idEntries + i),
910 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
911 lpID->idEntries[i].icon.wResId = i;
913 *lplpiID = lpiID;
914 return handle;
917 /* fail */
919 HeapFree( GetProcessHeap(), 0, lpiID);
920 return 0;
923 /*************************************************************************
924 * InternalExtractIcon [SHELL.39]
926 * This abortion is called directly by Progman
928 HGLOBAL16 WINAPI InternalExtractIcon(HINSTANCE16 hInstance,
929 LPCSTR lpszExeFileName, UINT16 nIconIndex,
930 WORD n )
932 HGLOBAL16 hRet = 0;
933 HGLOBAL16* RetPtr = NULL;
934 LPBYTE pData;
935 OFSTRUCT ofs;
936 DWORD sig;
937 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
938 UINT16 iconDirCount = 0,iconCount = 0;
940 TRACE(reg,"(%04x,file %s,start %d,extract %d\n",
941 hInstance, lpszExeFileName, nIconIndex, n);
943 if( hFile == HFILE_ERROR32 || !n ) return 0;
945 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
946 RetPtr = (HICON16*)GlobalLock16(hRet);
948 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
950 sig = SHELL_GetResourceTable(hFile,&pData);
952 if((sig == IMAGE_OS2_SIGNATURE)
953 || (sig == 1)) /* .ICO file */
955 HICON16 hIcon = 0;
956 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
957 NE_NAMEINFO* pIconStorage = NULL;
958 NE_NAMEINFO* pIconDir = NULL;
959 LPicoICONDIR lpiID = NULL;
961 if( pData == (BYTE*)-1 )
963 /* check for .ICO file */
965 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
966 if( hIcon ) { iconDirCount = 1; iconCount = lpiID->idCount; }
968 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
970 /* find icon directory and icon repository */
972 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
974 iconDirCount = pTInfo->count;
975 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
976 TRACE(reg,"\tfound directory - %i icon families\n", iconDirCount);
978 if( pTInfo->type_id == NE_RSCTYPE_ICON )
980 iconCount = pTInfo->count;
981 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
982 TRACE(reg,"\ttotal icons - %i\n", iconCount);
984 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
987 /* load resources and create icons */
989 if( (pIconStorage && pIconDir) || lpiID )
990 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
991 else if( nIconIndex < iconDirCount )
993 UINT16 i, icon;
995 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
997 for( i = nIconIndex; i < nIconIndex + n; i++ )
999 /* .ICO files have only one icon directory */
1001 if( lpiID == NULL )
1002 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
1003 *(WORD*)pData );
1004 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
1005 GlobalFree16(hIcon);
1008 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
1010 hIcon = 0;
1011 if( lpiID )
1012 hIcon = ICO_LoadIcon( hInstance, hFile,
1013 lpiID->idEntries + RetPtr[icon-nIconIndex]);
1014 else
1015 for( i = 0; i < iconCount; i++ )
1016 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
1017 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
1018 *(WORD*)pData );
1019 if( hIcon )
1021 RetPtr[icon-nIconIndex] = LoadIconHandler( hIcon, TRUE );
1022 FarSetOwner( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
1024 else
1025 RetPtr[icon-nIconIndex] = 0;
1028 if( lpiID ) HeapFree( GetProcessHeap(), 0, lpiID);
1029 else HeapFree( GetProcessHeap(), 0, pData);
1031 if( sig == IMAGE_NT_SIGNATURE)
1033 LPBYTE peimage,idata,igdata;
1034 LPIMAGE_DOS_HEADER dheader;
1035 LPIMAGE_NT_HEADERS pe_header;
1036 LPIMAGE_SECTION_HEADER pe_sections;
1037 LPIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
1038 LPIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
1039 HANDLE32 fmapping;
1040 int i,j;
1041 LPIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
1042 CURSORICONDIR **cids;
1044 fmapping = CreateFileMapping32A(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
1045 if (fmapping == 0) { /* FIXME, INVALID_HANDLE_VALUE? */
1046 WARN(reg,"failed to create filemap.\n");
1047 _lclose32( hFile);
1048 return 0;
1050 peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
1051 if (!peimage) {
1052 WARN(reg,"failed to mmap filemap.\n");
1053 CloseHandle(fmapping);
1054 _lclose32( hFile);
1055 return 0;
1057 dheader = (LPIMAGE_DOS_HEADER)peimage;
1058 /* it is a pe header, SHELL_GetResourceTable checked that */
1059 pe_header = (LPIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
1060 /* probably makes problems with short PE headers... but I haven't seen
1061 * one yet...
1063 pe_sections = (LPIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
1064 rootresdir = NULL;
1065 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) {
1066 if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
1067 continue;
1068 /* FIXME: doesn't work when the resources are not in a seperate section */
1069 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) {
1070 rootresdir = (LPIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
1071 break;
1075 if (!rootresdir) {
1076 WARN(reg,"haven't found section for resource directory.\n");
1077 UnmapViewOfFile(peimage);
1078 CloseHandle(fmapping);
1079 _lclose32( hFile);
1080 return 0;
1082 icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICON32W,
1083 (DWORD)rootresdir,FALSE);
1084 if (!icongroupresdir) {
1085 WARN(reg,"No Icongroupresourcedirectory!\n");
1086 UnmapViewOfFile(peimage);
1087 CloseHandle(fmapping);
1088 _lclose32( hFile);
1089 return 0;
1092 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
1093 if( nIconIndex == (UINT16)-1 ) {
1094 RetPtr[0] = iconDirCount;
1095 UnmapViewOfFile(peimage);
1096 CloseHandle(fmapping);
1097 _lclose32( hFile);
1098 return hRet;
1101 if (nIconIndex >= iconDirCount) {
1102 WARN(reg,"nIconIndex %d is larger than iconDirCount %d\n",
1103 nIconIndex,iconDirCount);
1104 UnmapViewOfFile(peimage);
1105 CloseHandle(fmapping);
1106 _lclose32( hFile);
1107 GlobalFree16(hRet);
1108 return 0;
1110 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
1112 /* caller just wanted the number of entries */
1114 xresent = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
1115 /* assure we don't get too much ... */
1116 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
1118 /* starting from specified index ... */
1119 xresent = xresent+nIconIndex;
1121 for (i=0;i<n;i++,xresent++) {
1122 CURSORICONDIR *cid;
1123 LPIMAGE_RESOURCE_DIRECTORY resdir;
1125 /* go down this resource entry, name */
1126 resdir = (LPIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
1127 /* default language (0) */
1128 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1129 igdataent = (LPIMAGE_RESOURCE_DATA_ENTRY)resdir;
1131 /* lookup address in mapped image for virtual address */
1132 igdata = NULL;
1133 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1134 if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
1135 continue;
1136 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1137 continue;
1138 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1140 if (!igdata) {
1141 WARN(reg,"no matching real address for icongroup!\n");
1142 UnmapViewOfFile(peimage);
1143 CloseHandle(fmapping);
1144 _lclose32( hFile);
1145 return 0;
1147 /* found */
1148 cid = (CURSORICONDIR*)igdata;
1149 cids[i] = cid;
1150 RetPtr[i] = LookupIconIdFromDirectoryEx32(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1152 iconresdir=GetResDirEntryW(rootresdir,RT_ICON32W,
1153 (DWORD)rootresdir,FALSE);
1154 if (!iconresdir) {
1155 WARN(reg,"No Iconresourcedirectory!\n");
1156 UnmapViewOfFile(peimage);
1157 CloseHandle(fmapping);
1158 _lclose32( hFile);
1159 return 0;
1161 for (i=0;i<n;i++) {
1162 LPIMAGE_RESOURCE_DIRECTORY xresdir;
1164 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir,FALSE);
1165 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1167 idataent = (LPIMAGE_RESOURCE_DATA_ENTRY)xresdir;
1169 idata = NULL;
1170 /* map virtual to address in image */
1171 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1172 if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
1173 continue;
1174 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1175 continue;
1176 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1178 if (!idata) {
1179 WARN(reg,"no matching real address found for icondata!\n");
1180 RetPtr[i]=0;
1181 continue;
1183 RetPtr[i] = CreateIconFromResourceEx32(idata,idataent->Size,TRUE,0x00030000,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1185 UnmapViewOfFile(peimage);
1186 CloseHandle(fmapping);
1187 _lclose32( hFile);
1188 return hRet;
1190 _lclose32( hFile );
1191 /* return array with icon handles */
1192 return hRet;
1196 /*************************************************************************
1197 * ExtractIcon16 (SHELL.34)
1199 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
1200 UINT16 nIconIndex )
1202 return ExtractIcon32A( hInstance, lpszExeFileName, nIconIndex );
1206 /*************************************************************************
1207 * ExtractIcon32A (SHELL32.133)
1209 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
1210 UINT32 nIconIndex )
1212 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
1214 if( handle )
1216 HICON16* ptr = (HICON16*)GlobalLock16(handle);
1217 HICON16 hIcon = *ptr;
1219 GlobalFree16(handle);
1220 return hIcon;
1222 return 0;
1225 /*************************************************************************
1226 * ExtractIcon32W (SHELL32.180)
1228 HICON32 WINAPI ExtractIcon32W( HINSTANCE32 hInstance, LPCWSTR lpszExeFileName,
1229 UINT32 nIconIndex )
1231 LPSTR exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
1232 HICON32 ret = ExtractIcon32A(hInstance,exefn,nIconIndex);
1234 HeapFree(GetProcessHeap(),0,exefn);
1235 return ret;
1239 /*************************************************************************
1240 * ExtractAssociatedIcon [SHELL.36]
1242 * Return icon for given file (either from file itself or from associated
1243 * executable) and patch parameters if needed.
1245 HICON32 WINAPI ExtractAssociatedIcon32A(HINSTANCE32 hInst,LPSTR lpIconPath,
1246 LPWORD lpiIcon)
1248 return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
1251 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst,LPSTR lpIconPath,
1252 LPWORD lpiIcon)
1254 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1256 if( hIcon < 2 )
1259 if( hIcon == 1 ) /* no icons found in given file */
1261 char tempPath[0x80];
1262 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
1264 if( uRet > 32 && tempPath[0] )
1266 strcpy(lpIconPath,tempPath);
1267 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1269 if( hIcon > 2 ) return hIcon;
1271 else hIcon = 0;
1274 if( hIcon == 1 )
1275 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
1276 else
1277 *lpiIcon = 6; /* generic icon - found nothing */
1279 GetModuleFileName16(hInst, lpIconPath, 0x80);
1280 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE16(*lpiIcon));
1283 return hIcon;
1286 /*************************************************************************
1287 * FindEnvironmentString [SHELL.38]
1289 * Returns a pointer into the DOS environment... Ugh.
1291 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
1293 UINT16 l = strlen(entry);
1294 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
1296 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
1298 if( !*(lpEnv+l) )
1299 return (lpEnv + l); /* empty entry */
1300 else if ( *(lpEnv+l)== '=' )
1301 return (lpEnv + l + 1);
1303 return NULL;
1306 SEGPTR WINAPI FindEnvironmentString(LPSTR str)
1308 SEGPTR spEnv = GetDOSEnvironment();
1309 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
1311 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
1313 if( lpString ) /* offset should be small enough */
1314 return spEnv + (lpString - lpEnv);
1316 return (SEGPTR)NULL;
1319 /*************************************************************************
1320 * DoEnvironmentSubst [SHELL.37]
1322 * Replace %KEYWORD% in the str with the value of variable KEYWORD
1323 * from "DOS" environment.
1325 DWORD WINAPI DoEnvironmentSubst(LPSTR str,WORD length)
1327 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
1328 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
1329 LPSTR lpstr = str;
1330 LPSTR lpbstr = lpBuffer;
1332 CharToOem32A(str,str);
1334 TRACE(reg,"accept %s\n", str);
1336 while( *lpstr && lpbstr - lpBuffer < length )
1338 LPSTR lpend = lpstr;
1340 if( *lpstr == '%' )
1342 do { lpend++; } while( *lpend && *lpend != '%' );
1343 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
1345 LPSTR lpKey;
1346 *lpend = '\0';
1347 lpKey = SHELL_FindString(lpEnv, lpstr+1);
1348 if( lpKey ) /* found key value */
1350 int l = strlen(lpKey);
1352 if( l > length - (lpbstr - lpBuffer) - 1 )
1354 WARN(reg,"Env subst aborted - string too short\n");
1355 *lpend = '%';
1356 break;
1358 strcpy(lpbstr, lpKey);
1359 lpbstr += l;
1361 else break;
1362 *lpend = '%';
1363 lpstr = lpend + 1;
1365 else break; /* back off and whine */
1367 continue;
1370 *lpbstr++ = *lpstr++;
1373 *lpbstr = '\0';
1374 if( lpstr - str == strlen(str) )
1376 strncpy(str, lpBuffer, length);
1377 length = 1;
1379 else
1380 length = 0;
1382 TRACE(reg," return %s\n", str);
1384 OemToChar32A(str,str);
1385 HeapFree( GetProcessHeap(), 0, lpBuffer);
1387 /* Return str length in the LOWORD
1388 * and 1 in HIWORD if subst was successful.
1390 return (DWORD)MAKELONG(strlen(str), length);
1393 /*************************************************************************
1394 * ShellHookProc [SHELL.103]
1395 * System-wide WH_SHELL hook.
1397 LRESULT WINAPI ShellHookProc(INT16 code, WPARAM16 wParam, LPARAM lParam)
1399 TRACE(reg,"%i, %04x, %08x\n", code, wParam,
1400 (unsigned)lParam );
1401 if( SHELL_hHook && SHELL_hWnd )
1403 UINT16 uMsg = 0;
1404 switch( code )
1406 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
1407 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
1408 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
1410 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
1412 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
1415 /*************************************************************************
1416 * RegisterShellHook [SHELL.102]
1418 BOOL32 WINAPI RegisterShellHook(HWND16 hWnd, UINT16 uAction)
1420 TRACE(reg,"%04x [%u]\n", hWnd, uAction );
1422 switch( uAction )
1424 case 2: /* register hWnd as a shell window */
1426 if( !SHELL_hHook )
1428 HMODULE16 hShell = GetModuleHandle16( "SHELL" );
1430 SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc,
1431 hShell, 0 );
1432 if( SHELL_hHook )
1434 uMsgWndCreated = RegisterWindowMessage32A( lpstrMsgWndCreated );
1435 uMsgWndDestroyed = RegisterWindowMessage32A( lpstrMsgWndDestroyed );
1436 uMsgShellActivate = RegisterWindowMessage32A( lpstrMsgShellActivate );
1438 else WARN(reg, "unable to install ShellHookProc()!\n");
1441 if( SHELL_hHook ) return ((SHELL_hWnd = hWnd) != 0);
1442 break;
1444 default:
1446 WARN(reg, "unknown code %i\n", uAction );
1448 /* just in case */
1450 SHELL_hWnd = 0;
1452 return FALSE;
1456 /*************************************************************************
1457 * SHGetFileInfoA [SHELL32.218]
1459 DWORD WINAPI SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,
1460 SHFILEINFO32A *psfi, UINT32 sizeofpsfi,
1461 UINT32 flags )
1463 FIXME(shell,"(%s,0x%08lx,%p,%d,0x%08x): stub\n",
1464 path,dwFileAttributes,psfi,sizeofpsfi,flags);
1465 return TRUE;
1468 /*************************************************************************
1469 * SHAppBarMessage32 [SHELL32.207]
1471 UINT32 WINAPI SHAppBarMessage32(DWORD msg, PAPPBARDATA data)
1473 FIXME(shell,"(0x%08lx,%p): stub\n", msg, data);
1474 #if 0
1475 switch (msg) {
1476 case ABM_ACTIVATE:
1477 case ABM_GETAUTOHIDEBAR:
1478 case ABM_GETSTATE:
1479 case ABM_GETTASKBARPOS:
1480 case ABM_NEW:
1481 case ABM_QUERYPOS:
1482 case ABM_REMOVE:
1483 case ABM_SETAUTOHIDEBAR:
1484 case ABM_SETPOS:
1485 case ABM_WINDOWPOSCHANGED:
1488 #endif
1489 return 0;
1492 /*************************************************************************
1493 * CommandLineToArgvW [SHELL32.7]
1495 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
1497 LPWSTR *argv,s,t;
1498 int i;
1500 /* to get writeable copy */
1501 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
1502 s=cmdline;i=0;
1503 while (*s) {
1504 /* space */
1505 if (*s==0x0020) {
1506 i++;
1507 s++;
1508 while (*s && *s==0x0020)
1509 s++;
1510 continue;
1512 s++;
1514 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
1515 s=t=cmdline;
1516 i=0;
1517 while (*s) {
1518 if (*s==0x0020) {
1519 *s=0;
1520 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
1521 *s=0x0020;
1522 while (*s && *s==0x0020)
1523 s++;
1524 if (*s)
1525 t=s+1;
1526 else
1527 t=s;
1528 continue;
1530 s++;
1532 if (*t)
1533 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
1534 HeapFree( GetProcessHeap(), 0, cmdline );
1535 argv[i]=NULL;
1536 *numargs=i;
1537 return argv;
1540 /*************************************************************************
1541 * Control_RunDLL [SHELL32.12]
1543 * Wild speculation in the following!
1545 * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
1548 void WINAPI Control_RunDLL (HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4)
1550 TRACE(exec, "(%08x, %p, \"%s\", %08lx)\n",
1551 hwnd, code ? code : "(null)", cmd ? cmd : "(null)", arg4);
1554 /*************************************************************************
1557 void WINAPI FreeIconList( DWORD dw )
1559 FIXME(reg, "empty stub\n" );
1562 /*************************************************************************
1563 * SHELL32_DllGetClassObject [SHELL32.14]
1565 * http://premium.microsoft.com/msdn/library/sdkdoc/api2_48fo.htm
1567 DWORD WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID *ppv)
1569 char xclsid[50],xiid[50];
1570 HRESULT hres = E_OUTOFMEMORY;
1573 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1574 WINE_StringFromCLSID((LPCLSID)iid,xiid);
1575 TRACE(shell,"(%s,%s,%p)\n",xclsid,xiid,ppv);
1577 *ppv = NULL;
1578 /* SDK example code looks like this:
1580 HRESULT hres = E_OUTOFMEMORY;
1582 *ppv = NULL;
1583 CClassFactory *pClassFactory = new CClassFactory(rclsid);
1585 if (pClassFactory) {
1586 hRes = pClassFactory->QueryInterface(riid,ppv);
1587 pClassFactory->Release();
1589 return hRes;
1591 * The magic of the whole stuff is still unclear to me, so just hack together
1592 * something.
1595 if (!memcmp(rclsid,&CLSID_ShellDesktop,sizeof(CLSID_ShellDesktop))) {
1596 TRACE(shell," requested CLSID_ShellDesktop, creating it.\n");
1597 *ppv = IShellFolder_Constructor();
1598 FIXME(shell,"Initialize this folder to be the shell desktop folder\n");
1599 return 0;
1602 FIXME(shell, " -> clsid not found. returning E_OUTOFMEMORY.\n");
1603 return hres;
1606 /*************************************************************************
1607 * SHGetDesktopFolder [SHELL32.216]
1608 * returns the interface to the shell desktop folder.
1610 * [SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
1611 * CLSID_ShellDesktop.
1613 * CoCreateInstance(CLSID_Desktop, NULL,
1614 * CLSCTX_INPROC, IID_IShellFolder, &pshf);
1616 * So what we are doing is currently wrong....
1618 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
1619 *shellfolder = IShellFolder_Constructor();
1620 return NOERROR;
1623 /*************************************************************************
1624 * SHGetMalloc [SHELL32.220]
1625 * returns the interface to shell malloc.
1627 * [SDK header win95/shlobj.h:
1628 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
1630 * What we are currently doing is not very wrong, since we always use the same
1631 * heap (ProcessHeap).
1633 DWORD WINAPI SHGetMalloc(LPMALLOC32 *lpmal) {
1634 TRACE(shell,"(%p)\n", lpmal);
1635 return CoGetMalloc32(0,lpmal);
1638 /*************************************************************************
1639 * SHGetSpecialFolderLocation [SHELL32.223]
1640 * returns the PIDL of a special folder
1642 * nFolder is a CSIDL_xxxxx.
1644 HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl) {
1645 FIXME(shell,"(%04x,%d,%p),stub!\n", hwndOwner,nFolder,ppidl);
1646 *ppidl = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2*sizeof(ITEMIDLIST));
1647 FIXME(shell, "we return only the empty ITEMIDLIST currently.\n");
1648 (*ppidl)->mkid.cb = 0;
1649 return NOERROR;
1652 /*************************************************************************
1653 * SHGetPathFromIDList [SHELL32.221]
1654 * returns the path from a passed PIDL.
1656 BOOL32 WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath) {
1657 FIXME(shell,"(%p,%p),stub!\n",pidl,pszPath);
1658 lstrcpy32A(pszPath,"E:\\"); /* FIXME */
1659 return NOERROR;