1 /* 2 * Shell basics 3 * 4 * Copyright 1998 Marcus Meissner 5 * Copyright 1998 Juergen Schmied (jsch) * <juergen.schmied@metronet.de> 6 * Copyright 2017 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2.1 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, write to the Free Software 20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 21 */ 22 23 #include <wine/config.h> 24 25 #define WIN32_NO_STATUS 26 #define _INC_WINDOWS 27 #define COBJMACROS 28 29 #include <windef.h> 30 #include <winbase.h> 31 #include <shellapi.h> 32 #include <shlobj.h> 33 #include <shlwapi.h> 34 #include <strsafe.h> 35 #include <winnls.h> 36 37 #include "undocshell.h" 38 #include "pidl.h" 39 #include "shell32_main.h" 40 #include "shresdef.h" 41 42 #include <wine/debug.h> 43 #include <wine/unicode.h> 44 45 #include <reactos/version.h> 46 #include <reactos/buildno.h> 47 48 WINE_DEFAULT_DEBUG_CHANNEL(shell); 49 50 const char * const SHELL_Authors[] = { "Copyright 1993-"COPYRIGHT_YEAR" WINE team", "Copyright 1998-"COPYRIGHT_YEAR" ReactOS Team", 0 }; 51 52 /************************************************************************* 53 * CommandLineToArgvW [SHELL32.@] 54 * 55 * We must interpret the quotes in the command line to rebuild the argv 56 * array correctly: 57 * - arguments are separated by spaces or tabs 58 * - quotes serve as optional argument delimiters 59 * '"a b"' -> 'a b' 60 * - escaped quotes must be converted back to '"' 61 * '\"' -> '"' 62 * - consecutive backslashes preceding a quote see their number halved with 63 * the remainder escaping the quote: 64 * 2n backslashes + quote -> n backslashes + quote as an argument delimiter 65 * 2n+1 backslashes + quote -> n backslashes + literal quote 66 * - backslashes that are not followed by a quote are copied literally: 67 * 'a\b' -> 'a\b' 68 * 'a\\b' -> 'a\\b' 69 * - in quoted strings, consecutive quotes see their number divided by three 70 * with the remainder modulo 3 deciding whether to close the string or not. 71 * Note that the opening quote must be counted in the consecutive quotes, 72 * that's the (1+) below: 73 * (1+) 3n quotes -> n quotes 74 * (1+) 3n+1 quotes -> n quotes plus closes the quoted string 75 * (1+) 3n+2 quotes -> n+1 quotes plus closes the quoted string 76 * - in unquoted strings, the first quote opens the quoted string and the 77 * remaining consecutive quotes follow the above rule. 78 */ 79 LPWSTR* WINAPI CommandLineToArgvW(LPCWSTR lpCmdline, int* numargs) 80 { 81 DWORD argc; 82 LPWSTR *argv; 83 LPCWSTR s; 84 LPWSTR d; 85 LPWSTR cmdline; 86 int qcount,bcount; 87 88 if(!numargs) 89 { 90 SetLastError(ERROR_INVALID_PARAMETER); 91 return NULL; 92 } 93 94 if (*lpCmdline==0) 95 { 96 /* Return the path to the executable */ 97 DWORD len, deslen=MAX_PATH, size; 98 99 size = sizeof(LPWSTR)*2 + deslen*sizeof(WCHAR); 100 for (;;) 101 { 102 if (!(argv = LocalAlloc(LMEM_FIXED, size))) return NULL; 103 len = GetModuleFileNameW(0, (LPWSTR)(argv+2), deslen); 104 if (!len) 105 { 106 LocalFree(argv); 107 return NULL; 108 } 109 if (len < deslen) break; 110 deslen*=2; 111 size = sizeof(LPWSTR)*2 + deslen*sizeof(WCHAR); 112 LocalFree( argv ); 113 } 114 argv[0]=(LPWSTR)(argv+2); 115 argv[1]=NULL; 116 *numargs=1; 117 118 return argv; 119 } 120 121 /* --- First count the arguments */ 122 argc=1; 123 s=lpCmdline; 124 /* The first argument, the executable path, follows special rules */ 125 if (*s=='"') 126 { 127 /* The executable path ends at the next quote, no matter what */ 128 s++; 129 while (*s) 130 if (*s++=='"') 131 break; 132 } 133 else 134 { 135 /* The executable path ends at the next space, no matter what */ 136 while (*s && *s!=' ' && *s!='\t') 137 s++; 138 } 139 /* skip to the first argument, if any */ 140 while (*s==' ' || *s=='\t') 141 s++; 142 if (*s) 143 argc++; 144 145 /* Analyze the remaining arguments */ 146 qcount=bcount=0; 147 while (*s) 148 { 149 if ((*s==' ' || *s=='\t') && qcount==0) 150 { 151 /* skip to the next argument and count it if any */ 152 while (*s==' ' || *s=='\t') 153 s++; 154 if (*s) 155 argc++; 156 bcount=0; 157 } 158 else if (*s=='\\') 159 { 160 /* '\', count them */ 161 bcount++; 162 s++; 163 } 164 else if (*s=='"') 165 { 166 /* '"' */ 167 if ((bcount & 1)==0) 168 qcount++; /* unescaped '"' */ 169 s++; 170 bcount=0; 171 /* consecutive quotes, see comment in copying code below */ 172 while (*s=='"') 173 { 174 qcount++; 175 s++; 176 } 177 qcount=qcount % 3; 178 if (qcount==2) 179 qcount=0; 180 } 181 else 182 { 183 /* a regular character */ 184 bcount=0; 185 s++; 186 } 187 } 188 189 /* Allocate in a single lump, the string array, and the strings that go 190 * with it. This way the caller can make a single LocalFree() call to free 191 * both, as per MSDN. 192 */ 193 argv=LocalAlloc(LMEM_FIXED, (argc+1)*sizeof(LPWSTR)+(strlenW(lpCmdline)+1)*sizeof(WCHAR)); 194 if (!argv) 195 return NULL; 196 cmdline=(LPWSTR)(argv+argc+1); 197 strcpyW(cmdline, lpCmdline); 198 199 /* --- Then split and copy the arguments */ 200 argv[0]=d=cmdline; 201 argc=1; 202 /* The first argument, the executable path, follows special rules */ 203 if (*d=='"') 204 { 205 /* The executable path ends at the next quote, no matter what */ 206 s=d+1; 207 while (*s) 208 { 209 if (*s=='"') 210 { 211 s++; 212 break; 213 } 214 *d++=*s++; 215 } 216 } 217 else 218 { 219 /* The executable path ends at the next space, no matter what */ 220 while (*d && *d!=' ' && *d!='\t') 221 d++; 222 s=d; 223 if (*s) 224 s++; 225 } 226 /* close the executable path */ 227 *d++=0; 228 /* skip to the first argument and initialize it if any */ 229 while (*s==' ' || *s=='\t') 230 s++; 231 if (!*s) 232 { 233 /* There are no parameters so we are all done */ 234 argv[argc]=NULL; 235 *numargs=argc; 236 return argv; 237 } 238 239 /* Split and copy the remaining arguments */ 240 argv[argc++]=d; 241 qcount=bcount=0; 242 while (*s) 243 { 244 if ((*s==' ' || *s=='\t') && qcount==0) 245 { 246 /* close the argument */ 247 *d++=0; 248 bcount=0; 249 250 /* skip to the next one and initialize it if any */ 251 do { 252 s++; 253 } while (*s==' ' || *s=='\t'); 254 if (*s) 255 argv[argc++]=d; 256 } 257 else if (*s=='\\') 258 { 259 *d++=*s++; 260 bcount++; 261 } 262 else if (*s=='"') 263 { 264 if ((bcount & 1)==0) 265 { 266 /* Preceded by an even number of '\', this is half that 267 * number of '\', plus a quote which we erase. 268 */ 269 d-=bcount/2; 270 qcount++; 271 } 272 else 273 { 274 /* Preceded by an odd number of '\', this is half that 275 * number of '\' followed by a '"' 276 */ 277 d=d-bcount/2-1; 278 *d++='"'; 279 } 280 s++; 281 bcount=0; 282 /* Now count the number of consecutive quotes. Note that qcount 283 * already takes into account the opening quote if any, as well as 284 * the quote that lead us here. 285 */ 286 while (*s=='"') 287 { 288 if (++qcount==3) 289 { 290 *d++='"'; 291 qcount=0; 292 } 293 s++; 294 } 295 if (qcount==2) 296 qcount=0; 297 } 298 else 299 { 300 /* a regular character */ 301 *d++=*s++; 302 bcount=0; 303 } 304 } 305 *d='\0'; 306 argv[argc]=NULL; 307 *numargs=argc; 308 309 return argv; 310 } 311 312 static DWORD shgfi_get_exe_type(LPCWSTR szFullPath) 313 { 314 BOOL status = FALSE; 315 HANDLE hfile; 316 DWORD BinaryType; 317 IMAGE_DOS_HEADER mz_header; 318 IMAGE_NT_HEADERS nt; 319 DWORD len; 320 char magic[4]; 321 322 status = GetBinaryTypeW (szFullPath, &BinaryType); 323 if (!status) 324 return 0; 325 if (BinaryType == SCS_DOS_BINARY || BinaryType == SCS_PIF_BINARY) 326 return 0x4d5a; 327 328 hfile = CreateFileW( szFullPath, GENERIC_READ, FILE_SHARE_READ, 329 NULL, OPEN_EXISTING, 0, 0 ); 330 if ( hfile == INVALID_HANDLE_VALUE ) 331 return 0; 332 333 /* 334 * The next section is adapted from MODULE_GetBinaryType, as we need 335 * to examine the image header to get OS and version information. We 336 * know from calling GetBinaryTypeA that the image is valid and either 337 * an NE or PE, so much error handling can be omitted. 338 * Seek to the start of the file and read the header information. 339 */ 340 341 SetFilePointer( hfile, 0, NULL, SEEK_SET ); 342 ReadFile( hfile, &mz_header, sizeof(mz_header), &len, NULL ); 343 344 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); 345 ReadFile( hfile, magic, sizeof(magic), &len, NULL ); 346 if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE ) 347 { 348 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); 349 ReadFile( hfile, &nt, sizeof(nt), &len, NULL ); 350 CloseHandle( hfile ); 351 /* DLL files are not executable and should return 0 */ 352 if (nt.FileHeader.Characteristics & IMAGE_FILE_DLL) 353 return 0; 354 if (nt.OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) 355 { 356 return IMAGE_NT_SIGNATURE | 357 (nt.OptionalHeader.MajorSubsystemVersion << 24) | 358 (nt.OptionalHeader.MinorSubsystemVersion << 16); 359 } 360 return IMAGE_NT_SIGNATURE; 361 } 362 else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE ) 363 { 364 IMAGE_OS2_HEADER ne; 365 SetFilePointer( hfile, mz_header.e_lfanew, NULL, SEEK_SET ); 366 ReadFile( hfile, &ne, sizeof(ne), &len, NULL ); 367 CloseHandle( hfile ); 368 if (ne.ne_exetyp == 2) 369 return IMAGE_OS2_SIGNATURE | (ne.ne_expver << 16); 370 return 0; 371 } 372 CloseHandle( hfile ); 373 return 0; 374 } 375 376 /************************************************************************* 377 * SHELL_IsShortcut [internal] 378 * 379 * Decide if an item id list points to a shell shortcut 380 */ 381 BOOL SHELL_IsShortcut(LPCITEMIDLIST pidlLast) 382 { 383 char szTemp[MAX_PATH]; 384 HKEY keyCls; 385 BOOL ret = FALSE; 386 387 if (_ILGetExtension(pidlLast, szTemp, MAX_PATH) && 388 HCR_MapTypeToValueA(szTemp, szTemp, MAX_PATH, TRUE)) 389 { 390 if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_CLASSES_ROOT, szTemp, 0, KEY_QUERY_VALUE, &keyCls)) 391 { 392 if (ERROR_SUCCESS == RegQueryValueExA(keyCls, "IsShortcut", NULL, NULL, NULL, NULL)) 393 ret = TRUE; 394 395 RegCloseKey(keyCls); 396 } 397 } 398 399 return ret; 400 } 401 402 #define SHGFI_KNOWN_FLAGS \ 403 (SHGFI_SMALLICON | SHGFI_OPENICON | SHGFI_SHELLICONSIZE | SHGFI_PIDL | \ 404 SHGFI_USEFILEATTRIBUTES | SHGFI_ADDOVERLAYS | SHGFI_OVERLAYINDEX | \ 405 SHGFI_ICON | SHGFI_DISPLAYNAME | SHGFI_TYPENAME | SHGFI_ATTRIBUTES | \ 406 SHGFI_ICONLOCATION | SHGFI_EXETYPE | SHGFI_SYSICONINDEX | \ 407 SHGFI_LINKOVERLAY | SHGFI_SELECTED | SHGFI_ATTR_SPECIFIED) 408 409 /************************************************************************* 410 * SHGetFileInfoW [SHELL32.@] 411 * 412 */ 413 DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path,DWORD dwFileAttributes, 414 SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags ) 415 { 416 WCHAR szLocation[MAX_PATH], szFullPath[MAX_PATH]; 417 int iIndex; 418 DWORD_PTR ret = TRUE; 419 DWORD dwAttributes = 0; 420 IShellFolder * psfParent = NULL; 421 IExtractIconW * pei = NULL; 422 LPITEMIDLIST pidlLast = NULL, pidl = NULL; 423 HRESULT hr = S_OK; 424 BOOL IconNotYetLoaded=TRUE; 425 UINT uGilFlags = 0; 426 HIMAGELIST big_icons, small_icons; 427 428 TRACE("%s fattr=0x%x sfi=%p(attr=0x%08x) size=0x%x flags=0x%x\n", 429 (flags & SHGFI_PIDL)? "pidl" : debugstr_w(path), dwFileAttributes, 430 psfi, psfi ? psfi->dwAttributes : 0, sizeofpsfi, flags); 431 432 if (!path) 433 return FALSE; 434 435 /* windows initializes these values regardless of the flags */ 436 if (psfi != NULL) 437 { 438 psfi->szDisplayName[0] = '\0'; 439 psfi->szTypeName[0] = '\0'; 440 psfi->hIcon = NULL; 441 } 442 443 if (!(flags & SHGFI_PIDL)) 444 { 445 /* SHGetFileInfo should work with absolute and relative paths */ 446 if (PathIsRelativeW(path)) 447 { 448 GetCurrentDirectoryW(MAX_PATH, szLocation); 449 PathCombineW(szFullPath, szLocation, path); 450 } 451 else 452 { 453 lstrcpynW(szFullPath, path, MAX_PATH); 454 } 455 } 456 else 457 { 458 SHGetPathFromIDListW((LPITEMIDLIST)path, szFullPath); 459 } 460 461 if (flags & SHGFI_EXETYPE) 462 { 463 if (!(flags & SHGFI_SYSICONINDEX)) 464 { 465 if (flags & SHGFI_USEFILEATTRIBUTES) 466 { 467 return TRUE; 468 } 469 else if (GetFileAttributesW(szFullPath) != INVALID_FILE_ATTRIBUTES) 470 { 471 return shgfi_get_exe_type(szFullPath); 472 } 473 } 474 } 475 476 /* 477 * psfi is NULL normally to query EXE type. If it is NULL, none of the 478 * below makes sense anyway. Windows allows this and just returns FALSE 479 */ 480 if (psfi == NULL) 481 return FALSE; 482 483 /* 484 * translate the path into a pidl only when SHGFI_USEFILEATTRIBUTES 485 * is not specified. 486 * The pidl functions fail on not existing file names 487 */ 488 489 if (flags & SHGFI_PIDL) 490 { 491 pidl = ILClone((LPCITEMIDLIST)path); 492 } 493 else if (!(flags & SHGFI_USEFILEATTRIBUTES)) 494 { 495 hr = SHILCreateFromPathW(szFullPath, &pidl, &dwAttributes); 496 } 497 498 if ((flags & SHGFI_PIDL) || !(flags & SHGFI_USEFILEATTRIBUTES)) 499 { 500 /* get the parent shellfolder */ 501 if (pidl) 502 { 503 hr = SHBindToParent( pidl, &IID_IShellFolder, (LPVOID*)&psfParent, 504 (LPCITEMIDLIST*)&pidlLast ); 505 if (SUCCEEDED(hr)) 506 pidlLast = ILClone(pidlLast); 507 else 508 hr = S_OK; 509 ILFree(pidl); 510 } 511 else 512 { 513 ERR("pidl is null!\n"); 514 return FALSE; 515 } 516 } 517 518 /* get the attributes of the child */ 519 if (SUCCEEDED(hr) && (flags & SHGFI_ATTRIBUTES)) 520 { 521 if (!(flags & SHGFI_ATTR_SPECIFIED)) 522 { 523 psfi->dwAttributes = 0xffffffff; 524 } 525 if (psfParent) 526 { 527 IShellFolder_GetAttributesOf(psfParent, 1, (LPCITEMIDLIST*)&pidlLast, 528 &(psfi->dwAttributes)); 529 } 530 } 531 532 if (flags & SHGFI_USEFILEATTRIBUTES) 533 { 534 if (flags & SHGFI_ICON) 535 { 536 psfi->dwAttributes = 0; 537 } 538 } 539 540 /* get the displayname */ 541 if (SUCCEEDED(hr) && (flags & SHGFI_DISPLAYNAME)) 542 { 543 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) 544 { 545 lstrcpyW (psfi->szDisplayName, PathFindFileNameW(szFullPath)); 546 } 547 else if (psfParent) 548 { 549 STRRET str; 550 hr = IShellFolder_GetDisplayNameOf( psfParent, pidlLast, 551 SHGDN_INFOLDER, &str); 552 StrRetToStrNW (psfi->szDisplayName, MAX_PATH, &str, pidlLast); 553 } 554 } 555 556 /* get the type name */ 557 if (SUCCEEDED(hr) && (flags & SHGFI_TYPENAME)) 558 { 559 static const WCHAR szFolder[] = { 'F','o','l','d','e','r',0 }; 560 static const WCHAR szFile[] = { 'F','i','l','e',0 }; 561 static const WCHAR szSpaceFile[] = { ' ','f','i','l','e',0 }; 562 563 if (!(flags & SHGFI_USEFILEATTRIBUTES) || (flags & SHGFI_PIDL)) 564 { 565 char ftype[80]; 566 567 _ILGetFileType(pidlLast, ftype, 80); 568 MultiByteToWideChar(CP_ACP, 0, ftype, -1, psfi->szTypeName, 80 ); 569 } 570 else 571 { 572 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 573 strcatW (psfi->szTypeName, szFolder); 574 else 575 { 576 WCHAR sTemp[64]; 577 578 lstrcpyW(sTemp,PathFindExtensionW(szFullPath)); 579 if (sTemp[0] == 0 || (sTemp[0] == '.' && sTemp[1] == 0)) 580 { 581 /* "name" or "name." => "File" */ 582 lstrcpynW (psfi->szTypeName, szFile, 64); 583 } 584 else if (!( HCR_MapTypeToValueW(sTemp, sTemp, 64, TRUE) && 585 HCR_MapTypeToValueW(sTemp, psfi->szTypeName, 80, FALSE ))) 586 { 587 if (sTemp[0]) 588 { 589 lstrcpynW (psfi->szTypeName, sTemp, 64); 590 strcatW (psfi->szTypeName, szSpaceFile); 591 } 592 else 593 { 594 lstrcpynW (psfi->szTypeName, szFile, 64); 595 } 596 } 597 } 598 } 599 } 600 601 /* ### icons ###*/ 602 603 Shell_GetImageLists( &big_icons, &small_icons ); 604 605 if (flags & SHGFI_OPENICON) 606 uGilFlags |= GIL_OPENICON; 607 608 if (flags & SHGFI_LINKOVERLAY) 609 uGilFlags |= GIL_FORSHORTCUT; 610 else if ((flags&SHGFI_ADDOVERLAYS) || 611 (flags&(SHGFI_ICON|SHGFI_SMALLICON))==SHGFI_ICON) 612 { 613 if (SHELL_IsShortcut(pidlLast)) 614 uGilFlags |= GIL_FORSHORTCUT; 615 } 616 617 if (flags & SHGFI_OVERLAYINDEX) 618 FIXME("SHGFI_OVERLAYINDEX unhandled\n"); 619 620 if (flags & SHGFI_SELECTED) 621 FIXME("set icon to selected, stub\n"); 622 623 if (flags & SHGFI_SHELLICONSIZE) 624 FIXME("set icon to shell size, stub\n"); 625 626 /* get the iconlocation */ 627 if (SUCCEEDED(hr) && (flags & SHGFI_ICONLOCATION )) 628 { 629 UINT uDummy,uFlags; 630 631 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) 632 { 633 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 634 { 635 lstrcpyW(psfi->szDisplayName, swShell32Name); 636 psfi->iIcon = -IDI_SHELL_FOLDER; 637 } 638 else 639 { 640 WCHAR* szExt; 641 static const WCHAR p1W[] = {'%','1',0}; 642 WCHAR sTemp [MAX_PATH]; 643 644 szExt = PathFindExtensionW(szFullPath); 645 TRACE("szExt=%s\n", debugstr_w(szExt)); 646 if ( szExt && 647 HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) && 648 HCR_GetIconW(sTemp, sTemp, NULL, MAX_PATH, &psfi->iIcon)) 649 { 650 if (lstrcmpW(p1W, sTemp)) 651 strcpyW(psfi->szDisplayName, sTemp); 652 else 653 { 654 /* the icon is in the file */ 655 strcpyW(psfi->szDisplayName, szFullPath); 656 } 657 } 658 else 659 ret = FALSE; 660 } 661 } 662 else if (psfParent) 663 { 664 hr = IShellFolder_GetUIObjectOf(psfParent, 0, 1, 665 (LPCITEMIDLIST*)&pidlLast, &IID_IExtractIconW, 666 &uDummy, (LPVOID*)&pei); 667 if (SUCCEEDED(hr)) 668 { 669 hr = IExtractIconW_GetIconLocation(pei, uGilFlags, 670 szLocation, MAX_PATH, &iIndex, &uFlags); 671 672 if (uFlags & GIL_NOTFILENAME) 673 ret = FALSE; 674 else 675 { 676 lstrcpyW (psfi->szDisplayName, szLocation); 677 psfi->iIcon = iIndex; 678 } 679 IExtractIconW_Release(pei); 680 } 681 } 682 } 683 684 /* get icon index (or load icon)*/ 685 if (SUCCEEDED(hr) && (flags & (SHGFI_ICON | SHGFI_SYSICONINDEX))) 686 { 687 if (flags & SHGFI_USEFILEATTRIBUTES && !(flags & SHGFI_PIDL)) 688 { 689 WCHAR sTemp [MAX_PATH]; 690 WCHAR * szExt; 691 int icon_idx=0; 692 693 lstrcpynW(sTemp, szFullPath, MAX_PATH); 694 695 if (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 696 psfi->iIcon = SIC_GetIconIndex(swShell32Name, -IDI_SHELL_FOLDER, 0); 697 else 698 { 699 static const WCHAR p1W[] = {'%','1',0}; 700 701 psfi->iIcon = 0; 702 szExt = PathFindExtensionW(sTemp); 703 if ( szExt && 704 HCR_MapTypeToValueW(szExt, sTemp, MAX_PATH, TRUE) && 705 HCR_GetIconW(sTemp, sTemp, NULL, MAX_PATH, &icon_idx)) 706 { 707 if (!lstrcmpW(p1W,sTemp)) /* icon is in the file */ 708 strcpyW(sTemp, szFullPath); 709 710 if (flags & SHGFI_SYSICONINDEX) 711 { 712 psfi->iIcon = SIC_GetIconIndex(sTemp,icon_idx,0); 713 if (psfi->iIcon == -1) 714 psfi->iIcon = 0; 715 } 716 else 717 { 718 UINT ret; 719 if (flags & SHGFI_SMALLICON) 720 ret = PrivateExtractIconsW( sTemp,icon_idx, 721 GetSystemMetrics( SM_CXSMICON ), 722 GetSystemMetrics( SM_CYSMICON ), 723 &psfi->hIcon, 0, 1, 0); 724 else 725 ret = PrivateExtractIconsW( sTemp, icon_idx, 726 GetSystemMetrics( SM_CXICON), 727 GetSystemMetrics( SM_CYICON), 728 &psfi->hIcon, 0, 1, 0); 729 if (ret != 0 && ret != (UINT)-1) 730 { 731 IconNotYetLoaded=FALSE; 732 psfi->iIcon = icon_idx; 733 } 734 } 735 } 736 } 737 } 738 else if (psfParent) 739 { 740 if (!(PidlToSicIndex(psfParent, pidlLast, !(flags & SHGFI_SMALLICON), 741 uGilFlags, &(psfi->iIcon)))) 742 { 743 ret = FALSE; 744 } 745 } 746 if (ret && (flags & SHGFI_SYSICONINDEX)) 747 { 748 if (flags & SHGFI_SMALLICON) 749 ret = (DWORD_PTR)small_icons; 750 else 751 ret = (DWORD_PTR)big_icons; 752 } 753 } 754 755 /* icon handle */ 756 if (SUCCEEDED(hr) && (flags & SHGFI_ICON) && IconNotYetLoaded) 757 { 758 if (flags & SHGFI_SMALLICON) 759 psfi->hIcon = ImageList_GetIcon( small_icons, psfi->iIcon, ILD_NORMAL); 760 else 761 psfi->hIcon = ImageList_GetIcon( big_icons, psfi->iIcon, ILD_NORMAL); 762 } 763 764 if (flags & ~SHGFI_KNOWN_FLAGS) 765 FIXME("unknown flags %08x\n", flags & ~SHGFI_KNOWN_FLAGS); 766 767 if (psfParent) 768 IShellFolder_Release(psfParent); 769 770 if (hr != S_OK) 771 ret = FALSE; 772 773 SHFree(pidlLast); 774 775 TRACE ("icon=%p index=0x%08x attr=0x%08x name=%s type=%s ret=0x%08lx\n", 776 psfi->hIcon, psfi->iIcon, psfi->dwAttributes, 777 debugstr_w(psfi->szDisplayName), debugstr_w(psfi->szTypeName), ret); 778 779 return ret; 780 } 781 782 /************************************************************************* 783 * SHGetFileInfoA [SHELL32.@] 784 * 785 * Note: 786 * MSVBVM60.__vbaNew2 expects this function to return a value in range 787 * 1 .. 0x7fff when the function succeeds and flags does not contain 788 * SHGFI_EXETYPE or SHGFI_SYSICONINDEX (see bug 7701) 789 */ 790 DWORD_PTR WINAPI SHGetFileInfoA(LPCSTR path,DWORD dwFileAttributes, 791 SHFILEINFOA *psfi, UINT sizeofpsfi, 792 UINT flags ) 793 { 794 INT len; 795 LPWSTR temppath = NULL; 796 LPCWSTR pathW; 797 DWORD_PTR ret; 798 SHFILEINFOW temppsfi; 799 800 if (flags & SHGFI_PIDL) 801 { 802 /* path contains a pidl */ 803 pathW = (LPCWSTR)path; 804 } 805 else 806 { 807 len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); 808 temppath = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); 809 MultiByteToWideChar(CP_ACP, 0, path, -1, temppath, len); 810 pathW = temppath; 811 } 812 813 if (psfi) 814 { 815 temppsfi.hIcon = psfi->hIcon; 816 temppsfi.iIcon = psfi->iIcon; 817 temppsfi.dwAttributes = psfi->dwAttributes; 818 819 ret = SHGetFileInfoW(pathW, dwFileAttributes, &temppsfi, sizeof(temppsfi), flags); 820 psfi->hIcon = temppsfi.hIcon; 821 psfi->iIcon = temppsfi.iIcon; 822 psfi->dwAttributes = temppsfi.dwAttributes; 823 824 WideCharToMultiByte(CP_ACP, 0, temppsfi.szDisplayName, -1, 825 psfi->szDisplayName, sizeof(psfi->szDisplayName), NULL, NULL); 826 827 WideCharToMultiByte(CP_ACP, 0, temppsfi.szTypeName, -1, 828 psfi->szTypeName, sizeof(psfi->szTypeName), NULL, NULL); 829 } 830 else 831 ret = SHGetFileInfoW(pathW, dwFileAttributes, NULL, 0, flags); 832 833 HeapFree(GetProcessHeap(), 0, temppath); 834 835 return ret; 836 } 837 838 /************************************************************************* 839 * DuplicateIcon [SHELL32.@] 840 */ 841 HICON WINAPI DuplicateIcon( HINSTANCE hInstance, HICON hIcon) 842 { 843 ICONINFO IconInfo; 844 HICON hDupIcon = 0; 845 846 TRACE("%p %p\n", hInstance, hIcon); 847 848 if (GetIconInfo(hIcon, &IconInfo)) 849 { 850 hDupIcon = CreateIconIndirect(&IconInfo); 851 852 /* clean up hbmMask and hbmColor */ 853 DeleteObject(IconInfo.hbmMask); 854 DeleteObject(IconInfo.hbmColor); 855 } 856 857 return hDupIcon; 858 } 859 860 /************************************************************************* 861 * ExtractIconA [SHELL32.@] 862 */ 863 HICON WINAPI ExtractIconA(HINSTANCE hInstance, LPCSTR lpszFile, UINT nIconIndex) 864 { 865 HICON ret; 866 INT len = MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, NULL, 0); 867 LPWSTR lpwstrFile = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 868 869 TRACE("%p %s %d\n", hInstance, lpszFile, nIconIndex); 870 871 MultiByteToWideChar(CP_ACP, 0, lpszFile, -1, lpwstrFile, len); 872 ret = ExtractIconW(hInstance, lpwstrFile, nIconIndex); 873 HeapFree(GetProcessHeap(), 0, lpwstrFile); 874 875 return ret; 876 } 877 878 /************************************************************************* 879 * ExtractIconW [SHELL32.@] 880 */ 881 HICON WINAPI ExtractIconW(HINSTANCE hInstance, LPCWSTR lpszFile, UINT nIconIndex) 882 { 883 HICON hIcon = NULL; 884 UINT ret; 885 UINT cx = GetSystemMetrics(SM_CXICON), cy = GetSystemMetrics(SM_CYICON); 886 887 TRACE("%p %s %d\n", hInstance, debugstr_w(lpszFile), nIconIndex); 888 889 if (nIconIndex == (UINT)-1) 890 { 891 ret = PrivateExtractIconsW(lpszFile, 0, cx, cy, NULL, NULL, 0, LR_DEFAULTCOLOR); 892 if (ret != (UINT)-1 && ret) 893 return (HICON)(UINT_PTR)ret; 894 return NULL; 895 } 896 else 897 ret = PrivateExtractIconsW(lpszFile, nIconIndex, cx, cy, &hIcon, NULL, 1, LR_DEFAULTCOLOR); 898 899 if (ret == (UINT)-1) 900 return (HICON)1; 901 else if (ret > 0 && hIcon) 902 return hIcon; 903 904 return NULL; 905 } 906 907 /************************************************************************* 908 * Printer_LoadIconsW [SHELL32.205] 909 */ 910 VOID WINAPI Printer_LoadIconsW(LPCWSTR wsPrinterName, HICON * pLargeIcon, HICON * pSmallIcon) 911 { 912 INT iconindex=IDI_SHELL_PRINTERS_FOLDER; 913 914 TRACE("(%s, %p, %p)\n", debugstr_w(wsPrinterName), pLargeIcon, pSmallIcon); 915 916 /* We should check if wsPrinterName is 917 1. the Default Printer or not 918 2. connected or not 919 3. a Local Printer or a Network-Printer 920 and use different Icons 921 */ 922 if((wsPrinterName != NULL) && (wsPrinterName[0] != 0)) 923 { 924 FIXME("(select Icon by PrinterName %s not implemented)\n", debugstr_w(wsPrinterName)); 925 } 926 927 if(pLargeIcon != NULL) 928 *pLargeIcon = LoadImageW(shell32_hInstance, 929 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON, 930 0, 0, LR_DEFAULTCOLOR|LR_DEFAULTSIZE); 931 932 if(pSmallIcon != NULL) 933 *pSmallIcon = LoadImageW(shell32_hInstance, 934 (LPCWSTR) MAKEINTRESOURCE(iconindex), IMAGE_ICON, 935 16, 16, LR_DEFAULTCOLOR); 936 } 937 938 /************************************************************************* 939 * Printers_RegisterWindowW [SHELL32.213] 940 * used by "printui.dll": 941 * find the Window of the given Type for the specific Printer and 942 * return the already existent hwnd or open a new window 943 */ 944 BOOL WINAPI Printers_RegisterWindowW(LPCWSTR wsPrinter, DWORD dwType, 945 HANDLE * phClassPidl, HWND * phwnd) 946 { 947 FIXME("(%s, %x, %p (%p), %p (%p)) stub!\n", debugstr_w(wsPrinter), dwType, 948 phClassPidl, (phClassPidl != NULL) ? *(phClassPidl) : NULL, 949 phwnd, (phwnd != NULL) ? *(phwnd) : NULL); 950 951 return FALSE; 952 } 953 954 /************************************************************************* 955 * Printers_UnregisterWindow [SHELL32.214] 956 */ 957 VOID WINAPI Printers_UnregisterWindow(HANDLE hClassPidl, HWND hwnd) 958 { 959 FIXME("(%p, %p) stub!\n", hClassPidl, hwnd); 960 } 961 962 /*************************************************************************/ 963 964 typedef struct 965 { 966 LPCWSTR szApp; 967 #ifdef __REACTOS__ 968 LPCWSTR szOSVersion; 969 #endif 970 LPCWSTR szOtherStuff; 971 HICON hIcon; 972 } ABOUT_INFO; 973 974 #define DROP_FIELD_TOP (-15) 975 #define DROP_FIELD_HEIGHT 15 976 977 /************************************************************************* 978 * SHAppBarMessage [SHELL32.@] 979 */ 980 UINT_PTR WINAPI SHAppBarMessage(DWORD msg, PAPPBARDATA data) 981 { 982 int width=data->rc.right - data->rc.left; 983 int height=data->rc.bottom - data->rc.top; 984 RECT rec=data->rc; 985 986 TRACE("msg=%d, data={cb=%d, hwnd=%p, callback=%x, edge=%d, rc=%s, lparam=%lx}\n", 987 msg, data->cbSize, data->hWnd, data->uCallbackMessage, data->uEdge, 988 wine_dbgstr_rect(&data->rc), data->lParam); 989 990 switch (msg) 991 { 992 case ABM_GETSTATE: 993 return ABS_ALWAYSONTOP | ABS_AUTOHIDE; 994 995 case ABM_GETTASKBARPOS: 996 GetWindowRect(data->hWnd, &rec); 997 data->rc=rec; 998 return TRUE; 999 1000 case ABM_ACTIVATE: 1001 SetActiveWindow(data->hWnd); 1002 return TRUE; 1003 1004 case ABM_GETAUTOHIDEBAR: 1005 return 0; /* pretend there is no autohide bar */ 1006 1007 case ABM_NEW: 1008 /* cbSize, hWnd, and uCallbackMessage are used. All other ignored */ 1009 SetWindowPos(data->hWnd,HWND_TOP,0,0,0,0,SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE); 1010 return TRUE; 1011 1012 case ABM_QUERYPOS: 1013 GetWindowRect(data->hWnd, &(data->rc)); 1014 return TRUE; 1015 1016 case ABM_REMOVE: 1017 FIXME("ABM_REMOVE broken\n"); 1018 /* FIXME: this is wrong; should it be DestroyWindow instead? */ 1019 /*CloseHandle(data->hWnd);*/ 1020 return TRUE; 1021 1022 case ABM_SETAUTOHIDEBAR: 1023 SetWindowPos(data->hWnd,HWND_TOP,rec.left+1000,rec.top, 1024 width,height,SWP_SHOWWINDOW); 1025 return TRUE; 1026 1027 case ABM_SETPOS: 1028 data->uEdge=(ABE_RIGHT | ABE_LEFT); 1029 SetWindowPos(data->hWnd,HWND_TOP,data->rc.left,data->rc.top, 1030 width,height,SWP_SHOWWINDOW); 1031 return TRUE; 1032 1033 case ABM_WINDOWPOSCHANGED: 1034 return TRUE; 1035 } 1036 1037 return FALSE; 1038 } 1039 1040 /************************************************************************* 1041 * SHHelpShortcuts_RunDLLA [SHELL32.@] 1042 * 1043 */ 1044 DWORD WINAPI SHHelpShortcuts_RunDLLA(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4) 1045 { 1046 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4); 1047 return 0; 1048 } 1049 1050 /************************************************************************* 1051 * SHHelpShortcuts_RunDLLA [SHELL32.@] 1052 * 1053 */ 1054 DWORD WINAPI SHHelpShortcuts_RunDLLW(DWORD dwArg1, DWORD dwArg2, DWORD dwArg3, DWORD dwArg4) 1055 { 1056 FIXME("(%x, %x, %x, %x) stub!\n", dwArg1, dwArg2, dwArg3, dwArg4); 1057 return 0; 1058 } 1059 1060 /************************************************************************* 1061 * SHLoadInProc [SHELL32.@] 1062 * Create an instance of specified object class from within 1063 * the shell process and release it immediately 1064 */ 1065 HRESULT WINAPI SHLoadInProc (REFCLSID rclsid) 1066 { 1067 void *ptr = NULL; 1068 1069 TRACE("%s\n", debugstr_guid(rclsid)); 1070 1071 CoCreateInstance(rclsid, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown,&ptr); 1072 if(ptr) 1073 { 1074 IUnknown * pUnk = ptr; 1075 IUnknown_Release(pUnk); 1076 return S_OK; 1077 } 1078 return DISP_E_MEMBERNOTFOUND; 1079 } 1080 1081 static VOID SetRegTextData(HWND hWnd, HKEY hKey, LPCWSTR Value, UINT uID) 1082 { 1083 DWORD dwBufferSize; 1084 DWORD dwType; 1085 LPWSTR lpBuffer; 1086 1087 if( RegQueryValueExW(hKey, Value, NULL, &dwType, NULL, &dwBufferSize) == ERROR_SUCCESS ) 1088 { 1089 if(dwType == REG_SZ) 1090 { 1091 lpBuffer = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, dwBufferSize); 1092 1093 if(lpBuffer) 1094 { 1095 if( RegQueryValueExW(hKey, Value, NULL, &dwType, (LPBYTE)lpBuffer, &dwBufferSize) == ERROR_SUCCESS ) 1096 { 1097 SetDlgItemTextW(hWnd, uID, lpBuffer); 1098 } 1099 1100 HeapFree(GetProcessHeap(), 0, lpBuffer); 1101 } 1102 } 1103 } 1104 } 1105 1106 INT_PTR CALLBACK AboutAuthorsDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) 1107 { 1108 switch(msg) 1109 { 1110 case WM_INITDIALOG: 1111 { 1112 const char* const *pstr = SHELL_Authors; 1113 1114 // Add the authors to the list 1115 SendDlgItemMessageW( hWnd, IDC_ABOUT_AUTHORS_LISTBOX, WM_SETREDRAW, FALSE, 0 ); 1116 1117 while (*pstr) 1118 { 1119 WCHAR name[64]; 1120 1121 /* authors list is in utf-8 format */ 1122 MultiByteToWideChar( CP_UTF8, 0, *pstr, -1, name, sizeof(name)/sizeof(WCHAR) ); 1123 SendDlgItemMessageW( hWnd, IDC_ABOUT_AUTHORS_LISTBOX, LB_ADDSTRING, (WPARAM)-1, (LPARAM)name ); 1124 pstr++; 1125 } 1126 1127 SendDlgItemMessageW( hWnd, IDC_ABOUT_AUTHORS_LISTBOX, WM_SETREDRAW, TRUE, 0 ); 1128 1129 return TRUE; 1130 } 1131 } 1132 1133 return FALSE; 1134 } 1135 /************************************************************************* 1136 * AboutDlgProc (internal) 1137 */ 1138 static INT_PTR CALLBACK AboutDlgProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) 1139 { 1140 static DWORD cxLogoBmp; 1141 static DWORD cyLogoBmp, cyLineBmp; 1142 static HBITMAP hLogoBmp, hLineBmp; 1143 static HWND hWndAuthors; 1144 1145 switch(msg) 1146 { 1147 case WM_INITDIALOG: 1148 { 1149 ABOUT_INFO *info = (ABOUT_INFO *)lParam; 1150 1151 if (info) 1152 { 1153 const WCHAR szRegKey[] = L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; 1154 HKEY hRegKey; 1155 MEMORYSTATUSEX MemStat; 1156 WCHAR szAppTitle[512]; 1157 WCHAR szAppTitleTemplate[512]; 1158 WCHAR szAuthorsText[20]; 1159 1160 // Preload the ROS bitmap 1161 hLogoBmp = (HBITMAP)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDB_REACTOS), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); 1162 hLineBmp = (HBITMAP)LoadImage(shell32_hInstance, MAKEINTRESOURCE(IDB_LINEBAR), IMAGE_BITMAP, 0, 0, LR_DEFAULTCOLOR); 1163 1164 if(hLogoBmp && hLineBmp) 1165 { 1166 BITMAP bmpLogo; 1167 1168 GetObject( hLogoBmp, sizeof(BITMAP), &bmpLogo ); 1169 1170 cxLogoBmp = bmpLogo.bmWidth; 1171 cyLogoBmp = bmpLogo.bmHeight; 1172 1173 GetObject( hLineBmp, sizeof(BITMAP), &bmpLogo ); 1174 cyLineBmp = bmpLogo.bmHeight; 1175 } 1176 1177 // Set App-specific stuff (icon, app name, szOtherStuff string) 1178 SendDlgItemMessageW(hWnd, IDC_ABOUT_ICON, STM_SETICON, (WPARAM)info->hIcon, 0); 1179 1180 GetWindowTextW( hWnd, szAppTitleTemplate, sizeof(szAppTitleTemplate) / sizeof(WCHAR) ); 1181 swprintf( szAppTitle, szAppTitleTemplate, info->szApp ); 1182 SetWindowTextW( hWnd, szAppTitle ); 1183 1184 SetDlgItemTextW( hWnd, IDC_ABOUT_APPNAME, info->szApp ); 1185 #ifdef __REACTOS__ 1186 SetDlgItemTextW( hWnd, IDC_ABOUT_VERSION, info->szOSVersion ); 1187 #endif 1188 SetDlgItemTextW( hWnd, IDC_ABOUT_OTHERSTUFF, info->szOtherStuff ); 1189 1190 // Set the registered user and organization name 1191 if(RegOpenKeyExW( HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_QUERY_VALUE, &hRegKey ) == ERROR_SUCCESS) 1192 { 1193 SetRegTextData( hWnd, hRegKey, L"RegisteredOwner", IDC_ABOUT_REG_USERNAME ); 1194 SetRegTextData( hWnd, hRegKey, L"RegisteredOrganization", IDC_ABOUT_REG_ORGNAME ); 1195 1196 RegCloseKey( hRegKey ); 1197 } 1198 1199 // Set the value for the installed physical memory 1200 MemStat.dwLength = sizeof(MemStat); 1201 if( GlobalMemoryStatusEx(&MemStat) ) 1202 { 1203 WCHAR szBuf[12]; 1204 1205 if (MemStat.ullTotalPhys > 1024 * 1024 * 1024) 1206 { 1207 double dTotalPhys; 1208 WCHAR szDecimalSeparator[4]; 1209 WCHAR szUnits[3]; 1210 1211 // We're dealing with GBs or more 1212 MemStat.ullTotalPhys /= 1024 * 1024; 1213 1214 if (MemStat.ullTotalPhys > 1024 * 1024) 1215 { 1216 // We're dealing with TBs or more 1217 MemStat.ullTotalPhys /= 1024; 1218 1219 if (MemStat.ullTotalPhys > 1024 * 1024) 1220 { 1221 // We're dealing with PBs or more 1222 MemStat.ullTotalPhys /= 1024; 1223 1224 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 1225 wcscpy( szUnits, L"PB" ); 1226 } 1227 else 1228 { 1229 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 1230 wcscpy( szUnits, L"TB" ); 1231 } 1232 } 1233 else 1234 { 1235 dTotalPhys = (double)MemStat.ullTotalPhys / 1024; 1236 wcscpy( szUnits, L"GB" ); 1237 } 1238 1239 // We need the decimal point of the current locale to display the RAM size correctly 1240 if (GetLocaleInfoW(LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, 1241 szDecimalSeparator, 1242 sizeof(szDecimalSeparator) / sizeof(WCHAR)) > 0) 1243 { 1244 UCHAR uDecimals; 1245 UINT uIntegral; 1246 1247 uIntegral = (UINT)dTotalPhys; 1248 uDecimals = (UCHAR)((UINT)(dTotalPhys * 100) - uIntegral * 100); 1249 1250 // Display the RAM size with 2 decimals 1251 swprintf(szBuf, L"%u%s%02u %s", uIntegral, szDecimalSeparator, uDecimals, szUnits); 1252 } 1253 } 1254 else 1255 { 1256 // We're dealing with MBs, don't show any decimals 1257 swprintf( szBuf, L"%u MB", (UINT)MemStat.ullTotalPhys / 1024 / 1024 ); 1258 } 1259 1260 SetDlgItemTextW( hWnd, IDC_ABOUT_PHYSMEM, szBuf); 1261 } 1262 1263 // Add the Authors dialog 1264 hWndAuthors = CreateDialogW( shell32_hInstance, MAKEINTRESOURCEW(IDD_ABOUT_AUTHORS), hWnd, AboutAuthorsDlgProc ); 1265 LoadStringW( shell32_hInstance, IDS_SHELL_ABOUT_AUTHORS, szAuthorsText, sizeof(szAuthorsText) / sizeof(WCHAR) ); 1266 SetDlgItemTextW( hWnd, IDC_ABOUT_AUTHORS, szAuthorsText ); 1267 } 1268 1269 return TRUE; 1270 } 1271 1272 case WM_PAINT: 1273 { 1274 if(hLogoBmp && hLineBmp) 1275 { 1276 PAINTSTRUCT ps; 1277 HDC hdc; 1278 HDC hdcMem; 1279 HGDIOBJ hOldObj; 1280 1281 hdc = BeginPaint(hWnd, &ps); 1282 hdcMem = CreateCompatibleDC(hdc); 1283 1284 if(hdcMem) 1285 { 1286 hOldObj = SelectObject(hdcMem, hLogoBmp); 1287 BitBlt(hdc, 0, 0, cxLogoBmp, cyLogoBmp, hdcMem, 0, 0, SRCCOPY); 1288 1289 SelectObject(hdcMem, hLineBmp); 1290 BitBlt(hdc, 0, cyLogoBmp, cxLogoBmp, cyLineBmp, hdcMem, 0, 0, SRCCOPY); 1291 1292 SelectObject(hdcMem, hOldObj); 1293 DeleteDC(hdcMem); 1294 } 1295 1296 EndPaint(hWnd, &ps); 1297 } 1298 }; break; 1299 1300 case WM_COMMAND: 1301 { 1302 switch(wParam) 1303 { 1304 case IDOK: 1305 case IDCANCEL: 1306 EndDialog(hWnd, TRUE); 1307 return TRUE; 1308 1309 case IDC_ABOUT_AUTHORS: 1310 { 1311 static BOOL bShowingAuthors = FALSE; 1312 WCHAR szAuthorsText[20]; 1313 1314 if(bShowingAuthors) 1315 { 1316 LoadStringW( shell32_hInstance, IDS_SHELL_ABOUT_AUTHORS, szAuthorsText, sizeof(szAuthorsText) / sizeof(WCHAR) ); 1317 ShowWindow( hWndAuthors, SW_HIDE ); 1318 } 1319 else 1320 { 1321 LoadStringW( shell32_hInstance, IDS_SHELL_ABOUT_BACK, szAuthorsText, sizeof(szAuthorsText) / sizeof(WCHAR) ); 1322 ShowWindow( hWndAuthors, SW_SHOW ); 1323 } 1324 1325 SetDlgItemTextW( hWnd, IDC_ABOUT_AUTHORS, szAuthorsText ); 1326 bShowingAuthors = !bShowingAuthors; 1327 return TRUE; 1328 } 1329 } 1330 }; break; 1331 1332 case WM_CLOSE: 1333 EndDialog(hWnd, TRUE); 1334 break; 1335 } 1336 1337 return 0; 1338 } 1339 1340 1341 /************************************************************************* 1342 * ShellAboutA [SHELL32.288] 1343 */ 1344 BOOL WINAPI ShellAboutA( HWND hWnd, LPCSTR szApp, LPCSTR szOtherStuff, HICON hIcon ) 1345 { 1346 BOOL ret; 1347 LPWSTR appW = NULL, otherW = NULL; 1348 int len; 1349 1350 if (szApp) 1351 { 1352 len = MultiByteToWideChar(CP_ACP, 0, szApp, -1, NULL, 0); 1353 appW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1354 MultiByteToWideChar(CP_ACP, 0, szApp, -1, appW, len); 1355 } 1356 if (szOtherStuff) 1357 { 1358 len = MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, NULL, 0); 1359 otherW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); 1360 MultiByteToWideChar(CP_ACP, 0, szOtherStuff, -1, otherW, len); 1361 } 1362 1363 ret = ShellAboutW(hWnd, appW, otherW, hIcon); 1364 1365 HeapFree(GetProcessHeap(), 0, otherW); 1366 HeapFree(GetProcessHeap(), 0, appW); 1367 return ret; 1368 } 1369 1370 1371 /************************************************************************* 1372 * ShellAboutW [SHELL32.289] 1373 */ 1374 BOOL WINAPI ShellAboutW( HWND hWnd, LPCWSTR szApp, LPCWSTR szOtherStuff, 1375 HICON hIcon ) 1376 { 1377 ABOUT_INFO info; 1378 HRSRC hRes; 1379 DLGTEMPLATE *DlgTemplate; 1380 BOOL bRet; 1381 #ifdef __REACTOS__ 1382 WCHAR szVersionString[256]; 1383 #endif 1384 1385 TRACE("\n"); 1386 1387 // DialogBoxIndirectParamW will be called with the hInstance of the calling application, so we have to preload the dialog template 1388 hRes = FindResourceW(shell32_hInstance, MAKEINTRESOURCEW(IDD_ABOUT), (LPWSTR)RT_DIALOG); 1389 if(!hRes) 1390 return FALSE; 1391 1392 DlgTemplate = (DLGTEMPLATE *)LoadResource(shell32_hInstance, hRes); 1393 if(!DlgTemplate) 1394 return FALSE; 1395 1396 #ifdef __REACTOS__ 1397 /* Output the version OS kernel strings */ 1398 StringCchPrintfW(szVersionString, _countof(szVersionString), L"%S (%S)", KERNEL_VERSION_STR, KERNEL_VERSION_BUILD_STR); 1399 #endif 1400 1401 info.szApp = szApp; 1402 #ifdef __REACTOS__ 1403 info.szOSVersion = szVersionString; 1404 #endif 1405 info.szOtherStuff = szOtherStuff; 1406 info.hIcon = hIcon ? hIcon : LoadIconW( 0, (LPWSTR)IDI_WINLOGO ); 1407 1408 bRet = DialogBoxIndirectParamW((HINSTANCE)GetWindowLongPtrW( hWnd, GWLP_HINSTANCE ), 1409 DlgTemplate, hWnd, AboutDlgProc, (LPARAM)&info ); 1410 return bRet; 1411 } 1412 1413 /************************************************************************* 1414 * FreeIconList (SHELL32.@) 1415 */ 1416 void WINAPI FreeIconList( DWORD dw ) 1417 { 1418 FIXME("%x: stub\n",dw); 1419 } 1420 1421 /************************************************************************* 1422 * SHLoadNonloadedIconOverlayIdentifiers (SHELL32.@) 1423 */ 1424 HRESULT WINAPI SHLoadNonloadedIconOverlayIdentifiers( VOID ) 1425 { 1426 FIXME("stub\n"); 1427 return S_OK; 1428 } 1429