2 * Shell Library Functions
22 extern HANDLE
CURSORICON_LoadHandler( HANDLE
, HINSTANCE
, BOOL
);
23 extern WORD
GetIconID( HANDLE hResource
, DWORD resType
);
25 /*************************************************************************
26 * DragAcceptFiles [SHELL.9]
28 void DragAcceptFiles(HWND hWnd
, BOOL b
)
30 WND
* wnd
= WIN_FindWndPtr(hWnd
);
33 wnd
->dwExStyle
= b
? wnd
->dwExStyle
| WS_EX_ACCEPTFILES
34 : wnd
->dwExStyle
& ~WS_EX_ACCEPTFILES
;
38 /*************************************************************************
39 * DragQueryFile [SHELL.11]
41 UINT
DragQueryFile(HDROP16 hDrop
, WORD wFile
, LPSTR lpszFile
, WORD wLength
)
43 /* hDrop is a global memory block allocated with GMEM_SHARE
44 * with DROPFILESTRUCT as a header and filenames following
45 * it, zero length filename is in the end */
47 LPDROPFILESTRUCT lpDropFileStruct
;
51 dprintf_reg(stddeb
,"DragQueryFile(%04x, %i, %p, %u)\n",
52 hDrop
,wFile
,lpszFile
,wLength
);
54 lpDropFileStruct
= (LPDROPFILESTRUCT
) GlobalLock16(hDrop
);
57 dprintf_reg(stddeb
,"DragQueryFile: unable to lock handle!\n");
60 lpCurrent
= (LPSTR
) lpDropFileStruct
+ lpDropFileStruct
->wSize
;
65 while (*lpCurrent
++); /* skip filename */
67 return (wFile
== 0xFFFF) ? i
: 0;
70 i
= strlen(lpCurrent
);
71 if (!lpszFile
) return i
+1; /* needed buffer size */
73 i
= (wLength
> i
) ? i
: wLength
-1;
74 strncpy(lpszFile
, lpCurrent
, i
);
77 GlobalUnlock16(hDrop
);
82 /*************************************************************************
83 * DragFinish [SHELL.12]
85 void DragFinish(HDROP16 h
)
87 GlobalFree16((HGLOBAL16
)h
);
91 /*************************************************************************
92 * DragQueryPoint [SHELL.13]
94 BOOL
DragQueryPoint(HDROP16 hDrop
, POINT16
*p
)
96 LPDROPFILESTRUCT lpDropFileStruct
;
99 lpDropFileStruct
= (LPDROPFILESTRUCT
) GlobalLock16(hDrop
);
101 memcpy(p
,&lpDropFileStruct
->ptMousePos
,sizeof(POINT16
));
102 bRet
= lpDropFileStruct
->fInNonClientArea
;
104 GlobalUnlock16(hDrop
);
108 /*************************************************************************
109 * SHELL_FindExecutable
110 * Utility for code sharing between FindExecutable and ShellExecute
112 static HINSTANCE
SHELL_FindExecutable( LPCSTR lpFile
,
117 char *extension
= NULL
; /* pointer to file extension */
118 char tmpext
[5]; /* local copy to mung as we please */
119 char filetype
[256]; /* registry name for this filetype */
120 LONG filetypelen
=256; /* length of above */
121 char command
[256]; /* command from registry */
122 LONG commandlen
=256; /* This is the most DOS can handle :) */
123 char buffer
[256]; /* Used to GetProfileString */
124 HINSTANCE retval
=31; /* default - 'No association was found' */
125 char *tok
; /* token pointer */
126 int i
; /* random counter */
128 dprintf_exec(stddeb
, "SHELL_FindExecutable: File %s, Dir %s\n",
129 (lpFile
!= NULL
?lpFile
:"-"),
130 (lpDirectory
!= NULL
?lpDirectory
:"-"));
132 lpResult
[0]='\0'; /* Start off with an empty return string */
134 /* trap NULL parameters on entry */
135 if (( lpFile
== NULL
) || ( lpDirectory
== NULL
) ||
136 ( lpResult
== NULL
) || ( lpOperation
== NULL
))
138 /* FIXME - should throw a warning, perhaps! */
139 return 2; /* File not found. Close enough, I guess. */
142 /* First thing we need is the file's extension */
143 extension
= strrchr( lpFile
, '.' ); /* Assume last "." is the one; */
144 /* File->Run in progman uses */
146 if ((extension
== NULL
) || (extension
== &lpFile
[strlen(lpFile
)]))
148 return 31; /* no association */
151 /* Make local copy & lowercase it for reg & 'programs=' lookup */
152 strncpy( tmpext
, extension
, 5 );
153 if (strlen(extension
)<=4)
154 tmpext
[strlen(extension
)]='\0';
157 for (i
=0;i
<strlen(tmpext
);i
++) tmpext
[i
]=tolower(tmpext
[i
]);
158 dprintf_exec(stddeb
, "SHELL_FindExecutable: %s file\n", tmpext
);
160 /* Three places to check: */
161 /* 1. win.ini, [windows], programs (NB no leading '.') */
162 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
163 /* 3. win.ini, [extensions], extension (NB no leading '.' */
164 /* All I know of the order is that registry is checked before */
165 /* extensions; however, it'd make sense to check the programs */
166 /* section first, so that's what happens here. */
168 /* See if it's a program */
169 GetProfileString("windows", "programs", "exe pif bat com",
170 buffer
, sizeof(buffer
)); /* FIXME check return code! */
172 for (i
=0;i
<strlen(buffer
); i
++) buffer
[i
]=tolower(buffer
[i
]);
174 tok
= strtok(buffer
, " \t"); /* ? */
177 if (strcmp(tok
, &tmpext
[1])==0) /* have to skip the leading "." */
179 strcpy(lpResult
, lpFile
); /* Need to perhaps check that */
180 /* the file has a path attached */
181 dprintf_exec(stddeb
, "SHELL_FindExecutable: found %s\n",
183 return 33; /* Greater than 32 to indicate success FIXME */
184 /* According to the docs, I should be returning */
185 /* a handle for the executable. Does this mean */
186 /* I'm supposed to open the executable file or */
187 /* something? More RTFM, I guess... */
189 tok
=strtok(NULL
, " \t");
193 if (RegQueryValue16( (HKEY
)HKEY_CLASSES_ROOT
, tmpext
, filetype
,
194 &filetypelen
) == SHELL_ERROR_SUCCESS
)
196 filetype
[filetypelen
]='\0';
197 dprintf_exec(stddeb
, "SHELL_FindExecutable: File type: %s\n",
200 /* Looking for ...buffer\shell\lpOperation\command */
201 strcat( filetype
, "\\shell\\" );
202 strcat( filetype
, lpOperation
);
203 strcat( filetype
, "\\command" );
205 if (RegQueryValue16( (HKEY
)HKEY_CLASSES_ROOT
, filetype
, command
,
206 &commandlen
) == SHELL_ERROR_SUCCESS
)
208 /* Is there a replace() function anywhere? */
209 command
[commandlen
]='\0';
210 strcpy( lpResult
, command
);
211 tok
=strstr( lpResult
, "%1" );
214 tok
[0]='\0'; /* truncate string at the percent */
215 strcat( lpResult
, lpFile
); /* what if no dir in lpFile? */
216 tok
=strstr( command
, "%1" );
217 if ((tok
!=NULL
) && (strlen(tok
)>2))
219 strcat( lpResult
, &tok
[2] );
225 else /* Check win.ini */
227 /* Toss the leading dot */
229 GetProfileString( "extensions", extension
, "", command
,
231 if (strlen(command
)!=0)
233 strcpy( lpResult
, command
);
234 tok
=strstr( lpResult
, "^" ); /* should be ^.extension? */
238 strcat( lpResult
, lpFile
); /* what if no dir in lpFile? */
239 tok
=strstr( command
, "^" ); /* see above */
240 if ((tok
!= NULL
) && (strlen(tok
)>5))
242 strcat( lpResult
, &tok
[5]);
249 dprintf_exec(stddeb
, "SHELL_FindExecutable: returning %s\n", lpResult
);
253 /*************************************************************************
254 * ShellExecute [SHELL.20]
256 HINSTANCE
ShellExecute(HWND hWnd
, LPCSTR lpOperation
, LPCSTR lpFile
,
257 LPSTR lpParameters
, LPCSTR lpDirectory
,
263 dprintf_exec(stddeb
, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
264 hWnd
, lpOperation
? lpOperation
:"<null>", lpFile
? lpFile
:"<null>",
265 lpParameters
? lpParameters
: "<null>",
266 lpDirectory
? lpDirectory
: "<null>", iShowCmd
);
268 if (lpFile
==NULL
) return 0; /* should not happen */
269 if (lpOperation
==NULL
) /* default is open */
272 retval
= SHELL_FindExecutable( lpFile
, lpDirectory
, lpOperation
, cmd
);
282 strcat(cmd
,lpParameters
);
285 dprintf_exec(stddeb
,"ShellExecute:starting %s\n",cmd
);
286 return WinExec(cmd
,iShowCmd
);
289 /*************************************************************************
290 * FindExecutable [SHELL.21]
292 HINSTANCE
FindExecutable(LPCSTR lpFile
, LPCSTR lpDirectory
, LPSTR lpResult
)
294 HINSTANCE retval
=31; /* default - 'No association was found' */
296 dprintf_exec(stddeb
, "FindExecutable: File %s, Dir %s\n",
297 (lpFile
!= NULL
?lpFile
:"-"),
298 (lpDirectory
!= NULL
?lpDirectory
:"-"));
300 lpResult
[0]='\0'; /* Start off with an empty return string */
302 /* trap NULL parameters on entry */
303 if (( lpFile
== NULL
) || ( lpDirectory
== NULL
) ||
304 ( lpResult
== NULL
))
306 /* FIXME - should throw a warning, perhaps! */
307 return 2; /* File not found. Close enough, I guess. */
310 retval
= SHELL_FindExecutable( lpFile
, lpDirectory
, "open",
313 dprintf_exec(stddeb
, "FindExecutable: returning %s\n", lpResult
);
317 static char AppName
[128], AppMisc
[1536];
319 /*************************************************************************
320 * AboutDlgProc [SHELL.33]
322 LRESULT
AboutDlgProc(HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
324 char Template
[512], AppTitle
[512];
328 SendDlgItemMessage32A(hWnd
,stc1
,STM_SETICON
,lParam
,0);
329 GetWindowText32A(hWnd
, Template
, sizeof(Template
));
330 sprintf(AppTitle
, Template
, AppName
);
331 SetWindowText32A(hWnd
, AppTitle
);
332 SetWindowText32A(GetDlgItem(hWnd
,100), AppMisc
);
338 EndDialog(hWnd
, TRUE
);
346 /*************************************************************************
347 * ShellAbout [SHELL.22]
349 INT
ShellAbout(HWND hWnd
, LPCSTR szApp
, LPCSTR szOtherStuff
, HICON hIcon
)
354 if (szApp
) strncpy(AppName
, szApp
, sizeof(AppName
));
356 AppName
[sizeof(AppName
)-1]=0;
358 if (szOtherStuff
) strncpy(AppMisc
, szOtherStuff
, sizeof(AppMisc
));
360 AppMisc
[sizeof(AppMisc
)-1]=0;
362 if (!hIcon
) hIcon
= LoadIcon16(0,MAKEINTRESOURCE(OIC_WINEICON
));
363 handle
= SYSRES_LoadResource( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX
);
364 if (!handle
) return FALSE
;
365 bRet
= DialogBoxIndirectParam16( WIN_GetWindowInstance( hWnd
),
367 MODULE_GetWndProcEntry16("AboutDlgProc"),
369 SYSRES_FreeResource( handle
);
373 /*************************************************************************
374 * SHELL_GetResourceTable
376 * FIXME: Implement GetPEResourceTable in w32sys.c and call it here.
378 BYTE
* SHELL_GetResourceTable(HFILE hFile
)
380 struct mz_header_s mz_header
;
381 struct ne_header_s ne_header
;
384 _llseek( hFile
, 0, SEEK_SET
);
385 if ((FILE_Read(hFile
,&mz_header
,sizeof(mz_header
)) != sizeof(mz_header
)) ||
386 (mz_header
.mz_magic
!= MZ_SIGNATURE
)) return (BYTE
*)-1;
388 _llseek( hFile
, mz_header
.ne_offset
, SEEK_SET
);
389 if (FILE_Read( hFile
, &ne_header
, sizeof(ne_header
) ) != sizeof(ne_header
))
392 if (ne_header
.ne_magic
== PE_SIGNATURE
)
393 { fprintf(stdnimp
,"Win32 FIXME: file %s line %i\n", __FILE__
, __LINE__
);
396 if (ne_header
.ne_magic
!= NE_SIGNATURE
) return NULL
;
398 size
= ne_header
.rname_tab_offset
- ne_header
.resource_tab_offset
;
400 if( size
> sizeof(NE_TYPEINFO
) )
402 BYTE
* pTypeInfo
= (BYTE
*)xmalloc(size
);
404 if( !pTypeInfo
) return NULL
;
406 _llseek(hFile
, mz_header
.ne_offset
+ne_header
.resource_tab_offset
, SEEK_SET
);
407 if( FILE_Read( hFile
, (char*)pTypeInfo
, size
) != size
)
408 { free(pTypeInfo
); return NULL
; }
416 /*************************************************************************
419 HANDLE
SHELL_LoadResource(HINSTANCE hInst
, HFILE hFile
, NE_NAMEINFO
* pNInfo
, WORD sizeShift
)
422 HANDLE handle
= DirectResAlloc( hInst
, 0x10, (DWORD
)pNInfo
->length
<< sizeShift
);
424 if( (ptr
= (BYTE
*)GlobalLock16( handle
)) )
426 _llseek( hFile
, (DWORD
)pNInfo
->offset
<< sizeShift
, SEEK_SET
);
427 FILE_Read( hFile
, (char*)ptr
, pNInfo
->length
<< sizeShift
);
433 /*************************************************************************
434 * InternalExtractIcon [SHELL.39]
436 * This abortion is called directly by Progman
438 HICON
InternalExtractIcon(HINSTANCE hInstance
, LPCSTR lpszExeFileName
, UINT nIconIndex
, WORD n
)
441 HICON
* RetPtr
= NULL
;
444 HFILE hFile
= OpenFile( lpszExeFileName
, &ofs
, OF_READ
);
446 dprintf_reg(stddeb
, "InternalExtractIcon(%04x, file '%s', start from %d, extract %d\n",
447 hInstance
, lpszExeFileName
, nIconIndex
, n
);
449 if( hFile
== HFILE_ERROR
|| !n
) return 0;
451 hRet
= GlobalAlloc16( GMEM_FIXED
, sizeof(HICON
)*n
);
452 RetPtr
= (HICON
*)GlobalLock16(hRet
);
454 *RetPtr
= (n
== 0xFFFF)? 0: 1; /* error return values */
456 pData
= SHELL_GetResourceTable(hFile
);
458 if( pData
== (BYTE
*)-1 )
460 /* FIXME: possible .ICO file */
462 fprintf(stddeb
,"InternalExtractIcon: cannot handle file %s\n", lpszExeFileName
);
464 else /* got resource table */
466 UINT iconDirCount
= 0;
468 NE_TYPEINFO
* pTInfo
= (NE_TYPEINFO
*)(pData
+ 2);
469 NE_NAMEINFO
* pIconStorage
= NULL
;
470 NE_NAMEINFO
* pIconDir
= NULL
;
472 /* find icon directory and icon repository */
474 while( pTInfo
->type_id
&& !(pIconStorage
&& pIconDir
) )
476 if( pTInfo
->type_id
== NE_RSCTYPE_GROUP_ICON
)
478 iconDirCount
= pTInfo
->count
;
479 pIconDir
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
480 dprintf_reg(stddeb
,"\tfound directory - %i icon families\n", iconDirCount
);
482 if( pTInfo
->type_id
== NE_RSCTYPE_ICON
)
484 iconCount
= pTInfo
->count
;
485 pIconStorage
= ((NE_NAMEINFO
*)(pTInfo
+ 1));
486 dprintf_reg(stddeb
,"\ttotal icons - %i\n", iconCount
);
488 pTInfo
= (NE_TYPEINFO
*)((char*)(pTInfo
+1)+pTInfo
->count
*sizeof(NE_NAMEINFO
));
491 /* load resources and create icons */
493 if( pIconStorage
&& pIconDir
)
495 if( nIconIndex
== (UINT
)-1 ) RetPtr
[0] = iconDirCount
;
496 else if( nIconIndex
< iconDirCount
)
501 if( n
> iconDirCount
- nIconIndex
) n
= iconDirCount
- nIconIndex
;
503 for( i
= nIconIndex
; i
< nIconIndex
+ n
; i
++ )
505 hIcon
= SHELL_LoadResource( hInstance
, hFile
, pIconDir
+ i
,
507 RetPtr
[i
-nIconIndex
] = GetIconID( hIcon
, 3 );
511 for( icon
= nIconIndex
; icon
< nIconIndex
+ n
; icon
++ )
514 for( i
= 0; i
< iconCount
; i
++ )
515 if( pIconStorage
[i
].id
== (RetPtr
[icon
-nIconIndex
] | 0x8000) )
516 hIcon
= SHELL_LoadResource( hInstance
, hFile
, pIconStorage
+ i
,
518 RetPtr
[icon
-nIconIndex
] = (hIcon
)?CURSORICON_LoadHandler( hIcon
, hInstance
, FALSE
):0;
526 /* return array with icon handles */
531 /*************************************************************************
532 * ExtractIcon [SHELL.34]
534 HICON
ExtractIcon(HINSTANCE hInstance
, LPCSTR lpszExeFileName
, WORD nIconIndex
)
536 HANDLE handle
= InternalExtractIcon(hInstance
,lpszExeFileName
,nIconIndex
, 1);
540 HICON
* ptr
= (HICON
*)GlobalLock16(handle
);
543 GlobalFree16(handle
);
549 /*************************************************************************
550 * ExtractAssociatedIcon [SHELL.36]
552 * Return icon for given file (either from file itself or from associated
553 * executable) and patch parameters if needed.
555 HICON16
ExtractAssociatedIcon(HINSTANCE16 hInst
,LPSTR lpIconPath
,LPWORD lpiIcon
)
557 HICON16 hIcon
= ExtractIcon(hInst
, lpIconPath
, *lpiIcon
);
562 if( hIcon
== 1 ) /* no icons found in given file */
565 UINT uRet
= FindExecutable(lpIconPath
,NULL
,tempPath
);
567 if( uRet
> 32 && tempPath
[0] )
569 strcpy(lpIconPath
,tempPath
);
570 hIcon
= ExtractIcon(hInst
, lpIconPath
, *lpiIcon
);
572 if( hIcon
> 2 ) return hIcon
;
578 *lpiIcon
= 2; /* MSDOS icon - we found .exe but no icons in it */
580 *lpiIcon
= 6; /* generic icon - found nothing */
582 GetModuleFileName(hInst
, lpIconPath
, 0x80);
583 hIcon
= LoadIcon16( hInst
, MAKEINTRESOURCE(*lpiIcon
));
589 /*************************************************************************
590 * FindEnvironmentString [SHELL.38]
592 * Returns a pointer into the DOS environment... Ugh.
594 LPSTR
SHELL_FindString(LPSTR lpEnv
, LPCSTR entry
)
596 UINT l
= strlen(entry
);
597 for( ; *lpEnv
; lpEnv
+=strlen(lpEnv
)+1 )
599 if( lstrncmpi32A(lpEnv
, entry
, l
) ) continue;
602 return (lpEnv
+ l
); /* empty entry */
603 else if ( *(lpEnv
+l
)== '=' )
604 return (lpEnv
+ l
+ 1);
609 SEGPTR
FindEnvironmentString(LPSTR str
)
611 SEGPTR spEnv
= GetDOSEnvironment();
612 LPSTR lpEnv
= (LPSTR
)PTR_SEG_TO_LIN(spEnv
);
614 LPSTR lpString
= (spEnv
)?SHELL_FindString(lpEnv
, str
):NULL
;
616 if( lpString
) /* offset should be small enough */
617 return spEnv
+ (lpString
- lpEnv
);
622 /*************************************************************************
623 * DoEnvironmentSubst [SHELL.37]
625 * Replace %KEYWORD% in the str with the value of variable KEYWORD
626 * from "DOS" environment.
628 DWORD
DoEnvironmentSubst(LPSTR str
,WORD length
)
630 LPSTR lpEnv
= (LPSTR
)PTR_SEG_TO_LIN(GetDOSEnvironment());
631 LPSTR lpBuffer
= (LPSTR
)xmalloc(length
);
633 LPSTR lpbstr
= lpBuffer
;
637 dprintf_reg(stddeb
,"DoEnvSubst: accept %s", str
);
639 while( *lpstr
&& lpbstr
- lpBuffer
< length
)
645 do { lpend
++; } while( *lpend
&& *lpend
!= '%' );
646 if( *lpend
== '%' && lpend
- lpstr
> 1 ) /* found key */
650 lpKey
= SHELL_FindString(lpEnv
, lpstr
+1);
651 if( lpKey
) /* found key value */
653 int l
= strlen(lpKey
);
655 if( l
> length
- (lpbstr
- lpBuffer
) - 1 )
657 fprintf(stdnimp
,"File %s, line %i: Env subst aborted - string too short\n",
662 strcpy(lpbstr
, lpKey
);
669 else break; /* back off and whine */
674 *lpbstr
++ = *lpstr
++;
678 if( lpstr
- str
== strlen(str
) )
680 strncpy(str
, lpBuffer
, length
);
686 dprintf_reg(stddeb
," return %s\n", str
);
691 /* Return str length in the LOWORD
692 * and 1 in HIWORD if subst was successful.
694 return (DWORD
)MAKELONG(strlen(str
), length
);
697 /*************************************************************************
698 * RegisterShellHook [SHELL.102]
700 int RegisterShellHook(void *ptr
)
702 dprintf_reg(stdnimp
, "RegisterShellHook : Empty Stub !!!\n");
707 /*************************************************************************
708 * ShellHookProc [SHELL.103]
710 int ShellHookProc(void)
712 dprintf_reg(stdnimp
, "ShellHookProc : Empty Stub !!!\n");