]> cygwin.com Git - cygwin-apps/setup.git/blame - mklink2.cc
* localdir.cc (LocalDirSetting::save): Call mkdir_p with isadir set
[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];
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
102extern "C"
103int
104mkcygsymlink (const char *from, const char *to)
105{
106 return IsWindowsNT () ? mkcygsymlink_nt (from, to)
107 : mkcygsymlink_9x (from, to);
108}
d2e8d256
CV
109
110struct {
111 FILE_LINK_INFORMATION fli;
112 WCHAR namebuf[32768];
113} sfli;
114
115extern "C"
116int
117mkcyghardlink (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}
This page took 0.059872 seconds and 5 git commands to generate.