]> cygwin.com Git - cygwin-apps/setup.git/blame - mklink2.cc
* Makefile.am: Treat libgetopt++ as full-fledged SUBDIRS.
[cygwin-apps/setup.git] / mklink2.cc
CommitLineData
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
11static 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
16doesn'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. */
22IShellLink *sl;
23
51ebb760 24extern "C"
904d24fe 25void
3c054baf 26make_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
50static int
51mkcygsymlink_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
73static int
74mkcygsymlink_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];
21aa9a8b 80 HANDLE h;
26922cd2
CV
81 SECURITY_DESCRIPTOR sd;
82 acl_t acl;
83 SECURITY_ATTRIBUTES sa = { sizeof (SECURITY_ATTRIBUTES),
84 nt_sec.GetPosixPerms (from, NULL, NULL, 0644,
85 sd, acl),
86 FALSE };
2f0315ad
CV
87
88 mklongpath (wfrom, from, len);
26922cd2 89 h = CreateFileW (wfrom, GENERIC_WRITE, 0, &sa, CREATE_NEW,
21aa9a8b 90 FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
2f0315ad 91 if (h == INVALID_HANDLE_VALUE)
26922cd2 92 return 1;
2f0315ad 93 strcpy (buf, SYMLINK_COOKIE);
770e3aed 94 strncat (buf, to, 4095);
2f0315ad
CV
95 if (WriteFile (h, buf, strlen (buf) + 1, &w, NULL))
96 {
97 CloseHandle (h);
98 SetFileAttributesW (wfrom, FILE_ATTRIBUTE_SYSTEM);
99 return 0;
100 }
101 CloseHandle (h);
102 DeleteFileW (wfrom);
103 return 1;
104}
105
106extern "C"
107int
108mkcygsymlink (const char *from, const char *to)
109{
110 return IsWindowsNT () ? mkcygsymlink_nt (from, to)
111 : mkcygsymlink_9x (from, to);
112}
d2e8d256
CV
113
114struct {
115 FILE_LINK_INFORMATION fli;
116 WCHAR namebuf[32768];
117} sfli;
118
119extern "C"
120int
121mkcyghardlink (const char *from, const char *to)
122{
123 if (!IsWindowsNT ())
124 return 1;
125
126 size_t flen = strlen (from) + 7;
127 size_t tlen = strlen (to) + 7;
128 wchar_t wfrom[flen];
129 wchar_t wto[tlen];
130 mklongpath (wfrom, from, flen);
131 wfrom[1] = '?';
132 mklongpath (wto, to, tlen);
133 wto[1] = '?';
134
135 HANDLE fh;
136 NTSTATUS status;
137 UNICODE_STRING uto;
138 OBJECT_ATTRIBUTES attr;
139 IO_STATUS_BLOCK io;
140
141 /* Open the existing file. */
142 RtlInitUnicodeString (&uto, wto);
143 InitializeObjectAttributes (&attr, &uto, OBJ_CASE_INSENSITIVE, NULL, NULL);
144 status = NtOpenFile (&fh, READ_CONTROL, &attr, &io, FILE_SHARE_VALID_FLAGS,
145 FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT);
146 if (!NT_SUCCESS (status))
147 return 1;
148 /* Create from as link to to. */
149 flen = wcslen (wfrom) * sizeof (WCHAR);
150 ULONG size = sizeof (FILE_LINK_INFORMATION) + flen;
151 sfli.fli.ReplaceIfExists = TRUE;
152 sfli.fli.RootDirectory = NULL;
153 sfli.fli.FileNameLength = flen;
154 memcpy (sfli.fli.FileName, wfrom, flen);
155 status = NtSetInformationFile (fh, &io, &sfli.fli, size, FileLinkInformation);
156 NtClose (fh);
157 return NT_SUCCESS (status) ? 0 : 1;
158}
This page took 0.066443 seconds and 5 git commands to generate.