diff --git a/dll/win32/shell32/wine/control.c b/dll/win32/shell32/wine/control.c index 6632d19632f..62760141cc1 100644 --- a/dll/win32/shell32/wine/control.c +++ b/dll/win32/shell32/wine/control.c @@ -69,8 +69,24 @@ CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) CPlApplet* applet; DWORD len; unsigned i; +#ifdef __REACTOS__ + UINT ret; + HICON hIconID; + UINT pIconID; + + CPLINFO info = { 0 }; + /* Since we do not know if our CPL will use ASCII or Unicode, + * we use a union that can handle both and check the size after + * it is read from the CPL to determine which is returned. */ + union + { + NEWCPLINFOA NewCplInfoA; + NEWCPLINFOW NewCplInfoW; + } Newcpl = { 0 }; +#else CPLINFO info; NEWCPLINFOW newinfo; +#endif if (!(applet = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*applet)))) return applet; @@ -125,8 +141,15 @@ CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) FIELD_OFFSET( CPlApplet, info[applet->count] )); for (i = 0; i < applet->count; i++) { +#ifdef __REACTOS__ + ZeroMemory(&Newcpl, sizeof(Newcpl)); + /* Set our defaults to CPL_DYNAMIC_RES */ + info.idIcon = info.idName = info.idInfo = CPL_DYNAMIC_RES; + info.lData = 0; +#else ZeroMemory(&newinfo, sizeof(newinfo)); newinfo.dwSize = sizeof(NEWCPLINFOA); +#endif applet->info[i].helpfile[0] = 0; /* proc is supposed to return a null value upon success for * CPL_INQUIRE and CPL_NEWINQUIRE @@ -136,6 +159,11 @@ CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) applet->proc(hWnd, CPL_INQUIRE, i, (LPARAM)&info); applet->info[i].data = info.lData; #ifdef __REACTOS__ + if (info.idIcon == 0 && info.idName == 0 && + info.idInfo == 0 && !info.lData) + { + ERR("'%S' does not implement CPL_INQUIRE\n", cmd); + } applet->info[i].idIcon = info.idIcon; #endif @@ -164,6 +192,53 @@ CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) if ((info.idIcon == CPL_DYNAMIC_RES) || (info.idName == CPL_DYNAMIC_RES) || (info.idInfo == CPL_DYNAMIC_RES)) { +#ifdef __REACTOS__ + applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&Newcpl); + applet->info[i].data = Newcpl.NewCplInfoA.lData; + + if (!Newcpl.NewCplInfoA.hIcon) + WARN("couldn't get icon for applet %u\n", i); + + /* This is CPL_NEWINQUIRE, so use the HICON value as idIcon */ + applet->info[i].icon = Newcpl.NewCplInfoA.hIcon; + + /* We get the Icon Group number which contains Icon #1. + * This uses a ReactOS specific flag LR_GROUPFROMICONID + * which asks for the group number of the specific icon. + * The 2nd param is the minused icon # and the flags tell the + * function to return its group number in pIconID. + * The other parameters tell the function not to do any skips. */ + ret = PrivateExtractIconsW(cmd, -1, 32, 32, &hIconID, &pIconID, 1, + LR_GROUPFROMICONID); + if (ret == 1 && pIconID) + applet->info[i].idIcon = pIconID; + + if (Newcpl.NewCplInfoA.dwSize == sizeof(NEWCPLINFOW)) + { + memcpy(applet->info[i].name, Newcpl.NewCplInfoW.szName, + sizeof(Newcpl.NewCplInfoW.szName)); + + memcpy(applet->info[i].info, Newcpl.NewCplInfoW.szInfo, + sizeof(Newcpl.NewCplInfoW.szInfo)); + + memcpy(applet->info[i].helpfile, Newcpl.NewCplInfoW.szHelpFile, + sizeof(Newcpl.NewCplInfoW.szHelpFile)); + } + else + { + MultiByteToWideChar(CP_ACP, 0, Newcpl.NewCplInfoA.szName, + ARRAYSIZE(Newcpl.NewCplInfoA.szName), + applet->info[i].name, ARRAYSIZE(applet->info[i].name)); + + MultiByteToWideChar(CP_ACP, 0, Newcpl.NewCplInfoA.szInfo, + ARRAYSIZE(Newcpl.NewCplInfoA.szInfo), + applet->info[i].info, ARRAYSIZE(applet->info[i].info)); + + MultiByteToWideChar(CP_ACP, 0, Newcpl.NewCplInfoA.szHelpFile, + ARRAYSIZE(Newcpl.NewCplInfoA.szHelpFile), + applet->info[i].helpfile, + ARRAYSIZE(applet->info[i].helpfile)); +#else applet->proc(hWnd, CPL_NEWINQUIRE, i, (LPARAM)&newinfo); applet->info[i].data = newinfo.lData; @@ -190,6 +265,7 @@ CPlApplet* Control_LoadApplet(HWND hWnd, LPCWSTR cmd, CPanel* panel) sizeof(((LPNEWCPLINFOA)&newinfo)->szHelpFile) / sizeof(CHAR), applet->info[i].helpfile, sizeof(applet->info[i].helpfile) / sizeof(WCHAR)); +#endif } } } diff --git a/sdk/include/psdk/winuser.h b/sdk/include/psdk/winuser.h index 7602917570f..ac7f99c7b71 100644 --- a/sdk/include/psdk/winuser.h +++ b/sdk/include/psdk/winuser.h @@ -1105,6 +1105,7 @@ extern "C" { #define LR_DEFAULTSIZE 64 #define LR_LOADREALSIZE 128 #define LR_VGACOLOR 128 +#define LR_GROUPFROMICONID 0x0400 /* REACTOS Specific Only */ #define LR_LOADMAP3DCOLORS 4096 #define LR_CREATEDIBSECTION 8192 #define LR_COPYFROMRESOURCE 0x4000 diff --git a/win32ss/user/user32/misc/exticon.c b/win32ss/user/user32/misc/exticon.c index 04d129ea0b0..d14e6d0f30b 100644 --- a/win32ss/user/user32/misc/exticon.c +++ b/win32ss/user/user32/misc/exticon.c @@ -645,6 +645,14 @@ static UINT ICO_ExtractIconExW( const IMAGE_RESOURCE_DIRECTORY_ENTRY *xresent; ULONG size; UINT i; +#ifdef __REACTOS__ + UINT j; + LPicoICONDIR lpiID = NULL; + BYTE *pCIDir = 0; + ULONG uSize = 0; + UINT16 iconCount = 0; + CURSORICONDIR *icodir; +#endif rootresdir = RtlImageDirectoryEntryToData((HMODULE)peimage, FALSE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size); if (!rootresdir) @@ -686,11 +694,73 @@ static UINT ICO_ExtractIconExW( while(nId is is the Index Number of the group */ + if (!(flags & LR_GROUPFROMICONID)) + { + if(xprdeTmp->Id == iId) + { + nIconIndex = n; + break; + } + } + else + { + *pIconId = xprdeTmp->Id; + nIconIndex = n; + + /* starting from specified index */ + xresent = (const IMAGE_RESOURCE_DIRECTORY_ENTRY*)(icongroupresdir+1) + nIconIndex; + for (i=0; i < nIcons; i++,xresent++) + { + const IMAGE_RESOURCE_DIRECTORY *resdir; + + /* go down this resource entry, name */ + resdir = (const IMAGE_RESOURCE_DIRECTORY *)((const char *)rootresdir + xresent->OffsetToDirectory); + + /* default language (0) */ + resdir = find_entry_default(resdir,rootresdir); + igdataent = (const IMAGE_RESOURCE_DATA_ENTRY*)resdir; + + /* lookup address in mapped image for virtual address */ + igdata = RtlImageRvaToVa(RtlImageNtHeader((HMODULE)peimage), (HMODULE)peimage, igdataent->OffsetToData, NULL); + if (!igdata) + { + ERR("no matching real address for icongroup!\n"); + goto end; /* failure */ + } + + pCIDir = ICO_GetIconDirectory(igdata, &lpiID, &uSize); + if (pCIDir) + { + iconCount = lpiID->idCount; + /* This is really a CURSORICONDIR pointer */ + icodir = (CURSORICONDIR*)igdata; + + /* Check all of the icons in this group for being iId */ + for (j=0; j < iconCount; j++) + { + /* Icon index is icodir->idEntries[j].wResId */ + if (iId == icodir->idEntries[j].wResId) + { + /* when we match it shows that this icon ID # + * is in this group number which is what we want */ + *pIconId = xprdeTmp->Id; // return the group # + ret = 1; // Return success for function + goto end; + } + } + } + HeapFree(GetProcessHeap(), 0, pCIDir); + } + } +#else if(xprdeTmp->Id == iId) { nIconIndex = n; break; } +#endif n++; xprdeTmp++; }