ReactOS 0.4.15-dev-8021-g7ce96fd
CShellLink.cpp
Go to the documentation of this file.
1/*
2 *
3 * Copyright 1997 Marcus Meissner
4 * Copyright 1998 Juergen Schmied
5 * Copyright 2005 Mike McCormack
6 * Copyright 2009 Andrew Hill
7 * Copyright 2013 Dominik Hornung
8 * Copyright 2017 Hermes Belusca-Maito
9 * Copyright 2018-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 *
25 * NOTES
26 * Nearly complete information about the binary formats
27 * of .lnk files available at http://www.wotsit.org
28 *
29 * You can use winedump to examine the contents of a link file:
30 * winedump lnk sc.lnk
31 *
32 * MSI advertised shortcuts are totally undocumented. They provide an
33 * icon for a program that is not yet installed, and invoke MSI to
34 * install the program when the shortcut is clicked on. They are
35 * created by passing a special string to SetPath, and the information
36 * in that string is parsed an stored.
37 */
38/*
39 * In the following is listed more documentation about the Shell Link file format,
40 * as well as its interface.
41 *
42 * General introduction about "Shell Links" (MSDN):
43 * https://msdn.microsoft.com/en-us/library/windows/desktop/bb776891(v=vs.85).aspx
44 *
45 *
46 * Details of the file format:
47 *
48 * - Official MSDN documentation "[MS-SHLLINK]: Shell Link (.LNK) Binary File Format":
49 * https://msdn.microsoft.com/en-us/library/dd871305.aspx
50 *
51 * - Forensics:
52 * http://forensicswiki.org/wiki/LNK
53 * http://computerforensics.parsonage.co.uk/downloads/TheMeaningofLIFE.pdf
54 * https://ithreats.files.wordpress.com/2009/05/lnk_the_windows_shortcut_file_format.pdf
55 * https://github.com/libyal/liblnk/blob/master/documentation/Windows%20Shortcut%20File%20(LNK)%20format.asciidoc
56 *
57 * - List of possible shell link header flags (SHELL_LINK_DATA_FLAGS enumeration):
58 * https://msdn.microsoft.com/en-us/library/windows/desktop/bb762540(v=vs.85).aspx
59 * https://msdn.microsoft.com/en-us/library/dd891314.aspx
60 *
61 *
62 * In addition to storing its target by using a PIDL, a shell link file also
63 * stores metadata to make the shell able to track the link target, in situations
64 * where the link target is moved amongst local or network directories, or moved
65 * to different volumes. For this, two structures are used:
66 *
67 * - The first and oldest one (from NewShell/WinNT4) is the "LinkInfo" structure,
68 * stored in a serialized manner at the beginning of the shell link file:
69 * https://msdn.microsoft.com/en-us/library/dd871404.aspx
70 * The official API for manipulating this is located in LINKINFO.DLL .
71 *
72 * - The second, more recent one, is an extra binary block appended to the
73 * extra-data list of the shell link file: this is the "TrackerDataBlock":
74 * https://msdn.microsoft.com/en-us/library/dd891376.aspx
75 * Its purpose is for link tracking, and works in coordination with the
76 * "Distributed Link Tracking" service ('TrkWks' client, 'TrkSvr' server).
77 * See a detailed explanation at:
78 * http://www.serverwatch.com/tutorials/article.php/1476701/Searching-for-the-Missing-Link-Distributed-Link-Tracking.htm
79 *
80 *
81 * MSI installations most of the time create so-called "advertised shortcuts".
82 * They provide an icon for a program that may not be installed yet, and invoke
83 * MSI to install the program when the shortcut is opened (resolved).
84 * The philosophy of this approach is explained in detail inside the MSDN article
85 * "Application Resiliency: Unlock the Hidden Features of Windows Installer"
86 * (by Michael Sanford), here:
87 * https://msdn.microsoft.com/en-us/library/aa302344.aspx
88 *
89 * This functionality is implemented by adding a binary "Darwin" data block
90 * of type "EXP_DARWIN_LINK", signature EXP_DARWIN_ID_SIG == 0xA0000006,
91 * to the shell link file:
92 * https://msdn.microsoft.com/en-us/library/dd871369.aspx
93 * or, this could be done more simply by specifying a special link target path
94 * with the IShellLink::SetPath() function. Defining the following GUID:
95 * SHELL32_AdvtShortcutComponent = "::{9db1186e-40df-11d1-aa8c-00c04fb67863}:"
96 * setting a target of the form:
97 * "::{SHELL32_AdvtShortcutComponent}:<MSI_App_ID>"
98 * would automatically create the necessary binary block.
99 *
100 * With that, the target of the shortcut now becomes the MSI data. The latter
101 * is parsed from MSI and retrieved by the shell that then can run the program.
102 *
103 * This MSI functionality, dubbed "link blessing", actually originates from an
104 * older technology introduced in Internet Explorer 3 (and now obsolete since
105 * Internet Explorer 7), called "MS Internet Component Download (MSICD)", see
106 * this MSDN introductory article:
107 * https://msdn.microsoft.com/en-us/library/aa741198(v=vs.85).aspx
108 * and leveraged in Internet Explorer 4 with "Software Update Channels", see:
109 * https://msdn.microsoft.com/en-us/library/aa740931(v=vs.85).aspx
110 * Applications supporting this technology could present shell links having
111 * a special target, see subsection "Modifying the Shortcut" in the article:
112 * https://msdn.microsoft.com/en-us/library/aa741201(v=vs.85).aspx#pub_shor
113 *
114 * Similarly as for the MSI shortcuts, these MSICD shortcuts are created by
115 * specifying a special link target path with the IShellLink::SetPath() function,
116 * defining the following GUID:
117 * SHELL32_AdvtShortcutProduct = "::{9db1186f-40df-11d1-aa8c-00c04fb67863}:"
118 * and setting a target of the form:
119 * "::{SHELL32_AdvtShortcutProduct}:<AppName>::<Path>" .
120 * A tool, called "blesslnk.exe", was also provided for automatizing the process;
121 * its ReadMe can be found in the (now outdated) MS "Internet Client SDK" (INetSDK,
122 * for MS Windows 95 and NT), whose contents can be read at:
123 * http://www.msfn.org/board/topic/145352-new-windows-lnk-vulnerability/?page=4#comment-944223
124 * The MS INetSDK can be found at:
125 * https://web.archive.org/web/20100924000013/http://support.microsoft.com/kb/177877
126 *
127 * Internally the shell link target of these MSICD shortcuts is converted into
128 * a binary data block of a type similar to Darwin / "EXP_DARWIN_LINK", but with
129 * a different signature EXP_LOGO3_ID_SIG == 0xA0000007 . Such shell links are
130 * called "Logo3" shortcuts. They were evoked in this user comment in "The Old
131 * New Thing" blog:
132 * https://blogs.msdn.microsoft.com/oldnewthing/20121210-00/?p=5883#comment-1025083
133 *
134 * The shell exports the API 'SoftwareUpdateMessageBox' (in shdocvw.dll) that
135 * displays a message when an update for an application supporting this
136 * technology is available.
137 *
138 */
139
140#include "precomp.h"
141
142#include <appmgmt.h>
143
145
146/*
147 * Allows to define whether or not Windows-compatible behaviour
148 * should be adopted when setting and retrieving icon location paths.
149 * See CShellLink::SetIconLocation(LPCWSTR pszIconPath, INT iIcon)
150 * for more details.
151 */
152#define ICON_LINK_WINDOWS_COMPAT
153
154#define SHLINK_LOCAL 0
155#define SHLINK_REMOTE 1
156
157/* link file formats */
158
159#include "pshpack1.h"
160
162{
170};
171
173{
178};
179
181{
184 WCHAR label[12]; /* assume 8.3 */
185};
186
187#include "poppack.h"
188
189/* IShellLink Implementation */
190
191static HRESULT ShellLink_UpdatePath(LPCWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath);
192
193/* strdup on the process heap */
195{
196 INT len;
197 LPWSTR p;
198
199 assert(str);
200
201 len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
202 p = (LPWSTR)HeapAlloc(heap, flags, len * sizeof(WCHAR));
203 if (!p)
204 return p;
206 return p;
207}
208
209static LPWSTR __inline strdupW(LPCWSTR src)
210{
211 LPWSTR dest;
212 if (!src) return NULL;
213 dest = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wcslen(src) + 1) * sizeof(WCHAR));
214 if (dest)
215 wcscpy(dest, src);
216 return dest;
217}
218
219// TODO: Use it for constructor & destructor too
221{
223 m_pPidl = NULL;
224
226 m_sPath = NULL;
227 ZeroMemory(&volume, sizeof(volume));
228
236 m_sArgs = NULL;
239
240 m_bRunAs = FALSE;
241 m_bDirty = FALSE;
242
243 if (m_pDBList)
245 m_pDBList = NULL;
246
248}
249
251{
252 m_Header.dwSize = sizeof(m_Header);
253 m_Header.clsid = CLSID_ShellLink;
254 m_Header.dwFlags = 0;
255
261
264 m_Header.wHotKey = 0;
265
266 m_pPidl = NULL;
267
268 m_sPath = NULL;
269 ZeroMemory(&volume, sizeof(volume));
270
274 m_sArgs = NULL;
276 m_bRunAs = FALSE;
277 m_bDirty = FALSE;
278 m_pDBList = NULL;
280 m_hIcon = NULL;
281 m_idCmdFirst = 0;
282
284
286}
287
289{
290 TRACE("-- destroying IShellLink(%p)\n", this);
291
293
295
303}
304
306{
307 TRACE("%p %p\n", this, pclsid);
308
309 if (pclsid == NULL)
310 return E_POINTER;
311 *pclsid = CLSID_ShellLink;
312 return S_OK;
313}
314
315/************************************************************************
316 * IPersistStream_IsDirty (IPersistStream)
317 */
319{
320 TRACE("(%p)\n", this);
321 return (m_bDirty ? S_OK : S_FALSE);
322}
323
325{
326 TRACE("(%p, %s, %x)\n", this, debugstr_w(pszFileName), dwMode);
327
328 if (dwMode == 0)
330
333 if (SUCCEEDED(hr))
334 {
337 hr = Load(stm);
339 m_bDirty = FALSE;
340 }
341 TRACE("-- returning hr %08x\n", hr);
342 return hr;
343}
344
346{
347 BOOL bAlreadyExists;
348 WCHAR szFullPath[MAX_PATH];
349
350 TRACE("(%p)->(%s)\n", this, debugstr_w(pszFileName));
351
352 if (!pszFileName)
353 return E_FAIL;
354
355 bAlreadyExists = PathFileExistsW(pszFileName);
356
359 if (SUCCEEDED(hr))
360 {
361 hr = Save(stm, FALSE);
362
363 if (SUCCEEDED(hr))
364 {
365 GetFullPathNameW(pszFileName, _countof(szFullPath), szFullPath, NULL);
366 if (bAlreadyExists)
368 else
370
371 if (m_sLinkPath)
373
375 m_bDirty = FALSE;
376 }
377 else
378 {
380 WARN("Failed to create shortcut %s\n", debugstr_w(pszFileName));
381 }
382 }
383
384 return hr;
385}
386
388{
389 FIXME("(%p)->(%s)\n", this, debugstr_w(pszFileName));
390 return S_OK;
391}
392
394{
395 *ppszFileName = NULL;
396
397 if (!m_sLinkPath)
398 {
399 /* IPersistFile::GetCurFile called before IPersistFile::Save */
400 return S_FALSE;
401 }
402
403 *ppszFileName = (LPOLESTR)CoTaskMemAlloc((wcslen(m_sLinkPath) + 1) * sizeof(WCHAR));
404 if (!*ppszFileName)
405 {
406 /* out of memory */
407 return E_OUTOFMEMORY;
408 }
409
410 /* copy last saved filename */
411 wcscpy(*ppszFileName, m_sLinkPath);
412
413 return S_OK;
414}
415
416static HRESULT Stream_LoadString(IStream* stm, BOOL unicode, LPWSTR *pstr)
417{
418 TRACE("%p\n", stm);
419
420 USHORT len;
421 DWORD count = 0;
422 HRESULT hr = stm->Read(&len, sizeof(len), &count);
423 if (FAILED(hr) || count != sizeof(len))
424 return E_FAIL;
425
426 if (unicode)
427 len *= sizeof(WCHAR);
428
429 TRACE("reading %d\n", len);
430 LPSTR temp = (LPSTR)HeapAlloc(GetProcessHeap(), 0, len + sizeof(WCHAR));
431 if (!temp)
432 return E_OUTOFMEMORY;
433 count = 0;
434 hr = stm->Read(temp, len, &count);
435 if (FAILED(hr) || count != len)
436 {
438 return E_FAIL;
439 }
440
441 TRACE("read %s\n", debugstr_an(temp, len));
442
443 /* convert to unicode if necessary */
444 LPWSTR str;
445 if (!unicode)
446 {
448 str = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (count + 1) * sizeof(WCHAR));
449 if (!str)
450 {
452 return E_OUTOFMEMORY;
453 }
456 }
457 else
458 {
459 count /= sizeof(WCHAR);
460 str = (LPWSTR)temp;
461 }
462 str[count] = 0;
463
464 *pstr = str;
465
466 return S_OK;
467}
468
469
470/*
471 * NOTE: The following 5 functions are part of LINKINFO.DLL
472 */
474{
475 WCHAR drive[4] = { path[0], ':', '\\', 0 };
476
477 volume->type = GetDriveTypeW(drive);
478 BOOL bRet = GetVolumeInformationW(drive, volume->label, _countof(volume->label), &volume->serial, NULL, NULL, NULL, 0);
479 TRACE("ret = %d type %d serial %08x name %s\n", bRet,
480 volume->type, volume->serial, debugstr_w(volume->label));
481 return bRet;
482}
483
485{
486 struct sized_chunk
487 {
488 DWORD size;
489 unsigned char data[1];
490 } *chunk;
491
492 TRACE("%p\n", stm);
493
494 DWORD size;
495 ULONG count;
496 HRESULT hr = stm->Read(&size, sizeof(size), &count);
497 if (FAILED(hr) || count != sizeof(size))
498 return E_FAIL;
499
500 chunk = static_cast<sized_chunk *>(HeapAlloc(GetProcessHeap(), 0, size));
501 if (!chunk)
502 return E_OUTOFMEMORY;
503
504 chunk->size = size;
505 hr = stm->Read(chunk->data, size - sizeof(size), &count);
506 if (FAILED(hr) || count != (size - sizeof(size)))
507 {
509 return E_FAIL;
510 }
511
512 TRACE("Read %d bytes\n", chunk->size);
513
514 *data = chunk;
515
516 return S_OK;
517}
518
520{
521 volume->serial = vol->dwVolSerial;
522 volume->type = vol->dwType;
523
524 if (!vol->dwVolLabelOfs)
525 return FALSE;
526 if (vol->dwSize <= vol->dwVolLabelOfs)
527 return FALSE;
528 INT len = vol->dwSize - vol->dwVolLabelOfs;
529
530 LPSTR label = (LPSTR)vol;
531 label += vol->dwVolLabelOfs;
533
534 return TRUE;
535}
536
538{
539 UINT len = 0;
540
541 while (len < maxlen && p[len])
542 len++;
543
544 UINT wlen = MultiByteToWideChar(CP_ACP, 0, p, len, NULL, 0);
545 LPWSTR path = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, (wlen + 1) * sizeof(WCHAR));
546 if (!path)
547 return NULL;
548 MultiByteToWideChar(CP_ACP, 0, p, len, path, wlen);
549 path[wlen] = 0;
550
551 return path;
552}
553
556{
557 char *p = NULL;
558 HRESULT hr = Stream_ReadChunk(stm, (LPVOID*) &p);
559 if (FAILED(hr))
560 return hr;
561
562 LOCATION_INFO *loc = reinterpret_cast<LOCATION_INFO *>(p);
563 if (loc->dwTotalSize < sizeof(LOCATION_INFO))
564 {
566 return E_FAIL;
567 }
568
569 /* if there's valid local volume information, load it */
570 if (loc->dwVolTableOfs &&
571 ((loc->dwVolTableOfs + sizeof(LOCAL_VOLUME_INFO)) <= loc->dwTotalSize))
572 {
574
577 }
578
579 /* if there's a local path, load it */
580 DWORD n = loc->dwLocalPathOfs;
581 if (n && n < loc->dwTotalSize)
582 *path = Stream_LoadPath(&p[n], loc->dwTotalSize - n);
583
584 TRACE("type %d serial %08x name %s path %s\n", volume->type,
585 volume->serial, debugstr_w(volume->label), debugstr_w(*path));
586
588 return S_OK;
589}
590
591
592/*
593 * The format of the advertised shortcut info is:
594 *
595 * Offset Description
596 * ------ -----------
597 * 0 Length of the block (4 bytes, usually 0x314)
598 * 4 tag (dword)
599 * 8 string data in ASCII
600 * 8+0x104 string data in UNICODE
601 *
602 * In the original Win32 implementation the buffers are not initialized
603 * to zero, so data trailing the string is random garbage.
604 */
606{
607 LPEXP_DARWIN_LINK pInfo;
608
609 *str = NULL;
610
612 if (!pInfo)
613 return E_FAIL;
614
615 /* Make sure that the size of the structure is valid */
616 if (pInfo->dbh.cbSize != sizeof(*pInfo))
617 {
618 ERR("Ooops. This structure is not as expected...\n");
619 return E_FAIL;
620 }
621
622 TRACE("dwSig %08x string = '%s'\n", pInfo->dbh.dwSignature, debugstr_w(pInfo->szwDarwinID));
623
624 *str = pInfo->szwDarwinID;
625 return S_OK;
626}
627
628/************************************************************************
629 * IPersistStream_Load (IPersistStream)
630 */
632{
633 TRACE("%p %p\n", this, stm);
634
635 if (!stm)
637
638 /* Free all the old stuff */
639 Reset();
640
641 ULONG dwBytesRead = 0;
642 HRESULT hr = stm->Read(&m_Header, sizeof(m_Header), &dwBytesRead);
643 if (FAILED(hr))
644 return hr;
645
646 if (dwBytesRead != sizeof(m_Header))
647 return E_FAIL;
648 if (m_Header.dwSize != sizeof(m_Header))
649 return E_FAIL;
650 if (!IsEqualIID(m_Header.clsid, CLSID_ShellLink))
651 return E_FAIL;
652
653 /* Load the new data in order */
654
655 if (TRACE_ON(shell))
656 {
657 SYSTEMTIME stCreationTime;
658 SYSTEMTIME stLastAccessTime;
659 SYSTEMTIME stLastWriteTime;
660 WCHAR sTemp[MAX_PATH];
661
665
667 NULL, sTemp, _countof(sTemp));
668 TRACE("-- stCreationTime: %s\n", debugstr_w(sTemp));
670 NULL, sTemp, _countof(sTemp));
671 TRACE("-- stLastAccessTime: %s\n", debugstr_w(sTemp));
673 NULL, sTemp, _countof(sTemp));
674 TRACE("-- stLastWriteTime: %s\n", debugstr_w(sTemp));
675 }
676
677 /* load all the new stuff */
679 {
680 hr = ILLoadFromStream(stm, &m_pPidl);
681 if (FAILED(hr))
682 return hr;
683 }
684 pdump(m_pPidl);
685
686 /* Load the location information... */
688 {
690 if (FAILED(hr))
691 return hr;
692 }
693 /* ... but if it is required not to use it, clear it */
695 {
697 m_sPath = NULL;
698 ZeroMemory(&volume, sizeof(volume));
699 }
700
701 BOOL unicode = !!(m_Header.dwFlags & SLDF_UNICODE);
702
704 {
705 hr = Stream_LoadString(stm, unicode, &m_sDescription);
706 if (FAILED(hr))
707 return hr;
708 TRACE("Description -> %s\n", debugstr_w(m_sDescription));
709 }
710
712 {
713 hr = Stream_LoadString(stm, unicode, &m_sPathRel);
714 if (FAILED(hr))
715 return hr;
716 TRACE("Relative Path-> %s\n", debugstr_w(m_sPathRel));
717 }
718
720 {
721 hr = Stream_LoadString(stm, unicode, &m_sWorkDir);
722 if (FAILED(hr))
723 return hr;
725 TRACE("Working Dir -> %s\n", debugstr_w(m_sWorkDir));
726 }
727
729 {
730 hr = Stream_LoadString(stm, unicode, &m_sArgs);
731 if (FAILED(hr))
732 return hr;
733 TRACE("Arguments -> %s\n", debugstr_w(m_sArgs));
734 }
735
737 {
738 hr = Stream_LoadString(stm, unicode, &m_sIcoPath);
739 if (FAILED(hr))
740 return hr;
741 TRACE("Icon file -> %s\n", debugstr_w(m_sIcoPath));
742 }
743
744 /* Now load the optional data block list */
746 if (FAILED(hr)) // FIXME: Should we fail?
747 return hr;
748
749 if (TRACE_ON(shell))
750 {
751#if (NTDDI_VERSION < NTDDI_LONGHORN)
753 {
754 hr = GetAdvertiseInfo(&sProduct, EXP_LOGO3_ID_SIG);
755 if (SUCCEEDED(hr))
756 TRACE("Product -> %s\n", debugstr_w(sProduct));
757 }
758#endif
760 {
762 if (SUCCEEDED(hr))
763 TRACE("Component -> %s\n", debugstr_w(sComponent));
764 }
765 }
766
768 m_bRunAs = TRUE;
769 else
770 m_bRunAs = FALSE;
771
772 TRACE("OK\n");
773
774 pdump(m_pPidl);
775
776 return S_OK;
777}
778
779/************************************************************************
780 * Stream_WriteString
781 *
782 * Helper function for IPersistStream_Save. Writes a unicode string
783 * with terminating nul byte to a stream, preceded by the its length.
784 */
786{
788 USHORT len;
789 DWORD count;
790
791 length = wcslen(str) + 1;
792 if (length > MAXUSHORT)
793 {
794 return E_INVALIDARG;
795 }
796
797 len = (USHORT)length;
798 HRESULT hr = stm->Write(&len, sizeof(len), &count);
799 if (FAILED(hr))
800 return hr;
801
802 length *= sizeof(WCHAR);
803
804 hr = stm->Write(str, (ULONG)length, &count);
805 if (FAILED(hr))
806 return hr;
807
808 return S_OK;
809}
810
811/************************************************************************
812 * Stream_WriteLocationInfo
813 *
814 * Writes the location info to a stream
815 *
816 * FIXME: One day we might want to write the network volume information
817 * and the final path.
818 * Figure out how Windows deals with unicode paths here.
819 */
822{
824 LOCATION_INFO *loc;
825
826 TRACE("%p %s %p\n", stm, debugstr_w(path), volume);
827
828 /* figure out the size of everything */
829 DWORD label_size = WideCharToMultiByte(CP_ACP, 0, volume->label, -1,
830 NULL, 0, NULL, NULL);
831 DWORD path_size = WideCharToMultiByte(CP_ACP, 0, path, -1,
832 NULL, 0, NULL, NULL);
833 DWORD volume_info_size = sizeof(*vol) + label_size;
834 DWORD final_path_size = 1;
835 DWORD total_size = sizeof(*loc) + volume_info_size + path_size + final_path_size;
836
837 /* create pointers to everything */
838 loc = static_cast<LOCATION_INFO *>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, total_size));
839 vol = (LOCAL_VOLUME_INFO*) &loc[1];
840 LPSTR szLabel = (LPSTR) &vol[1];
841 LPSTR szPath = &szLabel[label_size];
842 LPSTR szFinalPath = &szPath[path_size];
843
844 /* fill in the location information header */
845 loc->dwTotalSize = total_size;
846 loc->dwHeaderSize = sizeof(*loc);
847 loc->dwFlags = 1;
848 loc->dwVolTableOfs = sizeof(*loc);
849 loc->dwLocalPathOfs = sizeof(*loc) + volume_info_size;
850 loc->dwNetworkVolTableOfs = 0;
851 loc->dwFinalPathOfs = sizeof(*loc) + volume_info_size + path_size;
852
853 /* fill in the volume information */
854 vol->dwSize = volume_info_size;
855 vol->dwType = volume->type;
856 vol->dwVolSerial = volume->serial;
857 vol->dwVolLabelOfs = sizeof(*vol);
858
859 /* copy in the strings */
860 WideCharToMultiByte(CP_ACP, 0, volume->label, -1,
861 szLabel, label_size, NULL, NULL);
863 szPath, path_size, NULL, NULL);
864 *szFinalPath = 0;
865
866 ULONG count = 0;
867 HRESULT hr = stm->Write(loc, total_size, &count);
868 HeapFree(GetProcessHeap(), 0, loc);
869
870 return hr;
871}
872
873/************************************************************************
874 * IPersistStream_Save (IPersistStream)
875 *
876 * FIXME: makes assumptions about byte order
877 */
879{
880 TRACE("%p %p %x\n", this, stm, fClearDirty);
881
882 m_Header.dwSize = sizeof(m_Header);
883 m_Header.clsid = CLSID_ShellLink;
884
885 /*
886 * Reset the flags: keep only the flags related to data blocks as they were
887 * already set in accordance by the different mutator member functions.
888 * The other flags will be determined now by the presence or absence of data.
889 */
892#if (NTDDI_VERSION < NTDDI_LONGHORN)
894#endif
896 // TODO: When we will support Vista+ functionality, add other flags to this list.
897
898 /* The stored strings are in UNICODE */
900
901 if (m_pPidl)
903 if (m_sPath)
907 if (m_sPathRel && *m_sPathRel)
909 if (m_sWorkDir && *m_sWorkDir)
911 if (m_sArgs && *m_sArgs)
913 if (m_sIcoPath && *m_sIcoPath)
915 if (m_bRunAs)
917
918 /* Write the shortcut header */
919 ULONG count;
920 HRESULT hr = stm->Write(&m_Header, sizeof(m_Header), &count);
921 if (FAILED(hr))
922 {
923 ERR("Write failed\n");
924 return hr;
925 }
926
927 /* Save the data in order */
928
929 if (m_pPidl)
930 {
931 hr = ILSaveToStream(stm, m_pPidl);
932 if (FAILED(hr))
933 {
934 ERR("Failed to write PIDL\n");
935 return hr;
936 }
937 }
938
939 if (m_sPath)
940 {
942 if (FAILED(hr))
943 return hr;
944 }
945
947 {
949 if (FAILED(hr))
950 return hr;
951 }
952
954 {
956 if (FAILED(hr))
957 return hr;
958 }
959
961 {
963 if (FAILED(hr))
964 return hr;
965 }
966
968 {
970 if (FAILED(hr))
971 return hr;
972 }
973
975 {
977 if (FAILED(hr))
978 return hr;
979 }
980
981 /*
982 * Now save the data block list.
983 *
984 * NOTE that both advertised Product and Component are already saved
985 * inside Logo3 and Darwin data blocks in the m_pDBList list, and the
986 * m_Header.dwFlags is suitably initialized.
987 */
989 if (FAILED(hr))
990 return hr;
991
992 /* Clear the dirty bit if requested */
993 if (fClearDirty)
994 m_bDirty = FALSE;
995
996 return hr;
997}
998
999/************************************************************************
1000 * IPersistStream_GetSizeMax (IPersistStream)
1001 */
1003{
1004 TRACE("(%p)\n", this);
1005 return E_NOTIMPL;
1006}
1007
1009{
1011 return FALSE;
1012
1013 return TRUE;
1014}
1015
1016/**************************************************************************
1017 * ShellLink_UpdatePath
1018 * update absolute path in sPath using relative path in sPathRel
1019 */
1020static HRESULT ShellLink_UpdatePath(LPCWSTR sPathRel, LPCWSTR path, LPCWSTR sWorkDir, LPWSTR* psPath)
1021{
1022 if (!path || !psPath)
1023 return E_INVALIDARG;
1024
1025 if (!*psPath && sPathRel)
1026 {
1027 WCHAR buffer[2*MAX_PATH], abs_path[2*MAX_PATH];
1028 LPWSTR final = NULL;
1029
1030 /* first try if [directory of link file] + [relative path] finds an existing file */
1031
1032 GetFullPathNameW(path, MAX_PATH * 2, buffer, &final);
1033 if (!final)
1034 final = buffer;
1035 wcscpy(final, sPathRel);
1036
1037 *abs_path = '\0';
1038
1040 {
1041 if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final))
1042 wcscpy(abs_path, buffer);
1043 }
1044 else
1045 {
1046 /* try if [working directory] + [relative path] finds an existing file */
1047 if (sWorkDir)
1048 {
1049 wcscpy(buffer, sWorkDir);
1050 wcscpy(PathAddBackslashW(buffer), sPathRel);
1051
1053 if (!GetFullPathNameW(buffer, MAX_PATH, abs_path, &final))
1054 wcscpy(abs_path, buffer);
1055 }
1056 }
1057
1058 /* FIXME: This is even not enough - not all shell links can be resolved using this algorithm. */
1059 if (!*abs_path)
1060 wcscpy(abs_path, sPathRel);
1061
1062 *psPath = strdupW(abs_path);
1063 if (!*psPath)
1064 return E_OUTOFMEMORY;
1065 }
1066
1067 return S_OK;
1068}
1069
1071{
1072 HRESULT hr;
1073 LPWSTR pszFileW;
1074 WIN32_FIND_DATAW wfd;
1075
1076 TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%u)(%s)\n",
1077 this, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(m_sPath));
1078
1079 /* Allocate a temporary UNICODE buffer */
1080 pszFileW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchMaxPath * sizeof(WCHAR));
1081 if (!pszFileW)
1082 return E_OUTOFMEMORY;
1083
1084 /* Call the UNICODE function */
1085 hr = GetPath(pszFileW, cchMaxPath, &wfd, fFlags);
1086
1087 /* Convert the file path back to ANSI */
1088 WideCharToMultiByte(CP_ACP, 0, pszFileW, -1,
1089 pszFile, cchMaxPath, NULL, NULL);
1090
1091 /* Free the temporary buffer */
1092 HeapFree(GetProcessHeap(), 0, pszFileW);
1093
1094 if (pfd)
1095 {
1096 ZeroMemory(pfd, sizeof(*pfd));
1097
1098 /* Copy the file data if a file path was returned */
1099 if (*pszFile)
1100 {
1101 DWORD len;
1102
1103 /* Copy the fixed part */
1104 CopyMemory(pfd, &wfd, FIELD_OFFSET(WIN32_FIND_DATAA, cFileName));
1105
1106 /* Convert the file names to ANSI */
1107 len = lstrlenW(wfd.cFileName);
1108 WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, len + 1,
1109 pfd->cFileName, sizeof(pfd->cFileName), NULL, NULL);
1110 len = lstrlenW(wfd.cAlternateFileName);
1111 WideCharToMultiByte(CP_ACP, 0, wfd.cAlternateFileName, len + 1,
1112 pfd->cAlternateFileName, sizeof(pfd->cAlternateFileName), NULL, NULL);
1113 }
1114 }
1115
1116 return hr;
1117}
1118
1120{
1121 TRACE("(%p)->(ppidl=%p)\n", this, ppidl);
1122
1123 if (!m_pPidl)
1124 {
1125 *ppidl = NULL;
1126 return S_FALSE;
1127 }
1128
1129 *ppidl = ILClone(m_pPidl);
1130 return S_OK;
1131}
1132
1134{
1135 TRACE("(%p)->(pidl=%p)\n", this, pidl);
1136 return SetTargetFromPIDLOrPath(pidl, NULL);
1137}
1138
1140{
1141 TRACE("(%p)->(%p len=%u)\n", this, pszName, cchMaxName);
1142
1143 if (cchMaxName)
1144 *pszName = 0;
1145
1146 if (m_sDescription)
1148 pszName, cchMaxName, NULL, NULL);
1149
1150 return S_OK;
1151}
1152
1154{
1155 TRACE("(%p)->(pName=%s)\n", this, pszName);
1156
1159
1160 if (pszName)
1161 {
1163 if (!m_sDescription)
1164 return E_OUTOFMEMORY;
1165 }
1166 m_bDirty = TRUE;
1167
1168 return S_OK;
1169}
1170
1172{
1173 TRACE("(%p)->(%p len=%u)\n", this, pszDir, cchMaxPath);
1174
1175 if (cchMaxPath)
1176 *pszDir = 0;
1177
1178 if (m_sWorkDir)
1180 pszDir, cchMaxPath, NULL, NULL);
1181
1182 return S_OK;
1183}
1184
1186{
1187 TRACE("(%p)->(dir=%s)\n", this, pszDir);
1188
1190 m_sWorkDir = NULL;
1191
1192 if (pszDir)
1193 {
1195 if (!m_sWorkDir)
1196 return E_OUTOFMEMORY;
1197 }
1198 m_bDirty = TRUE;
1199
1200 return S_OK;
1201}
1202
1204{
1205 TRACE("(%p)->(%p len=%u)\n", this, pszArgs, cchMaxPath);
1206
1207 if (cchMaxPath)
1208 *pszArgs = 0;
1209
1210 if (m_sArgs)
1212 pszArgs, cchMaxPath, NULL, NULL);
1213
1214 return S_OK;
1215}
1216
1218{
1219 TRACE("(%p)->(args=%s)\n", this, pszArgs);
1220
1222 m_sArgs = NULL;
1223
1224 if (pszArgs)
1225 {
1226 m_sArgs = HEAP_strdupAtoW(GetProcessHeap(), 0, pszArgs);
1227 if (!m_sArgs)
1228 return E_OUTOFMEMORY;
1229 }
1230 m_bDirty = TRUE;
1231
1232 return S_OK;
1233}
1234
1236{
1237 TRACE("(%p)->(%p)(0x%08x)\n", this, pwHotkey, m_Header.wHotKey);
1238 *pwHotkey = m_Header.wHotKey;
1239 return S_OK;
1240}
1241
1243{
1244 TRACE("(%p)->(hotkey=%x)\n", this, wHotkey);
1245
1246 m_Header.wHotKey = wHotkey;
1247 m_bDirty = TRUE;
1248
1249 return S_OK;
1250}
1251
1253{
1254 TRACE("(%p)->(%p) %d\n", this, piShowCmd, m_Header.nShowCommand);
1255 *piShowCmd = m_Header.nShowCommand;
1256 return S_OK;
1257}
1258
1260{
1261 TRACE("(%p) %d\n", this, iShowCmd);
1262
1263 m_Header.nShowCommand = iShowCmd;
1264 m_bDirty = TRUE;
1265
1266 return S_OK;
1267}
1268
1270{
1271 HRESULT hr;
1272 LPWSTR pszIconPathW;
1273
1274 TRACE("(%p)->(%p len=%u iicon=%p)\n", this, pszIconPath, cchIconPath, piIcon);
1275
1276 /* Allocate a temporary UNICODE buffer */
1277 pszIconPathW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchIconPath * sizeof(WCHAR));
1278 if (!pszIconPathW)
1279 return E_OUTOFMEMORY;
1280
1281 /* Call the UNICODE function */
1282 hr = GetIconLocation(pszIconPathW, cchIconPath, piIcon);
1283
1284 /* Convert the file path back to ANSI */
1285 WideCharToMultiByte(CP_ACP, 0, pszIconPathW, -1,
1286 pszIconPath, cchIconPath, NULL, NULL);
1287
1288 /* Free the temporary buffer */
1289 HeapFree(GetProcessHeap(), 0, pszIconPathW);
1290
1291 return hr;
1292}
1293
1295{
1296 HRESULT hr;
1297 LPWSTR pszIconFileW;
1298
1299 TRACE("(%p)->(%u %p len=%u piIndex=%p pwFlags=%p)\n", this, uFlags, pszIconFile, cchMax, piIndex, pwFlags);
1300
1301 /* Allocate a temporary UNICODE buffer */
1302 pszIconFileW = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, cchMax * sizeof(WCHAR));
1303 if (!pszIconFileW)
1304 return E_OUTOFMEMORY;
1305
1306 /* Call the UNICODE function */
1307 hr = GetIconLocation(uFlags, pszIconFileW, cchMax, piIndex, pwFlags);
1308
1309 /* Convert the file path back to ANSI */
1310 WideCharToMultiByte(CP_ACP, 0, pszIconFileW, -1,
1311 pszIconFile, cchMax, NULL, NULL);
1312
1313 /* Free the temporary buffer */
1314 HeapFree(GetProcessHeap(), 0, pszIconFileW);
1315
1316 return hr;
1317}
1318
1319HRESULT STDMETHODCALLTYPE CShellLink::Extract(PCSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
1320{
1321 TRACE("(%p)->(path=%s iicon=%u)\n", this, pszFile, nIconIndex);
1322
1323 LPWSTR str = NULL;
1324 if (pszFile)
1325 {
1326 str = HEAP_strdupAtoW(GetProcessHeap(), 0, pszFile);
1327 if (!str)
1328 return E_OUTOFMEMORY;
1329 }
1330
1331 HRESULT hr = Extract(str, nIconIndex, phiconLarge, phiconSmall, nIconSize);
1332
1333 if (str)
1335
1336 return hr;
1337}
1338
1340{
1341 TRACE("(%p)->(path=%s iicon=%u)\n", this, pszIconPath, iIcon);
1342
1343 LPWSTR str = NULL;
1344 if (pszIconPath)
1345 {
1346 str = HEAP_strdupAtoW(GetProcessHeap(), 0, pszIconPath);
1347 if (!str)
1348 return E_OUTOFMEMORY;
1349 }
1350
1351 HRESULT hr = SetIconLocation(str, iIcon);
1352
1353 if (str)
1355
1356 return hr;
1357}
1358
1360{
1361 TRACE("(%p)->(path=%s %x)\n", this, pszPathRel, dwReserved);
1362
1364 m_sPathRel = NULL;
1365
1366 if (pszPathRel)
1367 {
1368 m_sPathRel = HEAP_strdupAtoW(GetProcessHeap(), 0, pszPathRel);
1369 m_bDirty = TRUE;
1370 }
1371
1373}
1374
1375static LPWSTR
1377{
1378 DWORD Result, sz = 0;
1379
1380 Result = CommandLineFromMsiDescriptor(component, NULL, &sz);
1381 if (Result != ERROR_SUCCESS)
1382 return NULL;
1383
1384 sz++;
1385 LPWSTR path = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sz * sizeof(WCHAR));
1386 Result = CommandLineFromMsiDescriptor(component, path, &sz);
1387 if (Result != ERROR_SUCCESS)
1388 {
1390 path = NULL;
1391 }
1392
1393 TRACE("returning %s\n", debugstr_w(path));
1394
1395 return path;
1396}
1397
1399{
1400 HRESULT hr = S_OK;
1401 BOOL bSuccess;
1402
1403 TRACE("(%p)->(hwnd=%p flags=%x)\n", this, hwnd, fFlags);
1404
1405 /* FIXME: use IResolveShellLink interface? */
1406
1407 // FIXME: See InvokeCommand().
1408
1409#if (NTDDI_VERSION < NTDDI_LONGHORN)
1410 // NOTE: For Logo3 (EXP_LOGO3_ID_SIG), check also for SHRestricted(REST_NOLOGO3CHANNELNOTIFY)
1412 {
1413 FIXME("Logo3 links are not supported yet!\n");
1414 return E_FAIL;
1415 }
1416#endif
1417
1418 /* Resolve Darwin (MSI) target */
1420 {
1421 LPWSTR component = NULL;
1422 hr = GetAdvertiseInfo(&component, EXP_DARWIN_ID_SIG);
1423 if (FAILED(hr))
1424 return E_FAIL;
1425
1426 /* Clear the cached path */
1429 if (!m_sPath)
1430 return E_FAIL;
1431 }
1432
1433 if (!m_sPath && m_pPidl)
1434 {
1436
1438 if (bSuccess && *buffer)
1439 {
1441 if (!m_sPath)
1442 return E_OUTOFMEMORY;
1443
1444 m_bDirty = TRUE;
1445 }
1446 else
1447 {
1448 hr = S_OK; /* don't report an error occurred while just caching information */
1449 }
1450 }
1451
1452 // FIXME: Strange to do that here...
1453 if (!m_sIcoPath && m_sPath)
1454 {
1456 if (!m_sIcoPath)
1457 return E_OUTOFMEMORY;
1458
1459 m_Header.nIconIndex = 0;
1460
1461 m_bDirty = TRUE;
1462 }
1463
1464 return hr;
1465}
1466
1468{
1469 TRACE("(%p)->(path=%s)\n", this, pszFile);
1470
1471 if (!pszFile)
1472 return E_INVALIDARG;
1473
1474 LPWSTR str = HEAP_strdupAtoW(GetProcessHeap(), 0, pszFile);
1475 if (!str)
1476 return E_OUTOFMEMORY;
1477
1478 HRESULT hr = SetPath(str);
1480
1481 return hr;
1482}
1483
1485{
1487
1488 TRACE("(%p)->(pfile=%p len=%u find_data=%p flags=%u)(%s)\n",
1489 this, pszFile, cchMaxPath, pfd, fFlags, debugstr_w(m_sPath));
1490
1491 if (cchMaxPath)
1492 *pszFile = 0;
1493 // FIXME: What if cchMaxPath == 0 , or pszFile == NULL ??
1494
1495 // FIXME: What about Darwin??
1496
1497 /*
1498 * Retrieve the path to the target from the PIDL (if we have one).
1499 * NOTE: Do NOT use the cached path (m_sPath from link info).
1500 */
1502 {
1503 if (fFlags & SLGP_SHORTPATH)
1505 // FIXME: Add support for SLGP_UNCPRIORITY
1506 }
1507 else
1508 {
1509 *buffer = 0;
1510 }
1511
1512 /* If we have a FindData structure, initialize it */
1513 if (pfd)
1514 {
1515 ZeroMemory(pfd, sizeof(*pfd));
1516
1517 /* Copy the file data if the target is a file path */
1518 if (*buffer)
1519 {
1520 pfd->dwFileAttributes = m_Header.dwFileAttributes;
1521 pfd->ftCreationTime = m_Header.ftCreationTime;
1522 pfd->ftLastAccessTime = m_Header.ftLastAccessTime;
1523 pfd->ftLastWriteTime = m_Header.ftLastWriteTime;
1524 pfd->nFileSizeHigh = 0;
1525 pfd->nFileSizeLow = m_Header.nFileSizeLow;
1526
1527 /*
1528 * Build temporarily a short path in pfd->cFileName (of size MAX_PATH),
1529 * then extract and store the short file name in pfd->cAlternateFileName.
1530 */
1531 GetShortPathNameW(buffer, pfd->cFileName, _countof(pfd->cFileName));
1532 lstrcpynW(pfd->cAlternateFileName,
1533 PathFindFileNameW(pfd->cFileName),
1534 _countof(pfd->cAlternateFileName));
1535
1536 /* Now extract and store the long file name in pfd->cFileName */
1537 lstrcpynW(pfd->cFileName,
1539 _countof(pfd->cFileName));
1540 }
1541 }
1542
1543 /* Finally check if we have a raw path the user actually wants to retrieve */
1544 if ((fFlags & SLGP_RAWPATH) && (m_Header.dwFlags & SLDF_HAS_EXP_SZ))
1545 {
1546 /* Search for a target environment block */
1547 LPEXP_SZ_LINK pInfo;
1549 if (pInfo && (pInfo->cbSize == sizeof(*pInfo)))
1550 lstrcpynW(buffer, pInfo->szwTarget, cchMaxPath);
1551 }
1552
1553 /* For diagnostics purposes only... */
1554 // NOTE: SLGP_UNCPRIORITY is unsupported
1555 fFlags &= ~(SLGP_RAWPATH | SLGP_SHORTPATH);
1556 if (fFlags) FIXME("(%p): Unsupported flags %lu\n", this, fFlags);
1557
1558 /* Copy the data back to the user */
1559 if (*buffer)
1560 lstrcpynW(pszFile, buffer, cchMaxPath);
1561
1562 return (*buffer ? S_OK : S_FALSE);
1563}
1564
1566{
1567 TRACE("(%p)->(%p len=%u)\n", this, pszName, cchMaxName);
1568
1569 *pszName = 0;
1570 if (m_sDescription)
1571 lstrcpynW(pszName, m_sDescription, cchMaxName);
1572
1573 return S_OK;
1574}
1575
1577{
1578 TRACE("(%p)->(desc=%s)\n", this, debugstr_w(pszName));
1579
1582
1583 if (pszName)
1584 {
1585 m_sDescription = strdupW(pszName);
1586 if (!m_sDescription)
1587 return E_OUTOFMEMORY;
1588 }
1589 m_bDirty = TRUE;
1590
1591 return S_OK;
1592}
1593
1595{
1596 TRACE("(%p)->(%p len %u)\n", this, pszDir, cchMaxPath);
1597
1598 if (cchMaxPath)
1599 *pszDir = 0;
1600
1601 if (m_sWorkDir)
1602 lstrcpynW(pszDir, m_sWorkDir, cchMaxPath);
1603
1604 return S_OK;
1605}
1606
1608{
1609 TRACE("(%p)->(dir=%s)\n", this, debugstr_w(pszDir));
1610
1612 m_sWorkDir = NULL;
1613
1614 if (pszDir)
1615 {
1617 if (!m_sWorkDir)
1618 return E_OUTOFMEMORY;
1619 }
1620 m_bDirty = TRUE;
1621
1622 return S_OK;
1623}
1624
1626{
1627 TRACE("(%p)->(%p len=%u)\n", this, pszArgs, cchMaxPath);
1628
1629 if (cchMaxPath)
1630 *pszArgs = 0;
1631
1632 if (m_sArgs)
1633 lstrcpynW(pszArgs, m_sArgs, cchMaxPath);
1634
1635 return S_OK;
1636}
1637
1639{
1640 TRACE("(%p)->(args=%s)\n", this, debugstr_w(pszArgs));
1641
1643 m_sArgs = NULL;
1644
1645 if (pszArgs)
1646 {
1647 m_sArgs = strdupW(pszArgs);
1648 if (!m_sArgs)
1649 return E_OUTOFMEMORY;
1650 }
1651 m_bDirty = TRUE;
1652
1653 return S_OK;
1654}
1655
1657{
1658 TRACE("(%p)->(%p len=%u iicon=%p)\n", this, pszIconPath, cchIconPath, piIcon);
1659
1660 if (cchIconPath)
1661 *pszIconPath = 0;
1662
1663 *piIcon = 0;
1664
1665 /* Update the original icon path location */
1667 {
1669
1670 /* Search for an icon environment block */
1671 LPEXP_SZ_LINK pInfo;
1673 if (pInfo && (pInfo->cbSize == sizeof(*pInfo)))
1674 {
1676
1677 m_Header.dwFlags &= ~SLDF_HAS_ICONLOCATION;
1679
1681 if (!m_sIcoPath)
1682 return E_OUTOFMEMORY;
1683
1685
1686 m_bDirty = TRUE;
1687 }
1688 }
1689
1690 *piIcon = m_Header.nIconIndex;
1691
1692 if (m_sIcoPath)
1693 lstrcpynW(pszIconPath, m_sIcoPath, cchIconPath);
1694
1695 return S_OK;
1696}
1697
1699 UINT uFlags, PWSTR pszIconFile, UINT cchMax, int *piIndex, UINT *pwFlags)
1700{
1701 LPCITEMIDLIST pidlLast;
1703
1704 HRESULT hr = SHBindToParent(pidl, IID_PPV_ARG(IShellFolder, &psf), &pidlLast);
1706 return hr;
1707
1709 hr = psf->GetUIObjectOf(0, 1, &pidlLast, IID_NULL_PPV_ARG(IExtractIconW, &pei));
1711 return hr;
1712
1713 hr = pei->GetIconLocation(uFlags, pszIconFile, cchMax, piIndex, pwFlags);
1715 return hr;
1716
1717 return S_OK;
1718}
1719
1721{
1722 HRESULT hr;
1723
1724 pszIconFile[0] = UNICODE_NULL;
1725
1726 /*
1727 * It is possible for a shell link to point to another shell link,
1728 * and in particular there is the possibility to point to itself.
1729 * Now, suppose we ask such a link to retrieve its associated icon.
1730 * This function would be called, and due to COM would be called again
1731 * recursively. To solve this issue, we forbid calling GetIconLocation()
1732 * with GIL_FORSHORTCUT set in uFlags, as done by Windows (shown by tests).
1733 */
1734 if (uFlags & GIL_FORSHORTCUT)
1735 return E_INVALIDARG;
1736
1737 /*
1738 * Now, we set GIL_FORSHORTCUT so that: i) we allow the icon extractor
1739 * of the target to give us a suited icon, and ii) we protect ourselves
1740 * against recursive call.
1741 */
1742 uFlags |= GIL_FORSHORTCUT;
1743
1744 if (uFlags & GIL_DEFAULTICON)
1745 return S_FALSE;
1746
1747 hr = GetIconLocation(pszIconFile, cchMax, piIndex);
1748 if (FAILED(hr) || pszIconFile[0] == UNICODE_NULL)
1749 {
1750 hr = SHELL_PidlGetIconLocationW(m_pPidl, uFlags, pszIconFile, cchMax, piIndex, pwFlags);
1751 }
1752 else
1753 {
1754 *pwFlags = GIL_NOTFILENAME | GIL_PERCLASS;
1755 }
1756
1757 return hr;
1758}
1759
1761CShellLink::Extract(PCWSTR pszFile, UINT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIconSize)
1762{
1763 HRESULT hr = NOERROR;
1764 UINT cxyLarge = LOWORD(nIconSize), cxySmall = HIWORD(nIconSize);
1765
1766 if (phiconLarge)
1767 {
1768 *phiconLarge = NULL;
1769 PrivateExtractIconsW(pszFile, nIconIndex, cxyLarge, cxyLarge, phiconLarge, NULL, 1, 0);
1770
1771 if (*phiconLarge == NULL)
1772 hr = S_FALSE;
1773 }
1774
1775 if (phiconSmall)
1776 {
1777 *phiconSmall = NULL;
1778 PrivateExtractIconsW(pszFile, nIconIndex, cxySmall, cxySmall, phiconSmall, NULL, 1, 0);
1779
1780 if (*phiconSmall == NULL)
1781 hr = S_FALSE;
1782 }
1783
1784 if (hr == S_FALSE)
1785 {
1786 if (phiconLarge && *phiconLarge)
1787 {
1788 DestroyIcon(*phiconLarge);
1789 *phiconLarge = NULL;
1790 }
1791 if (phiconSmall && *phiconSmall)
1792 {
1793 DestroyIcon(*phiconSmall);
1794 *phiconSmall = NULL;
1795 }
1796 }
1797
1798 return hr;
1799}
1800
1801#if 0
1802/* Extends the functionality of PathUnExpandEnvStringsW */
1803BOOL PathFullyUnExpandEnvStringsW(
1804 _In_ LPCWSTR pszPath,
1805 _Out_ LPWSTR pszBuf,
1806 _In_ UINT cchBuf)
1807{
1808 BOOL Ret = FALSE; // Set to TRUE as soon as PathUnExpandEnvStrings starts unexpanding.
1809 BOOL res;
1810 LPCWSTR p;
1811
1812 // *pszBuf = L'\0';
1813 while (*pszPath && cchBuf > 0)
1814 {
1815 /* Attempt unexpanding the path */
1816 res = PathUnExpandEnvStringsW(pszPath, pszBuf, cchBuf);
1817 if (!res)
1818 {
1819 /* The unexpansion failed. Try to find a path delimiter. */
1820 p = wcspbrk(pszPath, L" /\\:*?\"<>|%");
1821 if (!p) /* None found, we will copy the remaining path */
1822 p = pszPath + wcslen(pszPath);
1823 else /* Found one, we will copy the delimiter and skip it */
1824 ++p;
1825 /* If we overflow, we cannot unexpand more, so return FALSE */
1826 if (p - pszPath >= cchBuf)
1827 return FALSE; // *pszBuf = L'\0';
1828
1829 /* Copy the untouched portion of path up to the delimiter, included */
1830 wcsncpy(pszBuf, pszPath, p - pszPath);
1831 pszBuf[p - pszPath] = L'\0'; // NULL-terminate
1832
1833 /* Advance the pointers and decrease the remaining buffer size */
1834 cchBuf -= (p - pszPath);
1835 pszBuf += (p - pszPath);
1836 pszPath += (p - pszPath);
1837 }
1838 else
1839 {
1840 /*
1841 * The unexpansion succeeded. Skip the unexpanded part by trying
1842 * to find where the original path and the unexpanded string
1843 * become different.
1844 * NOTE: An alternative(?) would be to stop also at the last
1845 * path delimiter encountered in the loop (i.e. would be the
1846 * first path delimiter in the strings).
1847 */
1848 LPWSTR q;
1849
1850 /*
1851 * The algorithm starts at the end of the strings and loops back
1852 * while the characters are equal, until it finds a discrepancy.
1853 */
1854 p = pszPath + wcslen(pszPath);
1855 q = pszBuf + wcslen(pszBuf); // This wcslen should be < cchBuf
1856 while ((*p == *q) && (p > pszPath) && (q > pszBuf))
1857 {
1858 --p; --q;
1859 }
1860 /* Skip discrepancy */
1861 ++p; ++q;
1862
1863 /* Advance the pointers and decrease the remaining buffer size */
1864 cchBuf -= (q - pszBuf);
1865 pszBuf = q;
1866 pszPath = p;
1867
1868 Ret = TRUE;
1869 }
1870 }
1871
1872 return Ret;
1873}
1874#endif
1875
1877{
1878 HRESULT hr = E_FAIL;
1879 WCHAR szIconPath[MAX_PATH];
1880
1881 TRACE("(%p)->(path=%s iicon=%u)\n", this, debugstr_w(pszIconPath), iIcon);
1882
1883 if (pszIconPath)
1884 {
1885 /*
1886 * Check whether the user-given file path contains unexpanded
1887 * environment variables. If so, create a target environment block.
1888 * Note that in this block we will store the user-given path.
1889 * It will contain the unexpanded environment variables, but
1890 * it can also contain already expanded path that the user does
1891 * not want to see them unexpanded (e.g. so that they always
1892 * refer to the same place even if the would-be corresponding
1893 * environment variable could change).
1894 */
1895#ifdef ICON_LINK_WINDOWS_COMPAT
1896 /* Try to fully unexpand the icon path */
1897 // if (PathFullyUnExpandEnvStringsW(pszIconPath, szIconPath, _countof(szIconPath)))
1898 BOOL bSuccess = PathUnExpandEnvStringsW(pszIconPath, szIconPath, _countof(szIconPath));
1899 if (bSuccess && wcscmp(pszIconPath, szIconPath) != 0)
1900#else
1901 /*
1902 * In some situations, described in http://stackoverflow.com/questions/2976489/ishelllinkseticonlocation-translates-my-icon-path-into-program-files-which-i
1903 * the result of PathUnExpandEnvStringsW() could be wrong, and instead
1904 * one would have to store the actual provided icon location path, while
1905 * creating an icon environment block ONLY if that path already contains
1906 * environment variables. This is what the present case is trying to implement.
1907 */
1908 SHExpandEnvironmentStringsW(pszIconPath, szIconPath, _countof(szIconPath));
1909 if (wcscmp(pszIconPath, szIconPath) != 0)
1910#endif
1911 {
1912 /*
1913 * The user-given file path contains unexpanded environment
1914 * variables, so we need an icon environment block.
1915 */
1917 LPEXP_SZ_LINK pInfo;
1918
1919#ifdef ICON_LINK_WINDOWS_COMPAT
1920 /* Make pszIconPath point to the unexpanded path */
1921 LPCWSTR pszOrgIconPath = pszIconPath;
1922 pszIconPath = szIconPath;
1923#endif
1925 if (pInfo)
1926 {
1927 /* Make sure that the size of the structure is valid */
1928 if (pInfo->cbSize != sizeof(*pInfo))
1929 {
1930 ERR("Ooops. This structure is not as expected...\n");
1931
1932 /* Invalid structure, remove it altogether */
1933 m_Header.dwFlags &= ~SLDF_HAS_EXP_ICON_SZ;
1935
1936 /* Reset the pointer and go use the static buffer */
1937 pInfo = NULL;
1938 }
1939 }
1940 if (!pInfo)
1941 {
1942 /* Use the static buffer */
1943 pInfo = &buffer;
1944 buffer.cbSize = sizeof(buffer);
1945 buffer.dwSignature = EXP_SZ_ICON_SIG;
1946 }
1947
1948 lstrcpynW(pInfo->szwTarget, pszIconPath, _countof(pInfo->szwTarget));
1949 WideCharToMultiByte(CP_ACP, 0, pszIconPath, -1,
1950 pInfo->szTarget, _countof(pInfo->szTarget), NULL, NULL);
1951
1952 hr = S_OK;
1953 if (pInfo == &buffer)
1954 hr = AddDataBlock(pInfo);
1955 if (hr == S_OK)
1957
1958#ifdef ICON_LINK_WINDOWS_COMPAT
1959 /* Set pszIconPath back to the original one */
1960 pszIconPath = pszOrgIconPath;
1961#else
1962 /* Now, make pszIconPath point to the expanded path */
1963 pszIconPath = szIconPath;
1964#endif
1965 }
1966 else
1967 {
1968 /*
1969 * The user-given file path does not contain unexpanded environment
1970 * variables, so we need to remove any icon environment block.
1971 */
1972 m_Header.dwFlags &= ~SLDF_HAS_EXP_ICON_SZ;
1974
1975 /* pszIconPath points to the user path */
1976 }
1977 }
1978
1979#ifdef ICON_LINK_WINDOWS_COMPAT
1980 /* Store the original icon path location (may contain unexpanded environment strings) */
1981#endif
1982 if (pszIconPath)
1983 {
1984 m_Header.dwFlags &= ~SLDF_HAS_ICONLOCATION;
1986
1987 m_sIcoPath = strdupW(pszIconPath);
1988 if (!m_sIcoPath)
1989 return E_OUTOFMEMORY;
1990
1992 }
1993
1994 hr = S_OK;
1995
1996 m_Header.nIconIndex = iIcon;
1997 m_bDirty = TRUE;
1998
1999 return hr;
2000}
2001
2003{
2004 TRACE("(%p)->(path=%s %x)\n", this, debugstr_w(pszPathRel), dwReserved);
2005
2007 m_sPathRel = NULL;
2008
2009 if (pszPathRel)
2010 {
2011 m_sPathRel = strdupW(pszPathRel);
2012 if (!m_sPathRel)
2013 return E_OUTOFMEMORY;
2014 }
2015 m_bDirty = TRUE;
2016
2018}
2019
2021{
2022 if (!str)
2023 return NULL;
2024
2025 LPCWSTR p = wcschr(str, L':');
2026 if (!p)
2027 return NULL;
2028
2029 DWORD len = p - str;
2030 LPWSTR ret = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * (len + 1));
2031 if (!ret)
2032 return ret;
2033
2034 memcpy(ret, str, sizeof(WCHAR)*len);
2035 ret[len] = 0;
2036 return ret;
2037}
2038
2040{
2042 LPEXP_DARWIN_LINK pInfo;
2043
2044 if ( (dwSig != EXP_DARWIN_ID_SIG)
2046 && (dwSig != EXP_LOGO3_ID_SIG)
2047#endif
2048 )
2049 {
2050 return E_INVALIDARG;
2051 }
2052
2053 if (!string)
2054 return S_FALSE;
2055
2057 if (pInfo)
2058 {
2059 /* Make sure that the size of the structure is valid */
2060 if (pInfo->dbh.cbSize != sizeof(*pInfo))
2061 {
2062 ERR("Ooops. This structure is not as expected...\n");
2063
2064 /* Invalid structure, remove it altogether */
2065 if (dwSig == EXP_DARWIN_ID_SIG)
2066 m_Header.dwFlags &= ~SLDF_HAS_DARWINID;
2067#if (NTDDI_VERSION < NTDDI_LONGHORN)
2068 else if (dwSig == EXP_LOGO3_ID_SIG)
2069 m_Header.dwFlags &= ~SLDF_HAS_LOGO3ID;
2070#endif
2071 RemoveDataBlock(dwSig);
2072
2073 /* Reset the pointer and go use the static buffer */
2074 pInfo = NULL;
2075 }
2076 }
2077 if (!pInfo)
2078 {
2079 /* Use the static buffer */
2080 pInfo = &buffer;
2081 buffer.dbh.cbSize = sizeof(buffer);
2082 buffer.dbh.dwSignature = dwSig;
2083 }
2084
2085 lstrcpynW(pInfo->szwDarwinID, string, _countof(pInfo->szwDarwinID));
2086 WideCharToMultiByte(CP_ACP, 0, string, -1,
2087 pInfo->szDarwinID, _countof(pInfo->szDarwinID), NULL, NULL);
2088
2089 HRESULT hr = S_OK;
2090 if (pInfo == &buffer)
2091 hr = AddDataBlock(pInfo);
2092 if (hr == S_OK)
2093 {
2094 if (dwSig == EXP_DARWIN_ID_SIG)
2096#if (NTDDI_VERSION < NTDDI_LONGHORN)
2097 else if (dwSig == EXP_LOGO3_ID_SIG)
2099#endif
2100 }
2101
2102 return hr;
2103}
2104
2106{
2107 HRESULT hr;
2108 LPCWSTR szComponent = NULL, szProduct = NULL, p;
2109 INT len;
2110 GUID guid;
2111 WCHAR szGuid[38+1];
2112
2114
2115 while (str[0])
2116 {
2117 /* each segment must start with two colons */
2118 if (str[0] != ':' || str[1] != ':')
2119 return E_FAIL;
2120
2121 /* the last segment is just two colons */
2122 if (!str[2])
2123 break;
2124 str += 2;
2125
2126 /* there must be a colon straight after a guid */
2127 p = wcschr(str, L':');
2128 if (!p)
2129 return E_FAIL;
2130 len = p - str;
2131 if (len != 38)
2132 return E_FAIL;
2133
2134 /* get the guid, and check if it's validly formatted */
2135 memcpy(szGuid, str, sizeof(WCHAR)*len);
2136 szGuid[len] = 0;
2137
2139 if (hr != S_OK)
2140 return hr;
2141 str = p + 1;
2142
2143 /* match it up to a guid that we care about */
2144 if (IsEqualGUID(guid, SHELL32_AdvtShortcutComponent) && !szComponent)
2145 szComponent = str; /* Darwin */
2146 else if (IsEqualGUID(guid, SHELL32_AdvtShortcutProduct) && !szProduct)
2147 szProduct = str; /* Logo3 */
2148 else
2149 return E_FAIL;
2150
2151 /* skip to the next field */
2152 str = wcschr(str, L':');
2153 if (!str)
2154 return E_FAIL;
2155 }
2156
2157 /* we have to have a component for an advertised shortcut */
2158 if (!szComponent)
2159 return E_FAIL;
2160
2161 szComponent = GetAdvertisedArg(szComponent);
2162 szProduct = GetAdvertisedArg(szProduct);
2163
2164 hr = WriteAdvertiseInfo(szComponent, EXP_DARWIN_ID_SIG);
2165 // if (FAILED(hr))
2166 // return hr;
2167#if (NTDDI_VERSION < NTDDI_LONGHORN)
2168 hr = WriteAdvertiseInfo(szProduct, EXP_LOGO3_ID_SIG);
2169 // if (FAILED(hr))
2170 // return hr;
2171#endif
2172
2173 HeapFree(GetProcessHeap(), 0, (PVOID)szComponent);
2174 HeapFree(GetProcessHeap(), 0, (PVOID)szProduct);
2175
2176 if (TRACE_ON(shell))
2177 {
2179 TRACE("Component = %s\n", debugstr_w(sComponent));
2180#if (NTDDI_VERSION < NTDDI_LONGHORN)
2181 GetAdvertiseInfo(&sProduct, EXP_LOGO3_ID_SIG);
2182 TRACE("Product = %s\n", debugstr_w(sProduct));
2183#endif
2184 }
2185
2186 return S_OK;
2187}
2188
2190{
2191 HRESULT hr = S_OK;
2192 LPITEMIDLIST pidlNew = NULL;
2194
2195 /*
2196 * Not both 'pidl' and 'pszFile' should be set.
2197 * But either one or both can be NULL.
2198 */
2199 if (pidl && pszFile)
2200 return E_FAIL;
2201
2202 if (pidl)
2203 {
2204 /* Clone the PIDL */
2205 pidlNew = ILClone(pidl);
2206 if (!pidlNew)
2207 return E_FAIL;
2208 }
2209 else if (pszFile)
2210 {
2211 /* Build a PIDL for this path target */
2212 hr = SHILCreateFromPathW(pszFile, &pidlNew, NULL);
2213 if (FAILED(hr))
2214 {
2215 /* This failed, try to resolve the path, then create a simple PIDL */
2216
2219
2221 {
2222 hr = E_INVALIDARG;
2223 szPath[0] = 0;
2224 }
2225 else
2226 {
2227 hr = S_OK;
2229 // NOTE: Don't make it failed here even if pidlNew was NULL.
2230 // We don't fail on purpose even if SHSimpleIDListFromPathW returns NULL.
2231 // This behaviour has been verified with tests.
2232 }
2233 }
2234 }
2235 // else if (!pidl && !pszFile) { pidlNew = NULL; hr = S_OK; }
2236
2237 ILFree(m_pPidl);
2238 m_pPidl = pidlNew;
2239
2240 if (!pszFile)
2241 {
2242 if (SHGetPathFromIDListW(pidlNew, szPath))
2243 pszFile = szPath;
2244 }
2245
2246 // TODO: Fully update link info, tracker, file attribs...
2247
2248 // if (pszFile)
2249 if (!pszFile)
2250 {
2251 *szPath = L'\0';
2252 pszFile = szPath;
2253 }
2254
2255 /* Update the cached path (for link info) */
2257
2258 if (m_sPath)
2260
2261 m_sPath = strdupW(pszFile);
2262 if (!m_sPath)
2263 return E_OUTOFMEMORY;
2264
2265 m_bDirty = TRUE;
2266 return hr;
2267}
2268
2270{
2271 LPWSTR unquoted = NULL;
2272 HRESULT hr = S_OK;
2273
2274 TRACE("(%p)->(path=%s)\n", this, debugstr_w(pszFile));
2275
2276 if (!pszFile)
2277 return E_INVALIDARG;
2278
2279 /*
2280 * Allow upgrading Logo3 shortcuts (m_Header.dwFlags & SLDF_HAS_LOGO3ID),
2281 * but forbid upgrading Darwin ones.
2282 */
2284 return S_FALSE;
2285
2286 /* quotes at the ends of the string are stripped */
2287 SIZE_T len = wcslen(pszFile);
2288 if (pszFile[0] == L'"' && pszFile[len-1] == L'"')
2289 {
2290 unquoted = strdupW(pszFile);
2291 PathUnquoteSpacesW(unquoted);
2292 pszFile = unquoted;
2293 }
2294
2295 /* any other quote marks are invalid */
2296 if (wcschr(pszFile, L'"'))
2297 {
2298 hr = S_FALSE;
2299 goto end;
2300 }
2301
2302 /* Clear the cached path */
2304 m_sPath = NULL;
2305
2306 /* Check for an advertised target (Logo3 or Darwin) */
2307 if (SetAdvertiseInfo(pszFile) != S_OK)
2308 {
2309 /* This is not an advertised target, but a regular path */
2311
2312 /*
2313 * Check whether the user-given file path contains unexpanded
2314 * environment variables. If so, create a target environment block.
2315 * Note that in this block we will store the user-given path.
2316 * It will contain the unexpanded environment variables, but
2317 * it can also contain already expanded path that the user does
2318 * not want to see them unexpanded (e.g. so that they always
2319 * refer to the same place even if the would-be corresponding
2320 * environment variable could change).
2321 */
2322 if (*pszFile)
2324 else
2325 *szPath = L'\0';
2326
2327 if (*pszFile && (wcscmp(pszFile, szPath) != 0))
2328 {
2329 /*
2330 * The user-given file path contains unexpanded environment
2331 * variables, so we need a target environment block.
2332 */
2334 LPEXP_SZ_LINK pInfo;
2335
2337 if (pInfo)
2338 {
2339 /* Make sure that the size of the structure is valid */
2340 if (pInfo->cbSize != sizeof(*pInfo))
2341 {
2342 ERR("Ooops. This structure is not as expected...\n");
2343
2344 /* Invalid structure, remove it altogether */
2345 m_Header.dwFlags &= ~SLDF_HAS_EXP_SZ;
2347
2348 /* Reset the pointer and go use the static buffer */
2349 pInfo = NULL;
2350 }
2351 }
2352 if (!pInfo)
2353 {
2354 /* Use the static buffer */
2355 pInfo = &buffer;
2356 buffer.cbSize = sizeof(buffer);
2357 buffer.dwSignature = EXP_SZ_LINK_SIG;
2358 }
2359
2360 lstrcpynW(pInfo->szwTarget, pszFile, _countof(pInfo->szwTarget));
2361 WideCharToMultiByte(CP_ACP, 0, pszFile, -1,
2362 pInfo->szTarget, _countof(pInfo->szTarget), NULL, NULL);
2363
2364 hr = S_OK;
2365 if (pInfo == &buffer)
2366 hr = AddDataBlock(pInfo);
2367 if (hr == S_OK)
2369
2370 /* Now, make pszFile point to the expanded path */
2371 pszFile = szPath;
2372 }
2373 else
2374 {
2375 /*
2376 * The user-given file path does not contain unexpanded environment
2377 * variables, so we need to remove any target environment block.
2378 */
2379 m_Header.dwFlags &= ~SLDF_HAS_EXP_SZ;
2381
2382 /* pszFile points to the user path */
2383 }
2384
2385 /* Set the target */
2386 hr = SetTargetFromPIDLOrPath(NULL, pszFile);
2387 }
2388
2389 m_bDirty = TRUE;
2390
2391end:
2392 HeapFree(GetProcessHeap(), 0, unquoted);
2393 return hr;
2394}
2395
2397{
2398 if (SHAddDataBlock(&m_pDBList, (DATABLOCK_HEADER*)pDataBlock))
2399 {
2400 m_bDirty = TRUE;
2401 return S_OK;
2402 }
2403 return S_FALSE;
2404}
2405
2407{
2408 DATABLOCK_HEADER* pBlock;
2409 PVOID pDataBlock;
2410
2411 TRACE("%p %08x %p\n", this, dwSig, ppDataBlock);
2412
2413 *ppDataBlock = NULL;
2414
2415 pBlock = SHFindDataBlock(m_pDBList, dwSig);
2416 if (!pBlock)
2417 {
2418 ERR("unknown datablock %08x (not found)\n", dwSig);
2419 return E_FAIL;
2420 }
2421
2422 pDataBlock = LocalAlloc(LMEM_ZEROINIT, pBlock->cbSize);
2423 if (!pDataBlock)
2424 return E_OUTOFMEMORY;
2425
2426 CopyMemory(pDataBlock, pBlock, pBlock->cbSize);
2427
2428 *ppDataBlock = pDataBlock;
2429 return S_OK;
2430}
2431
2433{
2434 if (SHRemoveDataBlock(&m_pDBList, dwSig))
2435 {
2436 m_bDirty = TRUE;
2437 return S_OK;
2438 }
2439 return S_FALSE;
2440}
2441
2443{
2444 TRACE("%p %p\n", this, pdwFlags);
2445 *pdwFlags = m_Header.dwFlags;
2446 return S_OK;
2447}
2448
2450{
2451#if 0 // FIXME!
2453 m_bDirty = TRUE;
2454 return S_OK;
2455#else
2456 FIXME("\n");
2457 return E_NOTIMPL;
2458#endif
2459}
2460
2461/**************************************************************************
2462 * CShellLink implementation of IShellExtInit::Initialize()
2463 *
2464 * Loads the shelllink from the dataobject the shell is pointing to.
2465 */
2467{
2468 TRACE("%p %p %p %p\n", this, pidlFolder, pdtobj, hkeyProgID);
2469
2470 if (!pdtobj)
2471 return E_FAIL;
2472
2473 FORMATETC format;
2474 format.cfFormat = CF_HDROP;
2475 format.ptd = NULL;
2476 format.dwAspect = DVASPECT_CONTENT;
2477 format.lindex = -1;
2478 format.tymed = TYMED_HGLOBAL;
2479
2480 STGMEDIUM stgm;
2481 HRESULT hr = pdtobj->GetData(&format, &stgm);
2482 if (FAILED(hr))
2483 return hr;
2484
2485 UINT count = DragQueryFileW((HDROP)stgm.hGlobal, -1, NULL, 0);
2486 if (count == 1)
2487 {
2488 count = DragQueryFileW((HDROP)stgm.hGlobal, 0, NULL, 0);
2489 count++;
2490 LPWSTR path = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, count * sizeof(WCHAR));
2491 if (path)
2492 {
2493 count = DragQueryFileW((HDROP)stgm.hGlobal, 0, path, count);
2494 hr = Load(path, 0);
2496 }
2497 }
2498 ReleaseStgMedium(&stgm);
2499
2500 return S_OK;
2501}
2502
2504{
2505 INT id = 0;
2506
2507 m_idCmdFirst = idCmdFirst;
2508
2509 TRACE("%p %p %u %u %u %u\n", this,
2510 hMenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
2511
2512 if (!hMenu)
2513 return E_INVALIDARG;
2514
2517
2518 MENUITEMINFOW mii;
2519 ZeroMemory(&mii, sizeof(mii));
2520 mii.cbSize = sizeof(mii);
2522 mii.dwTypeData = strOpen.GetBuffer();
2523 mii.cch = wcslen(mii.dwTypeData);
2524 mii.wID = idCmdFirst + id++;
2526 mii.fType = MFT_STRING;
2527 if (!InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii))
2528 return E_FAIL;
2529
2531 mii.dwTypeData = strOpenFileLoc.GetBuffer();
2532 mii.cch = wcslen(mii.dwTypeData);
2533 mii.wID = idCmdFirst + id++;
2534 mii.fState = MFS_ENABLED;
2535 mii.fType = MFT_STRING;
2536 if (!InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii))
2537 return E_FAIL;
2538
2539 UNREFERENCED_PARAMETER(indexMenu);
2540
2541 return MAKE_HRESULT(SEVERITY_SUCCESS, 0, id);
2542}
2543
2545{
2546 WCHAR szParams[MAX_PATH + 64];
2547 StringCbPrintfW(szParams, sizeof(szParams), L"/select,%s", m_sPath);
2548
2549 INT_PTR ret;
2550 ret = reinterpret_cast<INT_PTR>(ShellExecuteW(NULL, NULL, L"explorer.exe", szParams,
2552 if (ret <= 32)
2553 {
2554 ERR("ret: %08lX\n", ret);
2555 return E_FAIL;
2556 }
2557
2558 return S_OK;
2559}
2560
2562{
2563 TRACE("%p %p\n", this, lpici);
2564
2565 if (lpici->cbSize < sizeof(CMINVOKECOMMANDINFO))
2566 return E_INVALIDARG;
2567
2568 // NOTE: We could use lpici->hwnd (certainly in case lpici->fMask doesn't contain CMIC_MASK_FLAG_NO_UI)
2569 // as the parent window handle... ?
2570 /* FIXME: get using interface set from IObjectWithSite?? */
2571 // NOTE: We might need an extended version of Resolve that provides us with paths...
2572 HRESULT hr = Resolve(lpici->hwnd, 0);
2573 if (FAILED(hr))
2574 {
2575 TRACE("failed to resolve component error 0x%08x\n", hr);
2576 return hr;
2577 }
2578
2579 UINT idCmd = LOWORD(lpici->lpVerb);
2580 TRACE("idCmd: %d\n", idCmd);
2581
2582 switch (idCmd)
2583 {
2584 case IDCMD_OPEN:
2585 return DoOpen(lpici);
2587 return DoOpenFileLocation();
2588 default:
2589 return E_NOTIMPL;
2590 }
2591}
2592
2594{
2595 HRESULT hr;
2596 LPWSTR args = NULL;
2598 BOOL unicode = lpici->cbSize >= FIELD_OFFSET(CMINVOKECOMMANDINFOEX, ptInvoke) &&
2599 (lpici->fMask & CMIC_MASK_UNICODE);
2600
2601 if (unicode)
2602 {
2604 SIZE_T len = 2;
2605
2606 if (m_sArgs)
2607 len += wcslen(m_sArgs);
2608 if (iciex->lpParametersW)
2609 len += wcslen(iciex->lpParametersW);
2610
2611 args = (LPWSTR)HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2612 *args = 0;
2613 if (m_sArgs)
2615 if (iciex->lpParametersW)
2616 {
2617 wcscat(args, L" ");
2618 wcscat(args, iciex->lpParametersW);
2619 }
2620 }
2621 else if (m_sArgs != NULL)
2622 {
2623 args = strdupW(m_sArgs);
2624 }
2625
2627 ZeroMemory(&sei, sizeof(sei));
2628 sei.cbSize = sizeof(sei);
2631 if (m_pPidl)
2632 {
2633 sei.lpIDList = m_pPidl;
2634 sei.fMask |= SEE_MASK_IDLIST;
2635 }
2636 else
2637 {
2638 sei.lpFile = path;
2639 }
2640 sei.lpParameters = args;
2641 sei.lpClass = m_sLinkPath;
2643 sei.lpDirectory = m_sWorkDir;
2644 sei.lpVerb = L"open";
2645
2646 // HACK for ShellExecuteExW
2647 if (m_sPath && wcsstr(m_sPath, L".cpl"))
2648 sei.lpVerb = L"cplopen";
2649
2650 if (ShellExecuteExW(&sei))
2651 hr = S_OK;
2652 else
2653 hr = E_FAIL;
2654
2657
2658 return hr;
2659}
2660
2662{
2663 FIXME("%p %lu %u %p %p %u\n", this, idCmd, uType, pwReserved, pszName, cchMax);
2664 return E_NOTIMPL;
2665}
2666
2669{
2670 switch(uMsg)
2671 {
2672 case WM_INITDIALOG:
2673 if (lParam)
2674 {
2675 HWND hDlgCtrl = GetDlgItem(hwndDlg, IDC_SHORTEX_RUN_DIFFERENT);
2676 SendMessage(hDlgCtrl, BM_SETCHECK, BST_CHECKED, 0);
2677 }
2678 return TRUE;
2679 case WM_COMMAND:
2680 {
2681 HWND hDlgCtrl = GetDlgItem(hwndDlg, IDC_SHORTEX_RUN_DIFFERENT);
2682 if (LOWORD(wParam) == IDOK)
2683 {
2684 if (SendMessage(hDlgCtrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
2685 EndDialog(hwndDlg, 1);
2686 else
2687 EndDialog(hwndDlg, 0);
2688 }
2689 else if (LOWORD(wParam) == IDCANCEL)
2690 {
2691 EndDialog(hwndDlg, -1);
2692 }
2694 {
2695 if (SendMessage(hDlgCtrl, BM_GETCHECK, 0, 0) == BST_CHECKED)
2696 SendMessage(hDlgCtrl, BM_SETCHECK, BST_UNCHECKED, 0);
2697 else
2698 SendMessage(hDlgCtrl, BM_SETCHECK, BST_CHECKED, 0);
2699 }
2700 }
2701 }
2702 return FALSE;
2703}
2704
2705/**************************************************************************
2706* SH_GetTargetTypeByPath
2707*
2708* Function to get target type by passing full path to it
2709*/
2711{
2712 LPCWSTR pwszExt;
2713 static WCHAR wszBuf[MAX_PATH];
2714
2715 /* Get file information */
2716 SHFILEINFOW fi;
2717 if (!SHGetFileInfoW(lpcwFullPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME | SHGFI_USEFILEATTRIBUTES))
2718 {
2719 ERR("SHGetFileInfoW failed for %ls (%lu)\n", lpcwFullPath, GetLastError());
2720 fi.szTypeName[0] = L'\0';
2721 fi.hIcon = NULL;
2722 }
2723
2724 pwszExt = PathFindExtensionW(lpcwFullPath);
2725 if (pwszExt[0])
2726 {
2727 if (!fi.szTypeName[0])
2728 {
2729 /* The file type is unknown, so default to string "FileExtension File" */
2730 size_t cchRemaining = 0;
2731 LPWSTR pwszEnd = NULL;
2732
2733 StringCchPrintfExW(wszBuf, _countof(wszBuf), &pwszEnd, &cchRemaining, 0, L"%s ", pwszExt + 1);
2734 }
2735 else
2736 {
2737 /* Update file type */
2738 StringCbPrintfW(wszBuf, sizeof(wszBuf), L"%s (%s)", fi.szTypeName, pwszExt);
2739 }
2740 }
2741
2742 return wszBuf;
2743}
2744
2746{
2747 TRACE("CShellLink::OnInitDialog(hwnd %p hwndFocus %p lParam %p)\n", hwndDlg, hwndFocus, lParam);
2748
2750
2751 TRACE("m_sArgs: %S sComponent: %S m_sDescription: %S m_sIcoPath: %S m_sPath: %S m_sPathRel: %S sProduct: %S m_sWorkDir: %S\n", m_sArgs, sComponent, m_sDescription,
2753
2754 m_bInInit = TRUE;
2755
2756 /* Get file information */
2757 // FIXME! FIXME! Shouldn't we use m_sIcoPath, m_Header.nIconIndex instead???
2758 SHFILEINFOW fi;
2759 if (!SHGetFileInfoW(m_sLinkPath, 0, &fi, sizeof(fi), SHGFI_TYPENAME | SHGFI_ICON))
2760 {
2761 ERR("SHGetFileInfoW failed for %ls (%lu)\n", m_sLinkPath, GetLastError());
2762 fi.szTypeName[0] = L'\0';
2763 fi.hIcon = NULL;
2764 }
2765
2766 if (fi.hIcon)
2767 {
2768 if (m_hIcon)
2770 m_hIcon = fi.hIcon;
2772 }
2773 else
2774 ERR("ExtractIconW failed %ls %u\n", m_sIcoPath, m_Header.nIconIndex);
2775
2776 /* Target type */
2777 if (m_sPath)
2779
2780 /* Target location */
2781 if (m_sPath)
2782 {
2787 }
2788
2789 /* Target path */
2790 if (m_sPath)
2791 {
2792 WCHAR newpath[2*MAX_PATH] = L"\0";
2793 if (wcschr(m_sPath, ' '))
2794 StringCchPrintfExW(newpath, _countof(newpath), NULL, NULL, 0, L"\"%ls\"", m_sPath);
2795 else
2796 StringCchCopyExW(newpath, _countof(newpath), m_sPath, NULL, NULL, 0);
2797
2798 if (m_sArgs && m_sArgs[0])
2799 {
2800 StringCchCatW(newpath, _countof(newpath), L" ");
2801 StringCchCatW(newpath, _countof(newpath), m_sArgs);
2802 }
2803 SetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TARGET_TEXT, newpath);
2804 }
2805
2806 /* Working dir */
2807 if (m_sWorkDir)
2809
2810 /* Description */
2811 if (m_sDescription)
2813
2814 /* Hot key */
2816
2817 /* Run */
2819 const DWORD runshowcmd[] = { SW_SHOWNORMAL, SW_SHOWMINNOACTIVE, SW_SHOWMAXIMIZED };
2820 HWND hRunCombo = GetDlgItem(hwndDlg, IDC_SHORTCUT_RUN_COMBO);
2821 for (UINT i = 0; i < _countof(runstrings); ++i)
2822 {
2824 if (!LoadStringW(shell32_hInstance, runstrings[i], buf, _countof(buf)))
2825 break;
2826
2827 int index = SendMessageW(hRunCombo, CB_ADDSTRING, 0, (LPARAM)buf);
2828 if (index < 0)
2829 continue;
2830 SendMessageW(hRunCombo, CB_SETITEMDATA, index, runshowcmd[i]);
2831 if (!i || m_Header.nShowCommand == runshowcmd[i])
2832 SendMessageW(hRunCombo, CB_SETCURSEL, index, 0);
2833 }
2834
2835 /* auto-completion */
2838
2839 m_bInInit = FALSE;
2840
2841 return TRUE;
2842}
2843
2844void CShellLink::OnCommand(HWND hwndDlg, int id, HWND hwndCtl, UINT codeNotify)
2845{
2846 switch (id)
2847 {
2848 case IDC_SHORTCUT_FIND:
2854 return;
2855
2857 {
2858 WCHAR wszPath[MAX_PATH] = L"";
2859
2860 if (m_sIcoPath)
2861 wcscpy(wszPath, m_sIcoPath);
2862 else
2863 FindExecutableW(m_sPath, NULL, wszPath);
2864
2866 if (PickIconDlg(hwndDlg, wszPath, _countof(wszPath), &IconIndex))
2867 {
2868 SetIconLocation(wszPath, IconIndex);
2869 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
2870
2871 HICON hIconLarge = CreateShortcutIcon(wszPath, IconIndex);
2872 if (hIconLarge)
2873 {
2874 if (m_hIcon)
2876 m_hIcon = hIconLarge;
2878 }
2879 }
2880 return;
2881 }
2882
2884 {
2886 if (result == 1 || result == 0)
2887 {
2888 if (m_bRunAs != result)
2889 {
2890 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
2891 }
2892
2893 m_bRunAs = result;
2894 }
2895 return;
2896 }
2897 }
2898 if (codeNotify == EN_CHANGE || codeNotify == CBN_SELCHANGE)
2899 {
2900 if (!m_bInInit)
2901 PropSheet_Changed(GetParent(hwndDlg), hwndDlg);
2902 }
2903}
2904
2905LRESULT CShellLink::OnNotify(HWND hwndDlg, int idFrom, LPNMHDR pnmhdr)
2906{
2907 WCHAR wszBuf[MAX_PATH];
2908 LPPSHNOTIFY lppsn = (LPPSHNOTIFY)pnmhdr;
2909
2910 if (lppsn->hdr.code == PSN_APPLY)
2911 {
2912 /* set working directory */
2913 GetDlgItemTextW(hwndDlg, IDC_SHORTCUT_START_IN_EDIT, wszBuf, _countof(wszBuf));
2914 SetWorkingDirectory(wszBuf);
2915
2916 /* set link destination */
2917 GetDlgItemTextW(hwndDlg, IDC_SHORTCUT_TARGET_TEXT, wszBuf, _countof(wszBuf));
2918 LPWSTR lpszArgs = NULL;
2919 LPWSTR unquoted = strdupW(wszBuf);
2920 StrTrimW(unquoted, L" ");
2921
2922 if (!PathFileExistsW(unquoted))
2923 {
2924 lpszArgs = PathGetArgsW(unquoted);
2925 PathRemoveArgsW(unquoted);
2926 StrTrimW(lpszArgs, L" ");
2927 }
2928 if (unquoted[0] == '"' && unquoted[wcslen(unquoted) - 1] == '"')
2929 PathUnquoteSpacesW(unquoted);
2930
2931 WCHAR *pwszExt = PathFindExtensionW(unquoted);
2932 if (!wcsicmp(pwszExt, L".lnk"))
2933 {
2934 // FIXME load localized error msg
2935 MessageBoxW(hwndDlg, L"You cannot create a link to a shortcut", L"Error", MB_ICONERROR);
2937 return TRUE;
2938 }
2939
2940 if (!PathFileExistsW(unquoted))
2941 {
2942 // FIXME load localized error msg
2943 MessageBoxW(hwndDlg, L"The specified file name in the target box is invalid", L"Error", MB_ICONERROR);
2945 return TRUE;
2946 }
2947
2948 SetPath(unquoted);
2949 if (lpszArgs)
2950 SetArguments(lpszArgs);
2951 else
2952 SetArguments(L"\0");
2953
2954 HeapFree(GetProcessHeap(), 0, unquoted);
2955
2957
2959 if (index != CB_ERR)
2960 {
2962 }
2963
2964 TRACE("This %p m_sLinkPath %S\n", this, m_sLinkPath);
2968 return TRUE;
2969 }
2970 return FALSE;
2971}
2972
2974{
2975 if (m_hIcon)
2976 {
2978 m_hIcon = NULL;
2979 }
2980}
2981
2982/**************************************************************************
2983 * SH_ShellLinkDlgProc
2984 *
2985 * dialog proc of the shortcut property dialog
2986 */
2987
2990{
2991 LPPROPSHEETPAGEW ppsp;
2992 CShellLink *pThis = reinterpret_cast<CShellLink *>(GetWindowLongPtr(hwndDlg, DWLP_USER));
2993
2994 switch (uMsg)
2995 {
2996 case WM_INITDIALOG:
2997 ppsp = (LPPROPSHEETPAGEW)lParam;
2998 if (ppsp == NULL)
2999 break;
3000
3001 pThis = reinterpret_cast<CShellLink *>(ppsp->lParam);
3002 SetWindowLongPtr(hwndDlg, DWLP_USER, (LONG_PTR)pThis);
3003 return pThis->OnInitDialog(hwndDlg, (HWND)(wParam), lParam);
3004
3005 case WM_NOTIFY:
3006 return pThis->OnNotify(hwndDlg, (int)wParam, (NMHDR *)lParam);
3007
3008 case WM_COMMAND:
3009 pThis->OnCommand(hwndDlg, LOWORD(wParam), (HWND)lParam, HIWORD(wParam));
3010 break;
3011
3012 case WM_DESTROY:
3013 pThis->OnDestroy(hwndDlg);
3014 break;
3015
3016 default:
3017 break;
3018 }
3019
3020 return FALSE;
3021}
3022
3023/**************************************************************************
3024 * ShellLink_IShellPropSheetExt interface
3025 */
3026
3028{
3030 if (hPage == NULL)
3031 {
3032 ERR("failed to create property sheet page\n");
3033 return E_FAIL;
3034 }
3035
3036 if (!pfnAddPage(hPage, lParam))
3037 return E_FAIL;
3038
3039 return S_OK;
3040}
3041
3043{
3044 TRACE("(%p) (uPageID %u, pfnReplacePage %p lParam %p\n", this, uPageID, pfnReplacePage, lParam);
3045 return E_NOTIMPL;
3046}
3047
3049{
3050 TRACE("%p %p\n", this, punk);
3051
3052 m_site = punk;
3053
3054 return S_OK;
3055}
3056
3058{
3059 TRACE("%p %s %p\n", this, debugstr_guid(&iid), ppvSite);
3060
3061 if (m_site == NULL)
3062 return E_FAIL;
3063
3064 return m_site->QueryInterface(iid, ppvSite);
3065}
3066
3068 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
3069{
3070 TRACE("(%p)->(DataObject=%p)\n", this, pDataObject);
3071
3072 if (*pdwEffect == DROPEFFECT_NONE)
3073 return S_OK;
3074
3075 LPCITEMIDLIST pidlLast;
3077
3079
3080 if (SUCCEEDED(hr))
3081 {
3082 hr = psf->GetUIObjectOf(0, 1, &pidlLast, IID_NULL_PPV_ARG(IDropTarget, &m_DropTarget));
3083
3084 if (SUCCEEDED(hr))
3085 hr = m_DropTarget->DragEnter(pDataObject, dwKeyState, pt, pdwEffect);
3086 else
3087 *pdwEffect = DROPEFFECT_NONE;
3088 }
3089 else
3090 *pdwEffect = DROPEFFECT_NONE;
3091
3092 return S_OK;
3093}
3094
3096 DWORD *pdwEffect)
3097{
3098 TRACE("(%p)\n", this);
3099 HRESULT hr = S_OK;
3100 if (m_DropTarget)
3101 hr = m_DropTarget->DragOver(dwKeyState, pt, pdwEffect);
3102 return hr;
3103}
3104
3106{
3107 TRACE("(%p)\n", this);
3108 HRESULT hr = S_OK;
3109 if (m_DropTarget)
3110 {
3111 hr = m_DropTarget->DragLeave();
3113 }
3114
3115 return hr;
3116}
3117
3119 DWORD dwKeyState, POINTL pt, DWORD *pdwEffect)
3120{
3121 TRACE("(%p)\n", this);
3122 HRESULT hr = S_OK;
3123 if (m_DropTarget)
3124 hr = m_DropTarget->Drop(pDataObject, dwKeyState, pt, pdwEffect);
3125
3126 return hr;
3127}
3128
3129/**************************************************************************
3130 * IShellLink_ConstructFromFile
3131 */
3133{
3135 HRESULT hr = CShellLink::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IPersistFile, &ppf));
3136 if (FAILED(hr))
3137 return hr;
3138
3139 hr = ppf->Load(path, 0);
3140 if (FAILED(hr))
3141 return hr;
3142
3143 return ppf->QueryInterface(riid, ppv);
3144}
3145
3147{
3149 if (!ILGetDisplayNameExW(psf, pidl, path, 0))
3150 return E_FAIL;
3151
3153}
3154
3156{
3158 const COLORREF crMask = GetSysColor(COLOR_3DFACE);
3159 WCHAR wszLnkIcon[MAX_PATH];
3160 int lnk_idx;
3161 HDC hDC;
3163 HICON hIcon = NULL, hNewIcon = NULL, hShortcut;
3164
3165 if (HLM_GetIconW(IDI_SHELL_SHORTCUT - 1, wszLnkIcon, _countof(wszLnkIcon), &lnk_idx))
3166 {
3167 ::ExtractIconExW(wszLnkIcon, lnk_idx, &hShortcut, NULL, 1);
3168 }
3169 else
3170 {
3172 IMAGE_ICON, cx, cy, 0);
3173 }
3174
3175 ::ExtractIconExW(wszIconPath, IconIndex, &hIcon, NULL, 1);
3176 if (!hIcon || !hShortcut || !himl)
3177 goto cleanup;
3178
3180 if (hDC)
3181 {
3182 // create 32bpp bitmap
3183 BITMAPINFO bi;
3184 ZeroMemory(&bi, sizeof(bi));
3185 bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
3186 bi.bmiHeader.biWidth = cx;
3187 bi.bmiHeader.biHeight = cy;
3188 bi.bmiHeader.biPlanes = 1;
3189 bi.bmiHeader.biBitCount = 32;
3190 LPVOID pvBits;
3191 HBITMAP hbm = CreateDIBSection(hDC, &bi, DIB_RGB_COLORS, &pvBits, NULL, 0);
3192 if (hbm)
3193 {
3194 // draw the icon image
3195 HGDIOBJ hbmOld = SelectObject(hDC, hbm);
3196 {
3197 HBRUSH hbr = CreateSolidBrush(crMask);
3198 RECT rc = { 0, 0, cx, cy };
3199 FillRect(hDC, &rc, hbr);
3200 DeleteObject(hbr);
3201
3202 DrawIconEx(hDC, 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL);
3203 DrawIconEx(hDC, 0, 0, hShortcut, cx, cy, 0, NULL, DI_NORMAL);
3204 }
3205 SelectObject(hDC, hbmOld);
3206
3207 INT iAdded = ImageList_AddMasked(himl, hbm, crMask);
3208 hNewIcon = ImageList_GetIcon(himl, iAdded, ILD_NORMAL | ILD_TRANSPARENT);
3209
3211 }
3212 DeleteDC(hDC);
3213 }
3214
3215cleanup:
3216 if (hIcon)
3218 if (hShortcut)
3219 DestroyIcon(hShortcut);
3220 if (himl)
3222
3223 return hNewIcon;
3224}
static HDC hDC
Definition: 3dtext.c:33
#define PRF_TRYPROGRAMEXTENSIONS
Definition: PathResolve.cpp:40
#define shell32_hInstance
UINT cchMax
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
static WCHAR * strdupW(const WCHAR *src)
Definition: main.c:92
#define CF_HDROP
Definition: constants.h:410
void shell(int argc, const char *argv[])
Definition: cmds.c:1231
#define STDMETHODCALLTYPE
Definition: bdasup.h:9
#define FIXME(fmt,...)
Definition: debug.h:111
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
HIMAGELIST himl
EXTERN_C void WINAPI SHChangeNotify(LONG wEventId, UINT uFlags, LPCVOID dwItem1, LPCVOID dwItem2)
void Release()
Definition: atlcomcli.h:170
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define E_OUTOFMEMORY
Definition: ddrawi.h:100
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
void pdump(LPCITEMIDLIST pidl)
Definition: debughlp.cpp:311
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
DWORD WINAPI CommandLineFromMsiDescriptor(WCHAR *szDescriptor, WCHAR *szCommandLine, DWORD *pcchCommandLine)
Definition: msi.c:22
UINT uFlags
Definition: api.c:59
BOOL WINAPI ImageList_Destroy(HIMAGELIST himl)
Definition: imagelist.c:928
HICON WINAPI ImageList_GetIcon(HIMAGELIST himl, INT i, UINT fStyle)
Definition: imagelist.c:1963
INT WINAPI ImageList_AddMasked(HIMAGELIST himl, HBITMAP hBitmap, COLORREF clrMask)
Definition: imagelist.c:563
HIMAGELIST WINAPI ImageList_Create(INT cx, INT cy, UINT flags, INT cInitial, INT cGrow)
Definition: imagelist.c:804
#define wcschr
Definition: compat.h:17
#define GetProcessHeap()
Definition: compat.h:736
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
static __inline const char * debugstr_an(const char *s, int n)
Definition: compat.h:55
#define TRACE_ON(x)
Definition: compat.h:75
#define MAX_PATH
Definition: compat.h:34
#define HeapFree(x, y, z)
Definition: compat.h:735
#define CALLBACK
Definition: compat.h:35
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define wcsicmp
Definition: compat.h:15
#define lstrcpynW
Definition: compat.h:738
#define lstrlenW
Definition: compat.h:750
#define FAILED_UNEXPECTEDLY(hr)
Definition: precomp.h:121
static void cleanup(void)
Definition: main.c:1335
BOOL WINAPI DeleteFileW(IN LPCWSTR lpFileName)
Definition: delete.c:39
UINT WINAPI GetDriveTypeW(IN LPCWSTR lpRootPathName)
Definition: disk.c:497
DWORD WINAPI GetFileAttributesW(LPCWSTR lpFileName)
Definition: fileinfo.c:652
BOOL WINAPI GetVolumeInformationW(IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
Definition: volume.c:226
DWORD WINAPI GetShortPathNameW(IN LPCWSTR lpszLongPath, OUT LPWSTR lpszShortPath, IN DWORD cchBuffer)
Definition: path.c:1833
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
BOOL WINAPI FileTimeToSystemTime(IN CONST FILETIME *lpFileTime, OUT LPSYSTEMTIME lpSystemTime)
Definition: time.c:188
HRESULT WINAPI CLSIDFromString(LPCOLESTR idstr, LPCLSID id)
Definition: compobj.c:2338
void WINAPI ReleaseStgMedium(STGMEDIUM *pmedium)
Definition: ole2.c:2033
static const WCHAR IconIndex[]
Definition: install.c:52
BOOL WINAPI PickIconDlg(HWND hWndOwner, LPWSTR lpstrFile, UINT nMaxFile, INT *lpdwIconIndex)
Definition: dialogs.cpp:362
const GUID SHELL32_AdvtShortcutProduct
const GUID SHELL32_AdvtShortcutComponent
UINT WINAPI DragQueryFileW(HDROP hDrop, UINT lFile, LPWSTR lpszwFile, UINT lLength)
Definition: shellole.c:622
BOOL WINAPI PathResolveW(_Inout_ LPWSTR path, _Inout_opt_ LPCWSTR *dirs, _In_ DWORD flags)
Definition: shellpath.c:883
DATABLOCK_HEADER *WINAPI SHFindDataBlock(LPDBLIST lpList, DWORD dwSignature)
Definition: clist.c:424
HRESULT WINAPI SHReadDataBlockList(IStream *lpStream, LPDBLIST *lppList)
Definition: clist.c:235
VOID WINAPI SHFreeDataBlockList(LPDBLIST lpList)
Definition: clist.c:331
BOOL WINAPI SHAddDataBlock(LPDBLIST *lppList, const DATABLOCK_HEADER *lpNewItem)
Definition: clist.c:68
HRESULT WINAPI SHWriteDataBlockList(IStream *lpStream, LPDBLIST lpList)
Definition: clist.c:179
BOOL WINAPI SHRemoveDataBlock(LPDBLIST *lppList, DWORD dwSignature)
Definition: clist.c:355
HRESULT WINAPI SHCreateStreamOnFileW(LPCWSTR lpszPath, DWORD dwMode, IStream **lppStream)
Definition: istream.c:484
void WINAPI PathRemoveArgsW(LPWSTR lpszPath)
Definition: path.c:779
BOOL WINAPI PathRemoveFileSpecW(LPWSTR lpszPath)
Definition: path.c:629
LPWSTR WINAPI PathFindFileNameW(LPCWSTR lpszPath)
Definition: path.c:394
BOOL WINAPI PathUnExpandEnvStringsW(LPCWSTR path, LPWSTR buffer, UINT buf_len)
Definition: path.c:4191
LPWSTR WINAPI PathFindExtensionW(LPCWSTR lpszPath)
Definition: path.c:447
BOOL WINAPI PathFileExistsW(LPCWSTR lpszPath)
Definition: path.c:1777
VOID WINAPI PathUnquoteSpacesW(LPWSTR lpszPath)
Definition: path.c:1034
BOOL WINAPI PathIsFileSpecW(LPCWSTR lpszPath)
Definition: path.c:2133
LPWSTR WINAPI PathGetArgsW(LPCWSTR lpszPath)
Definition: path.c:506
BOOL WINAPI StrTrimW(LPWSTR lpszStr, LPCWSTR lpszTrim)
Definition: string.c:1877
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define assert(x)
Definition: debug.h:53
#define MAKE_HRESULT(sev, fac, code)
Definition: dmerror.h:30
#define pt(x, y)
Definition: drawing.c:79
static BOOLEAN bSuccess
Definition: drive.cpp:433
HPROPSHEETPAGE SH_CreatePropertySheetPage(LPCSTR resname, DLGPROC dlgproc, LPARAM lParam, LPWSTR szTitle)
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
pKey DeleteObject()
GLuint GLuint end
Definition: gl.h:1545
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint buffer
Definition: glext.h:5915
GLuint index
Definition: glext.h:6031
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLbitfield flags
Definition: glext.h:7161
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLuint64EXT * result
Definition: glext.h:11304
GLenum target
Definition: glext.h:7315
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
HLOCAL NTAPI LocalAlloc(UINT uFlags, SIZE_T dwBytes)
Definition: heapmem.c:1390
UINT WINAPI ExtractIconExW(LPCWSTR lpszFile, INT nIconIndex, HICON *phiconLarge, HICON *phiconSmall, UINT nIcons)
Definition: iconcache.cpp:849
LPVOID WINAPI CoTaskMemAlloc(SIZE_T size)
Definition: ifs.c:426
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
_CONST_RETURN wchar_t *__cdecl wcsstr(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_SubStr)
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
struct IContextMenu::tagCMInvokeCommandInfoEx * LPCMINVOKECOMMANDINFOEX
HRESULT GetData([in, unique] FORMATETC *pformatetcIn, [out] STGMEDIUM *pmedium)
const DWORD DROPEFFECT_NONE
Definition: oleidl.idl:929
HRESULT Write([in, size_is(cb)] const void *pv, [in] ULONG cb, [out] ULONG *pcbWritten)
HRESULT Read([out, size_is(cb), length_is(*pcbRead)] void *pv, [in] ULONG cb, [out] ULONG *pcbRead)
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define FAILED(hr)
Definition: intsafe.h:51
#define NTDDI_VERSION
Definition: k32.h:33
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
INT WINAPI GetDateFormatW(LCID lcid, DWORD dwFlags, const SYSTEMTIME *lpTime, LPCWSTR lpFormat, LPWSTR lpDateStr, INT cchOut)
Definition: lcformat.c:993
if(dx< 0)
Definition: linetemp.h:194
const GUID * guid
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int DoOpen(void)
Definition: cmds.c:2168
LPCWSTR szPath
Definition: env.c:37
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static HICON
Definition: imagelist.c:84
static const WCHAR label[]
Definition: itemdlg.c:1546
static char * dest
Definition: rtl.c:135
static const WCHAR szGuid[]
Definition: rtlstr.c:1892
static LPOLESTR
Definition: stg_prop.c:27
static const CLSID *static CLSID *static const GUID VARIANT VARIANT *static IServiceProvider DWORD *static HMENU
Definition: ordinal.c:63
#define _Out_
Definition: ms_sal.h:345
#define _In_
Definition: ms_sal.h:308
HICON hIcon
Definition: msconfig.c:44
struct _PSP * HPROPSHEETPAGE
Definition: mstask.idl:90
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
unsigned __int3264 UINT_PTR
Definition: mstsclib_h.h:274
_In_ HANDLE _In_ DWORD _In_ DWORD _Inout_opt_ LPOVERLAPPED _In_opt_ LPTRANSMIT_FILE_BUFFERS _In_ DWORD dwReserved
Definition: mswsock.h:95
unsigned int UINT
Definition: ndis.h:50
#define LOCALE_USER_DEFAULT
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
#define L(x)
Definition: ntvdm.h:50
#define STGM_CREATE
Definition: objbase.h:926
#define STGM_READWRITE
Definition: objbase.h:919
#define STGM_SHARE_EXCLUSIVE
Definition: objbase.h:923
#define STGM_SHARE_DENY_WRITE
Definition: objbase.h:922
#define STGM_READ
Definition: objbase.h:917
#define PathAddBackslashW
Definition: pathcch.h:301
#define LOWORD(l)
Definition: pedump.c:82
unsigned short USHORT
Definition: pedump.c:61
LPITEMIDLIST WINAPI ILClone(LPCITEMIDLIST pidl)
Definition: pidl.c:237
void WINAPI ILFree(LPITEMIDLIST pidl)
Definition: pidl.c:938
HRESULT WINAPI SHILCreateFromPathW(LPCWSTR path, LPITEMIDLIST *ppidl, DWORD *attributes)
Definition: pidl.c:401
HRESULT WINAPI SHBindToParent(LPCITEMIDLIST pidl, REFIID riid, LPVOID *ppv, LPCITEMIDLIST *ppidlLast)
Definition: pidl.c:1361
HRESULT WINAPI ILSaveToStream(IStream *pStream, LPCITEMIDLIST pPidl)
Definition: pidl.c:351
BOOL WINAPI SHGetPathFromIDListW(LPCITEMIDLIST pidl, LPWSTR pszPath)
Definition: pidl.c:1353
HRESULT WINAPI ILLoadFromStream(IStream *pStream, LPITEMIDLIST *ppPidl)
Definition: pidl.c:293
LPITEMIDLIST WINAPI SHSimpleIDListFromPathW(LPCWSTR lpszPath)
Definition: pidl.c:1133
BOOL ILGetDisplayNameExW(LPSHELLFOLDER psf, LPCITEMIDLIST pidl, LPWSTR path, DWORD type)
Definition: pidl.c:100
#define PSNRET_INVALID_NOCHANGEPAGE
Definition: prsht.h:131
#define PropSheet_Changed(d, w)
Definition: prsht.h:344
#define PSN_APPLY
Definition: prsht.h:117
#define PSNRET_NOERROR
Definition: prsht.h:129
struct _PROPSHEETPAGEW * LPPROPSHEETPAGEW
BOOL(CALLBACK * LPFNADDPROPSHEETPAGE)(HPROPSHEETPAGE, LPARAM)
Definition: prsht.h:327
struct _PSHNOTIFY * LPPSHNOTIFY
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
#define ILD_NORMAL
Definition: commctrl.h:417
_Out_opt_ int * cx
Definition: commctrl.h:585
#define ILC_COLOR32
Definition: commctrl.h:358
#define HKM_SETHOTKEY
Definition: commctrl.h:2231
#define ILD_TRANSPARENT
Definition: commctrl.h:418
#define ILC_MASK
Definition: commctrl.h:351
#define HKM_GETHOTKEY
Definition: commctrl.h:2232
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define WM_NOTIFY
Definition: richedit.h:61
const WCHAR * str
static calc_node_t temp
Definition: rpn_ieee.c:38
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcspbrk(_In_z_ const wchar_t *_Str, _In_z_ const wchar_t *_Control)
_CRTIMP wchar_t *__cdecl wcsncpy(wchar_t *_Dest, const wchar_t *_Source, size_t _Count)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static HANDLE heap
Definition: heap.c:65
#define NTDDI_LONGHORN
Definition: sdkddkver.h:102
DWORD_PTR WINAPI SHGetFileInfoW(LPCWSTR path, DWORD dwFileAttributes, SHFILEINFOW *psfi, UINT sizeofpsfi, UINT flags)
Definition: shell32_main.c:415
#define SEE_MASK_UNICODE
Definition: shellapi.h:37
#define SHGFI_ICON
Definition: shellapi.h:164
#define SHGFI_TYPENAME
Definition: shellapi.h:167
#define SHGFI_USEFILEATTRIBUTES
Definition: shellapi.h:181
#define SEE_MASK_ASYNCOK
Definition: shellapi.h:54
#define SEE_MASK_IDLIST
Definition: shellapi.h:27
#define SEE_MASK_NOASYNC
Definition: shellapi.h:33
_In_ LPCSTR pszDir
Definition: shellapi.h:584
#define SEE_MASK_FLAG_NO_UI
Definition: shellapi.h:36
#define SEE_MASK_HASLINKNAME
Definition: shellapi.h:49
HINSTANCE WINAPI FindExecutableW(LPCWSTR lpFile, LPCWSTR lpDirectory, LPWSTR lpResult)
Definition: shlexec.cpp:1257
HINSTANCE WINAPI ShellExecuteW(HWND hwnd, LPCWSTR lpVerb, LPCWSTR lpFile, LPCWSTR lpParameters, LPCWSTR lpDirectory, INT nShowCmd)
Definition: shlexec.cpp:2402
BOOL WINAPI DECLSPEC_HOTPATCH ShellExecuteExW(LPSHELLEXECUTEINFOW sei)
Definition: shlexec.cpp:2391
HRESULT hr
Definition: shlfolder.c:183
EXTERN_C HRESULT WINAPI SHOpenFolderAndSelectItems(PCIDLIST_ABSOLUTE pidlFolder, UINT cidl, PCUITEMID_CHILD_ARRAY apidl, DWORD dwFlags)
Definition: shlfolder.cpp:402
#define EXP_DARWIN_ID_SIG
Definition: shlobj.h:2040
#define SHCNE_UPDATEITEM
Definition: shlobj.h:1888
struct EXP_DARWIN_LINK * LPEXP_DARWIN_LINK
#define SHCNE_CREATE
Definition: shlobj.h:1876
#define EXP_SZ_LINK_SIG
Definition: shlobj.h:2036
@ SLDF_HAS_RELPATH
Definition: shlobj.h:1932
@ SLDF_HAS_EXP_SZ
Definition: shlobj.h:1938
@ SLDF_HAS_ID_LIST
Definition: shlobj.h:1929
@ SLDF_HAS_DARWINID
Definition: shlobj.h:1943
@ SLDF_RUN_IN_SEPARATE
Definition: shlobj.h:1939
@ SLDF_HAS_LINK_INFO
Definition: shlobj.h:1930
@ SLDF_HAS_WORKINGDIR
Definition: shlobj.h:1933
@ SLDF_HAS_ARGS
Definition: shlobj.h:1934
@ SLDF_FORCE_NO_LINKINFO
Definition: shlobj.h:1937
@ SLDF_HAS_EXP_ICON_SZ
Definition: shlobj.h:1945
@ SLDF_RUNAS_USER
Definition: shlobj.h:1944
@ SLDF_UNICODE
Definition: shlobj.h:1936
@ SLDF_RUN_WITH_SHIMLAYER
Definition: shlobj.h:1948
@ SLDF_HAS_ICONLOCATION
Definition: shlobj.h:1935
@ SLDF_HAS_NAME
Definition: shlobj.h:1931
#define EXP_SZ_ICON_SIG
Definition: shlobj.h:2044
#define SHCNF_PATHW
Definition: shlobj.h:1910
struct EXP_SZ_LINK * LPEXP_SZ_LINK
HRESULT WINAPI SHAutoComplete(HWND hwndEdit, DWORD dwFlags)
Definition: autocomp.cpp:191
#define PathRemoveBackslash
Definition: shlwapi.h:1023
#define SHACF_DEFAULT
Definition: shlwapi.h:1911
DWORD WINAPI SHExpandEnvironmentStringsW(LPCWSTR, LPWSTR, DWORD)
#define IDC_SHORTCUT_FIND
Definition: shresdef.h:474
#define IDS_SHORTCUT_RUN_MAX
Definition: shresdef.h:263
#define IDC_SHORTCUT_ADVANCED
Definition: shresdef.h:476
#define IDS_OPEN_VERB
Definition: shresdef.h:212
#define IDC_SHORTCUT_RUN_COMBO
Definition: shresdef.h:471
#define IDS_OPENFILELOCATION
Definition: shresdef.h:246
#define IDS_SHORTCUT_RUN_MIN
Definition: shresdef.h:262
#define IDC_SHORTCUT_LOCATION_EDIT
Definition: shresdef.h:463
#define IDC_SHORTCUT_TARGET_TEXT
Definition: shresdef.h:465
#define IDC_SHORTCUT_ICON
Definition: shresdef.h:458
#define IDC_SHORTCUT_KEY_HOTKEY
Definition: shresdef.h:469
#define IDC_SHORTEX_RUN_DIFFERENT
Definition: shresdef.h:479
#define IDI_SHELL_SHORTCUT
Definition: shresdef.h:580
#define IDS_SHORTCUT_RUN_NORMAL
Definition: shresdef.h:261
#define IDD_SHORTCUT_PROPERTIES
Definition: shresdef.h:399
#define IDC_SHORTCUT_CHANGE_ICON
Definition: shresdef.h:475
#define IDD_SHORTCUT_EXTENDED_PROPERTIES
Definition: shresdef.h:405
#define IDC_SHORTCUT_TYPE_EDIT
Definition: shresdef.h:461
#define IDC_SHORTCUT_COMMENT_EDIT
Definition: shresdef.h:473
#define IDC_SHORTCUT_START_IN_EDIT
Definition: shresdef.h:467
ITEMIDLIST UNALIGNED * LPITEMIDLIST
Definition: shtypes.idl:41
const ITEMIDLIST UNALIGNED * LPCITEMIDLIST
Definition: shtypes.idl:42
#define _countof(array)
Definition: sndvol32.h:68
#define TRACE(s)
Definition: solgame.cpp:4
static PIXELFORMATDESCRIPTOR pfd
Definition: ssstars.c:67
STRSAFEAPI StringCchCopyExW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags)
Definition: strsafe.h:184
STRSAFEAPI StringCchCatW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:325
STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:585
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
STRSAFEAPI StringCbPrintfW(STRSAFE_LPWSTR pszDest, size_t cbDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:557
DWORD dwLocalPathOfs
Definition: CShellLink.cpp:167
DWORD dwHeaderSize
Definition: CShellLink.cpp:164
DWORD dwVolTableOfs
Definition: CShellLink.cpp:166
DWORD dwFinalPathOfs
Definition: CShellLink.cpp:169
DWORD dwNetworkVolTableOfs
Definition: CShellLink.cpp:168
LPARAM lParam
Definition: prsht.h:227
NMHDR hdr
Definition: prsht.h:330
LPCWSTR lpDirectory
Definition: shellapi.h:334
LPCWSTR lpParameters
Definition: shellapi.h:333
WCHAR szTypeName[80]
Definition: shellapi.h:376
HICON hIcon
Definition: shellapi.h:372
Definition: match.c:390
uint16_t size
Definition: btrfs_drv.h:563
USHORT biBitCount
Definition: precomp.h:46
BITMAPINFOHEADER bmiHeader
Definition: wingdi.h:1476
LPWSTR dwTypeData
Definition: winuser.h:3269
UINT code
Definition: winuser.h:3159
WCHAR label[12]
Definition: CShellLink.cpp:184
#define GetWindowLongPtr
Definition: treelist.c:73
#define SetWindowLongPtr
Definition: treelist.c:70
uint16_t * PWSTR
Definition: typedefs.h:56
int32_t INT_PTR
Definition: typedefs.h:64
char * PSTR
Definition: typedefs.h:51
const uint16_t * PCWSTR
Definition: typedefs.h:57
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
const char * PCSTR
Definition: typedefs.h:52
#define MAXUSHORT
Definition: typedefs.h:83
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
int ret
HBITMAP WINAPI CreateDIBSection(HDC hDC, CONST BITMAPINFO *BitmapInfo, UINT Usage, VOID **Bits, HANDLE hSection, DWORD dwOffset)
Definition: bitmap.c:245
UINT WINAPI GetDlgItemTextW(HWND hDlg, int nIDDlgItem, LPWSTR lpString, int nMaxCount)
Definition: dialog.c:2263
#define ZeroMemory
Definition: winbase.h:1712
#define LMEM_ZEROINIT
Definition: winbase.h:375
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define CopyMemory
Definition: winbase.h:1710
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
UINT_PTR WPARAM
Definition: windef.h:207
DWORD COLORREF
Definition: windef.h:300
#define WINAPI
Definition: msvc.h:6
#define STG_E_INVALIDPOINTER
Definition: winerror.h:2571
#define S_FALSE
Definition: winerror.h:2357
#define SEVERITY_SUCCESS
Definition: winerror.h:64
#define NOERROR
Definition: winerror.h:2354
#define E_POINTER
Definition: winerror.h:2365
#define DIB_RGB_COLORS
Definition: wingdi.h:367
HGDIOBJ WINAPI SelectObject(_In_ HDC, _In_ HGDIOBJ)
Definition: dc.c:1539
#define DI_NORMAL
Definition: wingdi.h:72
HDC WINAPI CreateCompatibleDC(_In_opt_ HDC hdc)
int WINAPI FillRect(HDC, LPCRECT, HBRUSH)
HBRUSH WINAPI CreateSolidBrush(_In_ COLORREF)
BOOL WINAPI DeleteDC(_In_ HDC)
#define DATE_SHORTDATE
Definition: winnls.h:196
#define SW_SHOWNORMAL
Definition: winuser.h:770
#define SW_SHOWMAXIMIZED
Definition: winuser.h:773
DWORD WINAPI GetSysColor(_In_ int)
#define CB_SETITEMDATA
Definition: winuser.h:1966
#define DWLP_USER
Definition: winuser.h:872
#define MIIM_ID
Definition: winuser.h:722
#define STM_SETICON
Definition: winuser.h:2092
#define IDCANCEL
Definition: winuser.h:831
#define BST_UNCHECKED
Definition: winuser.h:199
#define IMAGE_ICON
Definition: winuser.h:212
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
UINT WINAPI PrivateExtractIconsW(_In_reads_(MAX_PATH) LPCWSTR szFileName, _In_ int nIconIndex, _In_ int cxIcon, _In_ int cyIcon, _Out_writes_opt_(nIcons) HICON *phicon, _Out_writes_opt_(nIcons) UINT *piconid, _In_ UINT nIcons, _In_ UINT flags)
#define WM_COMMAND
Definition: winuser.h:1740
#define CB_ERR
Definition: winuser.h:2435
HANDLE WINAPI LoadImageW(_In_opt_ HINSTANCE hInst, _In_ LPCWSTR name, _In_ UINT type, _In_ int cx, _In_ int cy, _In_ UINT fuLoad)
Definition: cursoricon.c:2234
#define CB_SETCURSEL
Definition: winuser.h:1961
BOOL WINAPI SetDlgItemTextW(_In_ HWND, _In_ int, _In_ LPCWSTR)
#define WM_INITDIALOG
Definition: winuser.h:1739
int WINAPI MessageBoxW(_In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType)
HWND WINAPI GetDlgItem(_In_opt_ HWND, _In_ int)
#define IDOK
Definition: winuser.h:830
#define CBN_SELCHANGE
Definition: winuser.h:1979
#define BM_SETCHECK
Definition: winuser.h:1921
#define MIIM_STATE
Definition: winuser.h:721
LRESULT WINAPI SendDlgItemMessageW(_In_ HWND, _In_ int, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define MFS_DEFAULT
Definition: winuser.h:748
#define MB_ICONERROR
Definition: winuser.h:787
#define SM_CYICON
Definition: winuser.h:973
BOOL WINAPI DrawIconEx(_In_ HDC, _In_ int, _In_ int, _In_ HICON, _In_ int, _In_ int, _In_ UINT, _In_opt_ HBRUSH, _In_ UINT)
Definition: cursoricon.c:2059
#define CB_ADDSTRING
Definition: winuser.h:1936
#define CB_GETITEMDATA
Definition: winuser.h:1950
#define SendMessage
Definition: winuser.h:5843
#define MFS_ENABLED
Definition: winuser.h:750
HWND WINAPI GetParent(_In_ HWND)
#define DWLP_MSGRESULT
Definition: winuser.h:870
#define MFT_STRING
Definition: winuser.h:746
#define WM_DESTROY
Definition: winuser.h:1609
#define MAKEINTRESOURCEW(i)
Definition: winuser.h:582
#define CB_GETCURSEL
Definition: winuser.h:1943
#define SM_CXICON
Definition: winuser.h:972
#define MAKEINTRESOURCE
Definition: winuser.h:591
int WINAPI GetSystemMetrics(_In_ int)
#define SW_SHOWMINNOACTIVE
Definition: winuser.h:777
#define MIIM_TYPE
Definition: winuser.h:725
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define BST_CHECKED
Definition: winuser.h:197
BOOL WINAPI InsertMenuItemW(_In_ HMENU, _In_ UINT, _In_ BOOL, _In_ LPCMENUITEMINFOW)
INT_PTR WINAPI DialogBoxParamW(_In_opt_ HINSTANCE, _In_ LPCWSTR, _In_opt_ HWND, _In_opt_ DLGPROC, _In_ LPARAM)
#define BM_GETCHECK
Definition: winuser.h:1918
BOOL WINAPI EndDialog(_In_ HWND, _In_ INT_PTR)
BOOL WINAPI DestroyIcon(_In_ HICON)
Definition: cursoricon.c:2084
#define EN_CHANGE
Definition: winuser.h:2022
#define COLOR_3DFACE
Definition: winuser.h:929
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
#define IID_PPV_ARG(Itype, ppType)
#define IID_NULL_PPV_ARG(Itype, ppType)
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185