2 * Shell Library Functions
20 #include "cursoricon.h"
21 #include "interfaces.h"
22 #include "sysmetrics.h"
27 static const char * const SHELL_People[] =
44 "Niels de Carpentier",
51 "Frans van Dorsselaer",
104 "Philippe De Muyter",
117 "Bernhard Rosenkraenzer",
118 "Johannes Ruscheinski",
120 "Constantine Sapuntzakis",
128 "Yngvi Sigurjonsson",
143 "Gregory Trubetskoy",
156 "Karl Guenter Wuensch",
159 "Nikita V. Youshchenko",
162 "Luiz Otavio L. Zorzella",
167 /* .ICO file ICONDIR definitions */
173 BYTE bWidth; /* Width, in pixels, of the image */
174 BYTE bHeight; /* Height, in pixels, of the image */
175 BYTE bColorCount; /* Number of colors in image (0 if >=8bpp) */
176 BYTE bReserved; /* Reserved ( must be 0) */
177 WORD wPlanes; /* Color Planes */
178 WORD wBitCount; /* Bits per pixel */
179 DWORD dwBytesInRes; /* How many bytes in this resource? */
180 DWORD dwImageOffset; /* Where in the file is this image? */
181 } icoICONDIRENTRY, *LPicoICONDIRENTRY;
185 WORD idReserved; /* Reserved (must be 0) */
186 WORD idType; /* Resource Type (1 for icons) */
187 WORD idCount; /* How many images? */
188 icoICONDIRENTRY idEntries[1]; /* An entry for each image (idCount of 'em) */
189 } icoICONDIR, *LPicoICONDIR;
193 static const char* lpstrMsgWndCreated = "OTHERWINDOWCREATED";
194 static const char* lpstrMsgWndDestroyed = "OTHERWINDOWDESTROYED";
195 static const char* lpstrMsgShellActivate = "ACTIVATESHELLWINDOW";
197 static HWND16 SHELL_hWnd = 0;
198 static HHOOK SHELL_hHook = 0;
199 static UINT16 uMsgWndCreated = 0;
200 static UINT16 uMsgWndDestroyed = 0;
201 static UINT16 uMsgShellActivate = 0;
203 /*************************************************************************
204 * DragAcceptFiles [SHELL.9]
206 void WINAPI DragAcceptFiles(HWND16 hWnd, BOOL16 b)
208 WND* wnd = WIN_FindWndPtr(hWnd);
211 wnd->dwExStyle = b? wnd->dwExStyle | WS_EX_ACCEPTFILES
212 : wnd->dwExStyle & ~WS_EX_ACCEPTFILES;
216 /*************************************************************************
217 * DragQueryFile [SHELL.11]
219 UINT16 WINAPI DragQueryFile(HDROP16 hDrop, WORD wFile, LPSTR lpszFile,
222 /* hDrop is a global memory block allocated with GMEM_SHARE
223 * with DROPFILESTRUCT as a header and filenames following
224 * it, zero length filename is in the end */
226 LPDROPFILESTRUCT lpDropFileStruct;
230 TRACE(reg,"(%04x, %i, %p, %u)\n",
231 hDrop,wFile,lpszFile,wLength);
233 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
234 if(!lpDropFileStruct) return 0;
236 lpCurrent = (LPSTR) lpDropFileStruct + lpDropFileStruct->wSize;
241 while (*lpCurrent++); /* skip filename */
243 return (wFile == 0xFFFF) ? i : 0;
246 i = strlen(lpCurrent);
247 if (!lpszFile) return i+1; /* needed buffer size */
249 i = (wLength > i) ? i : wLength-1;
250 strncpy(lpszFile, lpCurrent, i);
253 GlobalUnlock16(hDrop);
258 /*************************************************************************
259 * DragFinish [SHELL.12]
261 void WINAPI DragFinish(HDROP16 h)
263 GlobalFree16((HGLOBAL16)h);
267 /*************************************************************************
268 * DragQueryPoint [SHELL.13]
270 BOOL16 WINAPI DragQueryPoint(HDROP16 hDrop, POINT16 *p)
272 LPDROPFILESTRUCT lpDropFileStruct;
275 lpDropFileStruct = (LPDROPFILESTRUCT) GlobalLock16(hDrop);
277 memcpy(p,&lpDropFileStruct->ptMousePos,sizeof(POINT16));
278 bRet = lpDropFileStruct->fInNonClientArea;
280 GlobalUnlock16(hDrop);
284 /*************************************************************************
285 * SHELL_FindExecutable [Internal]
287 * Utility for code sharing between FindExecutable and ShellExecute
289 static HINSTANCE32 SHELL_FindExecutable( LPCSTR lpFile,
293 char *extension = NULL; /* pointer to file extension */
294 char tmpext[5]; /* local copy to mung as we please */
295 char filetype[256]; /* registry name for this filetype */
296 LONG filetypelen=256; /* length of above */
297 char command[256]; /* command from registry */
298 LONG commandlen=256; /* This is the most DOS can handle :) */
299 char buffer[256]; /* Used to GetProfileString */
300 HINSTANCE32 retval=31; /* default - 'No association was found' */
301 char *tok; /* token pointer */
302 int i; /* random counter */
303 char xlpFile[256]; /* result of SearchPath */
305 TRACE(exec, "%s\n", (lpFile != NULL?lpFile:"-") );
307 lpResult[0]='\0'; /* Start off with an empty return string */
309 /* trap NULL parameters on entry */
310 if (( lpFile == NULL ) || ( lpResult == NULL ) || ( lpOperation == NULL ))
312 WARN(exec, "(lpFile=%s,lpResult=%s,lpOperation=%s): NULL parameter\n",
313 lpFile, lpOperation, lpResult);
314 return 2; /* File not found. Close enough, I guess. */
317 if (SearchPath32A( NULL, lpFile,".exe",sizeof(xlpFile),xlpFile,NULL))
319 TRACE(exec, "SearchPath32A returned non-zero\n");
323 /* First thing we need is the file's extension */
324 extension = strrchr( xlpFile, '.' ); /* Assume last "." is the one; */
325 /* File->Run in progman uses */
327 TRACE(exec, "xlpFile=%s,extension=%s\n", xlpFile, extension);
329 if ((extension == NULL) || (extension == &xlpFile[strlen(xlpFile)]))
331 WARN(exec, "Returning 31 - No association\n");
332 return 31; /* no association */
335 /* Make local copy & lowercase it for reg & 'programs=' lookup */
336 lstrcpyn32A( tmpext, extension, 5 );
337 CharLower32A( tmpext );
338 TRACE(exec, "%s file\n", tmpext);
340 /* Three places to check: */
341 /* 1. win.ini, [windows], programs (NB no leading '.') */
342 /* 2. Registry, HKEY_CLASS_ROOT\<filetype>\shell\open\command */
343 /* 3. win.ini, [extensions], extension (NB no leading '.' */
344 /* All I know of the order is that registry is checked before */
345 /* extensions; however, it'd make sense to check the programs */
346 /* section first, so that's what happens here. */
348 /* See if it's a program - if GetProfileString fails, we skip this
349 * section. Actually, if GetProfileString fails, we've probably
350 * got a lot more to worry about than running a program... */
351 if ( GetProfileString32A("windows", "programs", "exe pif bat com",
352 buffer, sizeof(buffer)) > 0 )
354 for (i=0;i<strlen(buffer); i++) buffer[i]=tolower(buffer[i]);
356 tok = strtok(buffer, " \t"); /* ? */
359 if (strcmp(tok, &tmpext[1])==0) /* have to skip the leading "." */
361 strcpy(lpResult, xlpFile);
362 /* Need to perhaps check that the file has a path
364 TRACE(exec, "found %s\n",
368 /* Greater than 32 to indicate success FIXME According to the
369 * docs, I should be returning a handle for the
370 * executable. Does this mean I'm supposed to open the
371 * executable file or something? More RTFM, I guess... */
373 tok=strtok(NULL, " \t");
378 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, tmpext, filetype,
379 &filetypelen ) == SHELL_ERROR_SUCCESS )
381 filetype[filetypelen]='\0';
382 TRACE(exec, "File type: %s\n",
385 /* Looking for ...buffer\shell\lpOperation\command */
386 strcat( filetype, "\\shell\\" );
387 strcat( filetype, lpOperation );
388 strcat( filetype, "\\command" );
390 if (RegQueryValue16( (HKEY)HKEY_CLASSES_ROOT, filetype, command,
391 &commandlen ) == SHELL_ERROR_SUCCESS )
393 /* Is there a replace() function anywhere? */
394 command[commandlen]='\0';
395 strcpy( lpResult, command );
396 tok=strstr( lpResult, "%1" );
399 tok[0]='\0'; /* truncate string at the percent */
400 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
401 tok=strstr( command, "%1" );
402 if ((tok!=NULL) && (strlen(tok)>2))
404 strcat( lpResult, &tok[2] );
407 retval=33; /* FIXME see above */
410 else /* Check win.ini */
412 /* Toss the leading dot */
414 if ( GetProfileString32A( "extensions", extension, "", command,
415 sizeof(command)) > 0)
417 if (strlen(command)!=0)
419 strcpy( lpResult, command );
420 tok=strstr( lpResult, "^" ); /* should be ^.extension? */
424 strcat( lpResult, xlpFile ); /* what if no dir in xlpFile? */
425 tok=strstr( command, "^" ); /* see above */
426 if ((tok != NULL) && (strlen(tok)>5))
428 strcat( lpResult, &tok[5]);
431 retval=33; /* FIXME - see above */
436 TRACE(exec, "returning %s\n", lpResult);
440 /*************************************************************************
441 * ShellExecute16 [SHELL.20]
443 HINSTANCE16 WINAPI ShellExecute16( HWND16 hWnd, LPCSTR lpOperation,
444 LPCSTR lpFile, LPCSTR lpParameters,
445 LPCSTR lpDirectory, INT16 iShowCmd )
447 HINSTANCE16 retval=31;
451 TRACE(exec, "(%04x,'%s','%s','%s','%s',%x)\n",
452 hWnd, lpOperation ? lpOperation:"<null>", lpFile ? lpFile:"<null>",
453 lpParameters ? lpParameters : "<null>",
454 lpDirectory ? lpDirectory : "<null>", iShowCmd);
456 if (lpFile==NULL) return 0; /* should not happen */
457 if (lpOperation==NULL) /* default is open */
462 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
463 SetCurrentDirectory32A( lpDirectory );
466 retval = SHELL_FindExecutable( lpFile, lpOperation, cmd );
468 if (retval > 32) /* Found */
473 strcat(cmd,lpParameters);
476 TRACE(exec,"starting %s\n",cmd);
477 retval = WinExec32( cmd, iShowCmd );
479 if (lpDirectory) SetCurrentDirectory32A( old_dir );
484 /*************************************************************************
485 * ShellExecute32A (SHELL32.245)
487 HINSTANCE32 WINAPI ShellExecute32A( HWND32 hWnd, LPCSTR lpOperation,
488 LPCSTR lpFile, LPCSTR lpParameters,
489 LPCSTR lpDirectory, INT32 iShowCmd )
491 return ShellExecute16( hWnd, lpOperation, lpFile, lpParameters,
492 lpDirectory, iShowCmd );
496 /*************************************************************************
497 * FindExecutable16 (SHELL.21)
499 HINSTANCE16 WINAPI FindExecutable16( LPCSTR lpFile, LPCSTR lpDirectory,
502 return (HINSTANCE16)FindExecutable32A( lpFile, lpDirectory, lpResult );
505 /*************************************************************************
506 * FindExecutable32A (SHELL32.184)
508 HINSTANCE32 WINAPI FindExecutable32A( LPCSTR lpFile, LPCSTR lpDirectory,
511 HINSTANCE32 retval=31; /* default - 'No association was found' */
514 TRACE(exec, "File %s, Dir %s\n",
515 (lpFile != NULL?lpFile:"-"),
516 (lpDirectory != NULL?lpDirectory:"-"));
518 lpResult[0]='\0'; /* Start off with an empty return string */
520 /* trap NULL parameters on entry */
521 if (( lpFile == NULL ) || ( lpResult == NULL ))
523 /* FIXME - should throw a warning, perhaps! */
524 return 2; /* File not found. Close enough, I guess. */
529 GetCurrentDirectory32A( sizeof(old_dir), old_dir );
530 SetCurrentDirectory32A( lpDirectory );
533 retval = SHELL_FindExecutable( lpFile, "open", lpResult );
535 TRACE(exec, "returning %s\n", lpResult);
536 if (lpDirectory) SetCurrentDirectory32A( old_dir );
547 #define IDC_STATIC_TEXT 100
548 #define IDC_LISTBOX 99
549 #define IDC_WINE_TEXT 98
551 #define DROP_FIELD_TOP (-15)
552 #define DROP_FIELD_HEIGHT 15
554 extern HICON32 hIconTitleFont;
556 static BOOL32 __get_dropline( HWND32 hWnd, LPRECT32 lprect )
558 HWND32 hWndCtl = GetDlgItem32(hWnd, IDC_WINE_TEXT);
561 GetWindowRect32( hWndCtl, lprect );
562 MapWindowPoints32( 0, hWnd, (LPPOINT32)lprect, 2 );
563 lprect->bottom = (lprect->top += DROP_FIELD_TOP);
569 /*************************************************************************
570 * AboutDlgProc32 (not an exported API function)
572 LRESULT WINAPI AboutDlgProc32( HWND32 hWnd, UINT32 msg, WPARAM32 wParam,
576 char Template[512], AppTitle[512];
582 ABOUT_INFO *info = (ABOUT_INFO *)lParam;
585 const char* const *pstr = SHELL_People;
586 SendDlgItemMessage32A(hWnd, stc1, STM_SETICON32,info->hIcon, 0);
587 GetWindowText32A( hWnd, Template, sizeof(Template) );
588 sprintf( AppTitle, Template, info->szApp );
589 SetWindowText32A( hWnd, AppTitle );
590 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT),
591 info->szOtherStuff );
592 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
593 SendMessage32A( hWndCtl, WM_SETREDRAW, 0, 0 );
594 SendMessage32A( hWndCtl, WM_SETFONT, hIconTitleFont, 0 );
597 SendMessage32A( hWndCtl, LB_ADDSTRING32,
598 (WPARAM32)-1, (LPARAM)*pstr );
601 SendMessage32A( hWndCtl, WM_SETREDRAW, 1, 0 );
610 HDC32 hDC = BeginPaint32( hWnd, &ps );
612 if( __get_dropline( hWnd, &rect ) )
613 GRAPH_DrawLines( hDC, (LPPOINT32)&rect, 1, GetStockObject32( BLACK_PEN ) );
614 EndPaint32( hWnd, &ps );
618 case WM_LBTRACKPOINT:
620 hWndCtl = GetDlgItem32(hWnd, IDC_LISTBOX);
621 if( (INT16)GetKeyState16( VK_CONTROL ) < 0 )
623 if( DragDetect32( hWndCtl, *((LPPOINT32)&lParam) ) )
625 INT32 idx = SendMessage32A( hWndCtl, LB_GETCURSEL32, 0, 0 );
628 INT32 length = SendMessage32A( hWndCtl, LB_GETTEXTLEN32, (WPARAM32)idx, 0 );
629 HGLOBAL16 hMemObj = GlobalAlloc16( GMEM_MOVEABLE, length + 1 );
630 char* pstr = (char*)GlobalLock16( hMemObj );
634 HCURSOR16 hCursor = LoadCursor16( 0, MAKEINTRESOURCE16(OCR_DRAGOBJECT) );
635 SendMessage32A( hWndCtl, LB_GETTEXT32, (WPARAM32)idx, (LPARAM)pstr );
636 SendMessage32A( hWndCtl, LB_DELETESTRING32, (WPARAM32)idx, 0 );
637 UpdateWindow32( hWndCtl );
638 if( !DragObject16((HWND16)hWnd, (HWND16)hWnd, DRAGOBJ_DATA, 0, (WORD)hMemObj, hCursor) )
639 SendMessage32A( hWndCtl, LB_ADDSTRING32, (WPARAM32)-1, (LPARAM)pstr );
641 if( hMemObj ) GlobalFree16( hMemObj );
647 case WM_QUERYDROPOBJECT:
650 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
651 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA )
654 if( __get_dropline( hWnd, &rect ) )
656 POINT32 pt = { lpDragInfo->pt.x, lpDragInfo->pt.y };
657 rect.bottom += DROP_FIELD_HEIGHT;
658 if( PtInRect32( &rect, pt ) )
660 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
671 LPDRAGINFO lpDragInfo = (LPDRAGINFO)PTR_SEG_TO_LIN((SEGPTR)lParam);
672 if( lpDragInfo && lpDragInfo->wFlags == DRAGOBJ_DATA && lpDragInfo->hList )
674 char* pstr = (char*)GlobalLock16( (HGLOBAL16)(lpDragInfo->hList) );
677 static char __appendix_str[] = " with";
679 hWndCtl = GetDlgItem32( hWnd, IDC_WINE_TEXT );
680 SendMessage32A( hWndCtl, WM_GETTEXT, 512, (LPARAM)Template );
681 if( !lstrncmp32A( Template, "WINE", 4 ) )
682 SetWindowText32A( GetDlgItem32(hWnd, IDC_STATIC_TEXT), Template );
685 char* pch = Template + strlen(Template) - strlen(__appendix_str);
687 SendMessage32A( GetDlgItem32(hWnd, IDC_LISTBOX), LB_ADDSTRING32,
688 (WPARAM32)-1, (LPARAM)Template );
691 lstrcpy32A( Template, pstr );
692 lstrcat32A( Template, __appendix_str );
693 SetWindowText32A( hWndCtl, Template );
695 SetWindowLong32A( hWnd, DWL_MSGRESULT, 1 );
705 EndDialog32(hWnd, TRUE);
714 /*************************************************************************
715 * AboutDlgProc16 (SHELL.33)
717 LRESULT WINAPI AboutDlgProc16( HWND16 hWnd, UINT16 msg, WPARAM16 wParam,
720 return AboutDlgProc32( hWnd, msg, wParam, lParam );
724 /*************************************************************************
725 * ShellAbout16 (SHELL.22)
727 BOOL16 WINAPI ShellAbout16( HWND16 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
730 return ShellAbout32A( hWnd, szApp, szOtherStuff, hIcon );
733 /*************************************************************************
734 * ShellAbout32A (SHELL32.243)
736 BOOL32 WINAPI ShellAbout32A( HWND32 hWnd, LPCSTR szApp, LPCSTR szOtherStuff,
741 info.szOtherStuff = szOtherStuff;
743 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
744 return DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
745 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
746 hWnd, AboutDlgProc32, (LPARAM)&info );
750 /*************************************************************************
751 * ShellAbout32W (SHELL32.244)
753 BOOL32 WINAPI ShellAbout32W( HWND32 hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff,
759 info.szApp = HEAP_strdupWtoA( GetProcessHeap(), 0, szApp );
760 info.szOtherStuff = HEAP_strdupWtoA( GetProcessHeap(), 0, szOtherStuff );
762 if (!hIcon) info.hIcon = LoadIcon16( 0, MAKEINTRESOURCE16(OIC_WINEICON) );
763 ret = DialogBoxIndirectParam32A( WIN_GetWindowInstance( hWnd ),
764 SYSRES_GetResPtr( SYSRES_DIALOG_SHELL_ABOUT_MSGBOX ),
765 hWnd, AboutDlgProc32, (LPARAM)&info );
766 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szApp );
767 HeapFree( GetProcessHeap(), 0, (LPSTR)info.szOtherStuff );
771 /*************************************************************************
772 * Shell_NotifyIcon [SHELL32.249]
774 * This function is supposed to deal with the systray.
775 * Any ideas on how this is to be implimented?
777 BOOL32 WINAPI Shell_NotifyIcon( DWORD dwMessage,
778 PNOTIFYICONDATA pnid )
783 /*************************************************************************
784 * Shell_NotifyIcon [SHELL32.240]
786 * This function is supposed to deal with the systray.
787 * Any ideas on how this is to be implimented?
789 BOOL32 WINAPI Shell_NotifyIconA(DWORD dwMessage,
790 PNOTIFYICONDATA pnid )
795 /*************************************************************************
796 * SHELL_GetResourceTable
798 static DWORD SHELL_GetResourceTable(HFILE32 hFile,LPBYTE *retptr)
800 IMAGE_DOS_HEADER mz_header;
805 _llseek32( hFile, 0, SEEK_SET );
806 if ( (_lread32(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
807 (mz_header.e_magic != IMAGE_DOS_SIGNATURE)
808 ) { /* .ICO file ? */
809 if (mz_header.e_cblp == 1) { /* ICONHEADER.idType, must be 1 */
810 *retptr = (LPBYTE)-1;
814 return 0; /* failed */
816 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET );
817 if (_lread32( hFile, magic, sizeof(magic) ) != sizeof(magic))
819 _llseek32( hFile, mz_header.e_lfanew, SEEK_SET);
821 if (*(DWORD*)magic == IMAGE_NT_SIGNATURE)
822 return IMAGE_NT_SIGNATURE;
823 if (*(WORD*)magic == IMAGE_OS2_SIGNATURE) {
824 IMAGE_OS2_HEADER ne_header;
825 LPBYTE pTypeInfo = (LPBYTE)-1;
827 if (_lread32(hFile,&ne_header,sizeof(ne_header))!=sizeof(ne_header))
830 if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return 0;
831 size = ne_header.rname_tab_offset - ne_header.resource_tab_offset;
832 if( size > sizeof(NE_TYPEINFO) )
834 pTypeInfo = (BYTE*)HeapAlloc( GetProcessHeap(), 0, size);
836 _llseek32(hFile, mz_header.e_lfanew+ne_header.resource_tab_offset, SEEK_SET);
837 if( _lread32( hFile, (char*)pTypeInfo, size) != size ) {
838 HeapFree( GetProcessHeap(), 0, pTypeInfo);
844 return IMAGE_OS2_SIGNATURE;
846 return 0; /* failed */
849 /*************************************************************************
852 static HGLOBAL16 SHELL_LoadResource(HINSTANCE16 hInst, HFILE32 hFile, NE_NAMEINFO* pNInfo, WORD sizeShift)
855 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, (DWORD)pNInfo->length << sizeShift);
857 if( (ptr = (BYTE*)GlobalLock16( handle )) )
859 _llseek32( hFile, (DWORD)pNInfo->offset << sizeShift, SEEK_SET);
860 _lread32( hFile, (char*)ptr, pNInfo->length << sizeShift);
866 /*************************************************************************
869 static HGLOBAL16 ICO_LoadIcon(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIRENTRY lpiIDE)
872 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10, lpiIDE->dwBytesInRes);
874 if( (ptr = (BYTE*)GlobalLock16( handle )) )
876 _llseek32( hFile, lpiIDE->dwImageOffset, SEEK_SET);
877 _lread32( hFile, (char*)ptr, lpiIDE->dwBytesInRes);
883 /*************************************************************************
884 * ICO_GetIconDirectory
886 * Read .ico file and build phony ICONDIR struct for GetIconID
888 static HGLOBAL16 ICO_GetIconDirectory(HINSTANCE16 hInst, HFILE32 hFile, LPicoICONDIR* lplpiID )
890 WORD id[3]; /* idReserved, idType, idCount */
894 _llseek32( hFile, 0, SEEK_SET );
895 if( _lread32(hFile,(char*)id,sizeof(id)) != sizeof(id) ) return 0;
899 * - see http://www.microsoft.com/win32dev/ui/icons.htm
902 if( id[0] || id[1] != 1 || !id[2] ) return 0;
904 i = id[2]*sizeof(icoICONDIRENTRY) + sizeof(id);
906 lpiID = (LPicoICONDIR)HeapAlloc( GetProcessHeap(), 0, i);
908 if( _lread32(hFile,(char*)lpiID->idEntries,i) == i )
910 HGLOBAL16 handle = DirectResAlloc( hInst, 0x10,
911 id[2]*sizeof(ICONDIRENTRY) + sizeof(id) );
914 CURSORICONDIR* lpID = (CURSORICONDIR*)GlobalLock16( handle );
915 lpID->idReserved = lpiID->idReserved = id[0];
916 lpID->idType = lpiID->idType = id[1];
917 lpID->idCount = lpiID->idCount = id[2];
918 for( i=0; i < lpiID->idCount; i++ )
920 memcpy((void*)(lpID->idEntries + i),
921 (void*)(lpiID->idEntries + i), sizeof(ICONDIRENTRY) - 2);
922 lpID->idEntries[i].icon.wResId = i;
930 HeapFree( GetProcessHeap(), 0, lpiID);
934 /*************************************************************************
935 * InternalExtractIcon [SHELL.39]
937 * This abortion is called directly by Progman
939 HGLOBAL16 WINAPI InternalExtractIcon(HINSTANCE16 hInstance,
940 LPCSTR lpszExeFileName, UINT16 nIconIndex,
944 HGLOBAL16* RetPtr = NULL;
948 HFILE32 hFile = OpenFile32( lpszExeFileName, &ofs, OF_READ );
949 UINT16 iconDirCount = 0,iconCount = 0;
951 TRACE(reg,"(%04x,file %s,start %d,extract %d\n",
952 hInstance, lpszExeFileName, nIconIndex, n);
954 if( hFile == HFILE_ERROR32 || !n ) return 0;
956 hRet = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, sizeof(HICON16)*n);
957 RetPtr = (HICON16*)GlobalLock16(hRet);
959 *RetPtr = (n == 0xFFFF)? 0: 1; /* error return values */
961 sig = SHELL_GetResourceTable(hFile,&pData);
963 if((sig == IMAGE_OS2_SIGNATURE)
964 || (sig == 1)) /* .ICO file */
967 NE_TYPEINFO* pTInfo = (NE_TYPEINFO*)(pData + 2);
968 NE_NAMEINFO* pIconStorage = NULL;
969 NE_NAMEINFO* pIconDir = NULL;
970 LPicoICONDIR lpiID = NULL;
972 if( pData == (BYTE*)-1 )
974 /* check for .ICO file */
976 hIcon = ICO_GetIconDirectory(hInstance, hFile, &lpiID);
977 if( hIcon ) { iconDirCount = 1; iconCount = lpiID->idCount; }
979 else while( pTInfo->type_id && !(pIconStorage && pIconDir) )
981 /* find icon directory and icon repository */
983 if( pTInfo->type_id == NE_RSCTYPE_GROUP_ICON )
985 iconDirCount = pTInfo->count;
986 pIconDir = ((NE_NAMEINFO*)(pTInfo + 1));
987 TRACE(reg,"\tfound directory - %i icon families\n", iconDirCount);
989 if( pTInfo->type_id == NE_RSCTYPE_ICON )
991 iconCount = pTInfo->count;
992 pIconStorage = ((NE_NAMEINFO*)(pTInfo + 1));
993 TRACE(reg,"\ttotal icons - %i\n", iconCount);
995 pTInfo = (NE_TYPEINFO *)((char*)(pTInfo+1)+pTInfo->count*sizeof(NE_NAMEINFO));
998 /* load resources and create icons */
1000 if( (pIconStorage && pIconDir) || lpiID )
1001 if( nIconIndex == (UINT16)-1 ) RetPtr[0] = iconDirCount;
1002 else if( nIconIndex < iconDirCount )
1006 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
1008 for( i = nIconIndex; i < nIconIndex + n; i++ )
1010 /* .ICO files have only one icon directory */
1013 hIcon = SHELL_LoadResource( hInstance, hFile, pIconDir + i,
1015 RetPtr[i-nIconIndex] = GetIconID( hIcon, 3 );
1016 GlobalFree16(hIcon);
1019 for( icon = nIconIndex; icon < nIconIndex + n; icon++ )
1023 hIcon = ICO_LoadIcon( hInstance, hFile,
1024 lpiID->idEntries + RetPtr[icon-nIconIndex]);
1026 for( i = 0; i < iconCount; i++ )
1027 if( pIconStorage[i].id == (RetPtr[icon-nIconIndex] | 0x8000) )
1028 hIcon = SHELL_LoadResource( hInstance, hFile, pIconStorage + i,
1032 RetPtr[icon-nIconIndex] = LoadIconHandler( hIcon, TRUE );
1033 FarSetOwner( RetPtr[icon-nIconIndex], GetExePtr(hInstance) );
1036 RetPtr[icon-nIconIndex] = 0;
1039 if( lpiID ) HeapFree( GetProcessHeap(), 0, lpiID);
1040 else HeapFree( GetProcessHeap(), 0, pData);
1042 if( sig == IMAGE_NT_SIGNATURE)
1044 LPBYTE peimage,idata,igdata;
1045 LPIMAGE_DOS_HEADER dheader;
1046 LPIMAGE_NT_HEADERS pe_header;
1047 LPIMAGE_SECTION_HEADER pe_sections;
1048 LPIMAGE_RESOURCE_DIRECTORY rootresdir,iconresdir,icongroupresdir;
1049 LPIMAGE_RESOURCE_DATA_ENTRY idataent,igdataent;
1052 LPIMAGE_RESOURCE_DIRECTORY_ENTRY xresent;
1053 CURSORICONDIR **cids;
1055 fmapping = CreateFileMapping32A(hFile,NULL,PAGE_READONLY|SEC_COMMIT,0,0,NULL);
1056 if (fmapping == 0) { /* FIXME, INVALID_HANDLE_VALUE? */
1057 WARN(reg,"failed to create filemap.\n");
1061 peimage = MapViewOfFile(fmapping,FILE_MAP_READ,0,0,0);
1063 WARN(reg,"failed to mmap filemap.\n");
1064 CloseHandle(fmapping);
1068 dheader = (LPIMAGE_DOS_HEADER)peimage;
1069 /* it is a pe header, SHELL_GetResourceTable checked that */
1070 pe_header = (LPIMAGE_NT_HEADERS)(peimage+dheader->e_lfanew);
1071 /* probably makes problems with short PE headers... but I haven't seen
1074 pe_sections = (LPIMAGE_SECTION_HEADER)(((char*)pe_header)+sizeof(*pe_header));
1076 for (i=0;i<pe_header->FileHeader.NumberOfSections;i++) {
1077 if (pe_sections[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
1079 /* FIXME: doesn't work when the resources are not in a seperate section */
1080 if (pe_sections[i].VirtualAddress == pe_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress) {
1081 rootresdir = (LPIMAGE_RESOURCE_DIRECTORY)((char*)peimage+pe_sections[i].PointerToRawData);
1087 WARN(reg,"haven't found section for resource directory.\n");
1088 UnmapViewOfFile(peimage);
1089 CloseHandle(fmapping);
1093 icongroupresdir = GetResDirEntryW(rootresdir,RT_GROUP_ICON32W,
1094 (DWORD)rootresdir,FALSE);
1095 if (!icongroupresdir) {
1096 WARN(reg,"No Icongroupresourcedirectory!\n");
1097 UnmapViewOfFile(peimage);
1098 CloseHandle(fmapping);
1103 iconDirCount = icongroupresdir->NumberOfNamedEntries+icongroupresdir->NumberOfIdEntries;
1104 if( nIconIndex == (UINT16)-1 ) {
1105 RetPtr[0] = iconDirCount;
1106 UnmapViewOfFile(peimage);
1107 CloseHandle(fmapping);
1112 if (nIconIndex >= iconDirCount) {
1113 WARN(reg,"nIconIndex %d is larger than iconDirCount %d\n",
1114 nIconIndex,iconDirCount);
1115 UnmapViewOfFile(peimage);
1116 CloseHandle(fmapping);
1121 cids = (CURSORICONDIR**)HeapAlloc(GetProcessHeap(),0,n*sizeof(CURSORICONDIR*));
1123 /* caller just wanted the number of entries */
1125 xresent = (LPIMAGE_RESOURCE_DIRECTORY_ENTRY)(icongroupresdir+1);
1126 /* assure we don't get too much ... */
1127 if( n > iconDirCount - nIconIndex ) n = iconDirCount - nIconIndex;
1129 /* starting from specified index ... */
1130 xresent = xresent+nIconIndex;
1132 for (i=0;i<n;i++,xresent++) {
1134 LPIMAGE_RESOURCE_DIRECTORY resdir;
1136 /* go down this resource entry, name */
1137 resdir = (LPIMAGE_RESOURCE_DIRECTORY)((DWORD)rootresdir+(xresent->u2.s.OffsetToDirectory));
1138 /* default language (0) */
1139 resdir = GetResDirEntryW(resdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1140 igdataent = (LPIMAGE_RESOURCE_DATA_ENTRY)resdir;
1142 /* lookup address in mapped image for virtual address */
1144 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1145 if (igdataent->OffsetToData < pe_sections[j].VirtualAddress)
1147 if (igdataent->OffsetToData+igdataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1149 igdata = peimage+(igdataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1152 WARN(reg,"no matching real address for icongroup!\n");
1153 UnmapViewOfFile(peimage);
1154 CloseHandle(fmapping);
1159 cid = (CURSORICONDIR*)igdata;
1161 RetPtr[i] = LookupIconIdFromDirectoryEx32(igdata,TRUE,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1163 iconresdir=GetResDirEntryW(rootresdir,RT_ICON32W,
1164 (DWORD)rootresdir,FALSE);
1166 WARN(reg,"No Iconresourcedirectory!\n");
1167 UnmapViewOfFile(peimage);
1168 CloseHandle(fmapping);
1173 LPIMAGE_RESOURCE_DIRECTORY xresdir;
1175 xresdir = GetResDirEntryW(iconresdir,(LPWSTR)RetPtr[i],(DWORD)rootresdir,FALSE);
1176 xresdir = GetResDirEntryW(xresdir,(LPWSTR)0,(DWORD)rootresdir,TRUE);
1178 idataent = (LPIMAGE_RESOURCE_DATA_ENTRY)xresdir;
1181 /* map virtual to address in image */
1182 for (j=0;j<pe_header->FileHeader.NumberOfSections;j++) {
1183 if (idataent->OffsetToData < pe_sections[j].VirtualAddress)
1185 if (idataent->OffsetToData+idataent->Size > pe_sections[j].VirtualAddress+pe_sections[j].SizeOfRawData)
1187 idata = peimage+(idataent->OffsetToData-pe_sections[j].VirtualAddress+pe_sections[j].PointerToRawData);
1190 WARN(reg,"no matching real address found for icondata!\n");
1194 RetPtr[i] = CreateIconFromResourceEx32(idata,idataent->Size,TRUE,0x00030000,SYSMETRICS_CXICON,SYSMETRICS_CYICON,0);
1196 UnmapViewOfFile(peimage);
1197 CloseHandle(fmapping);
1202 /* return array with icon handles */
1207 /*************************************************************************
1208 * ExtractIcon16 (SHELL.34)
1210 HICON16 WINAPI ExtractIcon16( HINSTANCE16 hInstance, LPCSTR lpszExeFileName,
1213 return ExtractIcon32A( hInstance, lpszExeFileName, nIconIndex );
1217 /*************************************************************************
1218 * ExtractIcon32A (SHELL32.133)
1220 HICON32 WINAPI ExtractIcon32A( HINSTANCE32 hInstance, LPCSTR lpszExeFileName,
1223 HGLOBAL16 handle = InternalExtractIcon(hInstance,lpszExeFileName,nIconIndex, 1);
1227 HICON16* ptr = (HICON16*)GlobalLock16(handle);
1228 HICON16 hIcon = *ptr;
1230 GlobalFree16(handle);
1236 /*************************************************************************
1237 * ExtractIcon32W (SHELL32.180)
1239 HICON32 WINAPI ExtractIcon32W( HINSTANCE32 hInstance, LPCWSTR lpszExeFileName,
1242 LPSTR exefn = HEAP_strdupWtoA(GetProcessHeap(),0,lpszExeFileName);
1243 HICON32 ret = ExtractIcon32A(hInstance,exefn,nIconIndex);
1245 HeapFree(GetProcessHeap(),0,exefn);
1250 /*************************************************************************
1251 * ExtractAssociatedIcon [SHELL.36]
1253 * Return icon for given file (either from file itself or from associated
1254 * executable) and patch parameters if needed.
1256 HICON32 WINAPI ExtractAssociatedIcon32A(HINSTANCE32 hInst,LPSTR lpIconPath,
1259 return ExtractAssociatedIcon16(hInst,lpIconPath,lpiIcon);
1262 HICON16 WINAPI ExtractAssociatedIcon16(HINSTANCE16 hInst,LPSTR lpIconPath,
1265 HICON16 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1270 if( hIcon == 1 ) /* no icons found in given file */
1272 char tempPath[0x80];
1273 UINT16 uRet = FindExecutable16(lpIconPath,NULL,tempPath);
1275 if( uRet > 32 && tempPath[0] )
1277 strcpy(lpIconPath,tempPath);
1278 hIcon = ExtractIcon16(hInst, lpIconPath, *lpiIcon);
1280 if( hIcon > 2 ) return hIcon;
1286 *lpiIcon = 2; /* MSDOS icon - we found .exe but no icons in it */
1288 *lpiIcon = 6; /* generic icon - found nothing */
1290 GetModuleFileName16(hInst, lpIconPath, 0x80);
1291 hIcon = LoadIcon16( hInst, MAKEINTRESOURCE16(*lpiIcon));
1297 /*************************************************************************
1298 * FindEnvironmentString [SHELL.38]
1300 * Returns a pointer into the DOS environment... Ugh.
1302 LPSTR SHELL_FindString(LPSTR lpEnv, LPCSTR entry)
1304 UINT16 l = strlen(entry);
1305 for( ; *lpEnv ; lpEnv+=strlen(lpEnv)+1 )
1307 if( lstrncmpi32A(lpEnv, entry, l) ) continue;
1310 return (lpEnv + l); /* empty entry */
1311 else if ( *(lpEnv+l)== '=' )
1312 return (lpEnv + l + 1);
1317 SEGPTR WINAPI FindEnvironmentString(LPSTR str)
1319 SEGPTR spEnv = GetDOSEnvironment();
1320 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(spEnv);
1322 LPSTR lpString = (spEnv)?SHELL_FindString(lpEnv, str):NULL;
1324 if( lpString ) /* offset should be small enough */
1325 return spEnv + (lpString - lpEnv);
1327 return (SEGPTR)NULL;
1330 /*************************************************************************
1331 * DoEnvironmentSubst [SHELL.37]
1333 * Replace %KEYWORD% in the str with the value of variable KEYWORD
1334 * from "DOS" environment.
1336 DWORD WINAPI DoEnvironmentSubst(LPSTR str,WORD length)
1338 LPSTR lpEnv = (LPSTR)PTR_SEG_TO_LIN(GetDOSEnvironment());
1339 LPSTR lpBuffer = (LPSTR)HeapAlloc( GetProcessHeap(), 0, length);
1341 LPSTR lpbstr = lpBuffer;
1343 CharToOem32A(str,str);
1345 TRACE(reg,"accept %s\n", str);
1347 while( *lpstr && lpbstr - lpBuffer < length )
1349 LPSTR lpend = lpstr;
1353 do { lpend++; } while( *lpend && *lpend != '%' );
1354 if( *lpend == '%' && lpend - lpstr > 1 ) /* found key */
1358 lpKey = SHELL_FindString(lpEnv, lpstr+1);
1359 if( lpKey ) /* found key value */
1361 int l = strlen(lpKey);
1363 if( l > length - (lpbstr - lpBuffer) - 1 )
1365 WARN(reg,"Env subst aborted - string too short\n");
1369 strcpy(lpbstr, lpKey);
1376 else break; /* back off and whine */
1381 *lpbstr++ = *lpstr++;
1385 if( lpstr - str == strlen(str) )
1387 strncpy(str, lpBuffer, length);
1393 TRACE(reg," return %s\n", str);
1395 OemToChar32A(str,str);
1396 HeapFree( GetProcessHeap(), 0, lpBuffer);
1398 /* Return str length in the LOWORD
1399 * and 1 in HIWORD if subst was successful.
1401 return (DWORD)MAKELONG(strlen(str), length);
1404 /*************************************************************************
1405 * ShellHookProc [SHELL.103]
1406 * System-wide WH_SHELL hook.
1408 LRESULT WINAPI ShellHookProc(INT16 code, WPARAM16 wParam, LPARAM lParam)
1410 TRACE(reg,"%i, %04x, %08x\n", code, wParam,
1412 if( SHELL_hHook && SHELL_hWnd )
1417 case HSHELL_WINDOWCREATED: uMsg = uMsgWndCreated; break;
1418 case HSHELL_WINDOWDESTROYED: uMsg = uMsgWndDestroyed; break;
1419 case HSHELL_ACTIVATESHELLWINDOW: uMsg = uMsgShellActivate;
1421 PostMessage16( SHELL_hWnd, uMsg, wParam, 0 );
1423 return CallNextHookEx16( WH_SHELL, code, wParam, lParam );
1426 /*************************************************************************
1427 * RegisterShellHook [SHELL.102]
1429 BOOL32 WINAPI RegisterShellHook(HWND16 hWnd, UINT16 uAction)
1431 TRACE(reg,"%04x [%u]\n", hWnd, uAction );
1435 case 2: /* register hWnd as a shell window */
1439 HMODULE16 hShell = GetModuleHandle16( "SHELL" );
1441 SHELL_hHook = SetWindowsHookEx16( WH_SHELL, ShellHookProc,
1445 uMsgWndCreated = RegisterWindowMessage32A( lpstrMsgWndCreated );
1446 uMsgWndDestroyed = RegisterWindowMessage32A( lpstrMsgWndDestroyed );
1447 uMsgShellActivate = RegisterWindowMessage32A( lpstrMsgShellActivate );
1449 else WARN(reg, "unable to install ShellHookProc()!\n");
1452 if( SHELL_hHook ) return ((SHELL_hWnd = hWnd) != 0);
1457 WARN(reg, "unknown code %i\n", uAction );
1467 /*************************************************************************
1468 * SHGetFileInfoA [SHELL32.218]
1470 DWORD WINAPI SHGetFileInfo32A(LPCSTR path,DWORD dwFileAttributes,
1471 SHFILEINFO32A *psfi, UINT32 sizeofpsfi,
1474 FIXME(shell,"(%s,0x%08lx,%p,%d,0x%08x): stub\n",
1475 path,dwFileAttributes,psfi,sizeofpsfi,flags);
1479 /*************************************************************************
1480 * SHAppBarMessage32 [SHELL32.207]
1482 UINT32 WINAPI SHAppBarMessage32(DWORD msg, PAPPBARDATA data)
1484 FIXME(shell,"(0x%08lx,%p): stub\n", msg, data);
1488 case ABM_GETAUTOHIDEBAR:
1490 case ABM_GETTASKBARPOS:
1494 case ABM_SETAUTOHIDEBAR:
1496 case ABM_WINDOWPOSCHANGED:
1503 /*************************************************************************
1504 * CommandLineToArgvW [SHELL32.7]
1506 LPWSTR* WINAPI CommandLineToArgvW(LPWSTR cmdline,LPDWORD numargs)
1511 /* to get writeable copy */
1512 cmdline = HEAP_strdupW( GetProcessHeap(), 0, cmdline);
1519 while (*s && *s==0x0020)
1525 argv=(LPWSTR*)HeapAlloc( GetProcessHeap(), 0, sizeof(LPWSTR)*(i+1) );
1531 argv[i++]=HEAP_strdupW( GetProcessHeap(), 0, t );
1533 while (*s && *s==0x0020)
1544 argv[i++]=(LPWSTR)HEAP_strdupW( GetProcessHeap(), 0, t );
1545 HeapFree( GetProcessHeap(), 0, cmdline );
1551 /*************************************************************************
1552 * Control_RunDLL [SHELL32.12]
1554 * Wild speculation in the following!
1556 * http://premium.microsoft.com/msdn/library/techart/msdn193.htm
1559 void WINAPI Control_RunDLL (HWND32 hwnd, LPCVOID code, LPCSTR cmd, DWORD arg4)
1561 TRACE(exec, "(%08x, %p, \"%s\", %08lx)\n",
1562 hwnd, code ? code : "(null)", cmd ? cmd : "(null)", arg4);
1565 /*************************************************************************
1568 void WINAPI FreeIconList( DWORD dw )
1570 FIXME(reg, "empty stub\n" );
1573 /*************************************************************************
1574 * SHELL32_DllGetClassObject [SHELL32.14]
1576 * http://premium.microsoft.com/msdn/library/sdkdoc/api2_48fo.htm
1578 DWORD WINAPI SHELL32_DllGetClassObject(REFCLSID rclsid,REFIID iid,LPVOID *ppv)
1580 char xclsid[50],xiid[50];
1581 HRESULT hres = E_OUTOFMEMORY;
1584 WINE_StringFromCLSID((LPCLSID)rclsid,xclsid);
1585 WINE_StringFromCLSID((LPCLSID)iid,xiid);
1586 TRACE(shell,"(%s,%s,%p)\n",xclsid,xiid,ppv);
1589 /* SDK example code looks like this:
1591 HRESULT hres = E_OUTOFMEMORY;
1594 CClassFactory *pClassFactory = new CClassFactory(rclsid);
1596 if (pClassFactory) {
1597 hRes = pClassFactory->QueryInterface(riid,ppv);
1598 pClassFactory->Release();
1602 * The magic of the whole stuff is still unclear to me, so just hack together
1606 if (!memcmp(rclsid,&CLSID_ShellDesktop,sizeof(CLSID_ShellDesktop))) {
1607 TRACE(shell," requested CLSID_ShellDesktop, creating it.\n");
1608 *ppv = IShellFolder_Constructor();
1609 FIXME(shell,"Initialize this folder to be the shell desktop folder\n");
1613 FIXME(shell, " -> clsid not found. returning E_OUTOFMEMORY.\n");
1617 /*************************************************************************
1618 * SHGetDesktopFolder [SHELL32.216]
1619 * returns the interface to the shell desktop folder.
1621 * [SDK header win95/shlobj.h: This is equivalent to call CoCreateInstance with
1622 * CLSID_ShellDesktop.
1624 * CoCreateInstance(CLSID_Desktop, NULL,
1625 * CLSCTX_INPROC, IID_IShellFolder, &pshf);
1627 * So what we are doing is currently wrong....
1629 DWORD WINAPI SHGetDesktopFolder(LPSHELLFOLDER *shellfolder) {
1630 *shellfolder = IShellFolder_Constructor();
1634 /*************************************************************************
1635 * SHGetMalloc [SHELL32.220]
1636 * returns the interface to shell malloc.
1638 * [SDK header win95/shlobj.h:
1639 * equivalent to: #define SHGetMalloc(ppmem) CoGetMalloc(MEMCTX_TASK, ppmem)
1641 * What we are currently doing is not very wrong, since we always use the same
1642 * heap (ProcessHeap).
1644 DWORD WINAPI SHGetMalloc(LPMALLOC32 *lpmal) {
1645 TRACE(shell,"(%p)\n", lpmal);
1646 return CoGetMalloc32(0,lpmal);
1649 /*************************************************************************
1650 * SHGetSpecialFolderLocation [SHELL32.223]
1651 * returns the PIDL of a special folder
1653 * nFolder is a CSIDL_xxxxx.
1655 HRESULT WINAPI SHGetSpecialFolderLocation(HWND32 hwndOwner, INT32 nFolder, LPITEMIDLIST * ppidl) {
1656 FIXME(shell,"(%04x,%d,%p),stub!\n", hwndOwner,nFolder,ppidl);
1657 *ppidl = (LPITEMIDLIST)HeapAlloc(GetProcessHeap(),0,2*sizeof(ITEMIDLIST));
1658 FIXME(shell, "we return only the empty ITEMIDLIST currently.\n");
1659 (*ppidl)->mkid.cb = 0;
1663 /*************************************************************************
1664 * SHGetPathFromIDList [SHELL32.221]
1665 * returns the path from a passed PIDL.
1667 BOOL32 WINAPI SHGetPathFromIDList(LPCITEMIDLIST pidl,LPSTR pszPath) {
1668 FIXME(shell,"(%p,%p),stub!\n",pidl,pszPath);
1669 lstrcpy32A(pszPath,"E:\\"); /* FIXME */