Release 970329
[wine/multimedia.git] / misc / shell.c
blobf97f53a211c794b96d6a917f8a097db3f1af5c11
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 "xmalloc.h"
22 #include "winreg.h"
24 /* .ICO file ICONDIR definitions */
26 #pragma pack(1)
28 typedef struct
30 BYTE bWidth; /* Width, in pixels, of the image */
31 BYTE bHeight; /* Height, in pixels, of the image */
32 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
33 BYTE bReserved; /* Reserved ( must be 0) */
34 WORD wPlanes; /* Color Planes */
35 WORD wBitCount; /* Bits per pixel */
36 DWORD dwBytesInRes; /* How many bytes in this resource? */
37 DWORD dwImageOffset; /* Where in the file is this image? */
38 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
40 typedef struct
42 WORD idReserved; /* Reserved (must be 0) */
43 WORD idType; /* Resource Type (1 for icons) */
44 WORD idCount; /* How many images? */
45 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
46 } icoICONDIR, *LPicoICONDIR;
48 #pragma pack(4)
50 extern HGLOBAL16 CURSORICON_LoadHandler( HGLOBAL16, HINSTANCE16, BOOL32);
51 extern WORD GetIconID( HGLOBAL16 hResource, DWORD resType );
53 /*************************************************************************
54 * DragAcceptFiles [SHELL.9]
56 void DragAcceptFiles(HWND16 hWnd, BOOL16 b)
58 WND* wnd = WIN_FindWndPtr(hWnd);
60 if( wnd )
61 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
62 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
66 /*************************************************************************
67 * DragQueryFile [SHELL.11]
69 UINT16 DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile, WORD wLength)
71 /* hDrop is a global memory block allocated with GMEM_SHARE
72 * with DROPFILESTRUCT as a header and filenames following
73 * it, zero length filename is in the end */
75 LPDROPFILESTRUCT lpDropFileStruct;
76 LPSTR lpCurrent;
77 WORD i;
79 dprintf_reg(stddeb,"DragQueryFile(%04x, %i, %p, %u)\n",
80 hDrop,wFile,lpszFile,wLength);
82 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
83 if(!lpDropFileStruct) return 0;
85 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
87 i = 0;
88 while (i++ < wFile)
90 while (*lpCurrent++); /* skip filename */
91 if (!*lpCurrent)
92 return (wFile == 0xFFFF) ? i : 0;
95 i = strlen(lpCurrent);
96 if (!lpszFile) return i+1; /* needed buffer size */
98 i = (wLength > i) ? i : wLength-1;
99 strncpy(lpszFile, lpCurrent, i);
100 lpszFile[i] = '\0';
102 GlobalUnlock16(hDrop);
103 return i;
107 /*************************************************************************
108 * DragFinish [SHELL.12]
110 void DragFinish(HDROP16 h)
112 GlobalFree16((HGLOBAL16)h);
116 /*************************************************************************
117 * DragQueryPoint [SHELL.13]
119 BOOL16 DragQueryPoint(HDROP16 hDrop, POINT16 *p)
121 LPDROPFILESTRUCT lpDropFileStruct;
122 BOOL16 bRet;
124 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
126 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
127 bRet = lpDropFileStruct->fInNonClientArea;
129 GlobalUnlock16(hDrop);
130 return bRet;
133 /*************************************************************************
134 * SHELL_FindExecutable
135 * Utility for code sharing between FindExecutable and ShellExecute
137 static HINSTANCE16 SHELL_FindExecutable( LPCSTR lpFile,
138 LPCSTR lpDirectory,
139 LPCSTR lpOperation,
140 LPSTR lpResult)
142 char *extension = NULL; /* pointer to file extension */
143 char tmpext[5]; /* local copy to mung as we please */
144 char filetype[256]; /* registry name for this filetype */
145 LONG filetypelen=256; /* length of above */
146 char command[256]; /* command from registry */
147 LONG commandlen=256; /* This is the most DOS can handle :) */
148 char buffer[256]; /* Used to GetProfileString */
149 HINSTANCE16 retval=31; /* default - 'No association was found' */
150 char *tok; /* token pointer */
151 int i; /* random counter */
152 char xlpFile[256]; /* result of SearchPath */
154 dprintf_exec(stddeb, "SHELL_FindExecutable: File %s, Dir %s\n",
155 (lpFile != NULL?lpFile:"-"),
156 (lpDirectory != NULL?lpDirectory:"-"));
158 lpResult[0]='\0'; /* Start off with an empty return string */
160 /* trap NULL parameters on entry */
161 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
163 /* FIXME - should throw a warning, perhaps! */
164 return 2; /* File not found. Close enough, I guess. */
166 if (SearchPath32A(lpDirectory,lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
167 lpFile = xlpFile;
169 /* First thing we need is the file's extension */
170 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
171 /* File->Run in progman uses */
172 /* .\FILE.EXE :( */
173 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
175 return 31; /* no association */
178 /* Make local copy & lowercase it for reg & 'programs=' lookup */
179 lstrcpyn32A( tmpext, extension, 5 );
180 CharLower32A( tmpext );
181 dprintf_exec(stddeb, "SHELL_FindExecutable: %s file\n", tmpext);
183 /* Three places to check: */
184 /* 1. win.ini, [windows], programs (NB no leading '.') */
185 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
186 /* 3. win.ini, [extensions], extension (NB no leading '.' */
187 /* All I know of the order is that registry is checked before */
188 /* extensions; however, it'd make sense to check the programs */
189 /* section first, so that's what happens here. */
191 /* See if it's a program - if GetProfileString fails, we skip this
192 * section. Actually, if GetProfileString fails, we've probably
193 * got a lot more to worry about than running a program... */
194 if ( GetProfileString32A("windows", "programs", "exe pif bat com",
195 buffer, sizeof(buffer)) > 0 )
197 for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
199 tok = strtok(buffer, " \t"); /* ? */
200 while( tok!= NULL)
202 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
204 strcpy(lpResult, xlpFile);
205 /* Need to perhaps check that the file has a path
206 * attached */
207 dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
208 lpResult);
209 return 33;
211 /* Greater than 32 to indicate success FIXME According to the
212 * docs, I should be returning a handle for the
213 * executable. Does this mean I'm supposed to open the
214 * executable file or something? More RTFM, I guess... */
216 tok=strtok(NULL, " \t");
220 /* Check registry */
221 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
222 &filetypelen ) == SHELL_ERROR_SUCCESS )
224 filetype[filetypelen]='\0';
225 dprintf_exec(stddeb, "SHELL_FindExecutable: File type: %s\n",
226 filetype);
228 /* Looking for ...buffer\shell\lpOperation\command */
229 strcat( filetype, "\\shell\\" );
230 strcat( filetype, lpOperation );
231 strcat( filetype, "\\command" );
233 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
234 &commandlen ) == SHELL_ERROR_SUCCESS )
236 /* Is there a replace() function anywhere? */
237 command[commandlen]='\0';
238 strcpy( lpResult, command );
239 tok=strstr( lpResult, "%1" );
240 if (tok != NULL)
242 tok[0]='\0'; /* truncate string at the percent */
243 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
244 tok=strstr( command, "%1" );
245 if ((tok!=NULL) && (strlen(tok)>2))
247 strcat( lpResult, &tok[2] );
250 retval=33; /* FIXME see above */
253 else /* Check win.ini */
255 /* Toss the leading dot */
256 extension++;
257 if ( GetProfileString32A( "extensions", extension, "", command,
258 sizeof(command)) > 0)
260 if (strlen(command)!=0)
262 strcpy( lpResult, command );
263 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
264 if (tok != NULL)
266 tok[0]='\0';
267 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
268 tok=strstr( command, "^" ); /* see above */
269 if ((tok != NULL) && (strlen(tok)>5))
271 strcat( lpResult, &tok[5]);
274 retval=33; /* FIXME - see above */
279 dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
280 return retval;
283 /*************************************************************************
284 * ShellExecute16 [SHELL.20]
286 HINSTANCE16 ShellExecute16( HWND16 hWnd, LPCSTR lpOperation, LPCSTR lpFile,
287 LPCSTR lpParameters, LPCSTR lpDirectory,
288 INT16 iShowCmd )
290 HINSTANCE16 retval=31;
291 char cmd[256];
293 dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
294 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
295 lpParameters ? lpParameters : "<null>",
296 lpDirectory ? lpDirectory : "<null>", iShowCmd);
298 if (lpFile==NULL) return 0; /* should not happen */
299 if (lpOperation==NULL) /* default is open */
300 lpOperation="open";
302 retval = SHELL_FindExecutable( lpFile, lpDirectory, lpOperation, cmd );
304 if ( retval <= 32 )
306 return retval;
309 if (lpParameters)
311 strcat(cmd," ");
312 strcat(cmd,lpParameters);
315 dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
316 return WinExec32(cmd,iShowCmd);
320 /*************************************************************************
321 * ShellExecute32A (SHELL32.84)
323 HINSTANCE32 ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation, LPCSTR lpFile,
324 LPCSTR lpParameters, LPCSTR lpDirectory,
325 INT32 iShowCmd )
327 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
328 lpDirectory, iShowCmd );
332 /*************************************************************************
333 * FindExecutable16 (SHELL.21)
335 HINSTANCE16 FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
336 LPSTR lpResult )
338 HINSTANCE16 retval=31; /* default - 'No association was found' */
340 dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n",
341 (lpFile != NULL?lpFile:"-"),
342 (lpDirectory != NULL?lpDirectory:"-"));
344 lpResult[0]='\0'; /* Start off with an empty return string */
346 /* trap NULL parameters on entry */
347 if (( lpFile == NULL ) || ( lpResult == NULL ))
349 /* FIXME - should throw a warning, perhaps! */
350 return 2; /* File not found. Close enough, I guess. */
353 retval = SHELL_FindExecutable( lpFile, lpDirectory, "open",
354 lpResult );
356 dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
357 return retval;
360 typedef struct
362 LPCSTR szApp;
363 LPCSTR szOtherStuff;
364 HICON32 hIcon;
365 } ABOUT_INFO;
368 /*************************************************************************
369 * AboutDlgProc32 (not an exported API function)
371 LRESULT AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
372 LPARAM lParam )
374 char Template[512], AppTitle[512];
376 switch(msg)
378 case WM_INITDIALOG:
380 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
381 if (info)
383 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON, info->hIcon, 0);
384 GetWindowText32A( hWnd, Template, sizeof(Template) );
385 sprintf( AppTitle, Template, info->szApp );
386 SetWindowText32A( hWnd, AppTitle );
387 SetWindowText32A( GetDlgItem32(hWnd,100), info->szOtherStuff );
390 return 1;
392 case WM_COMMAND:
393 if (wParam == IDOK)
395 EndDialog32(hWnd, TRUE);
396 return TRUE;
398 break;
400 return 0;
404 /*************************************************************************
405 * AboutDlgProc16 (SHELL.33)
407 LRESULT AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
408 LPARAM lParam )
410 return AboutDlgProc32( hWnd, msg, wParam, lParam );
414 /*************************************************************************
415 * ShellAbout16 (SHELL.22)
417 BOOL16 ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
418 HICON16 hIcon )
420 return ShellAbout32A( hWnd, szApp, szOtherStuff, hIcon );
423 /*************************************************************************
424 * ShellAbout32A (SHELL32.82)
426 BOOL32 ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
427 HICON32 hIcon )
429 ABOUT_INFO info;
430 info.szApp = szApp;
431 info.szOtherStuff = szOtherStuff;
432 info.hIcon = hIcon;
433 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
434 return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
435 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
436 hWnd, AboutDlgProc32, (LPARAM)&info );
440 /*************************************************************************
441 * ShellAbout32W (SHELL32.83)
443 BOOL32 ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
444 HICON32 hIcon )
446 BOOL32 ret;
447 ABOUT_INFO info;
449 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
450 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
451 info.hIcon = hIcon;
452 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
453 ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
454 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
455 hWnd, AboutDlgProc32, (LPARAM)&info );
456 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
457 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
458 return ret;
462 /*************************************************************************
463 * SHELL_GetResourceTable
465 * FIXME: Implement GetPEResourceTable in w32sys.c and call it here.
467 static BYTE* SHELL_GetResourceTable(HFILE32 hFile)
469 struct mz_header_s mz_header;
470 struct ne_header_s ne_header;
471 int size;
473 _llseek32( hFile, 0, SEEK_SET );
474 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
475 (mz_header.mz_magic != MZ_SIGNATURE)) return (BYTE*)-1;
477 _llseek32( hFile, mz_header.ne_offset, SEEK_SET );
478 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
479 return NULL;
481 if (ne_header.ne_magic == PE_SIGNATURE)
482 { fprintf(stdnimp,"Win32s FIXME: file %s line %i\n", __FILE__, __LINE__ );
483 return NULL; }
485 if (ne_header.ne_magic != NE_SIGNATURE) return NULL;
487 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
489 if( size > sizeof(NE_TYPEINFO) )
491 BYTE* pTypeInfo = (BYTE*)xmalloc(size);
493 if( !pTypeInfo ) return NULL;
495 _llseek32(hFile, mz_header.ne_offset+ne_header.resource_tab_offset, SEEK_SET);
496 if( _lread32( hFile, (char*)pTypeInfo, size) != size )
497 { free(pTypeInfo); return NULL; }
498 return pTypeInfo;
500 /* no resources */
502 return NULL;
505 /*************************************************************************
506 * SHELL_LoadResource
508 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
510 BYTE* ptr;
511 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
513 if( (ptr = (BYTE*)GlobalLock16( handle )) )
515 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
516 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
517 return handle;
519 return 0;
522 /*************************************************************************
523 * ICO_LoadIcon
525 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
527 BYTE* ptr;
528 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
530 if( (ptr = (BYTE*)GlobalLock16( handle )) )
532 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
533 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
534 return handle;
536 return 0;
539 /*************************************************************************
540 * ICO_GetIconDirectory
542 * Read .ico file and build phony ICONDIR struct for GetIconID
544 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
546 WORD id[3]; /* idReserved, idType, idCount */
547 LPicoICONDIR lpiID;
548 int i;
550 _llseek32( hFile, 0, SEEK_SET );
551 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
553 /* check .ICO header
555 * - see http://www.microsoft.com/win32dev/ui/icons.htm
558 if( id[0] || id[1] != 1 || !id[2] ) return 0;
560 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
562 lpiID = (LPicoICONDIR)xmalloc(i);
564 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
566 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
567 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
568 if( handle )
570 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
571 lpID->idReserved = lpiID->idReserved = id[0];
572 lpID->idType = lpiID->idType = id[1];
573 lpID->idCount = lpiID->idCount = id[2];
574 for( i=0; i < lpiID->idCount; i++ )
576 memcpy((void*)(lpID->idEntries + i),
577 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
578 lpID->idEntries[i].icon.wResId = i;
580 *lplpiID = lpiID;
581 return handle;
584 /* fail */
586 free(lpiID);
587 return 0;
590 /*************************************************************************
591 * InternalExtractIcon [SHELL.39]
593 * This abortion is called directly by Progman
595 HGLOBAL16 InternalExtractIcon(HINSTANCE16 hInstance, LPCSTR lpszExeFileName, UINT16 nIconIndex, WORD n )
597 HGLOBAL16 hRet = 0;
598 HGLOBAL16* RetPtr = NULL;
599 BYTE* pData;
600 OFSTRUCT ofs;
601 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
603 dprintf_reg(stddeb, "InternalExtractIcon(%04x, file '%s', start from %d, extract %d\n",
604 hInstance, lpszExeFileName, nIconIndex, n);
606 if( hFile == HFILE_ERROR32 || !n ) return 0;
608 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
609 RetPtr = (HICON16*)GlobalLock16(hRet);
611 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
613 pData = SHELL_GetResourceTable(hFile);
614 if( pData )
616 HICON16 hIcon = 0;
617 BOOL32 icoFile = FALSE;
618 UINT16 iconDirCount = 0;
619 UINT16 iconCount = 0;
620 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
621 NE_NAMEINFO* pIconStorage = NULL;
622 NE_NAMEINFO* pIconDir = NULL;
623 LPicoICONDIR lpiID = NULL;
625 if( pData == (BYTE*)-1 )
627 /* check for .ICO file */
629 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
630 if( hIcon )
631 { icoFile = TRUE; iconDirCount = 1; iconCount = lpiID->idCount; }
633 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
635 /* find icon directory and icon repository */
637 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
639 iconDirCount = pTInfo->count;
640 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
641 dprintf_reg(stddeb,"\tfound directory - %i icon families\n", iconDirCount);
643 if( pTInfo->type_id == NE_RSCTYPE_ICON )
645 iconCount = pTInfo->count;
646 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
647 dprintf_reg(stddeb,"\ttotal icons - %i\n", iconCount);
649 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
652 /* load resources and create icons */
654 if( (pIconStorage && pIconDir) || icoFile )
655 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
656 else if( nIconIndex < iconDirCount )
658 UINT16 i, icon;
660 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
662 for( i = nIconIndex; i < nIconIndex + n; i++ )
664 /* .ICO files have only one icon directory */
666 if( !icoFile )
667 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
668 *(WORD*)pData );
669 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
670 GlobalFree16(hIcon);
673 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
675 hIcon = 0;
676 if( icoFile )
677 hIcon = ICO_LoadIcon( hInstance, hFile, lpiID->idEntries + RetPtr[icon-nIconIndex]);
678 else
679 for( i = 0; i < iconCount; i++ )
680 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
681 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
682 *(WORD*)pData );
683 RetPtr[icon-nIconIndex] = (hIcon)?CURSORICON_LoadHandler( hIcon, hInstance, FALSE ):0;
686 if( icoFile ) free(lpiID);
687 else free(pData);
689 _lclose32( hFile );
691 /* return array with icon handles */
693 return hRet;
696 /*************************************************************************
697 * ExtractIcon16 (SHELL.34)
699 HICON16 ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
700 UINT16 nIconIndex )
702 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
704 if( handle )
706 HICON16* ptr = (HICON16*)GlobalLock16(handle);
707 HICON16 hIcon = *ptr;
709 GlobalFree16(handle);
710 return hIcon;
712 return 0;
716 /*************************************************************************
717 * ExtractIcon32A (SHELL32.20)
719 HICON32 ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
720 UINT32 nIconIndex )
722 /* FIXME */
723 return ExtractIcon16( hInstance, lpszExeFileName, nIconIndex );
727 /*************************************************************************
728 * ExtractAssociatedIcon [SHELL.36]
730 * Return icon for given file (either from file itself or from associated
731 * executable) and patch parameters if needed.
733 HICON16 ExtractAssociatedIcon(HINSTANCE16 hInst,LPSTR lpIconPath,LPWORD lpiIcon)
735 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
737 if( hIcon < 2 )
740 if( hIcon == 1 ) /* no icons found in given file */
742 char tempPath[0x80];
743 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
745 if( uRet > 32 && tempPath[0] )
747 strcpy(lpIconPath,tempPath);
748 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
750 if( hIcon > 2 ) return hIcon;
752 else hIcon = 0;
755 if( hIcon == 1 )
756 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
757 else
758 *lpiIcon = 6; /* generic icon - found nothing */
760 GetModuleFileName16(hInst, lpIconPath, 0x80);
761 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
764 return hIcon;
767 /*************************************************************************
768 * FindEnvironmentString [SHELL.38]
770 * Returns a pointer into the DOS environment... Ugh.
772 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
774 UINT16 l = strlen(entry);
775 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
777 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
779 if( !*(lpEnv+l) )
780 return (lpEnv + l); /* empty entry */
781 else if ( *(lpEnv+l)== '=' )
782 return (lpEnv + l + 1);
784 return NULL;
787 SEGPTR FindEnvironmentString(LPSTR str)
789 SEGPTR spEnv = GetDOSEnvironment();
790 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
792 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
794 if( lpString ) /* offset should be small enough */
795 return spEnv + (lpString - lpEnv);
797 return (SEGPTR)NULL;
800 /*************************************************************************
801 * DoEnvironmentSubst [SHELL.37]
803 * Replace %KEYWORD% in the str with the value of variable KEYWORD
804 * from "DOS" environment.
806 DWORD DoEnvironmentSubst(LPSTR str,WORD length)
808 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
809 LPSTR lpBuffer = (LPSTR)xmalloc(length);
810 LPSTR lpstr = str;
811 LPSTR lpbstr = lpBuffer;
813 CharToOem32A(str,str);
815 dprintf_reg(stddeb,"DoEnvSubst: accept %s", str);
817 while( *lpstr && lpbstr - lpBuffer < length )
819 LPSTR lpend = lpstr;
821 if( *lpstr == '%' )
823 do { lpend++; } while( *lpend && *lpend != '%' );
824 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
826 LPSTR lpKey;
827 *lpend = '\0';
828 lpKey = SHELL_FindString(lpEnv, lpstr+1);
829 if( lpKey ) /* found key value */
831 int l = strlen(lpKey);
833 if( l > length - (lpbstr - lpBuffer) - 1 )
835 fprintf(stdnimp,"File %s, line %i: Env subst aborted - string too short\n",
836 __FILE__, __LINE__);
837 *lpend = '%';
838 break;
840 strcpy(lpbstr, lpKey);
841 lpbstr += l;
843 else break;
844 *lpend = '%';
845 lpstr = lpend + 1;
847 else break; /* back off and whine */
849 continue;
852 *lpbstr++ = *lpstr++;
855 *lpbstr = '\0';
856 if( lpstr - str == strlen(str) )
858 strncpy(str, lpBuffer, length);
859 length = 1;
861 else
862 length = 0;
864 dprintf_reg(stddeb," return %s\n", str);
866 OemToChar32A(str,str);
867 free(lpBuffer);
869 /* Return str length in the LOWORD
870 * and 1 in HIWORD if subst was successful.
872 return (DWORD)MAKELONG(strlen(str), length);
875 /*************************************************************************
876 * RegisterShellHook [SHELL.102]
878 int RegisterShellHook(void *ptr)
880 fprintf(stdnimp, "RegisterShellHook( %p ) : Empty Stub !!!\n", ptr);
881 return 0;
885 /*************************************************************************
886 * ShellHookProc [SHELL.103]
888 int ShellHookProc(void)
890 fprintf(stdnimp, "ShellHookProc : Empty Stub !!!\n");
891 return 0;
894 /*************************************************************************
895 * SHGetFileInfoA [SHELL32.54]
897 DWORD
898 SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,SHFILEINFO32A *psfi,
899 UINT32 sizeofpsfi,UINT32 flags
901 fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%d,0x%08x)\n",
902 path,dwFileAttributes,psfi,sizeofpsfi,flags
904 return TRUE;
907 /*************************************************************************
908 * CommandLineToArgvW [SHELL32.2]
910 LPWSTR*
911 CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs) {
912 LPWSTR *argv,s,t;
913 int i;
915 /* to get writeable copy */
916 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
917 s=cmdline;i=0;
918 while (*s) {
919 /* space */
920 if (*s==0x0020) {
921 i++;
922 s++;
923 while (*s && *s==0x0020)
924 s++;
925 continue;
927 s++;
929 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
930 s=t=cmdline;
931 i=0;
932 while (*s) {
933 if (*s==0x0020) {
934 *s=0;
935 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
936 *s=0x0020;
937 while (*s && *s==0x0020)
938 s++;
939 if (*s)
940 t=s+1;
941 else
942 t=s;
943 continue;
945 s++;
947 if (*t)
948 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
949 HeapFree( GetProcessHeap(), 0, cmdline );
950 argv[i]=NULL;
951 *numargs=i;
952 return argv;