unrarsrc  6.1.7
About: unrar extracts, views and tests the contents of archives created with the RAR archiver.
  Fossies Dox: unrarsrc-6.1.7.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

win32lnk.cpp
Go to the documentation of this file.
1#define SYMLINK_FLAG_RELATIVE 1
2
3typedef struct _REPARSE_DATA_BUFFER {
4 ULONG ReparseTag;
6 USHORT Reserved;
7 union {
8 struct {
13 ULONG Flags;
14 WCHAR PathBuffer[1];
16 struct {
19 USHORT PrintNameOffset;
20 USHORT PrintNameLength;
21 WCHAR PathBuffer[1];
23 struct {
24 UCHAR DataBuffer[1];
26 };
28
29
30
31
33{
34 static bool PrivSet=false;
35 if (!PrivSet)
36 {
37 SetPrivilege(SE_RESTORE_NAME);
38 // Not sure if we really need it, but let's request anyway.
39 SetPrivilege(SE_CREATE_SYMBOLIC_LINK_NAME);
40 PrivSet=true;
41 }
42
43 const DWORD BufSize=sizeof(REPARSE_DATA_BUFFER)+2*NM+1024;
44 Array<byte> Buf(BufSize);
46
47 wchar SubstName[NM];
48 wcsncpyz(SubstName,hd->RedirName,ASIZE(SubstName));
49 size_t SubstLength=wcslen(SubstName);
50
51 wchar PrintName[NM],*PrintNameSrc=SubstName,*PrintNameDst=PrintName;
52 bool WinPrefix=wcsncmp(PrintNameSrc,L"\\??\\",4)==0;
53 if (WinPrefix)
54 PrintNameSrc+=4;
55 if (WinPrefix && wcsncmp(PrintNameSrc,L"UNC\\",4)==0)
56 {
57 *(PrintNameDst++)='\\'; // Insert second \ in beginning of share name.
58 PrintNameSrc+=3;
59 }
60 wcscpy(PrintNameDst,PrintNameSrc);
61
62 size_t PrintLength=wcslen(PrintName);
63
64 bool AbsPath=WinPrefix;
65 // IsFullPath is not really needed here, AbsPath check is enough.
66 // We added it just for extra safety, in case some Windows version would
67 // allow to create absolute targets with SYMLINK_FLAG_RELATIVE.
68 // Use hd->FileName instead of Name, since Name can include the destination
69 // path as a prefix, which can confuse IsRelativeSymlinkSafe algorithm.
70 if (!Cmd->AbsoluteLinks && (AbsPath || IsFullPath(hd->RedirName) ||
71 !IsRelativeSymlinkSafe(Cmd,hd->FileName,Name,hd->RedirName)))
72 return false;
73
74 CreatePath(Name,true,Cmd->DisableNames);
75
76 // Overwrite prompt was already issued and confirmed earlier, so we can
77 // remove existing symlink or regular file here. PrepareToDelete was also
78 // called earlier inside of uiAskReplaceEx.
79 if (FileExist(Name))
80 if (IsDir(GetFileAttr(Name)))
81 DelDir(Name);
82 else
83 DelFile(Name);
84
85 // 'DirTarget' check is important for Unix symlinks to directories.
86 // Unix symlinks do not have their own 'directory' attribute.
87 if (hd->Dir || hd->DirTarget)
88 {
89 if (!CreateDirectory(Name,NULL))
90 {
93 return false;
94 }
95 }
96 else
97 {
98 HANDLE hFile=CreateFile(Name,GENERIC_WRITE,0,NULL,CREATE_NEW,FILE_ATTRIBUTE_NORMAL,NULL);
99 if (hFile == INVALID_HANDLE_VALUE)
100 {
102 return false;
103 }
104 CloseHandle(hFile);
105 }
106
107
109 {
110 rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT;
111 rdb->ReparseDataLength=USHORT(
116 (SubstLength+1)*sizeof(WCHAR)+(PrintLength+1)*sizeof(WCHAR));
117 rdb->Reserved=0;
118
120 rdb->MountPointReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR));
121 wcscpy(rdb->MountPointReparseBuffer.PathBuffer,SubstName);
122
123 rdb->MountPointReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR));
124 rdb->MountPointReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR));
125 wcscpy(rdb->MountPointReparseBuffer.PathBuffer+SubstLength+1,PrintName);
126 }
127 else
129 {
130 rdb->ReparseTag=IO_REPARSE_TAG_SYMLINK;
131 rdb->ReparseDataLength=USHORT(
136 sizeof(rdb->SymbolicLinkReparseBuffer.Flags)+
137 (SubstLength+1)*sizeof(WCHAR)+(PrintLength+1)*sizeof(WCHAR));
138 rdb->Reserved=0;
139
141 rdb->SymbolicLinkReparseBuffer.SubstituteNameLength=USHORT(SubstLength*sizeof(WCHAR));
142 wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer,SubstName);
143
144 rdb->SymbolicLinkReparseBuffer.PrintNameOffset=USHORT((SubstLength+1)*sizeof(WCHAR));
145 rdb->SymbolicLinkReparseBuffer.PrintNameLength=USHORT(PrintLength*sizeof(WCHAR));
146 wcscpy(rdb->SymbolicLinkReparseBuffer.PathBuffer+SubstLength+1,PrintName);
147
149 }
150 else
151 return false;
152
153 HANDLE hFile=CreateFile(Name,GENERIC_READ|GENERIC_WRITE,0,NULL,
154 OPEN_EXISTING,FILE_FLAG_OPEN_REPARSE_POINT|
155 FILE_FLAG_BACKUP_SEMANTICS,NULL);
156 if (hFile==INVALID_HANDLE_VALUE)
157 {
160 return false;
161 }
162
163 DWORD Returned;
164 if (!DeviceIoControl(hFile,FSCTL_SET_REPARSE_POINT,rdb,
165 FIELD_OFFSET(REPARSE_DATA_BUFFER,GenericReparseBuffer)+
166 rdb->ReparseDataLength,NULL,0,&Returned,NULL))
167 {
168 CloseHandle(hFile);
170
171 DWORD LastError=GetLastError();
172 if ((LastError==ERROR_ACCESS_DENIED || LastError==ERROR_PRIVILEGE_NOT_HELD) &&
173 !IsUserAdmin())
177
178 if (hd->Dir)
179 RemoveDirectory(Name);
180 else
181 DeleteFile(Name);
182 return false;
183 }
184 File LinkFile;
185 LinkFile.SetHandle(hFile);
186 LinkFile.SetOpenFileTime(
187 Cmd->xmtime==EXTTIME_NONE ? NULL:&hd->mtime,
188 Cmd->xctime==EXTTIME_NONE ? NULL:&hd->ctime,
189 Cmd->xatime==EXTTIME_NONE ? NULL:&hd->atime);
190 LinkFile.Close();
191 if (!Cmd->IgnoreGeneralAttr)
192 SetFileAttr(Name,hd->FileAttr);
193 return true;
194}
ErrorHandler ErrHandler
void SetErrorCode(RAR_EXIT Code)
Definition: errhnd.cpp:243
void SysErrMsg()
Definition: errhnd.cpp:368
void CreateErrorMsg(const wchar *FileName)
Definition: errhnd.cpp:179
Definition: file.hpp:57
void SetHandle(FileHandle Handle)
Definition: file.hpp:131
void SetOpenFileTime(RarTime *ftm, RarTime *ftc=NULL, RarTime *fta=NULL)
Definition: file.cpp:663
virtual bool Close()
Definition: file.cpp:241
bool AbsoluteLinks
Definition: options.hpp:160
bool IgnoreGeneralAttr
Definition: options.hpp:181
bool DisableNames
Definition: options.hpp:138
EXTTIME_MODE xmtime
Definition: options.hpp:196
EXTTIME_MODE xatime
Definition: options.hpp:198
EXTTIME_MODE xctime
Definition: options.hpp:197
@ RARX_CREATE
Definition: errhnd.hpp:15
bool IsRelativeSymlinkSafe(CommandData *Cmd, const wchar *SrcName, const wchar *PrepSrcName, const wchar *TargetName)
Definition: extinfo.cpp:115
bool DelFile(const wchar *Name)
Definition: filefn.cpp:461
uint GetFileAttr(const wchar *Name)
Definition: filefn.cpp:280
bool CreatePath(const wchar *Path, bool SkipLastName, bool Silent)
Definition: filefn.cpp:41
bool DelDir(const wchar *Name)
Definition: filefn.cpp:481
bool IsDir(uint Attr)
Definition: filefn.cpp:218
bool SetFileAttr(const wchar *Name, uint Attr)
Definition: filefn.cpp:302
bool FileExist(const wchar *Name)
Definition: filefn.cpp:190
@ FSREDIR_WINSYMLINK
Definition: headers.hpp:109
@ FSREDIR_UNIXSYMLINK
Definition: headers.hpp:109
@ FSREDIR_JUNCTION
Definition: headers.hpp:109
@ EXTTIME_NONE
Definition: options.hpp:24
bool IsFullPath(const wchar *Path)
Definition: pathfn.cpp:569
#define ASIZE(x)
Definition: rardefs.hpp:10
wchar_t wchar
Definition: rartypes.hpp:13
void wcsncpyz(wchar *dest, const wchar *src, size_t maxlen)
Definition: strfn.cpp:275
RarTime atime
Definition: headers.hpp:190
wchar FileName[NM]
Definition: headers.hpp:184
RarTime ctime
Definition: headers.hpp:189
bool DirTarget
Definition: headers.hpp:240
bool Dir
Definition: headers.hpp:223
wchar RedirName[NM]
Definition: headers.hpp:239
RarTime mtime
Definition: headers.hpp:188
FILE_SYSTEM_REDIRECT RedirType
Definition: headers.hpp:238
uint FileAttr
Definition: headers.hpp:181
struct _REPARSE_DATA_BUFFER::@15::@19 GenericReparseBuffer
USHORT SubstituteNameLength
Definition: win32lnk.cpp:10
USHORT SubstituteNameOffset
Definition: win32lnk.cpp:9
struct _REPARSE_DATA_BUFFER::@15::@17 SymbolicLinkReparseBuffer
struct _REPARSE_DATA_BUFFER::@15::@18 MountPointReparseBuffer
USHORT ReparseDataLength
Definition: win32lnk.cpp:5
void uiMsg(UIMESSAGE_CODE Code)
Definition: ui.hpp:148
#define UINULL
Definition: ui.hpp:146
@ UIERROR_DIRCREATE
Definition: ui.hpp:16
@ UIERROR_NEEDADMIN
Definition: ui.hpp:17
@ UIERROR_SLINKCREATE
Definition: ui.hpp:16
bool SetPrivilege(LPCTSTR PrivName)
Definition: win32acl.cpp:115
bool CreateReparsePoint(CommandData *Cmd, const wchar *Name, FileHeader *hd)
Definition: win32lnk.cpp:32
#define SYMLINK_FLAG_RELATIVE
Definition: win32lnk.cpp:1
struct _REPARSE_DATA_BUFFER REPARSE_DATA_BUFFER
struct _REPARSE_DATA_BUFFER * PREPARSE_DATA_BUFFER