Release 970824
[wine/multimedia.git] / misc / shell.c
blobb3a9ffe3c94d0d00b3ac862569cc9bcba89fcb4a
1 /*
2 * Shell Library Functions
3 */
4 #include <stdlib.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <ctype.h>
9 #include "windows.h"
10 #include "file.h"
11 #include "shell.h"
12 #include "heap.h"
13 #include "module.h"
14 #include "neexe.h"
15 #include "resource.h"
16 #include "dlgs.h"
17 #include "win.h"
18 #include "cursoricon.h"
19 #include "stddebug.h"
20 #include "debug.h"
21 #include "winreg.h"
23 /* .ICO file ICONDIR definitions */
25 #pragma pack(1)
27 typedef struct
29 BYTE bWidth; /* Width, in pixels, of the image */
30 BYTE bHeight; /* Height, in pixels, of the image */
31 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
32 BYTE bReserved; /* Reserved ( must be 0) */
33 WORD wPlanes; /* Color Planes */
34 WORD wBitCount; /* Bits per pixel */
35 DWORD dwBytesInRes; /* How many bytes in this resource? */
36 DWORD dwImageOffset; /* Where in the file is this image? */
37 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
39 typedef struct
41 WORD idReserved; /* Reserved (must be 0) */
42 WORD idType; /* Resource Type (1 for icons) */
43 WORD idCount; /* How many images? */
44 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
45 } icoICONDIR, *LPicoICONDIR;
47 #pragma pack(4)
49 extern HGLOBAL16 CURSORICON_LoadHandler( HGLOBAL16, HINSTANCE16, BOOL32);
50 extern WORD GetIconID( HGLOBAL16 hResource, DWORD resType );
52 static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
53 static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
54 static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
56 static HWND16 SHELL_hWnd = 0;
57 static HHOOK SHELL_hHook = 0;
58 static UINT16 uMsgWndCreated = 0;
59 static UINT16 uMsgWndDestroyed = 0;
60 static UINT16 uMsgShellActivate = 0;
62 /*************************************************************************
63 * DragAcceptFiles [SHELL.9]
65 void WINAPI DragAcceptFiles(HWND16 hWnd, BOOL16 b)
67 WND* wnd = WIN_FindWndPtr(hWnd);
69 if( wnd )
70 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
71 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
75 /*************************************************************************
76 * DragQueryFile [SHELL.11]
78 UINT16 WINAPI DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile,
79 WORD wLength)
81 /* hDrop is a global memory block allocated with GMEM_SHARE
82 * with DROPFILESTRUCT as a header and filenames following
83 * it, zero length filename is in the end */
85 LPDROPFILESTRUCT lpDropFileStruct;
86 LPSTR lpCurrent;
87 WORD i;
89 dprintf_reg(stddeb,"DragQueryFile(%04x, %i, %p, %u)\n",
90 hDrop,wFile,lpszFile,wLength);
92 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
93 if(!lpDropFileStruct) return 0;
95 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
97 i = 0;
98 while (i++ < wFile)
100 while (*lpCurrent++); /* skip filename */
101 if (!*lpCurrent)
102 return (wFile == 0xFFFF) ? i : 0;
105 i = strlen(lpCurrent);
106 if (!lpszFile) return i+1; /* needed buffer size */
108 i = (wLength > i) ? i : wLength-1;
109 strncpy(lpszFile, lpCurrent, i);
110 lpszFile[i] = '\0';
112 GlobalUnlock16(hDrop);
113 return i;
117 /*************************************************************************
118 * DragFinish [SHELL.12]
120 void WINAPI DragFinish(HDROP16 h)
122 GlobalFree16((HGLOBAL16)h);
126 /*************************************************************************
127 * DragQueryPoint [SHELL.13]
129 BOOL16 WINAPI DragQueryPoint(HDROP16 hDrop, POINT16 *p)
131 LPDROPFILESTRUCT lpDropFileStruct;
132 BOOL16 bRet;
134 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
136 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
137 bRet = lpDropFileStruct->fInNonClientArea;
139 GlobalUnlock16(hDrop);
140 return bRet;
143 /*************************************************************************
144 * SHELL_FindExecutable
145 * Utility for code sharing between FindExecutable and ShellExecute
147 static HINSTANCE32 SHELL_FindExecutable( LPCSTR lpFile,
148 LPCSTR lpOperation,
149 LPSTR lpResult)
151 char *extension = NULL; /* pointer to file extension */
152 char tmpext[5]; /* local copy to mung as we please */
153 char filetype[256]; /* registry name for this filetype */
154 LONG filetypelen=256; /* length of above */
155 char command[256]; /* command from registry */
156 LONG commandlen=256; /* This is the most DOS can handle :) */
157 char buffer[256]; /* Used to GetProfileString */
158 HINSTANCE32 retval=31; /* default - 'No association was found' */
159 char *tok; /* token pointer */
160 int i; /* random counter */
161 char xlpFile[256]; /* result of SearchPath */
163 dprintf_exec(stddeb, "SHELL_FindExecutable: %s\n",
164 (lpFile != NULL?lpFile:"-") );
165 lpResult[0]='\0'; /* Start off with an empty return string */
167 /* trap NULL parameters on entry */
168 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
170 /* FIXME - should throw a warning, perhaps! */
171 return 2; /* File not found. Close enough, I guess. */
174 if (SearchPath32A( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
175 lpFile = xlpFile;
177 /* First thing we need is the file's extension */
178 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
179 /* File->Run in progman uses */
180 /* .\FILE.EXE :( */
181 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
183 return 31; /* no association */
186 /* Make local copy & lowercase it for reg & 'programs=' lookup */
187 lstrcpyn32A( tmpext, extension, 5 );
188 CharLower32A( tmpext );
189 dprintf_exec(stddeb, "SHELL_FindExecutable: %s file\n", tmpext);
191 /* Three places to check: */
192 /* 1. win.ini, [windows], programs (NB no leading '.') */
193 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
194 /* 3. win.ini, [extensions], extension (NB no leading '.' */
195 /* All I know of the order is that registry is checked before */
196 /* extensions; however, it'd make sense to check the programs */
197 /* section first, so that's what happens here. */
199 /* See if it's a program - if GetProfileString fails, we skip this
200 * section. Actually, if GetProfileString fails, we've probably
201 * got a lot more to worry about than running a program... */
202 if ( GetProfileString32A("windows", "programs", "exe pif bat com",
203 buffer, sizeof(buffer)) > 0 )
205 for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
207 tok = strtok(buffer, " \t"); /* ? */
208 while( tok!= NULL)
210 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
212 strcpy(lpResult, xlpFile);
213 /* Need to perhaps check that the file has a path
214 * attached */
215 dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
216 lpResult);
217 return 33;
219 /* Greater than 32 to indicate success FIXME According to the
220 * docs, I should be returning a handle for the
221 * executable. Does this mean I'm supposed to open the
222 * executable file or something? More RTFM, I guess... */
224 tok=strtok(NULL, " \t");
228 /* Check registry */
229 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
230 &filetypelen ) == SHELL_ERROR_SUCCESS )
232 filetype[filetypelen]='\0';
233 dprintf_exec(stddeb, "SHELL_FindExecutable: File type: %s\n",
234 filetype);
236 /* Looking for ...buffer\shell\lpOperation\command */
237 strcat( filetype, "\\shell\\" );
238 strcat( filetype, lpOperation );
239 strcat( filetype, "\\command" );
241 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
242 &commandlen ) == SHELL_ERROR_SUCCESS )
244 /* Is there a replace() function anywhere? */
245 command[commandlen]='\0';
246 strcpy( lpResult, command );
247 tok=strstr( lpResult, "%1" );
248 if (tok != NULL)
250 tok[0]='\0'; /* truncate string at the percent */
251 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
252 tok=strstr( command, "%1" );
253 if ((tok!=NULL) && (strlen(tok)>2))
255 strcat( lpResult, &tok[2] );
258 retval=33; /* FIXME see above */
261 else /* Check win.ini */
263 /* Toss the leading dot */
264 extension++;
265 if ( GetProfileString32A( "extensions", extension, "", command,
266 sizeof(command)) > 0)
268 if (strlen(command)!=0)
270 strcpy( lpResult, command );
271 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
272 if (tok != NULL)
274 tok[0]='\0';
275 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
276 tok=strstr( command, "^" ); /* see above */
277 if ((tok != NULL) && (strlen(tok)>5))
279 strcat( lpResult, &tok[5]);
282 retval=33; /* FIXME - see above */
287 dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
288 return retval;
291 /*************************************************************************
292 * ShellExecute16 [SHELL.20]
294 HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
295 LPCSTR lpFile, LPCSTR lpParameters,
296 LPCSTR lpDirectory, INT16 iShowCmd )
298 HINSTANCE16 retval=31;
299 char old_dir[1024];
300 char cmd[256];
302 dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
303 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
304 lpParameters ? lpParameters : "<null>",
305 lpDirectory ? lpDirectory : "<null>", iShowCmd);
307 if (lpFile==NULL) return 0; /* should not happen */
308 if (lpOperation==NULL) /* default is open */
309 lpOperation="open";
311 if (lpDirectory)
313 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
314 SetCurrentDirectory32A( lpDirectory );
317 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
319 if (retval > 32) /* Found */
321 if (lpParameters)
323 strcat(cmd," ");
324 strcat(cmd,lpParameters);
327 dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
328 retval = WinExec32( cmd, iShowCmd );
330 if (lpDirectory) SetCurrentDirectory32A( old_dir );
331 return retval;
335 /*************************************************************************
336 * ShellExecute32A (SHELL32.84)
338 HINSTANCE32 WINAPI ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation,
339 LPCSTR lpFile, LPCSTR lpParameters,
340 LPCSTR lpDirectory, INT32 iShowCmd )
342 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
343 lpDirectory, iShowCmd );
347 /*************************************************************************
348 * FindExecutable16 (SHELL.21)
350 HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
351 LPSTR lpResult )
353 return (HINSTANCE16)FindExecutable32A( lpFile, lpDirectory, lpResult );
356 /*************************************************************************
357 * FindExecutable32A (SHELL32.184)
359 HINSTANCE32 WINAPI FindExecutable32A( LPCSTR lpFile, LPCSTR lpDirectory,
360 LPSTR lpResult )
362 HINSTANCE32 retval=31; /* default - 'No association was found' */
363 char old_dir[1024];
365 dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n",
366 (lpFile != NULL?lpFile:"-"),
367 (lpDirectory != NULL?lpDirectory:"-"));
369 lpResult[0]='\0'; /* Start off with an empty return string */
371 /* trap NULL parameters on entry */
372 if (( lpFile == NULL ) || ( lpResult == NULL ))
374 /* FIXME - should throw a warning, perhaps! */
375 return 2; /* File not found. Close enough, I guess. */
378 if (lpDirectory)
380 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
381 SetCurrentDirectory32A( lpDirectory );
384 retval = SHELL_FindExecutable( lpFile, "open", lpResult );
386 dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
387 if (lpDirectory) SetCurrentDirectory32A( old_dir );
388 return retval;
391 typedef struct
393 LPCSTR szApp;
394 LPCSTR szOtherStuff;
395 HICON32 hIcon;
396 } ABOUT_INFO;
399 /*************************************************************************
400 * AboutDlgProc32 (not an exported API function)
402 LRESULT WINAPI AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
403 LPARAM lParam )
405 char Template[512], AppTitle[512];
407 switch(msg)
409 case WM_INITDIALOG:
411 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
412 if (info)
414 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON, info->hIcon, 0);
415 GetWindowText32A( hWnd, Template, sizeof(Template) );
416 sprintf( AppTitle, Template, info->szApp );
417 SetWindowText32A( hWnd, AppTitle );
418 SetWindowText32A( GetDlgItem32(hWnd,100), info->szOtherStuff );
421 return 1;
423 case WM_COMMAND:
424 if (wParam == IDOK)
426 EndDialog32(hWnd, TRUE);
427 return TRUE;
429 break;
431 return 0;
435 /*************************************************************************
436 * AboutDlgProc16 (SHELL.33)
438 LRESULT WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
439 LPARAM lParam )
441 return AboutDlgProc32( hWnd, msg, wParam, lParam );
445 /*************************************************************************
446 * ShellAbout16 (SHELL.22)
448 BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
449 HICON16 hIcon )
451 return ShellAbout32A( hWnd, szApp, szOtherStuff, hIcon );
454 /*************************************************************************
455 * ShellAbout32A (SHELL32.82)
457 BOOL32 WINAPI ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
458 HICON32 hIcon )
460 ABOUT_INFO info;
461 info.szApp = szApp;
462 info.szOtherStuff = szOtherStuff;
463 info.hIcon = hIcon;
464 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
465 return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
466 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
467 hWnd, AboutDlgProc32, (LPARAM)&info );
471 /*************************************************************************
472 * ShellAbout32W (SHELL32.83)
474 BOOL32 WINAPI ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
475 HICON32 hIcon )
477 BOOL32 ret;
478 ABOUT_INFO info;
480 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
481 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
482 info.hIcon = hIcon;
483 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
484 ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
485 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
486 hWnd, AboutDlgProc32, (LPARAM)&info );
487 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
488 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
489 return ret;
493 /*************************************************************************
494 * SHELL_GetResourceTable
496 * FIXME: Implement GetPEResourceTable in w32sys.c and call it here.
498 static BYTE* SHELL_GetResourceTable(HFILE32 hFile)
500 BYTE* pTypeInfo = NULL;
501 IMAGE_DOS_HEADER mz_header;
502 IMAGE_OS2_HEADER ne_header;
503 int size;
505 _llseek32( hFile, 0, SEEK_SET );
506 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
507 (mz_header.e_magic != IMAGE_DOS_SIGNATURE)) return (BYTE*)-1;
509 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
510 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
511 return NULL;
513 if (ne_header.ne_magic == IMAGE_NT_SIGNATURE)
514 { fprintf(stdnimp,"Win32s FIXME: file %s line %i\n", __FILE__, __LINE__ );
515 return NULL; }
517 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return NULL;
519 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
521 if( size > sizeof(NE_TYPEINFO) )
523 pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
524 if( pTypeInfo )
526 _llseek32(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
527 if( _lread32( hFile, (char*)pTypeInfo, size) != size )
529 HeapFree( GetProcessHeap(), 0, pTypeInfo);
530 pTypeInfo = NULL;
534 /* no resources */
536 return pTypeInfo;
539 /*************************************************************************
540 * SHELL_LoadResource
542 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
544 BYTE* ptr;
545 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
547 if( (ptr = (BYTE*)GlobalLock16( handle )) )
549 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
550 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
551 return handle;
553 return 0;
556 /*************************************************************************
557 * ICO_LoadIcon
559 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
561 BYTE* ptr;
562 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
564 if( (ptr = (BYTE*)GlobalLock16( handle )) )
566 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
567 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
568 return handle;
570 return 0;
573 /*************************************************************************
574 * ICO_GetIconDirectory
576 * Read .ico file and build phony ICONDIR struct for GetIconID
578 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
580 WORD id[3]; /* idReserved, idType, idCount */
581 LPicoICONDIR lpiID;
582 int i;
584 _llseek32( hFile, 0, SEEK_SET );
585 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
587 /* check .ICO header
589 * - see http://www.microsoft.com/win32dev/ui/icons.htm
592 if( id[0] || id[1] != 1 || !id[2] ) return 0;
594 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
596 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
598 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
600 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
601 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
602 if( handle )
604 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
605 lpID->idReserved = lpiID->idReserved = id[0];
606 lpID->idType = lpiID->idType = id[1];
607 lpID->idCount = lpiID->idCount = id[2];
608 for( i=0; i < lpiID->idCount; i++ )
610 memcpy((void*)(lpID->idEntries + i),
611 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
612 lpID->idEntries[i].icon.wResId = i;
614 *lplpiID = lpiID;
615 return handle;
618 /* fail */
620 HeapFree( GetProcessHeap(), 0, lpiID);
621 return 0;
624 /*************************************************************************
625 * InternalExtractIcon [SHELL.39]
627 * This abortion is called directly by Progman
629 HGLOBAL16 WINAPI InternalExtractIcon(HINSTANCE16 hInstance,
630 LPCSTR lpszExeFileName, UINT16 nIconIndex,
631 WORD n )
633 HGLOBAL16 hRet = 0;
634 HGLOBAL16* RetPtr = NULL;
635 BYTE* pData;
636 OFSTRUCT ofs;
637 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
639 dprintf_reg(stddeb, "InternalExtractIcon(%04x, file '%s', start from %d, extract %d\n",
640 hInstance, lpszExeFileName, nIconIndex, n);
642 if( hFile == HFILE_ERROR32 || !n ) return 0;
644 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
645 RetPtr = (HICON16*)GlobalLock16(hRet);
647 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
649 if( (pData = SHELL_GetResourceTable(hFile)) )
651 HICON16 hIcon = 0;
652 UINT16 iconDirCount = 0;
653 UINT16 iconCount = 0;
654 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
655 NE_NAMEINFO* pIconStorage = NULL;
656 NE_NAMEINFO* pIconDir = NULL;
657 LPicoICONDIR lpiID = NULL;
659 if( pData == (BYTE*)-1 )
661 /* check for .ICO file */
663 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
664 if( hIcon ) { iconDirCount = 1; iconCount = lpiID->idCount; }
666 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
668 /* find icon directory and icon repository */
670 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
672 iconDirCount = pTInfo->count;
673 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
674 dprintf_reg(stddeb,"\tfound directory - %i icon families\n", iconDirCount);
676 if( pTInfo->type_id == NE_RSCTYPE_ICON )
678 iconCount = pTInfo->count;
679 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
680 dprintf_reg(stddeb,"\ttotal icons - %i\n", iconCount);
682 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
685 /* load resources and create icons */
687 if( (pIconStorage && pIconDir) || lpiID )
688 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
689 else if( nIconIndex < iconDirCount )
691 UINT16 i, icon;
693 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
695 for( i = nIconIndex; i < nIconIndex + n; i++ )
697 /* .ICO files have only one icon directory */
699 if( lpiID == NULL )
700 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
701 *(WORD*)pData );
702 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
703 GlobalFree16(hIcon);
706 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
708 hIcon = 0;
709 if( lpiID )
710 hIcon = ICO_LoadIcon( hInstance, hFile,
711 lpiID->idEntries + RetPtr[icon-nIconIndex]);
712 else
713 for( i = 0; i < iconCount; i++ )
714 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
715 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
716 *(WORD*)pData );
717 RetPtr[icon-nIconIndex] = (hIcon)?CURSORICON_LoadHandler( hIcon, hInstance, FALSE ):0;
720 if( lpiID ) HeapFree( GetProcessHeap(), 0, lpiID);
721 else HeapFree( GetProcessHeap(), 0, pData);
723 _lclose32( hFile );
725 /* return array with icon handles */
727 return hRet;
730 /*************************************************************************
731 * ExtractIcon16 (SHELL.34)
733 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
734 UINT16 nIconIndex )
736 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
738 if( handle )
740 HICON16* ptr = (HICON16*)GlobalLock16(handle);
741 HICON16 hIcon = *ptr;
743 GlobalFree16(handle);
744 return hIcon;
746 return 0;
750 /*************************************************************************
751 * ExtractIcon32A (SHELL32.20)
753 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
754 UINT32 nIconIndex )
756 /* FIXME */
757 return ExtractIcon16( hInstance, lpszExeFileName, nIconIndex );
761 /*************************************************************************
762 * ExtractAssociatedIcon [SHELL.36]
764 * Return icon for given file (either from file itself or from associated
765 * executable) and patch parameters if needed.
767 HICON16 WINAPI ExtractAssociatedIcon(HINSTANCE16 hInst,LPSTR lpIconPath,
768 LPWORD lpiIcon)
770 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
772 if( hIcon < 2 )
775 if( hIcon == 1 ) /* no icons found in given file */
777 char tempPath[0x80];
778 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
780 if( uRet > 32 && tempPath[0] )
782 strcpy(lpIconPath,tempPath);
783 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
785 if( hIcon > 2 ) return hIcon;
787 else hIcon = 0;
790 if( hIcon == 1 )
791 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
792 else
793 *lpiIcon = 6; /* generic icon - found nothing */
795 GetModuleFileName16(hInst, lpIconPath, 0x80);
796 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
799 return hIcon;
802 /*************************************************************************
803 * FindEnvironmentString [SHELL.38]
805 * Returns a pointer into the DOS environment... Ugh.
807 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
809 UINT16 l = strlen(entry);
810 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
812 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
814 if( !*(lpEnv+l) )
815 return (lpEnv + l); /* empty entry */
816 else if ( *(lpEnv+l)== '=' )
817 return (lpEnv + l + 1);
819 return NULL;
822 SEGPTR WINAPI FindEnvironmentString(LPSTR str)
824 SEGPTR spEnv = GetDOSEnvironment();
825 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
827 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
829 if( lpString ) /* offset should be small enough */
830 return spEnv + (lpString - lpEnv);
832 return (SEGPTR)NULL;
835 /*************************************************************************
836 * DoEnvironmentSubst [SHELL.37]
838 * Replace %KEYWORD% in the str with the value of variable KEYWORD
839 * from "DOS" environment.
841 DWORD WINAPI DoEnvironmentSubst(LPSTR str,WORD length)
843 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
844 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
845 LPSTR lpstr = str;
846 LPSTR lpbstr = lpBuffer;
848 CharToOem32A(str,str);
850 dprintf_reg(stddeb,"DoEnvSubst: accept %s", str);
852 while( *lpstr && lpbstr - lpBuffer < length )
854 LPSTR lpend = lpstr;
856 if( *lpstr == '%' )
858 do { lpend++; } while( *lpend && *lpend != '%' );
859 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
861 LPSTR lpKey;
862 *lpend = '\0';
863 lpKey = SHELL_FindString(lpEnv, lpstr+1);
864 if( lpKey ) /* found key value */
866 int l = strlen(lpKey);
868 if( l > length - (lpbstr - lpBuffer) - 1 )
870 fprintf(stdnimp,"File %s, line %i: Env subst aborted - string too short\n",
871 __FILE__, __LINE__);
872 *lpend = '%';
873 break;
875 strcpy(lpbstr, lpKey);
876 lpbstr += l;
878 else break;
879 *lpend = '%';
880 lpstr = lpend + 1;
882 else break; /* back off and whine */
884 continue;
887 *lpbstr++ = *lpstr++;
890 *lpbstr = '\0';
891 if( lpstr - str == strlen(str) )
893 strncpy(str, lpBuffer, length);
894 length = 1;
896 else
897 length = 0;
899 dprintf_reg(stddeb," return %s\n", str);
901 OemToChar32A(str,str);
902 HeapFree( GetProcessHeap(), 0, lpBuffer);
904 /* Return str length in the LOWORD
905 * and 1 in HIWORD if subst was successful.
907 return (DWORD)MAKELONG(strlen(str), length);
910 /*************************************************************************
911 * ShellHookProc [SHELL.103]
912 * System-wide WH_SHELL hook.
914 LRESULT WINAPI ShellHookProc(INT16 code, WPARAM16 wParam, LPARAM lParam)
916 dprintf_reg(stddeb,"ShellHookProc: %i, %04x, %08x\n", code, wParam,
917 (unsigned)lParam );
918 if( SHELL_hHook && SHELL_hWnd )
920 UINT16 uMsg = 0;
921 switch( code )
923 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
924 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
925 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
927 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
929 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
932 /*************************************************************************
933 * RegisterShellHook [SHELL.102]
935 BOOL32 WINAPI RegisterShellHook(HWND16 hWnd, UINT16 uAction)
937 dprintf_reg(stddeb,"RegisterShellHook: %04x [%u]\n", hWnd, uAction );
939 switch( uAction )
941 case 2: /* register hWnd as a shell window */
943 if( !SHELL_hHook )
945 HMODULE16 hShell = GetModuleHandle16( "SHELL" );
947 SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc,
948 hShell, 0 );
949 if( SHELL_hHook )
951 uMsgWndCreated = RegisterWindowMessage32A( lpstrMsgWndCreated );
952 uMsgWndDestroyed = RegisterWindowMessage32A( lpstrMsgWndDestroyed );
953 uMsgShellActivate = RegisterWindowMessage32A( lpstrMsgShellActivate );
955 else fprintf( stderr, "\tunable to install ShellHookProc()!\n");
958 if( SHELL_hHook ) return ((SHELL_hWnd = hWnd) != 0);
959 break;
961 default:
963 fprintf( stderr, "RegisterShellHook: unknown code %i\n", uAction );
965 /* just in case */
967 SHELL_hWnd = 0;
969 return FALSE;
973 /*************************************************************************
974 * SHGetFileInfoA [SHELL32.54]
976 DWORD WINAPI SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,
977 SHFILEINFO32A *psfi, UINT32 sizeofpsfi,
978 UINT32 flags )
980 fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%d,0x%08x)\n",
981 path,dwFileAttributes,psfi,sizeofpsfi,flags
983 return TRUE;
986 /*************************************************************************
987 * CommandLineToArgvW [SHELL32.2]
989 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
991 LPWSTR *argv,s,t;
992 int i;
994 /* to get writeable copy */
995 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
996 s=cmdline;i=0;
997 while (*s) {
998 /* space */
999 if (*s==0x0020) {
1000 i++;
1001 s++;
1002 while (*s && *s==0x0020)
1003 s++;
1004 continue;
1006 s++;
1008 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
1009 s=t=cmdline;
1010 i=0;
1011 while (*s) {
1012 if (*s==0x0020) {
1013 *s=0;
1014 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
1015 *s=0x0020;
1016 while (*s && *s==0x0020)
1017 s++;
1018 if (*s)
1019 t=s+1;
1020 else
1021 t=s;
1022 continue;
1024 s++;
1026 if (*t)
1027 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
1028 HeapFree( GetProcessHeap(), 0, cmdline );
1029 argv[i]=NULL;
1030 *numargs=i;
1031 return argv;