Release 960928
[wine/multimedia.git] / misc / shell.c
blob4e80173d49f62fe0d966931aa4d35b1f5c30604f
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 "module.h"
13 #include "neexe.h"
14 #include "resource.h"
15 #include "dlgs.h"
16 #include "win.h"
17 #include "cursoricon.h"
18 #include "stddebug.h"
19 #include "debug.h"
20 #include "xmalloc.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 HANDLE CURSORICON_LoadHandler( HANDLE, HINSTANCE, BOOL);
50 extern WORD GetIconID( HANDLE hResource, DWORD resType );
52 /*************************************************************************
53 * DragAcceptFiles [SHELL.9]
55 void DragAcceptFiles(HWND hWnd, BOOL b)
57 WND* wnd = WIN_FindWndPtr(hWnd);
59 if( wnd )
60 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
61 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
65 /*************************************************************************
66 * DragQueryFile [SHELL.11]
68 UINT DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile, WORD wLength)
70 /* hDrop is a global memory block allocated with GMEM_SHARE
71 * with DROPFILESTRUCT as a header and filenames following
72 * it, zero length filename is in the end */
74 LPDROPFILESTRUCT lpDropFileStruct;
75 LPSTR lpCurrent;
76 WORD i;
78 dprintf_reg(stddeb,"DragQueryFile(%04x, %i, %p, %u)\n",
79 hDrop,wFile,lpszFile,wLength);
81 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
82 if(!lpDropFileStruct)
84 dprintf_reg(stddeb,"DragQueryFile: unable to lock handle!\n");
85 return 0;
87 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
89 i = 0;
90 while (i++ < wFile)
92 while (*lpCurrent++); /* skip filename */
93 if (!*lpCurrent)
94 return (wFile == 0xFFFF) ? i : 0;
97 i = strlen(lpCurrent);
98 if (!lpszFile) return i+1; /* needed buffer size */
100 i = (wLength > i) ? i : wLength-1;
101 strncpy(lpszFile, lpCurrent, i);
102 lpszFile[i] = '\0';
104 GlobalUnlock16(hDrop);
105 return i;
109 /*************************************************************************
110 * DragFinish [SHELL.12]
112 void DragFinish(HDROP16 h)
114 GlobalFree16((HGLOBAL16)h);
118 /*************************************************************************
119 * DragQueryPoint [SHELL.13]
121 BOOL DragQueryPoint(HDROP16 hDrop, POINT16 *p)
123 LPDROPFILESTRUCT lpDropFileStruct;
124 BOOL bRet;
126 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
128 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
129 bRet = lpDropFileStruct->fInNonClientArea;
131 GlobalUnlock16(hDrop);
132 return bRet;
135 /*************************************************************************
136 * SHELL_FindExecutable
137 * Utility for code sharing between FindExecutable and ShellExecute
139 static HINSTANCE SHELL_FindExecutable( LPCSTR lpFile,
140 LPCSTR lpDirectory,
141 LPCSTR lpOperation,
142 LPSTR lpResult)
144 char *extension = NULL; /* pointer to file extension */
145 char tmpext[5]; /* local copy to mung as we please */
146 char filetype[256]; /* registry name for this filetype */
147 LONG filetypelen=256; /* length of above */
148 char command[256]; /* command from registry */
149 LONG commandlen=256; /* This is the most DOS can handle :) */
150 char buffer[256]; /* Used to GetProfileString */
151 HINSTANCE retval=31; /* default - 'No association was found' */
152 char *tok; /* token pointer */
153 int i; /* random counter */
154 char xlpFile[256]; /* result of SearchPath */
156 dprintf_exec(stddeb, "SHELL_FindExecutable: File %s, Dir %s\n",
157 (lpFile != NULL?lpFile:"-"),
158 (lpDirectory != NULL?lpDirectory:"-"));
160 lpResult[0]='\0'; /* Start off with an empty return string */
162 /* trap NULL parameters on entry */
163 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
165 /* FIXME - should throw a warning, perhaps! */
166 return 2; /* File not found. Close enough, I guess. */
168 if (SearchPath32A(lpDirectory,lpFile,NULL,sizeof(xlpFile),xlpFile,NULL))
169 lpFile = xlpFile;
170 else {
171 if (SearchPath32A(lpDirectory,lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
172 lpFile = xlpFile;
175 /* First thing we need is the file's extension */
176 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
177 /* File->Run in progman uses */
178 /* .\FILE.EXE :( */
179 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
181 return 31; /* no association */
184 /* Make local copy & lowercase it for reg & 'programs=' lookup */
185 strncpy( tmpext, extension, 5 );
186 if (strlen(extension)<=4)
187 tmpext[strlen(extension)]='\0';
188 else
189 tmpext[4]='\0';
190 for (i=0;i<strlen(tmpext);i++) tmpext[i]=tolower(tmpext[i]);
191 dprintf_exec(stddeb, "SHELL_FindExecutable: %s file\n", tmpext);
193 /* Three places to check: */
194 /* 1. win.ini, [windows], programs (NB no leading '.') */
195 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
196 /* 3. win.ini, [extensions], extension (NB no leading '.' */
197 /* All I know of the order is that registry is checked before */
198 /* extensions; however, it'd make sense to check the programs */
199 /* section first, so that's what happens here. */
201 /* See if it's a program */
202 GetProfileString("windows", "programs", "exe pif bat com",
203 buffer, sizeof(buffer)); /* FIXME check return code! */
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); /* Need to perhaps check that */
213 /* the file has a path attached */
214 dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
215 lpResult);
216 return 33; /* Greater than 32 to indicate success FIXME */
217 /* According to the docs, I should be returning */
218 /* a handle for the executable. Does this mean */
219 /* I'm supposed to open the executable file or */
220 /* something? More RTFM, I guess... */
222 tok=strtok(NULL, " \t");
225 /* Check registry */
226 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
227 &filetypelen ) == SHELL_ERROR_SUCCESS )
229 filetype[filetypelen]='\0';
230 dprintf_exec(stddeb, "SHELL_FindExecutable: File type: %s\n",
231 filetype);
233 /* Looking for ...buffer\shell\lpOperation\command */
234 strcat( filetype, "\\shell\\" );
235 strcat( filetype, lpOperation );
236 strcat( filetype, "\\command" );
238 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
239 &commandlen ) == SHELL_ERROR_SUCCESS )
241 /* Is there a replace() function anywhere? */
242 command[commandlen]='\0';
243 strcpy( lpResult, command );
244 tok=strstr( lpResult, "%1" );
245 if (tok != NULL)
247 tok[0]='\0'; /* truncate string at the percent */
248 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
249 tok=strstr( command, "%1" );
250 if ((tok!=NULL) && (strlen(tok)>2))
252 strcat( lpResult, &tok[2] );
255 retval=33;
258 else /* Check win.ini */
260 /* Toss the leading dot */
261 extension++;
262 GetProfileString( "extensions", extension, "", command,
263 sizeof(command));
264 if (strlen(command)!=0)
266 strcpy( lpResult, command );
267 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
268 if (tok != NULL)
270 tok[0]='\0';
271 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
272 tok=strstr( command, "^" ); /* see above */
273 if ((tok != NULL) && (strlen(tok)>5))
275 strcat( lpResult, &tok[5]);
278 retval=33;
282 dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
283 return retval;
286 /*************************************************************************
287 * ShellExecute [SHELL.20]
289 HINSTANCE ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
290 LPSTR lpParameters, LPCSTR lpDirectory,
291 INT iShowCmd)
293 HINSTANCE retval=31;
294 char cmd[256];
296 dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
297 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
298 lpParameters ? lpParameters : "<null>",
299 lpDirectory ? lpDirectory : "<null>", iShowCmd);
301 if (lpFile==NULL) return 0; /* should not happen */
302 if (lpOperation==NULL) /* default is open */
303 lpOperation="open";
305 retval = SHELL_FindExecutable( lpFile, lpDirectory, lpOperation, cmd );
307 if ( retval <= 32 )
309 return retval;
312 if (lpParameters)
314 strcat(cmd," ");
315 strcat(cmd,lpParameters);
318 dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
319 return WinExec(cmd,iShowCmd);
322 /*************************************************************************
323 * FindExecutable [SHELL.21]
325 HINSTANCE FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
327 HINSTANCE retval=31; /* default - 'No association was found' */
329 dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n",
330 (lpFile != NULL?lpFile:"-"),
331 (lpDirectory != NULL?lpDirectory:"-"));
333 lpResult[0]='\0'; /* Start off with an empty return string */
335 /* trap NULL parameters on entry */
336 if (( lpFile == NULL ) || ( lpResult == NULL ))
338 /* FIXME - should throw a warning, perhaps! */
339 return 2; /* File not found. Close enough, I guess. */
342 retval = SHELL_FindExecutable( lpFile, lpDirectory, "open",
343 lpResult );
345 dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
346 return retval;
349 static char AppName[128], AppMisc[1536];
351 /*************************************************************************
352 * AboutDlgProc [SHELL.33]
354 LRESULT AboutDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
356 char Template[512], AppTitle[512];
358 switch(msg) {
359 case WM_INITDIALOG:
360 SendDlgItemMessage32A(hWnd,stc1,STM_SETICON,lParam,0);
361 GetWindowText32A(hWnd, Template, sizeof(Template));
362 sprintf(AppTitle, Template, AppName);
363 SetWindowText32A(hWnd, AppTitle);
364 SetWindowText32A(GetDlgItem(hWnd,100), AppMisc);
365 return 1;
367 case WM_COMMAND:
368 switch (wParam) {
369 case IDOK:
370 EndDialog(hWnd, TRUE);
371 return TRUE;
373 break;
375 return FALSE;
378 /*************************************************************************
379 * ShellAbout [SHELL.22]
381 INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON16 hIcon)
383 HANDLE handle;
384 BOOL bRet;
386 if (szApp) strncpy(AppName, szApp, sizeof(AppName));
387 else *AppName = 0;
388 AppName[sizeof(AppName)-1]=0;
390 if (szOtherStuff) strncpy(AppMisc, szOtherStuff, sizeof(AppMisc));
391 else *AppMisc = 0;
392 AppMisc[sizeof(AppMisc)-1]=0;
394 if (!hIcon) hIcon = LoadIcon16(0,MAKEINTRESOURCE(OIC_WINEICON));
395 handle = SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX );
396 if (!handle) return FALSE;
397 bRet = DialogBoxIndirectParam16( WIN_GetWindowInstance( hWnd ),
398 handle, hWnd,
399 MODULE_GetWndProcEntry16("AboutDlgProc"),
400 (LONG)hIcon );
401 SYSRES_FreeResource( handle );
402 return bRet;
405 /*************************************************************************
406 * SHELL_GetResourceTable
408 * FIXME: Implement GetPEResourceTable in w32sys.c and call it here.
410 static BYTE* SHELL_GetResourceTable(HFILE hFile)
412 struct mz_header_s mz_header;
413 struct ne_header_s ne_header;
414 int size;
416 _llseek( hFile, 0, SEEK_SET );
417 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
418 (mz_header.mz_magic != MZ_SIGNATURE)) return (BYTE*)-1;
420 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
421 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
422 return NULL;
424 if (ne_header.ne_magic == PE_SIGNATURE)
425 { fprintf(stdnimp,"Win32s FIXME: file %s line %i\n", __FILE__, __LINE__ );
426 return NULL; }
428 if (ne_header.ne_magic != NE_SIGNATURE) return NULL;
430 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
432 if( size > sizeof(NE_TYPEINFO) )
434 BYTE* pTypeInfo = (BYTE*)xmalloc(size);
436 if( !pTypeInfo ) return NULL;
438 _llseek(hFile, mz_header.ne_offset+ne_header.resource_tab_offset, SEEK_SET);
439 if( _lread32( hFile, (char*)pTypeInfo, size) != size )
440 { free(pTypeInfo); return NULL; }
441 return pTypeInfo;
443 /* no resources */
445 return NULL;
448 /*************************************************************************
449 * SHELL_LoadResource
451 static HANDLE SHELL_LoadResource(HINSTANCE hInst, HFILE hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
453 BYTE* ptr;
454 HANDLE handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
456 if( (ptr = (BYTE*)GlobalLock16( handle )) )
458 _llseek( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
459 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
460 return handle;
462 return (HANDLE)0;
465 /*************************************************************************
466 * ICO_LoadIcon
468 static HANDLE ICO_LoadIcon(HINSTANCE hInst, HFILE hFile, LPicoICONDIRENTRY lpiIDE)
470 BYTE* ptr;
471 HANDLE handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
473 if( (ptr = (BYTE*)GlobalLock16( handle )) )
475 _llseek( hFile, lpiIDE->dwImageOffset, SEEK_SET);
476 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
477 return handle;
479 return (HANDLE)0;
482 /*************************************************************************
483 * ICO_GetIconDirectory
485 * Read .ico file and build phony ICONDIR struct for GetIconID
487 static HANDLE ICO_GetIconDirectory(HINSTANCE hInst, HFILE hFile, LPicoICONDIR* lplpiID )
489 WORD id[3]; /* idReserved, idType, idCount */
490 LPicoICONDIR lpiID;
491 int i;
493 _llseek( hFile, 0, SEEK_SET );
494 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
496 /* check .ICO header
498 * - see http://www.microsoft.com/win32dev/ui/icons.htm
501 if( id[0] || id[1] != 1 || !id[2] ) return 0;
503 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
505 lpiID = (LPicoICONDIR)xmalloc(i);
507 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
509 HANDLE handle = DirectResAlloc( hInst, 0x10,
510 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
511 if( handle )
513 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
514 lpID->idReserved = lpiID->idReserved = id[0];
515 lpID->idType = lpiID->idType = id[1];
516 lpID->idCount = lpiID->idCount = id[2];
517 for( i=0; i < lpiID->idCount; i++ )
519 memcpy((void*)(lpID->idEntries + i),
520 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
521 lpID->idEntries[i].icon.wResId = i;
523 *lplpiID = lpiID;
524 return handle;
527 /* fail */
529 free(lpiID);
530 return 0;
533 /*************************************************************************
534 * InternalExtractIcon [SHELL.39]
536 * This abortion is called directly by Progman
538 HICON16 InternalExtractIcon(HINSTANCE hInstance, LPCSTR lpszExeFileName, UINT nIconIndex, WORD n )
540 HANDLE hRet = 0;
541 HICON16* RetPtr = NULL;
542 BYTE* pData;
543 OFSTRUCT ofs;
544 HFILE hFile = OpenFile( lpszExeFileName, &ofs, OF_READ );
546 dprintf_reg(stddeb, "InternalExtractIcon(%04x, file '%s', start from %d, extract %d\n",
547 hInstance, lpszExeFileName, nIconIndex, n);
549 if( hFile == HFILE_ERROR || !n ) return 0;
551 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
552 RetPtr = (HICON16*)GlobalLock16(hRet);
554 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
556 pData = SHELL_GetResourceTable(hFile);
557 if( pData )
559 HICON16 hIcon = 0;
560 BOOL icoFile = FALSE;
561 UINT iconDirCount = 0;
562 UINT iconCount = 0;
563 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
564 NE_NAMEINFO* pIconStorage = NULL;
565 NE_NAMEINFO* pIconDir = NULL;
566 LPicoICONDIR lpiID = NULL;
568 if( pData == (BYTE*)-1 )
570 /* check for .ICO file */
572 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
573 if( hIcon )
574 { icoFile = TRUE; iconDirCount = 1; iconCount = lpiID->idCount; }
576 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
578 /* find icon directory and icon repository */
580 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
582 iconDirCount = pTInfo->count;
583 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
584 dprintf_reg(stddeb,"\tfound directory - %i icon families\n", iconDirCount);
586 if( pTInfo->type_id == NE_RSCTYPE_ICON )
588 iconCount = pTInfo->count;
589 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
590 dprintf_reg(stddeb,"\ttotal icons - %i\n", iconCount);
592 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
595 /* load resources and create icons */
597 if( (pIconStorage && pIconDir) || icoFile )
598 if( nIconIndex == (UINT)-1 ) RetPtr[0] = iconDirCount;
599 else if( nIconIndex < iconDirCount )
601 UINT i, icon;
603 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
605 for( i = nIconIndex; i < nIconIndex + n; i++ )
607 /* .ICO files have only one icon directory */
609 if( !icoFile )
610 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
611 *(WORD*)pData );
612 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
613 GlobalFree16(hIcon);
616 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
618 hIcon = 0;
619 if( icoFile )
620 hIcon = ICO_LoadIcon( hInstance, hFile, lpiID->idEntries + RetPtr[icon-nIconIndex]);
621 else
622 for( i = 0; i < iconCount; i++ )
623 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
624 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
625 *(WORD*)pData );
626 RetPtr[icon-nIconIndex] = (hIcon)?CURSORICON_LoadHandler( hIcon, hInstance, FALSE ):0;
629 if( icoFile ) free(lpiID);
630 else free(pData);
632 _lclose( hFile );
634 /* return array with icon handles */
636 return hRet;
639 /*************************************************************************
640 * ExtractIcon [SHELL.34]
642 HICON16 ExtractIcon(HINSTANCE hInstance, LPCSTR lpszExeFileName, WORD nIconIndex)
644 HANDLE handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
646 if( handle )
648 HICON16* ptr = (HICON16*)GlobalLock16(handle);
649 HICON16 hIcon = *ptr;
651 GlobalFree16(handle);
652 return hIcon;
654 return 0;
657 /*************************************************************************
658 * ExtractAssociatedIcon [SHELL.36]
660 * Return icon for given file (either from file itself or from associated
661 * executable) and patch parameters if needed.
663 HICON16 ExtractAssociatedIcon(HINSTANCE16 hInst,LPSTR lpIconPath,LPWORD lpiIcon)
665 HICON16 hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
667 if( hIcon < 2 )
670 if( hIcon == 1 ) /* no icons found in given file */
672 char tempPath[0x80];
673 UINT uRet = FindExecutable(lpIconPath,NULL,tempPath);
675 if( uRet > 32 && tempPath[0] )
677 strcpy(lpIconPath,tempPath);
678 hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
680 if( hIcon > 2 ) return hIcon;
682 else hIcon = 0;
685 if( hIcon == 1 )
686 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
687 else
688 *lpiIcon = 6; /* generic icon - found nothing */
690 GetModuleFileName(hInst, lpIconPath, 0x80);
691 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
694 return hIcon;
697 /*************************************************************************
698 * FindEnvironmentString [SHELL.38]
700 * Returns a pointer into the DOS environment... Ugh.
702 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
704 UINT l = strlen(entry);
705 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
707 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
709 if( !*(lpEnv+l) )
710 return (lpEnv + l); /* empty entry */
711 else if ( *(lpEnv+l)== '=' )
712 return (lpEnv + l + 1);
714 return NULL;
717 SEGPTR FindEnvironmentString(LPSTR str)
719 SEGPTR spEnv = GetDOSEnvironment();
720 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
722 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
724 if( lpString ) /* offset should be small enough */
725 return spEnv + (lpString - lpEnv);
727 return (SEGPTR)NULL;
730 /*************************************************************************
731 * DoEnvironmentSubst [SHELL.37]
733 * Replace %KEYWORD% in the str with the value of variable KEYWORD
734 * from "DOS" environment.
736 DWORD DoEnvironmentSubst(LPSTR str,WORD length)
738 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
739 LPSTR lpBuffer = (LPSTR)xmalloc(length);
740 LPSTR lpstr = str;
741 LPSTR lpbstr = lpBuffer;
743 AnsiToOem(str,str);
745 dprintf_reg(stddeb,"DoEnvSubst: accept %s", str);
747 while( *lpstr && lpbstr - lpBuffer < length )
749 LPSTR lpend = lpstr;
751 if( *lpstr == '%' )
753 do { lpend++; } while( *lpend && *lpend != '%' );
754 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
756 LPSTR lpKey;
757 *lpend = '\0';
758 lpKey = SHELL_FindString(lpEnv, lpstr+1);
759 if( lpKey ) /* found key value */
761 int l = strlen(lpKey);
763 if( l > length - (lpbstr - lpBuffer) - 1 )
765 fprintf(stdnimp,"File %s, line %i: Env subst aborted - string too short\n",
766 __FILE__, __LINE__);
767 *lpend = '%';
768 break;
770 strcpy(lpbstr, lpKey);
771 lpbstr += l;
773 else break;
774 *lpend = '%';
775 lpstr = lpend + 1;
777 else break; /* back off and whine */
779 continue;
782 *lpbstr++ = *lpstr++;
785 *lpbstr = '\0';
786 if( lpstr - str == strlen(str) )
788 strncpy(str, lpBuffer, length);
789 length = 1;
791 else
792 length = 0;
794 dprintf_reg(stddeb," return %s\n", str);
796 OemToAnsi(str,str);
797 free(lpBuffer);
799 /* Return str length in the LOWORD
800 * and 1 in HIWORD if subst was successful.
802 return (DWORD)MAKELONG(strlen(str), length);
805 /*************************************************************************
806 * RegisterShellHook [SHELL.102]
808 int RegisterShellHook(void *ptr)
810 dprintf_reg(stdnimp, "RegisterShellHook : Empty Stub !!!\n");
811 return 0;
815 /*************************************************************************
816 * ShellHookProc [SHELL.103]
818 int ShellHookProc(void)
820 dprintf_reg(stdnimp, "ShellHookProc : Empty Stub !!!\n");
821 return 0;
824 /*************************************************************************
825 * SHGetFileInfoA [SHELL32.54]
827 DWORD
828 SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,SHFILEINFO32A *psfi,
829 UINT32 sizeofpsfi,UINT32 flags
831 fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%ld,0x%08lx)\n",
832 path,dwFileAttributes,psfi,sizeofpsfi,flags
834 return TRUE;