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