1 /* 2 * ReactOS kernel 3 * Copyright (C) 2004 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License along 16 * with this program; if not, write to the Free Software Foundation, Inc., 17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 18 */ 19 /* 20 * COPYRIGHT: See COPYING in the top level directory 21 * PROJECT: ReactOS system libraries 22 * FILE: dll/win32/userenv/desktop.c 23 * PURPOSE: Desktop and start menu support functions. 24 * PROGRAMMER: Eric Kohl 25 */ 26 27 #include "precomp.h" 28 29 #include <shlobj.h> 30 31 #define NDEBUG 32 #include <debug.h> 33 34 /* FUNCTIONS ***************************************************************/ 35 36 static 37 BOOL 38 GetDesktopPath(BOOL bCommonPath, 39 LPWSTR lpDesktopPath) 40 { 41 WCHAR szPath[MAX_PATH]; 42 DWORD dwLength; 43 DWORD dwType; 44 HKEY hKey; 45 LONG Error; 46 47 DPRINT("GetDesktopPath() called\n"); 48 49 Error = RegOpenKeyExW(HKEY_CURRENT_USER, 50 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", 51 0, 52 KEY_QUERY_VALUE, 53 &hKey); 54 if (Error != ERROR_SUCCESS) 55 { 56 DPRINT1("RegOpenKeyExW() failed\n"); 57 SetLastError((DWORD)Error); 58 return FALSE; 59 } 60 61 dwLength = MAX_PATH * sizeof(WCHAR); 62 Error = RegQueryValueExW(hKey, 63 bCommonPath ? L"Common Desktop" : L"Desktop", 64 0, 65 &dwType, 66 (LPBYTE)szPath, 67 &dwLength); 68 if (Error != ERROR_SUCCESS) 69 { 70 DPRINT1("RegQueryValueExW() failed\n"); 71 RegCloseKey(hKey); 72 SetLastError((DWORD)Error); 73 return FALSE; 74 } 75 76 RegCloseKey(hKey); 77 78 if (dwType == REG_EXPAND_SZ) 79 { 80 ExpandEnvironmentStringsW(szPath, 81 lpDesktopPath, 82 MAX_PATH); 83 } 84 else 85 { 86 wcscpy(lpDesktopPath, szPath); 87 } 88 89 DPRINT("GetDesktopPath() done\n"); 90 91 return TRUE; 92 } 93 94 95 static 96 BOOL 97 GetProgramsPath(BOOL bCommonPath, 98 LPWSTR lpProgramsPath) 99 { 100 WCHAR szPath[MAX_PATH]; 101 DWORD dwLength; 102 DWORD dwType; 103 HKEY hKey; 104 LONG Error; 105 106 DPRINT("GetProgramsPath() called\n"); 107 108 Error = RegOpenKeyExW(HKEY_CURRENT_USER, 109 L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\User Shell Folders", 110 0, 111 KEY_QUERY_VALUE, 112 &hKey); 113 if (Error != ERROR_SUCCESS) 114 { 115 DPRINT1("RegOpenKeyExW() failed\n"); 116 SetLastError((DWORD)Error); 117 return FALSE; 118 } 119 120 dwLength = MAX_PATH * sizeof(WCHAR); 121 Error = RegQueryValueExW(hKey, 122 bCommonPath ? L"Common Programs" : L"Programs", 123 0, 124 &dwType, 125 (LPBYTE)szPath, 126 &dwLength); 127 if (Error != ERROR_SUCCESS) 128 { 129 DPRINT1("RegQueryValueExW() failed\n"); 130 RegCloseKey(hKey); 131 SetLastError((DWORD)Error); 132 return FALSE; 133 } 134 135 RegCloseKey(hKey); 136 137 if (dwType == REG_EXPAND_SZ) 138 { 139 ExpandEnvironmentStringsW(szPath, 140 lpProgramsPath, 141 MAX_PATH); 142 } 143 else 144 { 145 wcscpy(lpProgramsPath, 146 szPath); 147 } 148 149 DPRINT("GetProgramsPath() done\n"); 150 151 return TRUE; 152 } 153 154 155 BOOL 156 WINAPI 157 AddDesktopItemA(BOOL bCommonItem, 158 LPCSTR lpItemName, 159 LPCSTR lpArguments, 160 LPCSTR lpIconLocation, 161 INT iIcon, 162 LPCSTR lpWorkingDirectory, /* Optional */ 163 WORD wHotKey, 164 INT iShowCmd) 165 { 166 UNICODE_STRING ItemName; 167 UNICODE_STRING Arguments; 168 UNICODE_STRING IconLocation; 169 UNICODE_STRING WorkingDirectory; 170 BOOL bResult; 171 172 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName, 173 (LPSTR)lpItemName)) 174 { 175 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 176 return FALSE; 177 } 178 179 if (!RtlCreateUnicodeStringFromAsciiz(&Arguments, 180 (LPSTR)lpArguments)) 181 { 182 RtlFreeUnicodeString(&ItemName); 183 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 184 return FALSE; 185 } 186 187 if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation, 188 (LPSTR)lpIconLocation)) 189 { 190 RtlFreeUnicodeString(&Arguments); 191 RtlFreeUnicodeString(&ItemName); 192 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 193 return FALSE; 194 } 195 196 if (lpWorkingDirectory != NULL) 197 { 198 if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory, 199 (LPSTR)lpWorkingDirectory)) 200 { 201 RtlFreeUnicodeString(&IconLocation); 202 RtlFreeUnicodeString(&Arguments); 203 RtlFreeUnicodeString(&ItemName); 204 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 205 return FALSE; 206 } 207 } 208 209 bResult = AddDesktopItemW(bCommonItem, 210 ItemName.Buffer, 211 Arguments.Buffer, 212 IconLocation.Buffer, 213 iIcon, 214 (lpWorkingDirectory != NULL) ? WorkingDirectory.Buffer : NULL, 215 wHotKey, 216 iShowCmd); 217 218 if (lpWorkingDirectory != NULL) 219 { 220 RtlFreeUnicodeString(&WorkingDirectory); 221 } 222 223 RtlFreeUnicodeString(&IconLocation); 224 RtlFreeUnicodeString(&Arguments); 225 RtlFreeUnicodeString(&ItemName); 226 227 return bResult; 228 } 229 230 231 BOOL 232 WINAPI 233 AddDesktopItemW(BOOL bCommonDesktop, 234 LPCWSTR lpItemName, 235 LPCWSTR lpArguments, 236 LPCWSTR lpIconLocation, 237 INT iIcon, 238 LPCWSTR lpWorkingDirectory, /* Optional */ 239 WORD wHotKey, 240 INT iShowCmd) 241 { 242 DYN_FUNCS Ole32; 243 WCHAR szLinkPath[MAX_PATH]; 244 WCHAR szArguments[MAX_PATH]; 245 WCHAR szCommand[MAX_PATH]; 246 WIN32_FIND_DATAW FindData; 247 HANDLE hFind; 248 LPWSTR Ptr; 249 DWORD dwLength; 250 IShellLinkW* psl; 251 IPersistFile* ppf; 252 HRESULT hr; 253 BOOL bResult; 254 255 DPRINT("AddDesktopItemW() called\n"); 256 257 bResult = FALSE; 258 259 if (!GetDesktopPath(bCommonDesktop, szLinkPath)) 260 { 261 DPRINT1("GetDesktopPath() failed\n"); 262 return FALSE; 263 } 264 DPRINT("Desktop path: '%S'\n", szLinkPath); 265 266 /* Make sure the path exists */ 267 hFind = FindFirstFileW(szLinkPath, 268 &FindData); 269 if (hFind == INVALID_HANDLE_VALUE) 270 { 271 DPRINT("'%S' does not exist\n", szLinkPath); 272 273 /* Create directory path */ 274 if (!CreateDirectoryPath(szLinkPath, NULL)) 275 return FALSE; 276 } 277 else 278 { 279 DPRINT("'%S' exists\n", szLinkPath); 280 FindClose(hFind); 281 } 282 283 /* Append backslash, item name and ".lnk" extension */ 284 wcscat(szLinkPath, L"\\"); 285 wcscat(szLinkPath, lpItemName); 286 wcscat(szLinkPath, L".lnk"); 287 DPRINT("Link path: '%S'\n", szLinkPath); 288 289 /* Split 'lpArguments' string into command and arguments */ 290 Ptr = wcschr(lpArguments, L' '); 291 DPRINT("Ptr %p lpArguments %p\n", Ptr, lpArguments); 292 if (Ptr != NULL) 293 { 294 dwLength = (DWORD)(Ptr - lpArguments); 295 DPRINT("dwLength %lu\n", dwLength); 296 memcpy(szCommand, lpArguments, dwLength * sizeof(WCHAR)); 297 szCommand[dwLength] = 0; 298 Ptr++; 299 wcscpy(szArguments, Ptr); 300 } 301 else 302 { 303 wcscpy(szCommand, lpArguments); 304 szArguments[0] = 0; 305 } 306 DPRINT("szCommand: '%S'\n", szCommand); 307 DPRINT("szArguments: '%S'\n", szArguments); 308 309 /* Dynamically load ole32.dll */ 310 if (!LoadDynamicImports(&DynOle32, &Ole32)) 311 { 312 DPRINT1("USERENV: Unable to load OLE32.DLL\n"); 313 return FALSE; 314 } 315 316 Ole32.fn.CoInitialize(NULL); 317 318 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink, 319 NULL, 320 CLSCTX_INPROC_SERVER, 321 &IID_IShellLinkW, 322 (LPVOID*)&psl); 323 if (!SUCCEEDED(hr)) 324 { 325 Ole32.fn.CoUninitialize(); 326 UnloadDynamicImports(&Ole32); 327 return FALSE; 328 } 329 330 hr = psl->lpVtbl->QueryInterface(psl, 331 &IID_IPersistFile, 332 (LPVOID*)&ppf); 333 if (SUCCEEDED(hr)) 334 { 335 psl->lpVtbl->SetDescription(psl, 336 lpItemName); 337 338 psl->lpVtbl->SetPath(psl, 339 szCommand); 340 341 psl->lpVtbl->SetArguments(psl, 342 szArguments); 343 344 psl->lpVtbl->SetIconLocation(psl, 345 lpIconLocation, 346 iIcon); 347 348 if (lpWorkingDirectory != NULL) 349 { 350 psl->lpVtbl->SetWorkingDirectory(psl, 351 lpWorkingDirectory); 352 } 353 else 354 { 355 psl->lpVtbl->SetWorkingDirectory(psl, 356 L"%HOMEDRIVE%%HOMEPATH%"); 357 } 358 359 psl->lpVtbl->SetHotkey(psl, 360 wHotKey); 361 362 psl->lpVtbl->SetShowCmd(psl, 363 iShowCmd); 364 365 hr = ppf->lpVtbl->Save(ppf, 366 szLinkPath, 367 TRUE); 368 if (SUCCEEDED(hr)) 369 bResult = TRUE; 370 371 ppf->lpVtbl->Release(ppf); 372 } 373 374 psl->lpVtbl->Release(psl); 375 376 Ole32.fn.CoUninitialize(); 377 378 UnloadDynamicImports(&Ole32); 379 380 DPRINT("AddDesktopItemW() done\n"); 381 382 return bResult; 383 } 384 385 386 BOOL 387 WINAPI 388 DeleteDesktopItemA(BOOL bCommonItem, 389 LPCSTR lpItemName) 390 { 391 UNICODE_STRING ItemName; 392 BOOL bResult; 393 394 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName, 395 (LPSTR)lpItemName)) 396 { 397 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 398 return FALSE; 399 } 400 401 bResult = DeleteDesktopItemW(bCommonItem, 402 ItemName.Buffer); 403 404 RtlFreeUnicodeString(&ItemName); 405 406 return bResult; 407 } 408 409 410 BOOL 411 WINAPI 412 DeleteDesktopItemW(BOOL bCommonItem, 413 LPCWSTR lpItemName) 414 { 415 WCHAR szLinkPath[MAX_PATH]; 416 417 DPRINT("DeleteDesktopItemW() called\n"); 418 419 if (!GetDesktopPath(bCommonItem, szLinkPath)) 420 { 421 DPRINT1("GetDesktopPath() failed\n"); 422 return FALSE; 423 } 424 425 wcscat(szLinkPath, L"\\"); 426 wcscat(szLinkPath, lpItemName); 427 wcscat(szLinkPath, L".lnk"); 428 DPRINT("Link path: '%S'\n", szLinkPath); 429 430 return DeleteFileW (szLinkPath); 431 } 432 433 434 BOOL 435 WINAPI 436 CreateGroupA(LPCSTR lpGroupName, 437 BOOL bCommonGroup) 438 { 439 UNICODE_STRING GroupName; 440 BOOL bResult; 441 442 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName, 443 (LPSTR)lpGroupName)) 444 { 445 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 446 return FALSE; 447 } 448 449 bResult = CreateGroupW(GroupName.Buffer, bCommonGroup); 450 451 RtlFreeUnicodeString(&GroupName); 452 453 return bResult; 454 } 455 456 457 BOOL 458 WINAPI 459 CreateGroupW(LPCWSTR lpGroupName, 460 BOOL bCommonGroup) 461 { 462 WCHAR szGroupPath[MAX_PATH]; 463 464 DPRINT1("CreateGroupW() called\n"); 465 466 if (lpGroupName == NULL || *lpGroupName == 0) 467 return TRUE; 468 469 if (!GetProgramsPath(bCommonGroup, szGroupPath)) 470 { 471 DPRINT1("GetProgramsPath() failed\n"); 472 return FALSE; 473 } 474 DPRINT1("Programs path: '%S'\n", szGroupPath); 475 476 wcscat(szGroupPath, L"\\"); 477 wcscat(szGroupPath, lpGroupName); 478 DPRINT1("Group path: '%S'\n", szGroupPath); 479 480 /* Create directory path */ 481 if (!CreateDirectoryPath (szGroupPath, NULL)) 482 return FALSE; 483 484 /* FIXME: Notify the shell */ 485 486 DPRINT1("CreateGroupW() done\n"); 487 488 return TRUE; 489 } 490 491 492 BOOL 493 WINAPI 494 DeleteGroupA(LPCSTR lpGroupName, 495 BOOL bCommonGroup) 496 { 497 UNICODE_STRING GroupName; 498 BOOL bResult; 499 500 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName, 501 (LPSTR)lpGroupName)) 502 { 503 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 504 return FALSE; 505 } 506 507 bResult = DeleteGroupW(GroupName.Buffer, bCommonGroup); 508 509 RtlFreeUnicodeString(&GroupName); 510 511 return bResult; 512 } 513 514 515 BOOL 516 WINAPI 517 DeleteGroupW(LPCWSTR lpGroupName, 518 BOOL bCommonGroup) 519 { 520 WCHAR szGroupPath[MAX_PATH]; 521 522 DPRINT("DeleteGroupW() called\n"); 523 524 if (lpGroupName == NULL || *lpGroupName == 0) 525 return TRUE; 526 527 if (!GetProgramsPath(bCommonGroup, szGroupPath)) 528 { 529 DPRINT1("GetProgramsPath() failed\n"); 530 return FALSE; 531 } 532 DPRINT("Programs path: '%S'\n", szGroupPath); 533 534 wcscat(szGroupPath, L"\\"); 535 wcscat(szGroupPath, lpGroupName); 536 DPRINT("Group path: '%S'\n", szGroupPath); 537 538 /* Remove directory path */ 539 if (!RemoveDirectoryPath (szGroupPath)) 540 return FALSE; 541 542 /* FIXME: Notify the shell */ 543 544 DPRINT("DeleteGroupW() done\n"); 545 546 return TRUE; 547 } 548 549 550 BOOL 551 WINAPI 552 AddItemA(LPCSTR lpGroupName, /* Optional */ 553 BOOL bCommonGroup, 554 LPCSTR lpItemName, 555 LPCSTR lpArguments, 556 LPCSTR lpIconLocation, 557 INT iIcon, 558 LPCSTR lpWorkingDirectory, /* Optional */ 559 WORD wHotKey, 560 INT iShowCmd) 561 { 562 UNICODE_STRING GroupName; 563 UNICODE_STRING ItemName; 564 UNICODE_STRING Arguments; 565 UNICODE_STRING IconLocation; 566 UNICODE_STRING WorkingDirectory; 567 BOOL bResult; 568 569 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName, 570 (LPSTR)lpItemName)) 571 { 572 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 573 return FALSE; 574 } 575 576 if (!RtlCreateUnicodeStringFromAsciiz(&Arguments, 577 (LPSTR)lpArguments)) 578 { 579 RtlFreeUnicodeString(&ItemName); 580 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 581 return FALSE; 582 } 583 584 if (!RtlCreateUnicodeStringFromAsciiz(&IconLocation, 585 (LPSTR)lpIconLocation)) 586 { 587 RtlFreeUnicodeString(&Arguments); 588 RtlFreeUnicodeString(&ItemName); 589 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 590 return FALSE; 591 } 592 593 if (lpGroupName != NULL) 594 { 595 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName, 596 (LPSTR)lpGroupName)) 597 { 598 RtlFreeUnicodeString(&IconLocation); 599 RtlFreeUnicodeString(&Arguments); 600 RtlFreeUnicodeString(&ItemName); 601 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 602 return FALSE; 603 } 604 } 605 606 if (lpWorkingDirectory != NULL) 607 { 608 if (!RtlCreateUnicodeStringFromAsciiz(&WorkingDirectory, 609 (LPSTR)lpWorkingDirectory)) 610 { 611 if (lpGroupName != NULL) 612 { 613 RtlFreeUnicodeString(&GroupName); 614 } 615 RtlFreeUnicodeString(&IconLocation); 616 RtlFreeUnicodeString(&Arguments); 617 RtlFreeUnicodeString(&ItemName); 618 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 619 return FALSE; 620 } 621 } 622 623 bResult = AddItemW((lpGroupName != NULL) ? GroupName.Buffer : NULL, 624 bCommonGroup, 625 ItemName.Buffer, 626 Arguments.Buffer, 627 IconLocation.Buffer, 628 iIcon, 629 (lpWorkingDirectory != NULL) ? WorkingDirectory.Buffer : NULL, 630 wHotKey, 631 iShowCmd); 632 633 if (lpGroupName != NULL) 634 { 635 RtlFreeUnicodeString(&GroupName); 636 } 637 638 if (lpWorkingDirectory != NULL) 639 { 640 RtlFreeUnicodeString(&WorkingDirectory); 641 } 642 643 RtlFreeUnicodeString(&IconLocation); 644 RtlFreeUnicodeString(&Arguments); 645 RtlFreeUnicodeString(&ItemName); 646 647 return bResult; 648 } 649 650 651 BOOL 652 WINAPI 653 AddItemW(LPCWSTR lpGroupName, /* Optional */ 654 BOOL bCommonGroup, 655 LPCWSTR lpItemName, 656 LPCWSTR lpArguments, 657 LPCWSTR lpIconLocation, 658 INT iIcon, 659 LPCWSTR lpWorkingDirectory, /* Optional */ 660 WORD wHotKey, 661 INT iShowCmd) 662 { 663 DYN_FUNCS Ole32; 664 WCHAR szLinkPath[MAX_PATH]; 665 WCHAR szArguments[MAX_PATH]; 666 WCHAR szCommand[MAX_PATH]; 667 WIN32_FIND_DATAW FindData; 668 HANDLE hFind; 669 LPWSTR Ptr; 670 DWORD dwLength; 671 IShellLinkW* psl; 672 IPersistFile* ppf; 673 HRESULT hr; 674 BOOL bResult; 675 676 DPRINT("AddItemW() called\n"); 677 678 bResult = FALSE; 679 680 if (!GetProgramsPath(bCommonGroup, szLinkPath)) 681 { 682 DPRINT1("GetProgramsPath() failed\n"); 683 return FALSE; 684 } 685 686 DPRINT("Programs path: '%S'\n", szLinkPath); 687 688 if (lpGroupName != NULL && *lpGroupName != 0) 689 { 690 wcscat(szLinkPath, L"\\"); 691 wcscat(szLinkPath, lpGroupName); 692 693 /* Make sure the path exists */ 694 hFind = FindFirstFileW(szLinkPath, 695 &FindData); 696 if (hFind == INVALID_HANDLE_VALUE) 697 { 698 DPRINT("'%S' does not exist\n", szLinkPath); 699 if (!CreateGroupW(lpGroupName, 700 bCommonGroup)) 701 return FALSE; 702 } 703 else 704 { 705 DPRINT("'%S' exists\n", szLinkPath); 706 FindClose(hFind); 707 } 708 } 709 710 wcscat(szLinkPath, L"\\"); 711 wcscat(szLinkPath, lpItemName); 712 wcscat(szLinkPath, L".lnk"); 713 DPRINT("Link path: '%S'\n", szLinkPath); 714 715 /* Split 'lpArguments' string into command and arguments */ 716 Ptr = wcschr(lpArguments, L' '); 717 DPRINT("Ptr %p lpArguments %p\n", Ptr, lpArguments); 718 if (Ptr != NULL) 719 { 720 dwLength = (DWORD)(Ptr - lpArguments); 721 DPRINT("dwLength %lu\n", dwLength); 722 memcpy(szCommand, lpArguments, dwLength * sizeof(WCHAR)); 723 szCommand[dwLength] = 0; 724 Ptr++; 725 wcscpy(szArguments, Ptr); 726 } 727 else 728 { 729 wcscpy(szCommand, lpArguments); 730 szArguments[0] = 0; 731 } 732 DPRINT("szCommand: '%S'\n", szCommand); 733 DPRINT("szArguments: '%S'\n", szArguments); 734 735 /* Dynamically load ole32.dll */ 736 if (!LoadDynamicImports(&DynOle32, &Ole32)) 737 { 738 DPRINT1("USERENV: Unable to load OLE32.DLL\n"); 739 return FALSE; 740 } 741 742 Ole32.fn.CoInitialize(NULL); 743 744 hr = Ole32.fn.CoCreateInstance(&CLSID_ShellLink, 745 NULL, 746 CLSCTX_INPROC_SERVER, 747 &IID_IShellLinkW, 748 (LPVOID*)&psl); 749 if (!SUCCEEDED(hr)) 750 { 751 Ole32.fn.CoUninitialize(); 752 UnloadDynamicImports(&Ole32); 753 return FALSE; 754 } 755 756 hr = psl->lpVtbl->QueryInterface(psl, 757 &IID_IPersistFile, 758 (LPVOID*)&ppf); 759 if (SUCCEEDED(hr)) 760 { 761 psl->lpVtbl->SetDescription(psl, 762 lpItemName); 763 764 psl->lpVtbl->SetPath(psl, 765 szCommand); 766 767 psl->lpVtbl->SetArguments(psl, 768 szArguments); 769 770 psl->lpVtbl->SetIconLocation(psl, 771 lpIconLocation, 772 iIcon); 773 774 if (lpWorkingDirectory != NULL) 775 { 776 psl->lpVtbl->SetWorkingDirectory(psl, 777 lpWorkingDirectory); 778 } 779 else 780 { 781 psl->lpVtbl->SetWorkingDirectory(psl, 782 L"%HOMEDRIVE%%HOMEPATH%"); 783 } 784 785 psl->lpVtbl->SetHotkey(psl, 786 wHotKey); 787 788 psl->lpVtbl->SetShowCmd(psl, 789 iShowCmd); 790 791 hr = ppf->lpVtbl->Save(ppf, 792 szLinkPath, 793 TRUE); 794 if (SUCCEEDED(hr)) 795 bResult = TRUE; 796 797 ppf->lpVtbl->Release(ppf); 798 } 799 800 psl->lpVtbl->Release(psl); 801 802 Ole32.fn.CoUninitialize(); 803 UnloadDynamicImports(&Ole32); 804 805 DPRINT("AddItemW() done\n"); 806 807 return bResult; 808 } 809 810 811 BOOL 812 WINAPI 813 DeleteItemA(LPCSTR lpGroupName, /* Optional */ 814 BOOL bCommonGroup, 815 LPCSTR lpItemName, 816 BOOL bDeleteGroup) 817 { 818 UNICODE_STRING GroupName; 819 UNICODE_STRING ItemName; 820 BOOL bResult; 821 822 if (lpGroupName != NULL) 823 { 824 if (!RtlCreateUnicodeStringFromAsciiz(&GroupName, 825 (LPSTR)lpGroupName)) 826 { 827 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 828 return FALSE; 829 } 830 } 831 832 if (!RtlCreateUnicodeStringFromAsciiz(&ItemName, 833 (LPSTR)lpItemName)) 834 { 835 if (lpGroupName != NULL) 836 { 837 RtlFreeUnicodeString(&GroupName); 838 } 839 840 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 841 return FALSE; 842 } 843 844 bResult = DeleteItemW((lpGroupName != NULL) ? GroupName.Buffer : NULL, 845 bCommonGroup, 846 ItemName.Buffer, 847 bDeleteGroup); 848 849 RtlFreeUnicodeString(&ItemName); 850 if (lpGroupName != NULL) 851 { 852 RtlFreeUnicodeString(&GroupName); 853 } 854 855 return bResult; 856 } 857 858 859 BOOL 860 WINAPI 861 DeleteItemW(LPCWSTR lpGroupName, /* Optional */ 862 BOOL bCommonGroup, 863 LPCWSTR lpItemName, 864 BOOL bDeleteGroup) 865 { 866 WCHAR szItemPath[MAX_PATH]; 867 LPWSTR Ptr; 868 869 DPRINT("DeleteItemW() called\n"); 870 871 if (!GetProgramsPath(bCommonGroup, szItemPath)) 872 { 873 DPRINT1("GetProgramsPath() failed\n"); 874 return FALSE; 875 } 876 DPRINT("Programs path: '%S'\n", szItemPath); 877 878 if (lpGroupName != NULL && *lpGroupName != 0) 879 { 880 wcscat(szItemPath, L"\\"); 881 wcscat(szItemPath, lpGroupName); 882 } 883 884 wcscat(szItemPath, L"\\"); 885 wcscat(szItemPath, lpItemName); 886 wcscat(szItemPath, L".lnk"); 887 DPRINT("Item path: '%S'\n", szItemPath); 888 889 if (!DeleteFileW(szItemPath)) 890 return FALSE; 891 892 /* FIXME: Notify the shell */ 893 894 if (bDeleteGroup) 895 { 896 Ptr = wcsrchr(szItemPath, L'\\'); 897 if (Ptr == NULL) 898 return TRUE; 899 900 *Ptr = 0; 901 DPRINT("Item path: '%S'\n", szItemPath); 902 if (RemoveDirectoryW(szItemPath)) 903 { 904 /* FIXME: Notify the shell */ 905 } 906 } 907 908 DPRINT("DeleteItemW() done\n"); 909 910 return TRUE; 911 } 912 913 /* EOF */ 914