Release 961222
[wine/multimedia.git] / misc / shell.c
blob486e73343545052e8771d346aeeda250199c0f57
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, BOOL);
51 extern WORD GetIconID( HGLOBAL16 hResource, DWORD resType );
53 /*************************************************************************
54 * DragAcceptFiles [SHELL.9]
56 void DragAcceptFiles(HWND hWnd, BOOL 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 UINT 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 BOOL 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,NULL,sizeof(xlpFile),xlpFile,NULL))
167 lpFile = xlpFile;
168 else {
169 if (SearchPath32A(lpDirectory,lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
170 lpFile = xlpFile;
173 /* First thing we need is the file's extension */
174 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
175 /* File->Run in progman uses */
176 /* .\FILE.EXE :( */
177 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
179 return 31; /* no association */
182 /* Make local copy & lowercase it for reg & 'programs=' lookup */
183 strncpy( tmpext, extension, 5 );
184 if (strlen(extension)<=4)
185 tmpext[strlen(extension)]='\0';
186 else
187 tmpext[4]='\0';
188 for (i=0;i<strlen(tmpext);i++) tmpext[i]=tolower(tmpext[i]);
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 * ShellExecute [SHELL.20]
294 HINSTANCE16 ShellExecute(HWND hWnd, LPCSTR lpOperation, LPCSTR lpFile,
295 LPSTR lpParameters, LPCSTR lpDirectory,
296 INT iShowCmd)
298 HINSTANCE16 retval=31;
299 char cmd[256];
301 dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
302 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
303 lpParameters ? lpParameters : "<null>",
304 lpDirectory ? lpDirectory : "<null>", iShowCmd);
306 if (lpFile==NULL) return 0; /* should not happen */
307 if (lpOperation==NULL) /* default is open */
308 lpOperation="open";
310 retval = SHELL_FindExecutable( lpFile, lpDirectory, lpOperation, cmd );
312 if ( retval <= 32 )
314 return retval;
317 if (lpParameters)
319 strcat(cmd," ");
320 strcat(cmd,lpParameters);
323 dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
324 return WinExec(cmd,iShowCmd);
327 /*************************************************************************
328 * FindExecutable [SHELL.21]
330 HINSTANCE16 FindExecutable(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResult)
332 HINSTANCE16 retval=31; /* default - 'No association was found' */
334 dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n",
335 (lpFile != NULL?lpFile:"-"),
336 (lpDirectory != NULL?lpDirectory:"-"));
338 lpResult[0]='\0'; /* Start off with an empty return string */
340 /* trap NULL parameters on entry */
341 if (( lpFile == NULL ) || ( lpResult == NULL ))
343 /* FIXME - should throw a warning, perhaps! */
344 return 2; /* File not found. Close enough, I guess. */
347 retval = SHELL_FindExecutable( lpFile, lpDirectory, "open",
348 lpResult );
350 dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
351 return retval;
354 static char AppName[128], AppMisc[1536];
356 /*************************************************************************
357 * AboutDlgProc [SHELL.33]
359 LRESULT AboutDlgProc(HWND hWnd, UINT msg, WPARAM16 wParam, LPARAM lParam)
361 char Template[512], AppTitle[512];
363 switch(msg) {
364 case WM_INITDIALOG:
365 SendDlgItemMessage32A(hWnd,stc1,STM_SETICON,lParam,0);
366 GetWindowText32A(hWnd, Template, sizeof(Template));
367 sprintf(AppTitle, Template, AppName);
368 SetWindowText32A(hWnd, AppTitle);
369 SetWindowText32A(GetDlgItem(hWnd,100), AppMisc);
370 return 1;
372 case WM_COMMAND:
373 switch (wParam) {
374 case IDOK:
375 EndDialog(hWnd, TRUE);
376 return TRUE;
378 break;
380 return FALSE;
383 /*************************************************************************
384 * ShellAbout [SHELL.22]
386 INT ShellAbout(HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON16 hIcon)
388 HGLOBAL16 handle;
389 BOOL bRet;
391 if (szApp) strncpy(AppName, szApp, sizeof(AppName));
392 else *AppName = 0;
393 AppName[sizeof(AppName)-1]=0;
395 if (szOtherStuff) strncpy(AppMisc, szOtherStuff, sizeof(AppMisc));
396 else *AppMisc = 0;
397 AppMisc[sizeof(AppMisc)-1]=0;
399 if (!hIcon) hIcon = LoadIcon16(0,MAKEINTRESOURCE(OIC_WINEICON));
400 handle = SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX );
401 if (!handle) return FALSE;
402 bRet = DialogBoxIndirectParam16( WIN_GetWindowInstance( hWnd ),
403 handle, hWnd,
404 (DLGPROC16)MODULE_GetWndProcEntry16("AboutDlgProc"),
405 (LPARAM)hIcon );
406 SYSRES_FreeResource( handle );
407 return bRet;
410 /*************************************************************************
411 * ShellAbout32W [SHELL32.83]
413 INT32 ShellAbout32W(HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff, HICON16 hIcon)
415 HGLOBAL16 handle;
416 BOOL bRet;
418 if (szApp) lstrcpynWtoA(AppName, szApp, sizeof(AppName));
419 else *AppName = 0;
420 AppName[sizeof(AppName)-1]=0;
422 if (szOtherStuff) lstrcpynWtoA(AppMisc, szOtherStuff, sizeof(AppMisc));
423 else *AppMisc = 0;
424 AppMisc[sizeof(AppMisc)-1]=0;
426 if (!hIcon) hIcon = LoadIcon16(0,MAKEINTRESOURCE(OIC_WINEICON));
427 handle = SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX );
428 if (!handle) return FALSE;
429 bRet = DialogBoxIndirectParam16( WIN_GetWindowInstance( hWnd ),
430 handle, hWnd,
431 (DLGPROC16)MODULE_GetWndProcEntry16("AboutDlgProc"),
432 (LPARAM)hIcon );
433 SYSRES_FreeResource( handle );
434 return bRet;
437 /*************************************************************************
438 * SHELL_GetResourceTable
440 * FIXME: Implement GetPEResourceTable in w32sys.c and call it here.
442 static BYTE* SHELL_GetResourceTable(HFILE hFile)
444 struct mz_header_s mz_header;
445 struct ne_header_s ne_header;
446 int size;
448 _llseek( hFile, 0, SEEK_SET );
449 if ((_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
450 (mz_header.mz_magic != MZ_SIGNATURE)) return (BYTE*)-1;
452 _llseek( hFile, mz_header.ne_offset, SEEK_SET );
453 if (_lread32( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
454 return NULL;
456 if (ne_header.ne_magic == PE_SIGNATURE)
457 { fprintf(stdnimp,"Win32s FIXME: file %s line %i\n", __FILE__, __LINE__ );
458 return NULL; }
460 if (ne_header.ne_magic != NE_SIGNATURE) return NULL;
462 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
464 if( size > sizeof(NE_TYPEINFO) )
466 BYTE* pTypeInfo = (BYTE*)xmalloc(size);
468 if( !pTypeInfo ) return NULL;
470 _llseek(hFile, mz_header.ne_offset+ne_header.resource_tab_offset, SEEK_SET);
471 if( _lread32( hFile, (char*)pTypeInfo, size) != size )
472 { free(pTypeInfo); return NULL; }
473 return pTypeInfo;
475 /* no resources */
477 return NULL;
480 /*************************************************************************
481 * SHELL_LoadResource
483 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
485 BYTE* ptr;
486 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
488 if( (ptr = (BYTE*)GlobalLock16( handle )) )
490 _llseek( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
491 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
492 return handle;
494 return 0;
497 /*************************************************************************
498 * ICO_LoadIcon
500 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE hFile, LPicoICONDIRENTRY lpiIDE)
502 BYTE* ptr;
503 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
505 if( (ptr = (BYTE*)GlobalLock16( handle )) )
507 _llseek( hFile, lpiIDE->dwImageOffset, SEEK_SET);
508 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
509 return handle;
511 return 0;
514 /*************************************************************************
515 * ICO_GetIconDirectory
517 * Read .ico file and build phony ICONDIR struct for GetIconID
519 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE hFile, LPicoICONDIR* lplpiID )
521 WORD id[3]; /* idReserved, idType, idCount */
522 LPicoICONDIR lpiID;
523 int i;
525 _llseek( hFile, 0, SEEK_SET );
526 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
528 /* check .ICO header
530 * - see http://www.microsoft.com/win32dev/ui/icons.htm
533 if( id[0] || id[1] != 1 || !id[2] ) return 0;
535 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
537 lpiID = (LPicoICONDIR)xmalloc(i);
539 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
541 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
542 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
543 if( handle )
545 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
546 lpID->idReserved = lpiID->idReserved = id[0];
547 lpID->idType = lpiID->idType = id[1];
548 lpID->idCount = lpiID->idCount = id[2];
549 for( i=0; i < lpiID->idCount; i++ )
551 memcpy((void*)(lpID->idEntries + i),
552 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
553 lpID->idEntries[i].icon.wResId = i;
555 *lplpiID = lpiID;
556 return handle;
559 /* fail */
561 free(lpiID);
562 return 0;
565 /*************************************************************************
566 * InternalExtractIcon [SHELL.39]
568 * This abortion is called directly by Progman
570 HGLOBAL16 InternalExtractIcon(HINSTANCE16 hInstance, LPCSTR lpszExeFileName, UINT nIconIndex, WORD n )
572 HGLOBAL16 hRet = 0;
573 HGLOBAL16* RetPtr = NULL;
574 BYTE* pData;
575 OFSTRUCT ofs;
576 HFILE hFile = OpenFile( lpszExeFileName, &ofs, OF_READ );
578 dprintf_reg(stddeb, "InternalExtractIcon(%04x, file '%s', start from %d, extract %d\n",
579 hInstance, lpszExeFileName, nIconIndex, n);
581 if( hFile == HFILE_ERROR || !n ) return 0;
583 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
584 RetPtr = (HICON16*)GlobalLock16(hRet);
586 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
588 pData = SHELL_GetResourceTable(hFile);
589 if( pData )
591 HICON16 hIcon = 0;
592 BOOL icoFile = FALSE;
593 UINT iconDirCount = 0;
594 UINT iconCount = 0;
595 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
596 NE_NAMEINFO* pIconStorage = NULL;
597 NE_NAMEINFO* pIconDir = NULL;
598 LPicoICONDIR lpiID = NULL;
600 if( pData == (BYTE*)-1 )
602 /* check for .ICO file */
604 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
605 if( hIcon )
606 { icoFile = TRUE; iconDirCount = 1; iconCount = lpiID->idCount; }
608 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
610 /* find icon directory and icon repository */
612 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
614 iconDirCount = pTInfo->count;
615 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
616 dprintf_reg(stddeb,"\tfound directory - %i icon families\n", iconDirCount);
618 if( pTInfo->type_id == NE_RSCTYPE_ICON )
620 iconCount = pTInfo->count;
621 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
622 dprintf_reg(stddeb,"\ttotal icons - %i\n", iconCount);
624 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
627 /* load resources and create icons */
629 if( (pIconStorage && pIconDir) || icoFile )
630 if( nIconIndex == (UINT)-1 ) RetPtr[0] = iconDirCount;
631 else if( nIconIndex < iconDirCount )
633 UINT i, icon;
635 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
637 for( i = nIconIndex; i < nIconIndex + n; i++ )
639 /* .ICO files have only one icon directory */
641 if( !icoFile )
642 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
643 *(WORD*)pData );
644 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
645 GlobalFree16(hIcon);
648 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
650 hIcon = 0;
651 if( icoFile )
652 hIcon = ICO_LoadIcon( hInstance, hFile, lpiID->idEntries + RetPtr[icon-nIconIndex]);
653 else
654 for( i = 0; i < iconCount; i++ )
655 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
656 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
657 *(WORD*)pData );
658 RetPtr[icon-nIconIndex] = (hIcon)?CURSORICON_LoadHandler( hIcon, hInstance, FALSE ):0;
661 if( icoFile ) free(lpiID);
662 else free(pData);
664 _lclose( hFile );
666 /* return array with icon handles */
668 return hRet;
671 /*************************************************************************
672 * ExtractIcon [SHELL.34]
674 HICON16 ExtractIcon(HINSTANCE16 hInstance, LPCSTR lpszExeFileName, WORD nIconIndex)
676 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
678 if( handle )
680 HICON16* ptr = (HICON16*)GlobalLock16(handle);
681 HICON16 hIcon = *ptr;
683 GlobalFree16(handle);
684 return hIcon;
686 return 0;
689 /*************************************************************************
690 * ExtractAssociatedIcon [SHELL.36]
692 * Return icon for given file (either from file itself or from associated
693 * executable) and patch parameters if needed.
695 HICON16 ExtractAssociatedIcon(HINSTANCE16 hInst,LPSTR lpIconPath,LPWORD lpiIcon)
697 HICON16 hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
699 if( hIcon < 2 )
702 if( hIcon == 1 ) /* no icons found in given file */
704 char tempPath[0x80];
705 UINT uRet = FindExecutable(lpIconPath,NULL,tempPath);
707 if( uRet > 32 && tempPath[0] )
709 strcpy(lpIconPath,tempPath);
710 hIcon = ExtractIcon(hInst, lpIconPath, *lpiIcon);
712 if( hIcon > 2 ) return hIcon;
714 else hIcon = 0;
717 if( hIcon == 1 )
718 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
719 else
720 *lpiIcon = 6; /* generic icon - found nothing */
722 GetModuleFileName16(hInst, lpIconPath, 0x80);
723 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
726 return hIcon;
729 /*************************************************************************
730 * FindEnvironmentString [SHELL.38]
732 * Returns a pointer into the DOS environment... Ugh.
734 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
736 UINT l = strlen(entry);
737 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
739 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
741 if( !*(lpEnv+l) )
742 return (lpEnv + l); /* empty entry */
743 else if ( *(lpEnv+l)== '=' )
744 return (lpEnv + l + 1);
746 return NULL;
749 SEGPTR FindEnvironmentString(LPSTR str)
751 SEGPTR spEnv = GetDOSEnvironment();
752 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
754 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
756 if( lpString ) /* offset should be small enough */
757 return spEnv + (lpString - lpEnv);
759 return (SEGPTR)NULL;
762 /*************************************************************************
763 * DoEnvironmentSubst [SHELL.37]
765 * Replace %KEYWORD% in the str with the value of variable KEYWORD
766 * from "DOS" environment.
768 DWORD DoEnvironmentSubst(LPSTR str,WORD length)
770 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
771 LPSTR lpBuffer = (LPSTR)xmalloc(length);
772 LPSTR lpstr = str;
773 LPSTR lpbstr = lpBuffer;
775 CharToOem32A(str,str);
777 dprintf_reg(stddeb,"DoEnvSubst: accept %s", str);
779 while( *lpstr && lpbstr - lpBuffer < length )
781 LPSTR lpend = lpstr;
783 if( *lpstr == '%' )
785 do { lpend++; } while( *lpend && *lpend != '%' );
786 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
788 LPSTR lpKey;
789 *lpend = '\0';
790 lpKey = SHELL_FindString(lpEnv, lpstr+1);
791 if( lpKey ) /* found key value */
793 int l = strlen(lpKey);
795 if( l > length - (lpbstr - lpBuffer) - 1 )
797 fprintf(stdnimp,"File %s, line %i: Env subst aborted - string too short\n",
798 __FILE__, __LINE__);
799 *lpend = '%';
800 break;
802 strcpy(lpbstr, lpKey);
803 lpbstr += l;
805 else break;
806 *lpend = '%';
807 lpstr = lpend + 1;
809 else break; /* back off and whine */
811 continue;
814 *lpbstr++ = *lpstr++;
817 *lpbstr = '\0';
818 if( lpstr - str == strlen(str) )
820 strncpy(str, lpBuffer, length);
821 length = 1;
823 else
824 length = 0;
826 dprintf_reg(stddeb," return %s\n", str);
828 OemToChar32A(str,str);
829 free(lpBuffer);
831 /* Return str length in the LOWORD
832 * and 1 in HIWORD if subst was successful.
834 return (DWORD)MAKELONG(strlen(str), length);
837 /*************************************************************************
838 * RegisterShellHook [SHELL.102]
840 int RegisterShellHook(void *ptr)
842 fprintf(stdnimp, "RegisterShellHook( %p ) : Empty Stub !!!\n", ptr);
843 return 0;
847 /*************************************************************************
848 * ShellHookProc [SHELL.103]
850 int ShellHookProc(void)
852 fprintf(stdnimp, "ShellHookProc : Empty Stub !!!\n");
853 return 0;
856 /*************************************************************************
857 * SHGetFileInfoA [SHELL32.54]
859 DWORD
860 SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,SHFILEINFO32A *psfi,
861 UINT32 sizeofpsfi,UINT32 flags
863 fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%d,0x%08x)\n",
864 path,dwFileAttributes,psfi,sizeofpsfi,flags
866 return TRUE;
869 /*************************************************************************
870 * CommandLineToArgvW [SHELL32.2]
872 LPWSTR*
873 CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs) {
874 LPWSTR *argv,s,t;
875 int i;
877 /* to get writeable copy */
878 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
879 s=cmdline;i=0;
880 while (*s) {
881 /* space */
882 if (*s==0x0020) {
883 i++;
884 s++;
885 while (*s && *s==0x0020)
886 s++;
887 continue;
889 s++;
891 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
892 s=t=cmdline;
893 i=0;
894 while (*s) {
895 if (*s==0x0020) {
896 *s=0;
897 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
898 *s=0x0020;
899 while (*s && *s==0x0020)
900 s++;
901 if (*s)
902 t=s+1;
903 else
904 t=s;
905 continue;
907 s++;
909 if (*t)
910 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
911 HeapFree( GetProcessHeap(), 0, cmdline );
912 argv[i]=NULL;
913 *numargs=i;
914 return argv;