xref: /aosp_15_r20/external/lzma/CPP/7zip/UI/FileManager/LinkDialog.cpp (revision f6dc9357d832569d4d1f5d24eacdb3935a1ae8e6)
1*f6dc9357SAndroid Build Coastguard Worker // LinkDialog.cpp
2*f6dc9357SAndroid Build Coastguard Worker 
3*f6dc9357SAndroid Build Coastguard Worker #include "StdAfx.h"
4*f6dc9357SAndroid Build Coastguard Worker 
5*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/ErrorMsg.h"
6*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileDir.h"
7*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileFind.h"
8*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileIO.h"
9*f6dc9357SAndroid Build Coastguard Worker #include "../../../Windows/FileName.h"
10*f6dc9357SAndroid Build Coastguard Worker 
11*f6dc9357SAndroid Build Coastguard Worker #include "LangUtils.h"
12*f6dc9357SAndroid Build Coastguard Worker 
13*f6dc9357SAndroid Build Coastguard Worker #include "BrowseDialog.h"
14*f6dc9357SAndroid Build Coastguard Worker #include "CopyDialogRes.h"
15*f6dc9357SAndroid Build Coastguard Worker #include "LinkDialog.h"
16*f6dc9357SAndroid Build Coastguard Worker #include "resourceGui.h"
17*f6dc9357SAndroid Build Coastguard Worker 
18*f6dc9357SAndroid Build Coastguard Worker #include "App.h"
19*f6dc9357SAndroid Build Coastguard Worker 
20*f6dc9357SAndroid Build Coastguard Worker #include "resource.h"
21*f6dc9357SAndroid Build Coastguard Worker 
22*f6dc9357SAndroid Build Coastguard Worker extern bool g_SymLink_Supported;
23*f6dc9357SAndroid Build Coastguard Worker 
24*f6dc9357SAndroid Build Coastguard Worker using namespace NWindows;
25*f6dc9357SAndroid Build Coastguard Worker using namespace NFile;
26*f6dc9357SAndroid Build Coastguard Worker 
27*f6dc9357SAndroid Build Coastguard Worker #ifdef Z7_LANG
28*f6dc9357SAndroid Build Coastguard Worker static const UInt32 kLangIDs[] =
29*f6dc9357SAndroid Build Coastguard Worker {
30*f6dc9357SAndroid Build Coastguard Worker   IDB_LINK_LINK,
31*f6dc9357SAndroid Build Coastguard Worker   IDT_LINK_PATH_FROM,
32*f6dc9357SAndroid Build Coastguard Worker   IDT_LINK_PATH_TO,
33*f6dc9357SAndroid Build Coastguard Worker   IDG_LINK_TYPE,
34*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_HARD,
35*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_SYM_FILE,
36*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_SYM_DIR,
37*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_JUNCTION,
38*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_WSL
39*f6dc9357SAndroid Build Coastguard Worker };
40*f6dc9357SAndroid Build Coastguard Worker #endif
41*f6dc9357SAndroid Build Coastguard Worker 
42*f6dc9357SAndroid Build Coastguard Worker 
GetSymLink(CFSTR path,CReparseAttr & attr,UString & errorMessage)43*f6dc9357SAndroid Build Coastguard Worker static bool GetSymLink(CFSTR path, CReparseAttr &attr, UString &errorMessage)
44*f6dc9357SAndroid Build Coastguard Worker {
45*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer buf;
46*f6dc9357SAndroid Build Coastguard Worker   if (!NIO::GetReparseData(path, buf, NULL))
47*f6dc9357SAndroid Build Coastguard Worker     return false;
48*f6dc9357SAndroid Build Coastguard Worker 
49*f6dc9357SAndroid Build Coastguard Worker   if (!attr.Parse(buf, buf.Size()))
50*f6dc9357SAndroid Build Coastguard Worker   {
51*f6dc9357SAndroid Build Coastguard Worker     SetLastError(attr.ErrorCode);
52*f6dc9357SAndroid Build Coastguard Worker     return false;
53*f6dc9357SAndroid Build Coastguard Worker   }
54*f6dc9357SAndroid Build Coastguard Worker 
55*f6dc9357SAndroid Build Coastguard Worker   CByteBuffer data2;
56*f6dc9357SAndroid Build Coastguard Worker   if (!FillLinkData(data2, attr.GetPath(),
57*f6dc9357SAndroid Build Coastguard Worker       !attr.IsMountPoint(), attr.IsSymLink_WSL()))
58*f6dc9357SAndroid Build Coastguard Worker   {
59*f6dc9357SAndroid Build Coastguard Worker     errorMessage = "Cannot reproduce reparse point";
60*f6dc9357SAndroid Build Coastguard Worker     return false;
61*f6dc9357SAndroid Build Coastguard Worker   }
62*f6dc9357SAndroid Build Coastguard Worker 
63*f6dc9357SAndroid Build Coastguard Worker   if (data2.Size() != buf.Size() ||
64*f6dc9357SAndroid Build Coastguard Worker       memcmp(data2, buf, buf.Size()) != 0)
65*f6dc9357SAndroid Build Coastguard Worker   {
66*f6dc9357SAndroid Build Coastguard Worker     errorMessage = "mismatch for reproduced reparse point";
67*f6dc9357SAndroid Build Coastguard Worker     return false;
68*f6dc9357SAndroid Build Coastguard Worker   }
69*f6dc9357SAndroid Build Coastguard Worker 
70*f6dc9357SAndroid Build Coastguard Worker   return true;
71*f6dc9357SAndroid Build Coastguard Worker }
72*f6dc9357SAndroid Build Coastguard Worker 
73*f6dc9357SAndroid Build Coastguard Worker 
74*f6dc9357SAndroid Build Coastguard Worker static const unsigned k_LinkType_Buttons[] =
75*f6dc9357SAndroid Build Coastguard Worker {
76*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_HARD,
77*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_SYM_FILE,
78*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_SYM_DIR,
79*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_JUNCTION,
80*f6dc9357SAndroid Build Coastguard Worker   IDR_LINK_TYPE_WSL
81*f6dc9357SAndroid Build Coastguard Worker };
82*f6dc9357SAndroid Build Coastguard Worker 
Set_LinkType_Radio(unsigned idb)83*f6dc9357SAndroid Build Coastguard Worker void CLinkDialog::Set_LinkType_Radio(unsigned idb)
84*f6dc9357SAndroid Build Coastguard Worker {
85*f6dc9357SAndroid Build Coastguard Worker   CheckRadioButton(
86*f6dc9357SAndroid Build Coastguard Worker       k_LinkType_Buttons[0],
87*f6dc9357SAndroid Build Coastguard Worker       k_LinkType_Buttons[Z7_ARRAY_SIZE(k_LinkType_Buttons) - 1],
88*f6dc9357SAndroid Build Coastguard Worker       idb);
89*f6dc9357SAndroid Build Coastguard Worker }
90*f6dc9357SAndroid Build Coastguard Worker 
OnInit()91*f6dc9357SAndroid Build Coastguard Worker bool CLinkDialog::OnInit()
92*f6dc9357SAndroid Build Coastguard Worker {
93*f6dc9357SAndroid Build Coastguard Worker   #ifdef Z7_LANG
94*f6dc9357SAndroid Build Coastguard Worker   LangSetWindowText(*this, IDD_LINK);
95*f6dc9357SAndroid Build Coastguard Worker   LangSetDlgItems(*this, kLangIDs, Z7_ARRAY_SIZE(kLangIDs));
96*f6dc9357SAndroid Build Coastguard Worker   #endif
97*f6dc9357SAndroid Build Coastguard Worker 
98*f6dc9357SAndroid Build Coastguard Worker   _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM));
99*f6dc9357SAndroid Build Coastguard Worker   _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO));
100*f6dc9357SAndroid Build Coastguard Worker 
101*f6dc9357SAndroid Build Coastguard Worker   if (!FilePath.IsEmpty())
102*f6dc9357SAndroid Build Coastguard Worker   {
103*f6dc9357SAndroid Build Coastguard Worker     NFind::CFileInfo fi;
104*f6dc9357SAndroid Build Coastguard Worker     unsigned linkType = 0;
105*f6dc9357SAndroid Build Coastguard Worker     if (!fi.Find(us2fs(FilePath)))
106*f6dc9357SAndroid Build Coastguard Worker       linkType = IDR_LINK_TYPE_SYM_FILE;
107*f6dc9357SAndroid Build Coastguard Worker     else
108*f6dc9357SAndroid Build Coastguard Worker     {
109*f6dc9357SAndroid Build Coastguard Worker       if (fi.HasReparsePoint())
110*f6dc9357SAndroid Build Coastguard Worker       {
111*f6dc9357SAndroid Build Coastguard Worker         CReparseAttr attr;
112*f6dc9357SAndroid Build Coastguard Worker         UString error;
113*f6dc9357SAndroid Build Coastguard Worker         const bool res = GetSymLink(us2fs(FilePath), attr, error);
114*f6dc9357SAndroid Build Coastguard Worker         if (!res && error.IsEmpty())
115*f6dc9357SAndroid Build Coastguard Worker         {
116*f6dc9357SAndroid Build Coastguard Worker           DWORD lastError = GetLastError();
117*f6dc9357SAndroid Build Coastguard Worker           if (lastError != 0)
118*f6dc9357SAndroid Build Coastguard Worker             error = NError::MyFormatMessage(lastError);
119*f6dc9357SAndroid Build Coastguard Worker         }
120*f6dc9357SAndroid Build Coastguard Worker 
121*f6dc9357SAndroid Build Coastguard Worker         UString s = attr.GetPath();
122*f6dc9357SAndroid Build Coastguard Worker         if (!attr.IsSymLink_WSL())
123*f6dc9357SAndroid Build Coastguard Worker         if (!attr.IsOkNamePair())
124*f6dc9357SAndroid Build Coastguard Worker         {
125*f6dc9357SAndroid Build Coastguard Worker           s += " : ";
126*f6dc9357SAndroid Build Coastguard Worker           s += attr.PrintName;
127*f6dc9357SAndroid Build Coastguard Worker         }
128*f6dc9357SAndroid Build Coastguard Worker 
129*f6dc9357SAndroid Build Coastguard Worker         if (!res)
130*f6dc9357SAndroid Build Coastguard Worker         {
131*f6dc9357SAndroid Build Coastguard Worker           s.Insert(0, L"ERROR: ");
132*f6dc9357SAndroid Build Coastguard Worker           if (!error.IsEmpty())
133*f6dc9357SAndroid Build Coastguard Worker           {
134*f6dc9357SAndroid Build Coastguard Worker             s += " : ";
135*f6dc9357SAndroid Build Coastguard Worker             s += error;
136*f6dc9357SAndroid Build Coastguard Worker           }
137*f6dc9357SAndroid Build Coastguard Worker         }
138*f6dc9357SAndroid Build Coastguard Worker 
139*f6dc9357SAndroid Build Coastguard Worker 
140*f6dc9357SAndroid Build Coastguard Worker         SetItemText(IDT_LINK_PATH_TO_CUR, s);
141*f6dc9357SAndroid Build Coastguard Worker 
142*f6dc9357SAndroid Build Coastguard Worker         const UString destPath = attr.GetPath();
143*f6dc9357SAndroid Build Coastguard Worker         _pathFromCombo.SetText(FilePath);
144*f6dc9357SAndroid Build Coastguard Worker         _pathToCombo.SetText(destPath);
145*f6dc9357SAndroid Build Coastguard Worker 
146*f6dc9357SAndroid Build Coastguard Worker         // if (res)
147*f6dc9357SAndroid Build Coastguard Worker         {
148*f6dc9357SAndroid Build Coastguard Worker           if (attr.IsMountPoint())
149*f6dc9357SAndroid Build Coastguard Worker             linkType = IDR_LINK_TYPE_JUNCTION;
150*f6dc9357SAndroid Build Coastguard Worker           else if (attr.IsSymLink_WSL())
151*f6dc9357SAndroid Build Coastguard Worker             linkType = IDR_LINK_TYPE_WSL;
152*f6dc9357SAndroid Build Coastguard Worker           else if (attr.IsSymLink_Win())
153*f6dc9357SAndroid Build Coastguard Worker           {
154*f6dc9357SAndroid Build Coastguard Worker             linkType =
155*f6dc9357SAndroid Build Coastguard Worker               fi.IsDir() ?
156*f6dc9357SAndroid Build Coastguard Worker                 IDR_LINK_TYPE_SYM_DIR :
157*f6dc9357SAndroid Build Coastguard Worker                 IDR_LINK_TYPE_SYM_FILE;
158*f6dc9357SAndroid Build Coastguard Worker             // if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE;
159*f6dc9357SAndroid Build Coastguard Worker           }
160*f6dc9357SAndroid Build Coastguard Worker 
161*f6dc9357SAndroid Build Coastguard Worker           if (linkType != 0)
162*f6dc9357SAndroid Build Coastguard Worker             Set_LinkType_Radio(linkType);
163*f6dc9357SAndroid Build Coastguard Worker         }
164*f6dc9357SAndroid Build Coastguard Worker       }
165*f6dc9357SAndroid Build Coastguard Worker       else
166*f6dc9357SAndroid Build Coastguard Worker       {
167*f6dc9357SAndroid Build Coastguard Worker         // no ReparsePoint
168*f6dc9357SAndroid Build Coastguard Worker         _pathFromCombo.SetText(AnotherPath);
169*f6dc9357SAndroid Build Coastguard Worker         _pathToCombo.SetText(FilePath);
170*f6dc9357SAndroid Build Coastguard Worker         if (fi.IsDir())
171*f6dc9357SAndroid Build Coastguard Worker           linkType = g_SymLink_Supported ?
172*f6dc9357SAndroid Build Coastguard Worker               IDR_LINK_TYPE_SYM_DIR :
173*f6dc9357SAndroid Build Coastguard Worker               IDR_LINK_TYPE_JUNCTION;
174*f6dc9357SAndroid Build Coastguard Worker         else
175*f6dc9357SAndroid Build Coastguard Worker           linkType = IDR_LINK_TYPE_HARD;
176*f6dc9357SAndroid Build Coastguard Worker       }
177*f6dc9357SAndroid Build Coastguard Worker     }
178*f6dc9357SAndroid Build Coastguard Worker     if (linkType != 0)
179*f6dc9357SAndroid Build Coastguard Worker       Set_LinkType_Radio(linkType);
180*f6dc9357SAndroid Build Coastguard Worker   }
181*f6dc9357SAndroid Build Coastguard Worker 
182*f6dc9357SAndroid Build Coastguard Worker   NormalizeSize();
183*f6dc9357SAndroid Build Coastguard Worker   return CModalDialog::OnInit();
184*f6dc9357SAndroid Build Coastguard Worker }
185*f6dc9357SAndroid Build Coastguard Worker 
OnSize(WPARAM,int xSize,int ySize)186*f6dc9357SAndroid Build Coastguard Worker bool CLinkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
187*f6dc9357SAndroid Build Coastguard Worker {
188*f6dc9357SAndroid Build Coastguard Worker   int mx, my;
189*f6dc9357SAndroid Build Coastguard Worker   GetMargins(8, mx, my);
190*f6dc9357SAndroid Build Coastguard Worker   int bx1, bx2, by;
191*f6dc9357SAndroid Build Coastguard Worker   GetItemSizes(IDCANCEL, bx1, by);
192*f6dc9357SAndroid Build Coastguard Worker   GetItemSizes(IDB_LINK_LINK, bx2, by);
193*f6dc9357SAndroid Build Coastguard Worker   int yPos = ySize - my - by;
194*f6dc9357SAndroid Build Coastguard Worker   int xPos = xSize - mx - bx1;
195*f6dc9357SAndroid Build Coastguard Worker 
196*f6dc9357SAndroid Build Coastguard Worker   InvalidateRect(NULL);
197*f6dc9357SAndroid Build Coastguard Worker 
198*f6dc9357SAndroid Build Coastguard Worker   {
199*f6dc9357SAndroid Build Coastguard Worker     RECT r, r2;
200*f6dc9357SAndroid Build Coastguard Worker     GetClientRectOfItem(IDB_LINK_PATH_FROM, r);
201*f6dc9357SAndroid Build Coastguard Worker     GetClientRectOfItem(IDB_LINK_PATH_TO, r2);
202*f6dc9357SAndroid Build Coastguard Worker     int bx = RECT_SIZE_X(r);
203*f6dc9357SAndroid Build Coastguard Worker     int newButtonXpos = xSize - mx - bx;
204*f6dc9357SAndroid Build Coastguard Worker 
205*f6dc9357SAndroid Build Coastguard Worker     MoveItem(IDB_LINK_PATH_FROM, newButtonXpos, r.top, bx, RECT_SIZE_Y(r));
206*f6dc9357SAndroid Build Coastguard Worker     MoveItem(IDB_LINK_PATH_TO, newButtonXpos, r2.top, bx, RECT_SIZE_Y(r2));
207*f6dc9357SAndroid Build Coastguard Worker 
208*f6dc9357SAndroid Build Coastguard Worker     int newComboXsize = newButtonXpos - mx - mx;
209*f6dc9357SAndroid Build Coastguard Worker     ChangeSubWindowSizeX(_pathFromCombo, newComboXsize);
210*f6dc9357SAndroid Build Coastguard Worker     ChangeSubWindowSizeX(_pathToCombo, newComboXsize);
211*f6dc9357SAndroid Build Coastguard Worker   }
212*f6dc9357SAndroid Build Coastguard Worker 
213*f6dc9357SAndroid Build Coastguard Worker   MoveItem(IDCANCEL, xPos, yPos, bx1, by);
214*f6dc9357SAndroid Build Coastguard Worker   MoveItem(IDB_LINK_LINK, xPos - mx - bx2, yPos, bx2, by);
215*f6dc9357SAndroid Build Coastguard Worker 
216*f6dc9357SAndroid Build Coastguard Worker   return false;
217*f6dc9357SAndroid Build Coastguard Worker }
218*f6dc9357SAndroid Build Coastguard Worker 
OnButtonClicked(unsigned buttonID,HWND buttonHWND)219*f6dc9357SAndroid Build Coastguard Worker bool CLinkDialog::OnButtonClicked(unsigned buttonID, HWND buttonHWND)
220*f6dc9357SAndroid Build Coastguard Worker {
221*f6dc9357SAndroid Build Coastguard Worker   switch (buttonID)
222*f6dc9357SAndroid Build Coastguard Worker   {
223*f6dc9357SAndroid Build Coastguard Worker     case IDB_LINK_PATH_FROM:
224*f6dc9357SAndroid Build Coastguard Worker       OnButton_SetPath(false);
225*f6dc9357SAndroid Build Coastguard Worker       return true;
226*f6dc9357SAndroid Build Coastguard Worker     case IDB_LINK_PATH_TO:
227*f6dc9357SAndroid Build Coastguard Worker       OnButton_SetPath(true);
228*f6dc9357SAndroid Build Coastguard Worker       return true;
229*f6dc9357SAndroid Build Coastguard Worker     case IDB_LINK_LINK:
230*f6dc9357SAndroid Build Coastguard Worker       OnButton_Link();
231*f6dc9357SAndroid Build Coastguard Worker       return true;
232*f6dc9357SAndroid Build Coastguard Worker   }
233*f6dc9357SAndroid Build Coastguard Worker   return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
234*f6dc9357SAndroid Build Coastguard Worker }
235*f6dc9357SAndroid Build Coastguard Worker 
OnButton_SetPath(bool to)236*f6dc9357SAndroid Build Coastguard Worker void CLinkDialog::OnButton_SetPath(bool to)
237*f6dc9357SAndroid Build Coastguard Worker {
238*f6dc9357SAndroid Build Coastguard Worker   UString currentPath;
239*f6dc9357SAndroid Build Coastguard Worker   NWindows::NControl::CComboBox &combo = to ?
240*f6dc9357SAndroid Build Coastguard Worker     _pathToCombo :
241*f6dc9357SAndroid Build Coastguard Worker     _pathFromCombo;
242*f6dc9357SAndroid Build Coastguard Worker   combo.GetText(currentPath);
243*f6dc9357SAndroid Build Coastguard Worker   // UString title = "Specify a location for output folder";
244*f6dc9357SAndroid Build Coastguard Worker   const UString title = LangString(IDS_SET_FOLDER);
245*f6dc9357SAndroid Build Coastguard Worker 
246*f6dc9357SAndroid Build Coastguard Worker   UString resultPath;
247*f6dc9357SAndroid Build Coastguard Worker   if (!MyBrowseForFolder(*this, title, currentPath, resultPath))
248*f6dc9357SAndroid Build Coastguard Worker     return;
249*f6dc9357SAndroid Build Coastguard Worker   NName::NormalizeDirPathPrefix(resultPath);
250*f6dc9357SAndroid Build Coastguard Worker   combo.SetCurSel(-1);
251*f6dc9357SAndroid Build Coastguard Worker   combo.SetText(resultPath);
252*f6dc9357SAndroid Build Coastguard Worker }
253*f6dc9357SAndroid Build Coastguard Worker 
ShowError(const wchar_t * s)254*f6dc9357SAndroid Build Coastguard Worker void CLinkDialog::ShowError(const wchar_t *s)
255*f6dc9357SAndroid Build Coastguard Worker {
256*f6dc9357SAndroid Build Coastguard Worker   ::MessageBoxW(*this, s, L"7-Zip", MB_ICONERROR);
257*f6dc9357SAndroid Build Coastguard Worker }
258*f6dc9357SAndroid Build Coastguard Worker 
ShowLastErrorMessage()259*f6dc9357SAndroid Build Coastguard Worker void CLinkDialog::ShowLastErrorMessage()
260*f6dc9357SAndroid Build Coastguard Worker {
261*f6dc9357SAndroid Build Coastguard Worker   ShowError(NError::MyFormatMessage(GetLastError()));
262*f6dc9357SAndroid Build Coastguard Worker }
263*f6dc9357SAndroid Build Coastguard Worker 
OnButton_Link()264*f6dc9357SAndroid Build Coastguard Worker void CLinkDialog::OnButton_Link()
265*f6dc9357SAndroid Build Coastguard Worker {
266*f6dc9357SAndroid Build Coastguard Worker   UString from, to;
267*f6dc9357SAndroid Build Coastguard Worker   _pathFromCombo.GetText(from);
268*f6dc9357SAndroid Build Coastguard Worker   _pathToCombo.GetText(to);
269*f6dc9357SAndroid Build Coastguard Worker 
270*f6dc9357SAndroid Build Coastguard Worker   if (from.IsEmpty())
271*f6dc9357SAndroid Build Coastguard Worker     return;
272*f6dc9357SAndroid Build Coastguard Worker   if (!NName::IsAbsolutePath(from))
273*f6dc9357SAndroid Build Coastguard Worker     from.Insert(0, CurDirPrefix);
274*f6dc9357SAndroid Build Coastguard Worker 
275*f6dc9357SAndroid Build Coastguard Worker   unsigned idb = 0;
276*f6dc9357SAndroid Build Coastguard Worker   for (unsigned i = 0;; i++)
277*f6dc9357SAndroid Build Coastguard Worker   {
278*f6dc9357SAndroid Build Coastguard Worker     if (i >= Z7_ARRAY_SIZE(k_LinkType_Buttons))
279*f6dc9357SAndroid Build Coastguard Worker       return;
280*f6dc9357SAndroid Build Coastguard Worker     idb = k_LinkType_Buttons[i];
281*f6dc9357SAndroid Build Coastguard Worker     if (IsButtonCheckedBool(idb))
282*f6dc9357SAndroid Build Coastguard Worker       break;
283*f6dc9357SAndroid Build Coastguard Worker   }
284*f6dc9357SAndroid Build Coastguard Worker 
285*f6dc9357SAndroid Build Coastguard Worker   NFind::CFileInfo info1, info2;
286*f6dc9357SAndroid Build Coastguard Worker   const bool finded1 = info1.Find(us2fs(from));
287*f6dc9357SAndroid Build Coastguard Worker   const bool finded2 = info2.Find(us2fs(to));
288*f6dc9357SAndroid Build Coastguard Worker 
289*f6dc9357SAndroid Build Coastguard Worker   const bool isDirLink = (
290*f6dc9357SAndroid Build Coastguard Worker       idb == IDR_LINK_TYPE_SYM_DIR ||
291*f6dc9357SAndroid Build Coastguard Worker       idb == IDR_LINK_TYPE_JUNCTION);
292*f6dc9357SAndroid Build Coastguard Worker 
293*f6dc9357SAndroid Build Coastguard Worker   const bool isWSL = (idb == IDR_LINK_TYPE_WSL);
294*f6dc9357SAndroid Build Coastguard Worker 
295*f6dc9357SAndroid Build Coastguard Worker   if (!isWSL)
296*f6dc9357SAndroid Build Coastguard Worker   if ((finded1 && info1.IsDir() != isDirLink) ||
297*f6dc9357SAndroid Build Coastguard Worker       (finded2 && info2.IsDir() != isDirLink))
298*f6dc9357SAndroid Build Coastguard Worker   {
299*f6dc9357SAndroid Build Coastguard Worker     ShowError(L"Incorrect link type");
300*f6dc9357SAndroid Build Coastguard Worker     return;
301*f6dc9357SAndroid Build Coastguard Worker   }
302*f6dc9357SAndroid Build Coastguard Worker 
303*f6dc9357SAndroid Build Coastguard Worker   if (idb == IDR_LINK_TYPE_HARD)
304*f6dc9357SAndroid Build Coastguard Worker   {
305*f6dc9357SAndroid Build Coastguard Worker     if (!NDir::MyCreateHardLink(us2fs(from), us2fs(to)))
306*f6dc9357SAndroid Build Coastguard Worker     {
307*f6dc9357SAndroid Build Coastguard Worker       ShowLastErrorMessage();
308*f6dc9357SAndroid Build Coastguard Worker       return;
309*f6dc9357SAndroid Build Coastguard Worker     }
310*f6dc9357SAndroid Build Coastguard Worker   }
311*f6dc9357SAndroid Build Coastguard Worker   else
312*f6dc9357SAndroid Build Coastguard Worker   {
313*f6dc9357SAndroid Build Coastguard Worker     if (finded1 && !info1.IsDir() && !info1.HasReparsePoint() && info1.Size != 0)
314*f6dc9357SAndroid Build Coastguard Worker     {
315*f6dc9357SAndroid Build Coastguard Worker       UString s ("WARNING: reparse point will hide the data of existing file");
316*f6dc9357SAndroid Build Coastguard Worker       s.Add_LF();
317*f6dc9357SAndroid Build Coastguard Worker       s += from;
318*f6dc9357SAndroid Build Coastguard Worker       ShowError(s);
319*f6dc9357SAndroid Build Coastguard Worker       return;
320*f6dc9357SAndroid Build Coastguard Worker     }
321*f6dc9357SAndroid Build Coastguard Worker 
322*f6dc9357SAndroid Build Coastguard Worker     const bool isSymLink = (idb != IDR_LINK_TYPE_JUNCTION);
323*f6dc9357SAndroid Build Coastguard Worker 
324*f6dc9357SAndroid Build Coastguard Worker     CByteBuffer data;
325*f6dc9357SAndroid Build Coastguard Worker     if (!FillLinkData(data, to, isSymLink, isWSL))
326*f6dc9357SAndroid Build Coastguard Worker     {
327*f6dc9357SAndroid Build Coastguard Worker       ShowError(L"Incorrect link");
328*f6dc9357SAndroid Build Coastguard Worker       return;
329*f6dc9357SAndroid Build Coastguard Worker     }
330*f6dc9357SAndroid Build Coastguard Worker 
331*f6dc9357SAndroid Build Coastguard Worker     CReparseAttr attr;
332*f6dc9357SAndroid Build Coastguard Worker     if (!attr.Parse(data, data.Size()))
333*f6dc9357SAndroid Build Coastguard Worker     {
334*f6dc9357SAndroid Build Coastguard Worker       ShowError(L"Internal conversion error");
335*f6dc9357SAndroid Build Coastguard Worker       return;
336*f6dc9357SAndroid Build Coastguard Worker     }
337*f6dc9357SAndroid Build Coastguard Worker 
338*f6dc9357SAndroid Build Coastguard Worker     bool res;
339*f6dc9357SAndroid Build Coastguard Worker     if (to.IsEmpty())
340*f6dc9357SAndroid Build Coastguard Worker     {
341*f6dc9357SAndroid Build Coastguard Worker       // res = NIO::SetReparseData(us2fs(from), isDirLink, NULL, 0);
342*f6dc9357SAndroid Build Coastguard Worker       res = NIO::DeleteReparseData(us2fs(from));
343*f6dc9357SAndroid Build Coastguard Worker     }
344*f6dc9357SAndroid Build Coastguard Worker     else
345*f6dc9357SAndroid Build Coastguard Worker       res = NIO::SetReparseData(us2fs(from), isDirLink, data, (DWORD)data.Size());
346*f6dc9357SAndroid Build Coastguard Worker 
347*f6dc9357SAndroid Build Coastguard Worker     if (!res)
348*f6dc9357SAndroid Build Coastguard Worker     {
349*f6dc9357SAndroid Build Coastguard Worker       ShowLastErrorMessage();
350*f6dc9357SAndroid Build Coastguard Worker       return;
351*f6dc9357SAndroid Build Coastguard Worker     }
352*f6dc9357SAndroid Build Coastguard Worker   }
353*f6dc9357SAndroid Build Coastguard Worker 
354*f6dc9357SAndroid Build Coastguard Worker   End(IDOK);
355*f6dc9357SAndroid Build Coastguard Worker }
356*f6dc9357SAndroid Build Coastguard Worker 
Link()357*f6dc9357SAndroid Build Coastguard Worker void CApp::Link()
358*f6dc9357SAndroid Build Coastguard Worker {
359*f6dc9357SAndroid Build Coastguard Worker   const unsigned srcPanelIndex = GetFocusedPanelIndex();
360*f6dc9357SAndroid Build Coastguard Worker   CPanel &srcPanel = Panels[srcPanelIndex];
361*f6dc9357SAndroid Build Coastguard Worker   if (!srcPanel.IsFSFolder())
362*f6dc9357SAndroid Build Coastguard Worker   {
363*f6dc9357SAndroid Build Coastguard Worker     srcPanel.MessageBox_Error_UnsupportOperation();
364*f6dc9357SAndroid Build Coastguard Worker     return;
365*f6dc9357SAndroid Build Coastguard Worker   }
366*f6dc9357SAndroid Build Coastguard Worker   CRecordVector<UInt32> indices;
367*f6dc9357SAndroid Build Coastguard Worker   srcPanel.Get_ItemIndices_Operated(indices);
368*f6dc9357SAndroid Build Coastguard Worker   if (indices.IsEmpty())
369*f6dc9357SAndroid Build Coastguard Worker     return;
370*f6dc9357SAndroid Build Coastguard Worker   if (indices.Size() != 1)
371*f6dc9357SAndroid Build Coastguard Worker   {
372*f6dc9357SAndroid Build Coastguard Worker     srcPanel.MessageBox_Error_LangID(IDS_SELECT_ONE_FILE);
373*f6dc9357SAndroid Build Coastguard Worker     return;
374*f6dc9357SAndroid Build Coastguard Worker   }
375*f6dc9357SAndroid Build Coastguard Worker   const UInt32 index = indices[0];
376*f6dc9357SAndroid Build Coastguard Worker   const UString itemName = srcPanel.GetItemName(index);
377*f6dc9357SAndroid Build Coastguard Worker 
378*f6dc9357SAndroid Build Coastguard Worker   const UString fsPrefix = srcPanel.GetFsPath();
379*f6dc9357SAndroid Build Coastguard Worker   const UString srcPath = fsPrefix + srcPanel.GetItemPrefix(index);
380*f6dc9357SAndroid Build Coastguard Worker   UString path = srcPath;
381*f6dc9357SAndroid Build Coastguard Worker   {
382*f6dc9357SAndroid Build Coastguard Worker     const unsigned destPanelIndex = (NumPanels <= 1) ? srcPanelIndex : (1 - srcPanelIndex);
383*f6dc9357SAndroid Build Coastguard Worker     CPanel &destPanel = Panels[destPanelIndex];
384*f6dc9357SAndroid Build Coastguard Worker     if (NumPanels > 1)
385*f6dc9357SAndroid Build Coastguard Worker       if (destPanel.IsFSFolder())
386*f6dc9357SAndroid Build Coastguard Worker         path = destPanel.GetFsPath();
387*f6dc9357SAndroid Build Coastguard Worker   }
388*f6dc9357SAndroid Build Coastguard Worker 
389*f6dc9357SAndroid Build Coastguard Worker   CLinkDialog dlg;
390*f6dc9357SAndroid Build Coastguard Worker   dlg.CurDirPrefix = fsPrefix;
391*f6dc9357SAndroid Build Coastguard Worker   dlg.FilePath = srcPath + itemName;
392*f6dc9357SAndroid Build Coastguard Worker   dlg.AnotherPath = path;
393*f6dc9357SAndroid Build Coastguard Worker 
394*f6dc9357SAndroid Build Coastguard Worker   if (dlg.Create(srcPanel.GetParent()) != IDOK)
395*f6dc9357SAndroid Build Coastguard Worker     return;
396*f6dc9357SAndroid Build Coastguard Worker 
397*f6dc9357SAndroid Build Coastguard Worker   // fix it: we should refresh panel with changed link
398*f6dc9357SAndroid Build Coastguard Worker 
399*f6dc9357SAndroid Build Coastguard Worker   RefreshTitleAlways();
400*f6dc9357SAndroid Build Coastguard Worker }
401