Release 980315
[wine/multimedia.git] / misc / shell.c
bloba7ae4c091d14a595ba2bd994ee9fac730b909eef
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 "debugstr.h"
27 #include "winreg.h"
29 static const char * const SHELL_People[] =
31 "Bob Amstadt",
32 "Dag Asheim",
33 "Martin Ayotte",
34 "Karl Backstr\366m",
35 "Peter Bajusz",
36 "Marcel Baur",
37 "Georg Beyerle",
38 "Ross Biro",
39 "Martin Boehme",
40 "Uwe Bonnes",
41 "Erik Bos",
42 "Fons Botman",
43 "John Brezak",
44 "Andrew Bulhak",
45 "John Burton",
46 "Niels de Carpentier",
47 "Gordon Chaffee",
48 "Jimen Ching",
49 "David A. Cuthbert",
50 "Huw D. M. Davies",
51 "Roman Dolejsi",
52 "Frans van Dorsselaer",
53 "Chris Faherty",
54 "Carsten Fallesen",
55 "Paul Falstad",
56 "David Faure",
57 "Claus Fischer",
58 "Olaf Flebbe",
59 "Chad Fraleigh",
60 "Peter Galbavy",
61 "Ramon Garcia",
62 "Matthew Ghio",
63 "Jody Goldberg",
64 "Hans de Graaff",
65 "Charles M. Hannum",
66 "Adrian Harvey",
67 "John Harvey",
68 "Cameron Heide",
69 "Jochen Hoenicke",
70 "Onno Hovers",
71 "Jeffrey Hsu",
72 "Miguel de Icaza",
73 "Jukka Iivonen",
74 "Lee Jaekil",
75 "Alexandre Julliard",
76 "Bang Jun-Young",
77 "Pavel Kankovsky",
78 "Jochen Karrer",
79 "Andreas Kirschbaum",
80 "Albrecht Kleine",
81 "Eric Kohl",
82 "Jon Konrath",
83 "Alex Korobka",
84 "Greg Kreider",
85 "Anand Kumria",
86 "Scott A. Laird",
87 "David Lee Lambert",
88 "Andrew Lewycky",
89 "Martin von Loewis",
90 "Michiel van Loon",
91 "Kenneth MacDonald",
92 "Peter MacDonald",
93 "William Magro",
94 "Juergen Marquardt",
95 "Ricardo Massaro",
96 "Marcus Meissner",
97 "Graham Menhennitt",
98 "David Metcalfe",
99 "Bruce Milner",
100 "Steffen Moeller",
101 "Andreas Mohr",
102 "James Moody",
103 "Philippe De Muyter",
104 "Itai Nahshon",
105 "Kristian Nielsen",
106 "Henrik Olsen",
107 "Michael Patra",
108 "Dimitrie O. Paun",
109 "Jim Peterson",
110 "Robert Pouliot",
111 "Keith Reynolds",
112 "Slaven Rezic",
113 "John Richardson",
114 "Rick Richardson",
115 "Doug Ridgway",
116 "Bernhard Rosenkraenzer",
117 "Johannes Ruscheinski",
118 "Thomas Sandford",
119 "Constantine Sapuntzakis",
120 "Pablo Saratxaga",
121 "Daniel Schepler",
122 "Peter Schlaile",
123 "Ulrich Schmid",
124 "Bernd Schmidt",
125 "Ingo Schneider",
126 "Victor Schneider",
127 "Yngvi Sigurjonsson",
128 "Stephen Simmons",
129 "Rick Sladkey",
130 "William Smith",
131 "Dominik Strasser",
132 "Vadim Strizhevsky",
133 "Bertho Stultiens",
134 "Erik Svendsen",
135 "Tristan Tarrant",
136 "Andrew Taylor",
137 "Duncan C Thomson",
138 "Goran Thyni",
139 "Jimmy Tirtawangsa",
140 "Jon Tombs",
141 "Linus Torvalds",
142 "Gregory Trubetskoy",
143 "Petri Tuomola",
144 "Michael Veksler",
145 "Sven Verdoolaege",
146 "Ronan Waide",
147 "Eric Warnke",
148 "Manfred Weichel",
149 "Morten Welinder",
150 "Len White",
151 "Lawson Whitney",
152 "Jan Willamowius",
153 "Carl Williams",
154 "Karl Guenter Wuensch",
155 "Eric Youngdale",
156 "James Youngman",
157 "Nikita V. Youshchenko",
158 "Mikolaj Zalewski",
159 "John Zero",
160 "Luiz Otavio L. Zorzella",
161 NULL
165 /* .ICO file ICONDIR definitions */
167 #pragma pack(1)
169 typedef struct
171 BYTE bWidth; /* Width, in pixels, of the image */
172 BYTE bHeight; /* Height, in pixels, of the image */
173 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
174 BYTE bReserved; /* Reserved ( must be 0) */
175 WORD wPlanes; /* Color Planes */
176 WORD wBitCount; /* Bits per pixel */
177 DWORD dwBytesInRes; /* How many bytes in this resource? */
178 DWORD dwImageOffset; /* Where in the file is this image? */
179 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
181 typedef struct
183 WORD idReserved; /* Reserved (must be 0) */
184 WORD idType; /* Resource Type (1 for icons) */
185 WORD idCount; /* How many images? */
186 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
187 } icoICONDIR, *LPicoICONDIR;
189 #pragma pack(4)
191 static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
192 static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
193 static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
195 static HWND16 SHELL_hWnd = 0;
196 static HHOOK SHELL_hHook = 0;
197 static UINT16 uMsgWndCreated = 0;
198 static UINT16 uMsgWndDestroyed = 0;
199 static UINT16 uMsgShellActivate = 0;
201 /*************************************************************************
202 * DragAcceptFiles [SHELL.9]
204 void WINAPI DragAcceptFiles(HWND16 hWnd, BOOL16 b)
206 WND* wnd = WIN_FindWndPtr(hWnd);
208 if( wnd )
209 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
210 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
214 /*************************************************************************
215 * DragQueryFile [SHELL.11]
217 UINT16 WINAPI DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile,
218 WORD wLength)
220 /* hDrop is a global memory block allocated with GMEM_SHARE
221 * with DROPFILESTRUCT as a header and filenames following
222 * it, zero length filename is in the end */
224 LPDROPFILESTRUCT lpDropFileStruct;
225 LPSTR lpCurrent;
226 WORD i;
228 TRACE(reg,"(%04x, %i, %p, %u)\n",
229 hDrop,wFile,lpszFile,wLength);
231 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
232 if(!lpDropFileStruct) return 0;
234 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
236 i = 0;
237 while (i++ < wFile)
239 while (*lpCurrent++); /* skip filename */
240 if (!*lpCurrent)
241 return (wFile == 0xFFFF) ? i : 0;
244 i = strlen(lpCurrent);
245 if (!lpszFile) return i+1; /* needed buffer size */
247 i = (wLength > i) ? i : wLength-1;
248 strncpy(lpszFile, lpCurrent, i);
249 lpszFile[i] = '\0';
251 GlobalUnlock16(hDrop);
252 return i;
256 /*************************************************************************
257 * DragFinish [SHELL.12]
259 void WINAPI DragFinish(HDROP16 h)
261 GlobalFree16((HGLOBAL16)h);
265 /*************************************************************************
266 * DragQueryPoint [SHELL.13]
268 BOOL16 WINAPI DragQueryPoint(HDROP16 hDrop, POINT16 *p)
270 LPDROPFILESTRUCT lpDropFileStruct;
271 BOOL16 bRet;
273 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
275 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
276 bRet = lpDropFileStruct->fInNonClientArea;
278 GlobalUnlock16(hDrop);
279 return bRet;
282 /*************************************************************************
283 * SHELL_FindExecutable
284 * Utility for code sharing between FindExecutable and ShellExecute
286 static HINSTANCE32 SHELL_FindExecutable( LPCSTR lpFile,
287 LPCSTR lpOperation,
288 LPSTR lpResult)
290 char *extension = NULL; /* pointer to file extension */
291 char tmpext[5]; /* local copy to mung as we please */
292 char filetype[256]; /* registry name for this filetype */
293 LONG filetypelen=256; /* length of above */
294 char command[256]; /* command from registry */
295 LONG commandlen=256; /* This is the most DOS can handle :) */
296 char buffer[256]; /* Used to GetProfileString */
297 HINSTANCE32 retval=31; /* default - 'No association was found' */
298 char *tok; /* token pointer */
299 int i; /* random counter */
300 char xlpFile[256]; /* result of SearchPath */
302 TRACE(exec, "%s\n",
303 (lpFile != NULL?lpFile:"-") );
304 lpResult[0]='\0'; /* Start off with an empty return string */
306 /* trap NULL parameters on entry */
307 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
309 /* FIXME - should throw a warning, perhaps! */
310 return 2; /* File not found. Close enough, I guess. */
313 if (SearchPath32A( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
314 lpFile = xlpFile;
316 /* First thing we need is the file's extension */
317 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
318 /* File->Run in progman uses */
319 /* .\FILE.EXE :( */
320 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
322 return 31; /* no association */
325 /* Make local copy & lowercase it for reg & 'programs=' lookup */
326 lstrcpyn32A( tmpext, extension, 5 );
327 CharLower32A( tmpext );
328 TRACE(exec, "%s file\n", tmpext);
330 /* Three places to check: */
331 /* 1. win.ini, [windows], programs (NB no leading '.') */
332 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
333 /* 3. win.ini, [extensions], extension (NB no leading '.' */
334 /* All I know of the order is that registry is checked before */
335 /* extensions; however, it'd make sense to check the programs */
336 /* section first, so that's what happens here. */
338 /* See if it's a program - if GetProfileString fails, we skip this
339 * section. Actually, if GetProfileString fails, we've probably
340 * got a lot more to worry about than running a program... */
341 if ( GetProfileString32A("windows", "programs", "exe pif bat com",
342 buffer, sizeof(buffer)) > 0 )
344 for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
346 tok = strtok(buffer, " \t"); /* ? */
347 while( tok!= NULL)
349 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
351 strcpy(lpResult, xlpFile);
352 /* Need to perhaps check that the file has a path
353 * attached */
354 TRACE(exec, "found %s\n",
355 lpResult);
356 return 33;
358 /* Greater than 32 to indicate success FIXME According to the
359 * docs, I should be returning a handle for the
360 * executable. Does this mean I'm supposed to open the
361 * executable file or something? More RTFM, I guess... */
363 tok=strtok(NULL, " \t");
367 /* Check registry */
368 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
369 &filetypelen ) == SHELL_ERROR_SUCCESS )
371 filetype[filetypelen]='\0';
372 TRACE(exec, "File type: %s\n",
373 filetype);
375 /* Looking for ...buffer\shell\lpOperation\command */
376 strcat( filetype, "\\shell\\" );
377 strcat( filetype, lpOperation );
378 strcat( filetype, "\\command" );
380 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
381 &commandlen ) == SHELL_ERROR_SUCCESS )
383 /* Is there a replace() function anywhere? */
384 command[commandlen]='\0';
385 strcpy( lpResult, command );
386 tok=strstr( lpResult, "%1" );
387 if (tok != NULL)
389 tok[0]='\0'; /* truncate string at the percent */
390 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
391 tok=strstr( command, "%1" );
392 if ((tok!=NULL) && (strlen(tok)>2))
394 strcat( lpResult, &tok[2] );
397 retval=33; /* FIXME see above */
400 else /* Check win.ini */
402 /* Toss the leading dot */
403 extension++;
404 if ( GetProfileString32A( "extensions", extension, "", command,
405 sizeof(command)) > 0)
407 if (strlen(command)!=0)
409 strcpy( lpResult, command );
410 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
411 if (tok != NULL)
413 tok[0]='\0';
414 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
415 tok=strstr( command, "^" ); /* see above */
416 if ((tok != NULL) && (strlen(tok)>5))
418 strcat( lpResult, &tok[5]);
421 retval=33; /* FIXME - see above */
426 TRACE(exec, "returning %s\n", lpResult);
427 return retval;
430 /*************************************************************************
431 * ShellExecute16 [SHELL.20]
433 HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
434 LPCSTR lpFile, LPCSTR lpParameters,
435 LPCSTR lpDirectory, INT16 iShowCmd )
437 HINSTANCE16 retval=31;
438 char old_dir[1024];
439 char cmd[256];
441 TRACE(exec, "(%04x,'%s','%s','%s','%s',%x)\n",
442 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
443 lpParameters ? lpParameters : "<null>",
444 lpDirectory ? lpDirectory : "<null>", iShowCmd);
446 if (lpFile==NULL) return 0; /* should not happen */
447 if (lpOperation==NULL) /* default is open */
448 lpOperation="open";
450 if (lpDirectory)
452 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
453 SetCurrentDirectory32A( lpDirectory );
456 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
458 if (retval > 32) /* Found */
460 if (lpParameters)
462 strcat(cmd," ");
463 strcat(cmd,lpParameters);
466 TRACE(exec,"starting %s\n",cmd);
467 retval = WinExec32( cmd, iShowCmd );
469 if (lpDirectory) SetCurrentDirectory32A( old_dir );
470 return retval;
474 /*************************************************************************
475 * ShellExecute32A (SHELL32.245)
477 HINSTANCE32 WINAPI ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation,
478 LPCSTR lpFile, LPCSTR lpParameters,
479 LPCSTR lpDirectory, INT32 iShowCmd )
481 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
482 lpDirectory, iShowCmd );
486 /*************************************************************************
487 * FindExecutable16 (SHELL.21)
489 HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
490 LPSTR lpResult )
492 return (HINSTANCE16)FindExecutable32A( lpFile, lpDirectory, lpResult );
495 /*************************************************************************
496 * FindExecutable32A (SHELL32.184)
498 HINSTANCE32 WINAPI FindExecutable32A( LPCSTR lpFile, LPCSTR lpDirectory,
499 LPSTR lpResult )
501 HINSTANCE32 retval=31; /* default - 'No association was found' */
502 char old_dir[1024];
504 TRACE(exec, "File %s, Dir %s\n",
505 (lpFile != NULL?lpFile:"-"),
506 (lpDirectory != NULL?lpDirectory:"-"));
508 lpResult[0]='\0'; /* Start off with an empty return string */
510 /* trap NULL parameters on entry */
511 if (( lpFile == NULL ) || ( lpResult == NULL ))
513 /* FIXME - should throw a warning, perhaps! */
514 return 2; /* File not found. Close enough, I guess. */
517 if (lpDirectory)
519 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
520 SetCurrentDirectory32A( lpDirectory );
523 retval = SHELL_FindExecutable( lpFile, "open", lpResult );
525 TRACE(exec, "returning %s\n", lpResult);
526 if (lpDirectory) SetCurrentDirectory32A( old_dir );
527 return retval;
530 typedef struct
532 LPCSTR szApp;
533 LPCSTR szOtherStuff;
534 HICON32 hIcon;
535 } ABOUT_INFO;
537 #define IDC_STATIC_TEXT 100
538 #define IDC_LISTBOX 99
539 #define IDC_WINE_TEXT 98
541 #define DROP_FIELD_TOP (-15)
542 #define DROP_FIELD_HEIGHT 15
544 extern HICON32 hIconTitleFont;
546 static BOOL32 __get_dropline( HWND32 hWnd, LPRECT32 lprect )
548 HWND32 hWndCtl = GetDlgItem32(hWnd, IDC_WINE_TEXT);
549 if( hWndCtl )
551 GetWindowRect32( hWndCtl, lprect );
552 MapWindowPoints32( 0, hWnd, (LPPOINT32)lprect, 2 );
553 lprect->bottom = (lprect->top += DROP_FIELD_TOP);
554 return TRUE;
556 return FALSE;
559 /*************************************************************************
560 * AboutDlgProc32 (not an exported API function)
562 LRESULT WINAPI AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
563 LPARAM lParam )
565 HWND32 hWndCtl;
566 char Template[512], AppTitle[512];
568 switch(msg)
570 case WM_INITDIALOG:
572 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
573 if (info)
575 const char* const *pstr = SHELL_People;
576 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON32,info->hIcon, 0);
577 GetWindowText32A( hWnd, Template, sizeof(Template) );
578 sprintf( AppTitle, Template, info->szApp );
579 SetWindowText32A( hWnd, AppTitle );
580 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT),
581 info->szOtherStuff );
582 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
583 SendMessage32A( hWndCtl, WM_SETREDRAW, 0, 0 );
584 SendMessage32A( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
585 while (*pstr)
587 SendMessage32A( hWndCtl, LB_ADDSTRING32,
588 (WPARAM32)-1, (LPARAM)*pstr );
589 pstr++;
591 SendMessage32A( hWndCtl, WM_SETREDRAW, 1, 0 );
594 return 1;
596 case WM_PAINT:
598 RECT32 rect;
599 PAINTSTRUCT32 ps;
600 HDC32 hDC = BeginPaint32( hWnd, &ps );
602 if( __get_dropline( hWnd, &rect ) )
603 GRAPH_DrawLines( hDC, (LPPOINT32)&rect, 1, GetStockObject32( BLACK_PEN ) );
604 EndPaint32( hWnd, &ps );
606 break;
608 case WM_LBTRACKPOINT:
610 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
611 if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
613 if( DragDetect32( hWndCtl, *((LPPOINT32)&lParam) ) )
615 INT32 idx = SendMessage32A( hWndCtl, LB_GETCURSEL32, 0, 0 );
616 if( idx != -1 )
618 INT32 length = SendMessage32A( hWndCtl, LB_GETTEXTLEN32, (WPARAM32)idx, 0 );
619 HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
620 char* pstr = (char*)GlobalLock16( hMemObj );
622 if( pstr )
624 HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE(OCR_DRAGOBJECT) );
625 SendMessage32A( hWndCtl, LB_GETTEXT32, (WPARAM32)idx, (LPARAM)pstr );
626 SendMessage32A( hWndCtl, LB_DELETESTRING32, (WPARAM32)idx, 0 );
627 UpdateWindow32( hWndCtl );
628 if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
629 SendMessage32A( hWndCtl, LB_ADDSTRING32, (WPARAM32)-1, (LPARAM)pstr );
631 if( hMemObj ) GlobalFree16( hMemObj );
635 break;
637 case WM_QUERYDROPOBJECT:
638 if( wParam == 0 )
640 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
641 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
643 RECT32 rect;
644 if( __get_dropline( hWnd, &rect ) )
646 POINT32 pt = { lpDragInfo->pt.x, lpDragInfo->pt.y };
647 rect.bottom += DROP_FIELD_HEIGHT;
648 if( PtInRect32( &rect, pt ) )
650 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
651 return TRUE;
656 break;
658 case WM_DROPOBJECT:
659 if( wParam == hWnd )
661 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
662 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
664 char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
665 if( pstr )
667 static char __appendix_str[] = " with";
669 hWndCtl = GetDlgItem32( hWnd, IDC_WINE_TEXT );
670 SendMessage32A( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
671 if( !lstrncmp32A( Template, "WINE", 4 ) )
672 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT), Template );
673 else
675 char* pch = Template + strlen(Template) - strlen(__appendix_str);
676 *pch = '\0';
677 SendMessage32A( GetDlgItem32(hWnd, IDC_LISTBOX), LB_ADDSTRING32,
678 (WPARAM32)-1, (LPARAM)Template );
681 lstrcpy32A( Template, pstr );
682 lstrcat32A( Template, __appendix_str );
683 SetWindowText32A( hWndCtl, Template );
685 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
686 return TRUE;
690 break;
692 case WM_COMMAND:
693 if (wParam == IDOK)
695 EndDialog32(hWnd, TRUE);
696 return TRUE;
698 break;
700 return 0;
704 /*************************************************************************
705 * AboutDlgProc16 (SHELL.33)
707 LRESULT WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
708 LPARAM lParam )
710 return AboutDlgProc32( hWnd, msg, wParam, lParam );
714 /*************************************************************************
715 * ShellAbout16 (SHELL.22)
717 BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
718 HICON16 hIcon )
720 return ShellAbout32A( hWnd, szApp, szOtherStuff, hIcon );
723 /*************************************************************************
724 * ShellAbout32A (SHELL32.243)
726 BOOL32 WINAPI ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
727 HICON32 hIcon )
729 ABOUT_INFO info;
730 info.szApp = szApp;
731 info.szOtherStuff = szOtherStuff;
732 info.hIcon = hIcon;
733 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
734 return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
735 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
736 hWnd, AboutDlgProc32, (LPARAM)&info );
740 /*************************************************************************
741 * ShellAbout32W (SHELL32.244)
743 BOOL32 WINAPI ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
744 HICON32 hIcon )
746 BOOL32 ret;
747 ABOUT_INFO info;
749 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
750 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
751 info.hIcon = hIcon;
752 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
753 ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
754 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
755 hWnd, AboutDlgProc32, (LPARAM)&info );
756 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
757 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
758 return ret;
761 /*************************************************************************
762 * Shell_NotifyIcon [SHELL32.249]
763 * FIXME
764 * This function is supposed to deal with the systray.
765 * Any ideas on how this is to be implimented?
767 BOOL32 WINAPI Shell_NotifyIcon( DWORD dwMessage,
768 PNOTIFYICONDATA pnid )
770 return FALSE;
773 /*************************************************************************
774 * Shell_NotifyIcon [SHELL32.240]
775 * FIXME
776 * This function is supposed to deal with the systray.
777 * Any ideas on how this is to be implimented?
779 BOOL32 WINAPI Shell_NotifyIconA(DWORD dwMessage,
780 PNOTIFYICONDATA pnid )
782 return FALSE;
785 /*************************************************************************
786 * SHELL_GetResourceTable
788 static DWORD SHELL_GetResourceTable(HFILE32 hFile,LPBYTE *retptr)
790 IMAGE_DOS_HEADER mz_header;
791 char magic[4];
792 int size;
794 *retptr = NULL;
795 _llseek32( hFile, 0, SEEK_SET );
796 if ( (_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
797 (mz_header.e_magic != IMAGE_DOS_SIGNATURE)
799 return 0;
801 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
802 if (_lread32( hFile, magic, sizeof(magic) ) != sizeof(magic))
803 return 0;
804 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET);
806 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
807 return IMAGE_NT_SIGNATURE;
808 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE) {
809 IMAGE_OS2_HEADER ne_header;
810 LPBYTE pTypeInfo = (LPBYTE)-1;
812 if (_lread32(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
813 return 0;
815 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return 0;
816 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
817 if( size > sizeof(NE_TYPEINFO) )
819 pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
820 if( pTypeInfo ) {
821 _llseek32(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
822 if( _lread32( hFile, (char*)pTypeInfo, size) != size ) {
823 HeapFree( GetProcessHeap(), 0, pTypeInfo);
824 pTypeInfo = NULL;
828 *retptr = pTypeInfo;
829 } else
830 *retptr = (LPBYTE)-1;
831 return IMAGE_OS2_SIGNATURE; /* handles .ICO too */
835 /*************************************************************************
836 * SHELL_LoadResource
838 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
840 BYTE* ptr;
841 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
843 if( (ptr = (BYTE*)GlobalLock16( handle )) )
845 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
846 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
847 return handle;
849 return 0;
852 /*************************************************************************
853 * ICO_LoadIcon
855 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
857 BYTE* ptr;
858 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
860 if( (ptr = (BYTE*)GlobalLock16( handle )) )
862 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
863 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
864 return handle;
866 return 0;
869 /*************************************************************************
870 * ICO_GetIconDirectory
872 * Read .ico file and build phony ICONDIR struct for GetIconID
874 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
876 WORD id[3]; /* idReserved, idType, idCount */
877 LPicoICONDIR lpiID;
878 int i;
880 _llseek32( hFile, 0, SEEK_SET );
881 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
883 /* check .ICO header
885 * - see http://www.microsoft.com/win32dev/ui/icons.htm
888 if( id[0] || id[1] != 1 || !id[2] ) return 0;
890 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
892 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
894 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
896 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
897 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
898 if( handle )
900 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
901 lpID->idReserved = lpiID->idReserved = id[0];
902 lpID->idType = lpiID->idType = id[1];
903 lpID->idCount = lpiID->idCount = id[2];
904 for( i=0; i < lpiID->idCount; i++ )
906 memcpy((void*)(lpID->idEntries + i),
907 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
908 lpID->idEntries[i].icon.wResId = i;
910 *lplpiID = lpiID;
911 return handle;
914 /* fail */
916 HeapFree( GetProcessHeap(), 0, lpiID);
917 return 0;
920 /*************************************************************************
921 * InternalExtractIcon [SHELL.39]
923 * This abortion is called directly by Progman
925 HGLOBAL16 WINAPI InternalExtractIcon(HINSTANCE16 hInstance,
926 LPCSTR lpszExeFileName, UINT16 nIconIndex,
927 WORD n )
929 HGLOBAL16 hRet = 0;
930 HGLOBAL16* RetPtr = NULL;
931 LPBYTE pData;
932 OFSTRUCT ofs;
933 DWORD sig;
934 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
935 UINT16 iconDirCount = 0,iconCount = 0;
937 TRACE(reg,"(%04x,file %s,start %d,extract %d\n",
938 hInstance, lpszExeFileName, nIconIndex, n);
940 if( hFile == HFILE_ERROR32 || !n ) return 0;
942 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
943 RetPtr = (HICON16*)GlobalLock16(hRet);
945 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
947 sig = SHELL_GetResourceTable(hFile,&pData);
949 if(sig == IMAGE_OS2_SIGNATURE)
951 HICON16 hIcon = 0;
952 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
953 NE_NAMEINFO* pIconStorage = NULL;
954 NE_NAMEINFO* pIconDir = NULL;
955 LPicoICONDIR lpiID = NULL;
957 if( pData == (BYTE*)-1 )
959 /* check for .ICO file */
961 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
962 if( hIcon ) { iconDirCount = 1; iconCount = lpiID->idCount; }
964 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
966 /* find icon directory and icon repository */
968 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
970 iconDirCount = pTInfo->count;
971 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
972 TRACE(reg,"\tfound directory - %i icon families\n", iconDirCount);
974 if( pTInfo->type_id == NE_RSCTYPE_ICON )
976 iconCount = pTInfo->count;
977 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
978 TRACE(reg,"\ttotal icons - %i\n", iconCount);
980 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
983 /* load resources and create icons */
985 if( (pIconStorage && pIconDir) || lpiID )
986 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
987 else if( nIconIndex < iconDirCount )
989 UINT16 i, icon;
991 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
993 for( i = nIconIndex; i < nIconIndex + n; i++ )
995 /* .ICO files have only one icon directory */
997 if( lpiID == NULL )
998 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
999 *(WORD*)pData );
1000 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
1001 GlobalFree16(hIcon);
1004 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
1006 hIcon = 0;
1007 if( lpiID )
1008 hIcon = ICO_LoadIcon( hInstance, hFile,
1009 lpiID->idEntries + RetPtr[icon-nIconIndex]);
1010 else
1011 for( i = 0; i < iconCount; i++ )
1012 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
1013 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
1014 *(WORD*)pData );
1015 if( hIcon )
1017 RetPtr[icon-nIconIndex] = LoadIconHandler( hIcon, TRUE );
1018 FarSetOwner( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
1020 else
1021 RetPtr[icon-nIconIndex] = 0;
1024 if( lpiID ) HeapFree( GetProcessHeap(), 0, lpiID);
1025 else HeapFree( GetProcessHeap(), 0, pData);
1027 if( sig == IMAGE_NT_SIGNATURE)
1029 LPBYTE peimage,idata,igdata;
1030 LPIMAGE_DOS_HEADER dheader;
1031 LPIMAGE_NT_HEADERS pe_header;
1032 LPIMAGE_SECTION_HEADER pe_sections;
1033 LPIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
1034 LPIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
1035 HANDLE32 fmapping;
1036 int i,j;
1037 LPIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
1038 CURSORICONDIR **cids;
1040 fmapping = CreateFileMapping32A(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
1041 if (fmapping == 0) { /* FIXME, INVALID_HANDLE_VALUE? */
1042 WARN(reg,"failed to create filemap.\n");
1043 _lclose32( hFile);
1044 return 0;
1046 peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
1047 if (!peimage) {
1048 WARN(reg,"failed to mmap filemap.\n");
1049 CloseHandle(fmapping);
1050 _lclose32( hFile);
1051 return 0;
1053 dheader = (LPIMAGE_DOS_HEADER)peimage;
1054 /* it is a pe header, SHELL_GetResourceTable checked that */
1055 pe_header = (LPIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
1056 /* probably makes problems with short PE headers... but I haven't seen
1057 * one yet...
1059 pe_sections = (LPIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
1060 rootresdir = NULL;
1061 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) {
1062 if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
1063 continue;
1064 /* FIXME: doesn't work when the resources are not in a seperate section */
1065 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) {
1066 rootresdir = (LPIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
1067 break;
1071 if (!rootresdir) {
1072 WARN(reg,"haven't found section for resource directory.\n");
1073 UnmapViewOfFile(peimage);
1074 CloseHandle(fmapping);
1075 _lclose32( hFile);
1076 return 0;
1078 icongroupresdir = GetResDirEntryW(rootresdir,(LPWSTR)RT_GROUP_ICON,(DWORD)rootresdir,FALSE);
1079 if (!icongroupresdir) {
1080 WARN(reg,"No Icongroupresourcedirectory!\n");
1081 UnmapViewOfFile(peimage);
1082 CloseHandle(fmapping);
1083 _lclose32( hFile);
1084 return 0;
1087 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
1088 if( nIconIndex == (UINT16)-1 ) {
1089 RetPtr[0] = iconDirCount;
1090 UnmapViewOfFile(peimage);
1091 CloseHandle(fmapping);
1092 _lclose32( hFile);
1093 return hRet;
1096 if (nIconIndex >= iconDirCount) {
1097 WARN(reg,"nIconIndex %d is larger than iconDirCount %d\n",
1098 nIconIndex,iconDirCount);
1099 UnmapViewOfFile(peimage);
1100 CloseHandle(fmapping);
1101 _lclose32( hFile);
1102 GlobalFree16(hRet);
1103 return 0;
1105 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
1107 /* caller just wanted the number of entries */
1109 xresent = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
1110 /* assure we don't get too much ... */
1111 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
1113 /* starting from specified index ... */
1114 xresent = xresent+nIconIndex;
1116 for (i=0;i<n;i++,xresent++) {
1117 CURSORICONDIR *cid;
1118 LPIMAGE_RESOURCE_DIRECTORY resdir;
1120 /* go down this resource entry, name */
1121 resdir = (LPIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
1122 /* default language (0) */
1123 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1124 igdataent = (LPIMAGE_RESOURCE_DATA_ENTRY)resdir;
1126 /* lookup address in mapped image for virtual address */
1127 igdata = NULL;
1128 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1129 if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
1130 continue;
1131 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1132 continue;
1133 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1135 if (!igdata) {
1136 WARN(reg,"no matching real address for icongroup!\n");
1137 UnmapViewOfFile(peimage);
1138 CloseHandle(fmapping);
1139 _lclose32( hFile);
1140 return 0;
1142 /* found */
1143 cid = (CURSORICONDIR*)igdata;
1144 cids[i] = cid;
1145 RetPtr[i] = LookupIconIdFromDirectoryEx32(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1147 iconresdir=GetResDirEntryW(rootresdir,(LPWSTR)RT_ICON,(DWORD)rootresdir,FALSE);
1148 if (!iconresdir) {
1149 WARN(reg,"No Iconresourcedirectory!\n");
1150 UnmapViewOfFile(peimage);
1151 CloseHandle(fmapping);
1152 _lclose32( hFile);
1153 return 0;
1155 for (i=0;i<n;i++) {
1156 LPIMAGE_RESOURCE_DIRECTORY xresdir;
1158 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir,FALSE);
1159 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1161 idataent = (LPIMAGE_RESOURCE_DATA_ENTRY)xresdir;
1163 idata = NULL;
1164 /* map virtual to address in image */
1165 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1166 if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
1167 continue;
1168 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1169 continue;
1170 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1172 if (!idata) {
1173 WARN(reg,"no matching real address found for icondata!\n");
1174 RetPtr[i]=0;
1175 continue;
1177 RetPtr[i] = CreateIconFromResourceEx32(idata,idataent->Size,TRUE,0x00030000,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1179 UnmapViewOfFile(peimage);
1180 CloseHandle(fmapping);
1181 _lclose32( hFile);
1182 return hRet;
1184 _lclose32( hFile );
1185 /* return array with icon handles */
1186 return hRet;
1190 /*************************************************************************
1191 * ExtractIcon16 (SHELL.34)
1193 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
1194 UINT16 nIconIndex )
1196 return ExtractIcon32A( hInstance, lpszExeFileName, nIconIndex );
1200 /*************************************************************************
1201 * ExtractIcon32A (SHELL32.133)
1203 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
1204 UINT32 nIconIndex )
1206 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
1208 if( handle )
1210 HICON16* ptr = (HICON16*)GlobalLock16(handle);
1211 HICON16 hIcon = *ptr;
1213 GlobalFree16(handle);
1214 return hIcon;
1216 return 0;
1219 /*************************************************************************
1220 * ExtractIcon32W (SHELL32.180)
1222 HICON32 WINAPI ExtractIcon32W( HINSTANCE32 hInstance, LPCWSTR lpszExeFileName,
1223 UINT32 nIconIndex )
1225 LPSTR exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
1226 HICON32 ret = ExtractIcon32A(hInstance,exefn,nIconIndex);
1228 HeapFree(GetProcessHeap(),0,exefn);
1229 return ret;
1233 /*************************************************************************
1234 * ExtractAssociatedIcon [SHELL.36]
1236 * Return icon for given file (either from file itself or from associated
1237 * executable) and patch parameters if needed.
1239 HICON32 WINAPI ExtractAssociatedIcon32A(HINSTANCE32 hInst,LPSTR lpIconPath,
1240 LPWORD lpiIcon)
1242 return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
1245 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst,LPSTR lpIconPath,
1246 LPWORD lpiIcon)
1248 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1250 if( hIcon < 2 )
1253 if( hIcon == 1 ) /* no icons found in given file */
1255 char tempPath[0x80];
1256 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
1258 if( uRet > 32 && tempPath[0] )
1260 strcpy(lpIconPath,tempPath);
1261 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1263 if( hIcon > 2 ) return hIcon;
1265 else hIcon = 0;
1268 if( hIcon == 1 )
1269 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
1270 else
1271 *lpiIcon = 6; /* generic icon - found nothing */
1273 GetModuleFileName16(hInst, lpIconPath, 0x80);
1274 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
1277 return hIcon;
1280 /*************************************************************************
1281 * FindEnvironmentString [SHELL.38]
1283 * Returns a pointer into the DOS environment... Ugh.
1285 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
1287 UINT16 l = strlen(entry);
1288 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
1290 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
1292 if( !*(lpEnv+l) )
1293 return (lpEnv + l); /* empty entry */
1294 else if ( *(lpEnv+l)== '=' )
1295 return (lpEnv + l + 1);
1297 return NULL;
1300 SEGPTR WINAPI FindEnvironmentString(LPSTR str)
1302 SEGPTR spEnv = GetDOSEnvironment();
1303 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
1305 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
1307 if( lpString ) /* offset should be small enough */
1308 return spEnv + (lpString - lpEnv);
1310 return (SEGPTR)NULL;
1313 /*************************************************************************
1314 * DoEnvironmentSubst [SHELL.37]
1316 * Replace %KEYWORD% in the str with the value of variable KEYWORD
1317 * from "DOS" environment.
1319 DWORD WINAPI DoEnvironmentSubst(LPSTR str,WORD length)
1321 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
1322 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
1323 LPSTR lpstr = str;
1324 LPSTR lpbstr = lpBuffer;
1326 CharToOem32A(str,str);
1328 TRACE(reg,"accept %s\n", str);
1330 while( *lpstr && lpbstr - lpBuffer < length )
1332 LPSTR lpend = lpstr;
1334 if( *lpstr == '%' )
1336 do { lpend++; } while( *lpend && *lpend != '%' );
1337 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
1339 LPSTR lpKey;
1340 *lpend = '\0';
1341 lpKey = SHELL_FindString(lpEnv, lpstr+1);
1342 if( lpKey ) /* found key value */
1344 int l = strlen(lpKey);
1346 if( l > length - (lpbstr - lpBuffer) - 1 )
1348 WARN(reg,"Env subst aborted - string too short\n");
1349 *lpend = '%';
1350 break;
1352 strcpy(lpbstr, lpKey);
1353 lpbstr += l;
1355 else break;
1356 *lpend = '%';
1357 lpstr = lpend + 1;
1359 else break; /* back off and whine */
1361 continue;
1364 *lpbstr++ = *lpstr++;
1367 *lpbstr = '\0';
1368 if( lpstr - str == strlen(str) )
1370 strncpy(str, lpBuffer, length);
1371 length = 1;
1373 else
1374 length = 0;
1376 TRACE(reg," return %s\n", str);
1378 OemToChar32A(str,str);
1379 HeapFree( GetProcessHeap(), 0, lpBuffer);
1381 /* Return str length in the LOWORD
1382 * and 1 in HIWORD if subst was successful.
1384 return (DWORD)MAKELONG(strlen(str), length);
1387 /*************************************************************************
1388 * ShellHookProc [SHELL.103]
1389 * System-wide WH_SHELL hook.
1391 LRESULT WINAPI ShellHookProc(INT16 code, WPARAM16 wParam, LPARAM lParam)
1393 TRACE(reg,"%i, %04x, %08x\n", code, wParam,
1394 (unsigned)lParam );
1395 if( SHELL_hHook && SHELL_hWnd )
1397 UINT16 uMsg = 0;
1398 switch( code )
1400 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
1401 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
1402 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
1404 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
1406 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
1409 LRESULT WINAPI FUNC004(INT16 code, WPARAM16 wParam, /*LPARAM*/WORD lParam)
1411 FIXME(reg,"(%d,%d,%d),STUB!\n",code,wParam,lParam);
1412 return ShellHookProc(code,wParam,(DWORD)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 fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%d,0x%08x)\n",
1464 path,dwFileAttributes,psfi,sizeofpsfi,flags
1466 return TRUE;
1469 /*************************************************************************
1470 * SHAppBarMessage32 [SHELL32.207]
1472 UINT32 WINAPI SHAppBarMessage32(DWORD msg, PAPPBARDATA data)
1474 fprintf(stdnimp,"SHAppBarMessage32(0x%08lx,%p)\n", msg, data);
1475 #if 0
1476 switch (msg) {
1477 case ABM_ACTIVATE:
1478 case ABM_GETAUTOHIDEBAR:
1479 case ABM_GETSTATE:
1480 case ABM_GETTASKBARPOS:
1481 case ABM_NEW:
1482 case ABM_QUERYPOS:
1483 case ABM_REMOVE:
1484 case ABM_SETAUTOHIDEBAR:
1485 case ABM_SETPOS:
1486 case ABM_WINDOWPOSCHANGED:
1489 #endif
1490 return 0;
1493 /*************************************************************************
1494 * CommandLineToArgvW [SHELL32.7]
1496 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
1498 LPWSTR *argv,s,t;
1499 int i;
1501 /* to get writeable copy */
1502 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
1503 s=cmdline;i=0;
1504 while (*s) {
1505 /* space */
1506 if (*s==0x0020) {
1507 i++;
1508 s++;
1509 while (*s && *s==0x0020)
1510 s++;
1511 continue;
1513 s++;
1515 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
1516 s=t=cmdline;
1517 i=0;
1518 while (*s) {
1519 if (*s==0x0020) {
1520 *s=0;
1521 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
1522 *s=0x0020;
1523 while (*s && *s==0x0020)
1524 s++;
1525 if (*s)
1526 t=s+1;
1527 else
1528 t=s;
1529 continue;
1531 s++;
1533 if (*t)
1534 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
1535 HeapFree( GetProcessHeap(), 0, cmdline );
1536 argv[i]=NULL;
1537 *numargs=i;
1538 return argv;
1541 /*************************************************************************
1542 * Control_RunDLL [SHELL32.12]
1544 * Wild speculation in the following!
1546 * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
1549 void WINAPI Control_RunDLL (HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4)
1551 TRACE(exec, "(%08x, %p, \"%s\", %08lx)\n",
1552 hwnd, code ? code : "(null)",
1553 cmd ? cmd : "(null)", arg4);
1556 /*************************************************************************
1559 void WINAPI FreeIconList( DWORD dw )
1561 fprintf( stdnimp, "FreeIconList: empty stub\n" );
1564 /*************************************************************************
1565 * SHELL32_DllGetClassObject [SHELL32.14]
1567 * http://premium.microsoft.com/msdn/library/sdkdoc/api2_48fo.htm
1569 DWORD WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID *ppv)
1571 char xclsid[50],xiid[50];
1572 HRESULT hres = E_OUTOFMEMORY;
1575 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1576 WINE_StringFromCLSID((LPCLSID)iid,xiid);
1577 fprintf(stderr,"SHELL32_DllGetClassObject(%s,%s,%p)\n",xclsid,xiid,ppv);
1579 *ppv = NULL;
1580 /* SDK example code looks like this:
1582 HRESULT hres = E_OUTOFMEMORY;
1584 *ppv = NULL;
1585 CClassFactory *pClassFactory = new CClassFactory(rclsid);
1587 if (pClassFactory) {
1588 hRes = pClassFactory->QueryInterface(riid,ppv);
1589 pClassFactory->Release();
1591 return hRes;
1593 * The magic of the whole stuff is still unclear to me, so just hack together
1594 * something.
1597 if (!memcmp(rclsid,&CLSID_ShellDesktop,sizeof(CLSID_ShellDesktop))) {
1598 fprintf(stderr," requested CLSID_ShellDesktop, creating it.\n");
1599 *ppv = IShellFolder_Constructor();
1600 /* FIXME: Initialize this folder to be the shell desktop folder */
1601 return 0;
1604 fprintf (stdnimp, " -> clsid not found. returning E_OUTOFMEMORY.\n");
1605 return hres;
1608 /*************************************************************************
1609 * SHGetDesktopFolder [SHELL32.216]
1610 * returns the interface to the shell desktop folder.
1612 * [SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
1613 * CLSID_ShellDesktop.
1615 * CoCreateInstance(CLSID_Desktop, NULL,
1616 * CLSCTX_INPROC, IID_IShellFolder, &pshf);
1618 * So what we are doing is currently wrong....
1620 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
1621 *shellfolder = IShellFolder_Constructor();
1622 return NOERROR;
1625 /*************************************************************************
1626 * SHGetMalloc [SHELL32.220]
1627 * returns the interface to shell malloc.
1629 * [SDK header win95/shlobj.h:
1630 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
1632 * What we are currently doing is not very wrong, since we always use the same
1633 * heap (ProcessHeap).
1635 DWORD WINAPI SHGetMalloc(LPMALLOC32 *lpmal) {
1636 fprintf(stderr,"SHGetMalloc()\n");
1637 return CoGetMalloc32(0,lpmal);
1640 /*************************************************************************
1641 * SHGetSpecialFolderLocation [SHELL32.223]
1642 * returns the PIDL of a special folder
1644 * nFolder is a CSIDL_xxxxx.
1646 HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl) {
1647 fprintf(stderr,"SHGetSpecialFolderLocation(%04x,%d,%p),stub!\n",
1648 hwndOwner,nFolder,ppidl
1650 *ppidl = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2*sizeof(ITEMIDLIST));
1651 /* FIXME: we return only the empty ITEMIDLIST currently. */
1652 (*ppidl)->mkid.cb = 0;
1653 return NOERROR;
1656 /*************************************************************************
1657 * SHGetPathFromIDList [SHELL32.221]
1658 * returns the path from a passed PIDL.
1660 BOOL32 WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath) {
1661 fprintf(stderr,"SHGetPathFromIDList(%p,%p),stub!\n",pidl,pszPath);
1662 lstrcpy32A(pszPath,"E:\\"); /* FIXME */
1663 return NOERROR;