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