]>
Commit | Line | Data |
---|---|---|
51ebb760 | 1 | #define CINTERFACE |
b24c88b3 | 2 | #include <stdlib.h> |
d2e8d256 | 3 | #include <wchar.h> |
904d24fe | 4 | #include "win32.h" |
d2e8d256 | 5 | #include "ntdll.h" |
904d24fe | 6 | #include "shlobj.h" |
b24c88b3 | 7 | #include "mklink2.h" |
2f0315ad | 8 | #include "filemanip.h" |
904d24fe | 9 | |
b24c88b3 RC |
10 | #if 0 |
11 | static const char *cvsid = | |
12 | "\n%%% $Id$\n"; | |
13 | #endif | |
8507f105 | 14 | |
904d24fe DD |
15 | /* This part of the code must be in C because the C++ interface to COM |
16 | doesn't work. */ | |
17 | ||
e36b0f1e CV |
18 | /* Initialized in WinMain. This is required under Windows 7. If |
19 | CoCreateInstance gets called from here, it fails to create the | |
20 | instance with an undocumented error code 0x80110474. | |
21 | FIXME: I have no idea why this happens. */ | |
22 | IShellLink *sl; | |
23 | ||
51ebb760 | 24 | extern "C" |
904d24fe | 25 | void |
3c054baf | 26 | make_link_2 (char const *exepath, char const *args, char const *icon, char const *lname) |
904d24fe | 27 | { |
904d24fe | 28 | IPersistFile *pf; |
4875ac88 | 29 | WCHAR widepath[MAX_PATH]; |
e36b0f1e CV |
30 | if (sl) |
31 | { | |
32 | sl->lpVtbl->QueryInterface (sl, &IID_IPersistFile, (void **) &pf); | |
904d24fe | 33 | |
e36b0f1e CV |
34 | sl->lpVtbl->SetPath (sl, exepath); |
35 | sl->lpVtbl->SetArguments (sl, args); | |
36 | sl->lpVtbl->SetIconLocation (sl, icon, 0); | |
904d24fe | 37 | |
e36b0f1e CV |
38 | MultiByteToWideChar (CP_ACP, 0, lname, -1, widepath, MAX_PATH); |
39 | pf->lpVtbl->Save (pf, widepath, TRUE); | |
904d24fe | 40 | |
e36b0f1e CV |
41 | pf->lpVtbl->Release (pf); |
42 | } | |
904d24fe | 43 | } |
b24c88b3 RC |
44 | |
45 | #define SYMLINK_COOKIE "!<symlink>" | |
46 | ||
47 | /* Predicate: file is not currently in existence. | |
48 | * A file race can occur otherwise. | |
49 | */ | |
2f0315ad CV |
50 | static int |
51 | mkcygsymlink_9x (const char *from, const char *to) | |
b24c88b3 RC |
52 | { |
53 | char buf[512]; | |
54 | unsigned long w; | |
2f0315ad | 55 | |
b24c88b3 | 56 | HANDLE h = CreateFileA (from, GENERIC_WRITE, 0, 0, CREATE_NEW, |
b41c2908 | 57 | FILE_ATTRIBUTE_NORMAL, 0); |
b24c88b3 RC |
58 | if (h == INVALID_HANDLE_VALUE) |
59 | return 1; | |
60 | strcpy (buf, SYMLINK_COOKIE); | |
61 | strcat (buf, to); | |
62 | if (WriteFile (h, buf, strlen (buf) + 1, &w, NULL)) | |
63 | { | |
64 | CloseHandle (h); | |
65 | SetFileAttributesA (from, FILE_ATTRIBUTE_SYSTEM); | |
66 | return 0; | |
67 | } | |
68 | CloseHandle (h); | |
69 | DeleteFileA (from); | |
70 | return 1; | |
71 | } | |
2f0315ad CV |
72 | |
73 | static int | |
74 | mkcygsymlink_nt (const char *from, const char *to) | |
75 | { | |
770e3aed | 76 | char buf[strlen (SYMLINK_COOKIE) + 4096]; |
2f0315ad CV |
77 | unsigned long w; |
78 | const size_t len = strlen (from) + 7; | |
79 | WCHAR wfrom[len]; | |
80 | ||
81 | mklongpath (wfrom, from, len); | |
b41c2908 CV |
82 | HANDLE h = CreateFileW (wfrom, STANDARD_RIGHTS_ALL | GENERIC_WRITE, |
83 | 0, 0, CREATE_NEW, | |
84 | FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, | |
85 | 0); | |
2f0315ad CV |
86 | if (h == INVALID_HANDLE_VALUE) |
87 | return 1; | |
88 | strcpy (buf, SYMLINK_COOKIE); | |
770e3aed | 89 | strncat (buf, to, 4095); |
2f0315ad CV |
90 | if (WriteFile (h, buf, strlen (buf) + 1, &w, NULL)) |
91 | { | |
be617b59 | 92 | nt_sec.SetPosixPerms (from, h, 0644); |
2f0315ad CV |
93 | CloseHandle (h); |
94 | SetFileAttributesW (wfrom, FILE_ATTRIBUTE_SYSTEM); | |
95 | return 0; | |
96 | } | |
97 | CloseHandle (h); | |
98 | DeleteFileW (wfrom); | |
99 | return 1; | |
100 | } | |
101 | ||
102 | extern "C" | |
103 | int | |
104 | mkcygsymlink (const char *from, const char *to) | |
105 | { | |
106 | return IsWindowsNT () ? mkcygsymlink_nt (from, to) | |
107 | : mkcygsymlink_9x (from, to); | |
108 | } | |
d2e8d256 CV |
109 | |
110 | struct { | |
111 | FILE_LINK_INFORMATION fli; | |
112 | WCHAR namebuf[32768]; | |
113 | } sfli; | |
114 | ||
115 | extern "C" | |
116 | int | |
117 | mkcyghardlink (const char *from, const char *to) | |
118 | { | |
119 | if (!IsWindowsNT ()) | |
120 | return 1; | |
121 | ||
122 | size_t flen = strlen (from) + 7; | |
123 | size_t tlen = strlen (to) + 7; | |
124 | wchar_t wfrom[flen]; | |
125 | wchar_t wto[tlen]; | |
126 | mklongpath (wfrom, from, flen); | |
127 | wfrom[1] = '?'; | |
128 | mklongpath (wto, to, tlen); | |
129 | wto[1] = '?'; | |
130 | ||
131 | HANDLE fh; | |
132 | NTSTATUS status; | |
133 | UNICODE_STRING uto; | |
134 | OBJECT_ATTRIBUTES attr; | |
135 | IO_STATUS_BLOCK io; | |
136 | ||
137 | /* Open the existing file. */ | |
138 | RtlInitUnicodeString (&uto, wto); | |
139 | InitializeObjectAttributes (&attr, &uto, OBJ_CASE_INSENSITIVE, NULL, NULL); | |
140 | status = NtOpenFile (&fh, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS, | |
141 | FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT); | |
142 | if (!NT_SUCCESS (status)) | |
143 | return 1; | |
144 | /* Create from as link to to. */ | |
145 | flen = wcslen (wfrom) * sizeof (WCHAR); | |
146 | ULONG size = sizeof (FILE_LINK_INFORMATION) + flen; | |
147 | sfli.fli.ReplaceIfExists = TRUE; | |
148 | sfli.fli.RootDirectory = NULL; | |
149 | sfli.fli.FileNameLength = flen; | |
150 | memcpy (sfli.fli.FileName, wfrom, flen); | |
151 | status = NtSetInformationFile (fh, &io, &sfli.fli, size, FileLinkInformation); | |
152 | NtClose (fh); | |
153 | return NT_SUCCESS (status) ? 0 : 1; | |
154 | } |