2 * Shell Library Functions
21 #include "cursoricon.h"
22 #include "interfaces.h"
23 #include "sysmetrics.h"
30 static const char * const SHELL_People[] =
45 "Niels de Carpentier",
51 "Frans van Dorsselaer",
112 "Bernhard Rosenkraenzer",
113 "Johannes Ruscheinski",
115 "Constantine Sapuntzakis",
123 "Yngvi Sigurjonsson",
138 "Gregory Trubetskoy",
150 "Karl Guenter Wuensch",
153 "Nikita V. Youshchenko",
160 /* .ICO file ICONDIR definitions */
166 BYTE bWidth; /* Width, in pixels, of the image */
167 BYTE bHeight; /* Height, in pixels, of the image */
168 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
169 BYTE bReserved; /* Reserved ( must be 0) */
170 WORD wPlanes; /* Color Planes */
171 WORD wBitCount; /* Bits per pixel */
172 DWORD dwBytesInRes; /* How many bytes in this resource? */
173 DWORD dwImageOffset; /* Where in the file is this image? */
174 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
178 WORD idReserved; /* Reserved (must be 0) */
179 WORD idType; /* Resource Type (1 for icons) */
180 WORD idCount; /* How many images? */
181 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
182 } icoICONDIR, *LPicoICONDIR;
186 static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
187 static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
188 static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
190 static HWND16 SHELL_hWnd = 0;
191 static HHOOK SHELL_hHook = 0;
192 static UINT16 uMsgWndCreated = 0;
193 static UINT16 uMsgWndDestroyed = 0;
194 static UINT16 uMsgShellActivate = 0;
196 /*************************************************************************
197 * DragAcceptFiles [SHELL.9]
199 void WINAPI DragAcceptFiles(HWND16 hWnd, BOOL16 b)
201 WND* wnd = WIN_FindWndPtr(hWnd);
204 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
205 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
209 /*************************************************************************
210 * DragQueryFile [SHELL.11]
212 UINT16 WINAPI DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile,
215 /* hDrop is a global memory block allocated with GMEM_SHARE
216 * with DROPFILESTRUCT as a header and filenames following
217 * it, zero length filename is in the end */
219 LPDROPFILESTRUCT lpDropFileStruct;
223 dprintf_reg(stddeb,"DragQueryFile(%04x, %i, %p, %u)\n",
224 hDrop,wFile,lpszFile,wLength);
226 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
227 if(!lpDropFileStruct) return 0;
229 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
234 while (*lpCurrent++); /* skip filename */
236 return (wFile == 0xFFFF) ? i : 0;
239 i = strlen(lpCurrent);
240 if (!lpszFile) return i+1; /* needed buffer size */
242 i = (wLength > i) ? i : wLength-1;
243 strncpy(lpszFile, lpCurrent, i);
246 GlobalUnlock16(hDrop);
251 /*************************************************************************
252 * DragFinish [SHELL.12]
254 void WINAPI DragFinish(HDROP16 h)
256 GlobalFree16((HGLOBAL16)h);
260 /*************************************************************************
261 * DragQueryPoint [SHELL.13]
263 BOOL16 WINAPI DragQueryPoint(HDROP16 hDrop, POINT16 *p)
265 LPDROPFILESTRUCT lpDropFileStruct;
268 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
270 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
271 bRet = lpDropFileStruct->fInNonClientArea;
273 GlobalUnlock16(hDrop);
277 /*************************************************************************
278 * SHELL_FindExecutable
279 * Utility for code sharing between FindExecutable and ShellExecute
281 static HINSTANCE32 SHELL_FindExecutable( LPCSTR lpFile,
285 char *extension = NULL; /* pointer to file extension */
286 char tmpext[5]; /* local copy to mung as we please */
287 char filetype[256]; /* registry name for this filetype */
288 LONG filetypelen=256; /* length of above */
289 char command[256]; /* command from registry */
290 LONG commandlen=256; /* This is the most DOS can handle :) */
291 char buffer[256]; /* Used to GetProfileString */
292 HINSTANCE32 retval=31; /* default - 'No association was found' */
293 char *tok; /* token pointer */
294 int i; /* random counter */
295 char xlpFile[256]; /* result of SearchPath */
297 dprintf_exec(stddeb, "SHELL_FindExecutable: %s\n",
298 (lpFile != NULL?lpFile:"-") );
299 lpResult[0]='\0'; /* Start off with an empty return string */
301 /* trap NULL parameters on entry */
302 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
304 /* FIXME - should throw a warning, perhaps! */
305 return 2; /* File not found. Close enough, I guess. */
308 if (SearchPath32A( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
311 /* First thing we need is the file's extension */
312 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
313 /* File->Run in progman uses */
315 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
317 return 31; /* no association */
320 /* Make local copy & lowercase it for reg & 'programs=' lookup */
321 lstrcpyn32A( tmpext, extension, 5 );
322 CharLower32A( tmpext );
323 dprintf_exec(stddeb, "SHELL_FindExecutable: %s file\n", tmpext);
325 /* Three places to check: */
326 /* 1. win.ini, [windows], programs (NB no leading '.') */
327 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
328 /* 3. win.ini, [extensions], extension (NB no leading '.' */
329 /* All I know of the order is that registry is checked before */
330 /* extensions; however, it'd make sense to check the programs */
331 /* section first, so that's what happens here. */
333 /* See if it's a program - if GetProfileString fails, we skip this
334 * section. Actually, if GetProfileString fails, we've probably
335 * got a lot more to worry about than running a program... */
336 if ( GetProfileString32A("windows", "programs", "exe pif bat com",
337 buffer, sizeof(buffer)) > 0 )
339 for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
341 tok = strtok(buffer, " \t"); /* ? */
344 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
346 strcpy(lpResult, xlpFile);
347 /* Need to perhaps check that the file has a path
349 dprintf_exec(stddeb, "SHELL_FindExecutable: found %s\n",
353 /* Greater than 32 to indicate success FIXME According to the
354 * docs, I should be returning a handle for the
355 * executable. Does this mean I'm supposed to open the
356 * executable file or something? More RTFM, I guess... */
358 tok=strtok(NULL, " \t");
363 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
364 &filetypelen ) == SHELL_ERROR_SUCCESS )
366 filetype[filetypelen]='\0';
367 dprintf_exec(stddeb, "SHELL_FindExecutable: File type: %s\n",
370 /* Looking for ...buffer\shell\lpOperation\command */
371 strcat( filetype, "\\shell\\" );
372 strcat( filetype, lpOperation );
373 strcat( filetype, "\\command" );
375 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
376 &commandlen ) == SHELL_ERROR_SUCCESS )
378 /* Is there a replace() function anywhere? */
379 command[commandlen]='\0';
380 strcpy( lpResult, command );
381 tok=strstr( lpResult, "%1" );
384 tok[0]='\0'; /* truncate string at the percent */
385 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
386 tok=strstr( command, "%1" );
387 if ((tok!=NULL) && (strlen(tok)>2))
389 strcat( lpResult, &tok[2] );
392 retval=33; /* FIXME see above */
395 else /* Check win.ini */
397 /* Toss the leading dot */
399 if ( GetProfileString32A( "extensions", extension, "", command,
400 sizeof(command)) > 0)
402 if (strlen(command)!=0)
404 strcpy( lpResult, command );
405 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
409 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
410 tok=strstr( command, "^" ); /* see above */
411 if ((tok != NULL) && (strlen(tok)>5))
413 strcat( lpResult, &tok[5]);
416 retval=33; /* FIXME - see above */
421 dprintf_exec(stddeb, "SHELL_FindExecutable: returning %s\n", lpResult);
425 /*************************************************************************
426 * ShellExecute16 [SHELL.20]
428 HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
429 LPCSTR lpFile, LPCSTR lpParameters,
430 LPCSTR lpDirectory, INT16 iShowCmd )
432 HINSTANCE16 retval=31;
436 dprintf_exec(stddeb, "ShellExecute(%04x,'%s','%s','%s','%s',%x)\n",
437 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
438 lpParameters ? lpParameters : "<null>",
439 lpDirectory ? lpDirectory : "<null>", iShowCmd);
441 if (lpFile==NULL) return 0; /* should not happen */
442 if (lpOperation==NULL) /* default is open */
447 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
448 SetCurrentDirectory32A( lpDirectory );
451 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
453 if (retval > 32) /* Found */
458 strcat(cmd,lpParameters);
461 dprintf_exec(stddeb,"ShellExecute:starting %s\n",cmd);
462 retval = WinExec32( cmd, iShowCmd );
464 if (lpDirectory) SetCurrentDirectory32A( old_dir );
469 /*************************************************************************
470 * ShellExecute32A (SHELL32.245)
472 HINSTANCE32 WINAPI ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation,
473 LPCSTR lpFile, LPCSTR lpParameters,
474 LPCSTR lpDirectory, INT32 iShowCmd )
476 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
477 lpDirectory, iShowCmd );
481 /*************************************************************************
482 * FindExecutable16 (SHELL.21)
484 HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
487 return (HINSTANCE16)FindExecutable32A( lpFile, lpDirectory, lpResult );
490 /*************************************************************************
491 * FindExecutable32A (SHELL32.184)
493 HINSTANCE32 WINAPI FindExecutable32A( LPCSTR lpFile, LPCSTR lpDirectory,
496 HINSTANCE32 retval=31; /* default - 'No association was found' */
499 dprintf_exec(stddeb, "FindExecutable: File %s, Dir %s\n",
500 (lpFile != NULL?lpFile:"-"),
501 (lpDirectory != NULL?lpDirectory:"-"));
503 lpResult[0]='\0'; /* Start off with an empty return string */
505 /* trap NULL parameters on entry */
506 if (( lpFile == NULL ) || ( lpResult == NULL ))
508 /* FIXME - should throw a warning, perhaps! */
509 return 2; /* File not found. Close enough, I guess. */
514 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
515 SetCurrentDirectory32A( lpDirectory );
518 retval = SHELL_FindExecutable( lpFile, "open", lpResult );
520 dprintf_exec(stddeb, "FindExecutable: returning %s\n", lpResult);
521 if (lpDirectory) SetCurrentDirectory32A( old_dir );
532 #define IDC_STATIC_TEXT 100
533 #define IDC_LISTBOX 99
534 #define IDC_WINE_TEXT 98
536 #define DROP_FIELD_TOP (-15)
537 #define DROP_FIELD_HEIGHT 15
539 extern HICON32 hIconTitleFont;
541 static BOOL32 __get_dropline( HWND32 hWnd, LPRECT32 lprect )
543 HWND32 hWndCtl = GetDlgItem32(hWnd, IDC_WINE_TEXT);
546 GetWindowRect32( hWndCtl, lprect );
547 MapWindowPoints32( 0, hWnd, (LPPOINT32)lprect, 2 );
548 lprect->bottom = (lprect->top += DROP_FIELD_TOP);
554 /*************************************************************************
555 * AboutDlgProc32 (not an exported API function)
557 LRESULT WINAPI AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
561 char Template[512], AppTitle[512];
567 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
570 const char* const *pstr = SHELL_People;
571 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON32,info->hIcon, 0);
572 GetWindowText32A( hWnd, Template, sizeof(Template) );
573 sprintf( AppTitle, Template, info->szApp );
574 SetWindowText32A( hWnd, AppTitle );
575 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT),
576 info->szOtherStuff );
577 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
578 SendMessage32A( hWndCtl, WM_SETREDRAW, 0, 0 );
579 SendMessage32A( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
582 SendMessage32A( hWndCtl, LB_ADDSTRING32,
583 (WPARAM32)-1, (LPARAM)*pstr );
586 SendMessage32A( hWndCtl, WM_SETREDRAW, 1, 0 );
595 HDC32 hDC = BeginPaint32( hWnd, &ps );
597 if( __get_dropline( hWnd, &rect ) )
598 GRAPH_DrawLines( hDC, (LPPOINT32)&rect, 1, GetStockObject32( BLACK_PEN ) );
599 EndPaint32( hWnd, &ps );
603 case WM_LBTRACKPOINT:
605 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
606 if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
608 if( DragDetect32( hWndCtl, *((LPPOINT32)&lParam) ) )
610 INT32 idx = SendMessage32A( hWndCtl, LB_GETCURSEL32, 0, 0 );
613 INT32 length = SendMessage32A( hWndCtl, LB_GETTEXTLEN32, (WPARAM32)idx, 0 );
614 HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
615 char* pstr = (char*)GlobalLock16( hMemObj );
619 HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE(OCR_DRAGOBJECT) );
620 SendMessage32A( hWndCtl, LB_GETTEXT32, (WPARAM32)idx, (LPARAM)pstr );
621 SendMessage32A( hWndCtl, LB_DELETESTRING32, (WPARAM32)idx, 0 );
622 UpdateWindow32( hWndCtl );
623 if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
624 SendMessage32A( hWndCtl, LB_ADDSTRING32, (WPARAM32)-1, (LPARAM)pstr );
626 if( hMemObj ) GlobalFree16( hMemObj );
632 case WM_QUERYDROPOBJECT:
635 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
636 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
639 if( __get_dropline( hWnd, &rect ) )
641 POINT32 pt = { lpDragInfo->pt.x, lpDragInfo->pt.y };
642 rect.bottom += DROP_FIELD_HEIGHT;
643 if( PtInRect32( &rect, pt ) )
645 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
656 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
657 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
659 char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
662 static char __appendix_str[] = " with";
664 hWndCtl = GetDlgItem32( hWnd, IDC_WINE_TEXT );
665 SendMessage32A( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
666 if( !lstrncmp32A( Template, "WINE", 4 ) )
667 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT), Template );
670 char* pch = Template + strlen(Template) - strlen(__appendix_str);
672 SendMessage32A( GetDlgItem32(hWnd, IDC_LISTBOX), LB_ADDSTRING32,
673 (WPARAM32)-1, (LPARAM)Template );
676 lstrcpy32A( Template, pstr );
677 lstrcat32A( Template, __appendix_str );
678 SetWindowText32A( hWndCtl, Template );
680 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
690 EndDialog32(hWnd, TRUE);
699 /*************************************************************************
700 * AboutDlgProc16 (SHELL.33)
702 LRESULT WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
705 return AboutDlgProc32( hWnd, msg, wParam, lParam );
709 /*************************************************************************
710 * ShellAbout16 (SHELL.22)
712 BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
715 return ShellAbout32A( hWnd, szApp, szOtherStuff, hIcon );
718 /*************************************************************************
719 * ShellAbout32A (SHELL32.243)
721 BOOL32 WINAPI ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
726 info.szOtherStuff = szOtherStuff;
728 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
729 return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
730 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
731 hWnd, AboutDlgProc32, (LPARAM)&info );
735 /*************************************************************************
736 * ShellAbout32W (SHELL32.244)
738 BOOL32 WINAPI ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
744 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
745 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
747 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE(OIC_WINEICON) );
748 ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
749 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
750 hWnd, AboutDlgProc32, (LPARAM)&info );
751 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
752 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
756 /*************************************************************************
757 * Shell_NotifyIcon [SHELL32.249]
759 * This function is supposed to deal with the systray.
760 * Any ideas on how this is to be implimented?
762 BOOL32 WINAPI Shell_NotifyIcon( DWORD dwMessage,
763 PNOTIFYICONDATA pnid )
768 /*************************************************************************
769 * Shell_NotifyIcon [SHELL32.240]
771 * This function is supposed to deal with the systray.
772 * Any ideas on how this is to be implimented?
774 BOOL32 WINAPI Shell_NotifyIconA(DWORD dwMessage,
775 PNOTIFYICONDATA pnid )
780 /*************************************************************************
781 * SHELL_GetResourceTable
783 static DWORD SHELL_GetResourceTable(HFILE32 hFile,LPBYTE *retptr)
785 IMAGE_DOS_HEADER mz_header;
790 _llseek32( hFile, 0, SEEK_SET );
791 if ( (_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
792 (mz_header.e_magic != IMAGE_DOS_SIGNATURE)
796 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
797 if (_lread32( hFile, magic, sizeof(magic) ) != sizeof(magic))
799 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET);
801 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
802 return IMAGE_NT_SIGNATURE;
803 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE) {
804 IMAGE_OS2_HEADER ne_header;
805 LPBYTE pTypeInfo = NULL;
807 if (_lread32(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
810 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return 0;
811 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
812 if( size > sizeof(NE_TYPEINFO) )
814 pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
816 _llseek32(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
817 if( _lread32( hFile, (char*)pTypeInfo, size) != size ) {
818 HeapFree( GetProcessHeap(), 0, pTypeInfo);
825 *retptr = (LPBYTE)-1;
826 return IMAGE_OS2_SIGNATURE; /* handles .ICO too */
830 /*************************************************************************
833 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
836 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
838 if( (ptr = (BYTE*)GlobalLock16( handle )) )
840 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
841 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
847 /*************************************************************************
850 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
853 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
855 if( (ptr = (BYTE*)GlobalLock16( handle )) )
857 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
858 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
864 /*************************************************************************
865 * ICO_GetIconDirectory
867 * Read .ico file and build phony ICONDIR struct for GetIconID
869 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
871 WORD id[3]; /* idReserved, idType, idCount */
875 _llseek32( hFile, 0, SEEK_SET );
876 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
880 * - see http://www.microsoft.com/win32dev/ui/icons.htm
883 if( id[0] || id[1] != 1 || !id[2] ) return 0;
885 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
887 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
889 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
891 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
892 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
895 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
896 lpID->idReserved = lpiID->idReserved = id[0];
897 lpID->idType = lpiID->idType = id[1];
898 lpID->idCount = lpiID->idCount = id[2];
899 for( i=0; i < lpiID->idCount; i++ )
901 memcpy((void*)(lpID->idEntries + i),
902 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
903 lpID->idEntries[i].icon.wResId = i;
911 HeapFree( GetProcessHeap(), 0, lpiID);
915 /*************************************************************************
916 * InternalExtractIcon [SHELL.39]
918 * This abortion is called directly by Progman
920 HGLOBAL16 WINAPI InternalExtractIcon(HINSTANCE16 hInstance,
921 LPCSTR lpszExeFileName, UINT16 nIconIndex,
925 HGLOBAL16* RetPtr = NULL;
929 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
930 UINT16 iconDirCount = 0,iconCount = 0;
932 dprintf_reg(stddeb,"InternalExtractIcon(%04x,file %s,start %d,extract %d\n",
933 hInstance, lpszExeFileName, nIconIndex, n);
935 if( hFile == HFILE_ERROR32 || !n ) return 0;
937 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
938 RetPtr = (HICON16*)GlobalLock16(hRet);
940 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
942 sig = SHELL_GetResourceTable(hFile,&pData);
944 if(sig == IMAGE_OS2_SIGNATURE)
947 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
948 NE_NAMEINFO* pIconStorage = NULL;
949 NE_NAMEINFO* pIconDir = NULL;
950 LPicoICONDIR lpiID = NULL;
952 if( pData == (BYTE*)-1 )
954 /* check for .ICO file */
956 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
957 if( hIcon ) { iconDirCount = 1; iconCount = lpiID->idCount; }
959 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
961 /* find icon directory and icon repository */
963 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
965 iconDirCount = pTInfo->count;
966 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
967 dprintf_reg(stddeb,"\tfound directory - %i icon families\n", iconDirCount);
969 if( pTInfo->type_id == NE_RSCTYPE_ICON )
971 iconCount = pTInfo->count;
972 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
973 dprintf_reg(stddeb,"\ttotal icons - %i\n", iconCount);
975 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
978 /* load resources and create icons */
980 if( (pIconStorage && pIconDir) || lpiID )
981 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
982 else if( nIconIndex < iconDirCount )
986 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
988 for( i = nIconIndex; i < nIconIndex + n; i++ )
990 /* .ICO files have only one icon directory */
993 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
995 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
999 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
1003 hIcon = ICO_LoadIcon( hInstance, hFile,
1004 lpiID->idEntries + RetPtr[icon-nIconIndex]);
1006 for( i = 0; i < iconCount; i++ )
1007 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
1008 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
1012 RetPtr[icon-nIconIndex] = LoadIconHandler( hIcon, TRUE );
1013 FarSetOwner( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
1016 RetPtr[icon-nIconIndex] = 0;
1019 if( lpiID ) HeapFree( GetProcessHeap(), 0, lpiID);
1020 else HeapFree( GetProcessHeap(), 0, pData);
1022 if( sig == IMAGE_NT_SIGNATURE)
1024 LPBYTE peimage,idata,igdata;
1025 LPIMAGE_DOS_HEADER dheader;
1026 LPIMAGE_NT_HEADERS pe_header;
1027 LPIMAGE_SECTION_HEADER pe_sections;
1028 LPIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
1029 LPIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
1032 LPIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
1033 CURSORICONDIR **cids;
1035 fmapping = CreateFileMapping32A(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
1036 if (fmapping == 0) { /* FIXME, INVALID_HANDLE_VALUE? */
1037 fprintf(stderr,"InternalExtractIcon:failed to create filemap.\n");
1041 peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
1043 fprintf(stderr,"InternalExtractIcon:failed to mmap filemap.\n");
1044 CloseHandle(fmapping);
1048 dheader = (LPIMAGE_DOS_HEADER)peimage;
1049 /* it is a pe header, SHELL_GetResourceTable checked that */
1050 pe_header = (LPIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
1051 /* probably makes problems with short PE headers... but I haven't seen
1054 pe_sections = (LPIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
1056 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) {
1057 if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
1059 /* FIXME: doesn't work when the resources are not in a seperate section */
1060 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) {
1061 rootresdir = (LPIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
1067 fprintf(stderr,"InternalExtractIcon: haven't found section for resource directory.\n");
1068 UnmapViewOfFile(peimage);
1069 CloseHandle(fmapping);
1073 icongroupresdir = GetResDirEntryW(rootresdir,(LPWSTR)RT_GROUP_ICON,(DWORD)rootresdir,FALSE);
1074 if (!icongroupresdir) {
1075 fprintf(stderr,"InternalExtractIcon: No Icongroupresourcedirectory!\n");
1076 UnmapViewOfFile(peimage);
1077 CloseHandle(fmapping);
1082 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
1083 if( nIconIndex == (UINT16)-1 ) {
1084 RetPtr[0] = iconDirCount;
1085 UnmapViewOfFile(peimage);
1086 CloseHandle(fmapping);
1091 if (nIconIndex >= iconDirCount) {
1092 fprintf(stderr,"nIconIndex %d is larger than iconDirCount %d\n",
1093 nIconIndex,iconDirCount
1095 UnmapViewOfFile(peimage);
1096 CloseHandle(fmapping);
1101 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
1103 /* caller just wanted the number of entries */
1105 xresent = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
1106 /* assure we don't get too much ... */
1107 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
1109 /* starting from specified index ... */
1110 xresent = xresent+nIconIndex;
1112 for (i=0;i<n;i++,xresent++) {
1114 LPIMAGE_RESOURCE_DIRECTORY resdir;
1116 /* go down this resource entry, name */
1117 resdir = (LPIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
1118 /* default language (0) */
1119 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1120 igdataent = (LPIMAGE_RESOURCE_DATA_ENTRY)resdir;
1122 /* lookup address in mapped image for virtual address */
1124 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1125 if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
1127 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1129 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1132 fprintf(stderr,"InternalExtractIcon: no matching real address found for icongroup!\n");
1133 UnmapViewOfFile(peimage);
1134 CloseHandle(fmapping);
1139 cid = (CURSORICONDIR*)igdata;
1141 RetPtr[i] = LookupIconIdFromDirectoryEx32(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1143 iconresdir=GetResDirEntryW(rootresdir,(LPWSTR)RT_ICON,(DWORD)rootresdir,FALSE);
1145 fprintf(stderr,"InternalExtractIcon: No Iconresourcedirectory!\n");
1146 UnmapViewOfFile(peimage);
1147 CloseHandle(fmapping);
1152 LPIMAGE_RESOURCE_DIRECTORY xresdir;
1154 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir,FALSE);
1155 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1157 idataent = (LPIMAGE_RESOURCE_DATA_ENTRY)xresdir;
1160 /* map virtual to address in image */
1161 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1162 if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
1164 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1166 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1169 fprintf(stderr,"InternalExtractIcon: no matching real address found for icondata!\n");
1173 RetPtr[i] = CreateIconFromResourceEx32(idata,idataent->Size,TRUE,0x00030000,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1175 UnmapViewOfFile(peimage);
1176 CloseHandle(fmapping);
1181 /* return array with icon handles */
1186 /*************************************************************************
1187 * ExtractIcon16 (SHELL.34)
1189 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
1192 return ExtractIcon32A( hInstance, lpszExeFileName, nIconIndex );
1196 /*************************************************************************
1197 * ExtractIcon32A (SHELL32.133)
1199 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
1202 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
1206 HICON16* ptr = (HICON16*)GlobalLock16(handle);
1207 HICON16 hIcon = *ptr;
1209 GlobalFree16(handle);
1215 /*************************************************************************
1216 * ExtractIcon32W (SHELL32.180)
1218 HICON32 WINAPI ExtractIcon32W( HINSTANCE32 hInstance, LPCWSTR lpszExeFileName,
1221 LPSTR exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
1222 HICON32 ret = ExtractIcon32A(hInstance,exefn,nIconIndex);
1224 HeapFree(GetProcessHeap(),0,exefn);
1229 /*************************************************************************
1230 * ExtractAssociatedIcon [SHELL.36]
1232 * Return icon for given file (either from file itself or from associated
1233 * executable) and patch parameters if needed.
1235 HICON32 WINAPI ExtractAssociatedIcon32A(HINSTANCE32 hInst,LPSTR lpIconPath,
1238 return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
1241 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst,LPSTR lpIconPath,
1244 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1249 if( hIcon == 1 ) /* no icons found in given file */
1251 char tempPath[0x80];
1252 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
1254 if( uRet > 32 && tempPath[0] )
1256 strcpy(lpIconPath,tempPath);
1257 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1259 if( hIcon > 2 ) return hIcon;
1265 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
1267 *lpiIcon = 6; /* generic icon - found nothing */
1269 GetModuleFileName16(hInst, lpIconPath, 0x80);
1270 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE(*lpiIcon));
1276 /*************************************************************************
1277 * FindEnvironmentString [SHELL.38]
1279 * Returns a pointer into the DOS environment... Ugh.
1281 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
1283 UINT16 l = strlen(entry);
1284 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
1286 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
1289 return (lpEnv + l); /* empty entry */
1290 else if ( *(lpEnv+l)== '=' )
1291 return (lpEnv + l + 1);
1296 SEGPTR WINAPI FindEnvironmentString(LPSTR str)
1298 SEGPTR spEnv = GetDOSEnvironment();
1299 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
1301 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
1303 if( lpString ) /* offset should be small enough */
1304 return spEnv + (lpString - lpEnv);
1306 return (SEGPTR)NULL;
1309 /*************************************************************************
1310 * DoEnvironmentSubst [SHELL.37]
1312 * Replace %KEYWORD% in the str with the value of variable KEYWORD
1313 * from "DOS" environment.
1315 DWORD WINAPI DoEnvironmentSubst(LPSTR str,WORD length)
1317 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
1318 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
1320 LPSTR lpbstr = lpBuffer;
1322 CharToOem32A(str,str);
1324 dprintf_reg(stddeb,"DoEnvSubst: accept %s", str);
1326 while( *lpstr && lpbstr - lpBuffer < length )
1328 LPSTR lpend = lpstr;
1332 do { lpend++; } while( *lpend && *lpend != '%' );
1333 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
1337 lpKey = SHELL_FindString(lpEnv, lpstr+1);
1338 if( lpKey ) /* found key value */
1340 int l = strlen(lpKey);
1342 if( l > length - (lpbstr - lpBuffer) - 1 )
1344 fprintf(stdnimp,"File %s, line %i: Env subst aborted - string too short\n",
1345 __FILE__, __LINE__);
1349 strcpy(lpbstr, lpKey);
1356 else break; /* back off and whine */
1361 *lpbstr++ = *lpstr++;
1365 if( lpstr - str == strlen(str) )
1367 strncpy(str, lpBuffer, length);
1373 dprintf_reg(stddeb," return %s\n", str);
1375 OemToChar32A(str,str);
1376 HeapFree( GetProcessHeap(), 0, lpBuffer);
1378 /* Return str length in the LOWORD
1379 * and 1 in HIWORD if subst was successful.
1381 return (DWORD)MAKELONG(strlen(str), length);
1384 /*************************************************************************
1385 * ShellHookProc [SHELL.103]
1386 * System-wide WH_SHELL hook.
1388 LRESULT WINAPI ShellHookProc(INT16 code, WPARAM16 wParam, LPARAM lParam)
1390 dprintf_reg(stddeb,"ShellHookProc: %i, %04x, %08x\n", code, wParam,
1392 if( SHELL_hHook && SHELL_hWnd )
1397 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
1398 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
1399 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
1401 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
1403 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
1406 LRESULT WINAPI FUNC004(INT16 code, WPARAM16 wParam, LPARAM lParam)
1408 fprintf(stderr,"FUNC004(%d,%d,%ld),STUB!\n",code,wParam,lParam);
1409 return ShellHookProc(code,wParam,lParam);
1412 /*************************************************************************
1413 * RegisterShellHook [SHELL.102]
1415 BOOL32 WINAPI RegisterShellHook(HWND16 hWnd, UINT16 uAction)
1417 dprintf_reg(stddeb,"RegisterShellHook: %04x [%u]\n", hWnd, uAction );
1421 case 2: /* register hWnd as a shell window */
1425 HMODULE16 hShell = GetModuleHandle16( "SHELL" );
1427 SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc,
1431 uMsgWndCreated = RegisterWindowMessage32A( lpstrMsgWndCreated );
1432 uMsgWndDestroyed = RegisterWindowMessage32A( lpstrMsgWndDestroyed );
1433 uMsgShellActivate = RegisterWindowMessage32A( lpstrMsgShellActivate );
1435 else fprintf( stderr, "\tunable to install ShellHookProc()!\n");
1438 if( SHELL_hHook ) return ((SHELL_hWnd = hWnd) != 0);
1443 fprintf( stderr, "RegisterShellHook: unknown code %i\n", uAction );
1453 /*************************************************************************
1454 * SHGetFileInfoA [SHELL32.218]
1456 DWORD WINAPI SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,
1457 SHFILEINFO32A *psfi, UINT32 sizeofpsfi,
1460 fprintf(stdnimp,"SHGetFileInfo32A(%s,0x%08lx,%p,%d,0x%08x)\n",
1461 path,dwFileAttributes,psfi,sizeofpsfi,flags
1466 /*************************************************************************
1467 * SHAppBarMessage32 [SHELL32.207]
1469 UINT32 WINAPI SHAppBarMessage32(DWORD msg, PAPPBARDATA data)
1471 fprintf(stdnimp,"SHAppBarMessage32(0x%08lx,%p)\n", msg, data);
1475 case ABM_GETAUTOHIDEBAR:
1477 case ABM_GETTASKBARPOS:
1481 case ABM_SETAUTOHIDEBAR:
1483 case ABM_WINDOWPOSCHANGED:
1490 /*************************************************************************
1491 * CommandLineToArgvW [SHELL32.7]
1493 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
1498 /* to get writeable copy */
1499 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
1506 while (*s && *s==0x0020)
1512 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
1518 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
1520 while (*s && *s==0x0020)
1531 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
1532 HeapFree( GetProcessHeap(), 0, cmdline );
1538 /*************************************************************************
1539 * Control_RunDLL [SHELL32.12]
1541 * Wild speculation in the following!
1543 * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
1546 void WINAPI Control_RunDLL (HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4)
1548 dprintf_exec (stddeb, "Control_RunDLL (%08x, %p, \"%s\", %08lx)\n",
1550 code ? code : "(null)",
1551 cmd ? cmd : "(null)",
1555 /*************************************************************************
1558 void WINAPI FreeIconList( DWORD dw )
1560 fprintf( stdnimp, "FreeIconList: empty stub\n" );
1563 /*************************************************************************
1564 * SHELL32_DllGetClassObject [SHELL32.14]
1566 * http://premium.microsoft.com/msdn/library/sdkdoc/api2_48fo.htm
1568 DWORD WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID *ppv)
1570 char xclsid[50],xiid[50];
1571 HRESULT hres = E_OUTOFMEMORY;
1574 StringFromCLSID((LPCLSID)rclsid,xclsid);
1575 StringFromCLSID((LPCLSID)iid,xiid);
1576 fprintf(stderr,"SHELL32_DllGetClassObject(%s,%s,%p)\n",xclsid,xiid,ppv);
1579 /* SDK example code looks like this:
1581 HRESULT hres = E_OUTOFMEMORY;
1584 CClassFactory *pClassFactory = new CClassFactory(rclsid);
1586 if (pClassFactory) {
1587 hRes = pClassFactory->QueryInterface(riid,ppv);
1588 pClassFactory->Release();
1592 * The magic of the whole stuff is still unclear to me, so just hack together
1596 if (!memcmp(rclsid,&CLSID_ShellDesktop,sizeof(CLSID_ShellDesktop))) {
1597 fprintf(stderr," requested CLSID_ShellDesktop, creating it.\n");
1598 *ppv = IShellFolder_Constructor();
1599 /* FIXME: Initialize this folder to be the shell desktop folder */
1603 fprintf (stdnimp, " -> clsid not found. returning E_OUTOFMEMORY.\n");
1607 /*************************************************************************
1608 * SHGetDesktopFolder [SHELL32.216]
1609 * returns the interface to the shell desktop folder.
1611 * [SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
1612 * CLSID_ShellDesktop.
1614 * CoCreateInstance(CLSID_Desktop, NULL,
1615 * CLSCTX_INPROC, IID_IShellFolder, &pshf);
1617 * So what we are doing is currently wrong....
1619 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
1620 *shellfolder = IShellFolder_Constructor();
1624 /*************************************************************************
1625 * SHGetMalloc [SHELL32.220]
1626 * returns the interface to shell malloc.
1628 * [SDK header win95/shlobj.h:
1629 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
1631 * What we are currently doing is not very wrong, since we always use the same
1632 * heap (ProcessHeap).
1634 DWORD WINAPI SHGetMalloc(LPMALLOC *lpmal) {
1635 fprintf(stderr,"SHGetMalloc()\n");
1636 *lpmal = IMalloc_Constructor();
1640 /*************************************************************************
1641 * SHGetSpecialFolderLocation [SHELL32.223]
1642 * returns the PIDL of a special folder
1644 * nFolder is a CSIDL_xxxxx.
1646 HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl) {
1647 fprintf(stderr,"SHGetSpecialFolderLocation(%04x,%d,%p),stub!\n",
1648 hwndOwner,nFolder,ppidl
1650 *ppidl = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2*sizeof(ITEMIDLIST));
1651 /* FIXME: we return only the empty ITEMIDLIST currently. */
1652 (*ppidl)->mkid.cb = 0;
1656 /*************************************************************************
1657 * SHGetPathFromIDList [SHELL32.221]
1658 * returns the path from a passed PIDL.
1660 BOOL32 WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath) {
1661 fprintf(stderr,"SHGetPathFromIDList(%p,%p),stub!\n",pidl,pszPath);
1662 lstrcpy32A(pszPath,"E:\\"); /* FIXME */