static bool GetSymLink(CFSTR path, CReparseAttr &attr) { NIO::CInFile file; if (!file.Open(path, FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)) return false; const unsigned kBufSize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE; CByteArr buf(kBufSize); DWORD returnedSize; if (!file.DeviceIoControlOut(my_FSCTL_GET_REPARSE_POINT, buf, kBufSize, &returnedSize)) return false; if (!attr.Parse(buf, returnedSize)) return false; CByteBuffer data2; if (!FillLinkData(data2, attr.GetPath(), attr.IsSymLink())) return false; if (data2.Size() != returnedSize || memcmp(data2, buf, returnedSize) != 0) return false; return true; }
bool CLinkDialog::OnInit() { #ifdef LANG LangSetWindowText(*this, IDD_LINK); LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs)); #endif _pathFromCombo.Attach(GetItem(IDC_LINK_PATH_FROM)); _pathToCombo.Attach(GetItem(IDC_LINK_PATH_TO)); if (!FilePath.IsEmpty()) { NFind::CFileInfo fi; int linkType = 0; if (!fi.Find(us2fs(FilePath))) linkType = IDR_LINK_TYPE_SYM_FILE; else { if (fi.HasReparsePoint()) { CReparseAttr attr; bool res = GetSymLink(us2fs(FilePath), attr); UString s = attr.PrintName; if (!attr.IsOkNamePair()) { s += L" : "; s += attr.SubsName; } if (!res) s = L"ERROR: " + s; SetItemText(IDT_LINK_PATH_TO_CUR, s); UString destPath = attr.GetPath(); _pathFromCombo.SetText(FilePath); _pathToCombo.SetText(destPath); if (res) { if (attr.IsMountPoint()) linkType = IDR_LINK_TYPE_JUNCTION; if (attr.IsSymLink()) { linkType = fi.IsDir() ? IDR_LINK_TYPE_SYM_DIR : IDR_LINK_TYPE_SYM_FILE; // if (attr.IsRelative()) linkType = IDR_LINK_TYPE_SYM_RELATIVE; } if (linkType != 0) Set_LinkType_Radio(linkType); } } else { _pathFromCombo.SetText(AnotherPath); _pathToCombo.SetText(FilePath); if (fi.IsDir()) linkType = g_SymLink_Supported ? IDR_LINK_TYPE_SYM_DIR : IDR_LINK_TYPE_JUNCTION; else linkType = IDR_LINK_TYPE_HARD; } } if (linkType != 0) Set_LinkType_Radio(linkType); } NormalizeSize(); return CModalDialog::OnInit(); }
STDMETHODIMP CArchiveUpdateCallback::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) { COM_TRY_BEGIN const CUpdatePair2 &up = (*UpdatePairs)[index]; NCOM::CPropVariant prop; if (up.NewData) { /* if (propID == kpidIsHardLink) { prop = _isHardLink; prop.Detach(value); return S_OK; } */ if (propID == kpidSymLink) { if (index == _hardIndex_From) { prop.Detach(value); return S_OK; } if (up.DirIndex >= 0) { #ifndef UNDER_CE const CDirItem &di = DirItems->Items[up.DirIndex]; // if (di.IsDir()) { CReparseAttr attr; DWORD errorCode = 0; if (attr.Parse(di.ReparseData, di.ReparseData.Size(), errorCode)) { UString simpleName = attr.GetPath(); if (attr.IsRelative()) prop = simpleName; else { const FString phyPath = DirItems->GetPhyPath(up.DirIndex); FString fullPath; if (NDir::MyGetFullPathName(phyPath, fullPath)) { prop = GetRelativePath(simpleName, fs2us(fullPath)); } } prop.Detach(value); return S_OK; } } #endif } } else if (propID == kpidHardLink) { if (index == _hardIndex_From) { const CKeyKeyValPair &pair = _map[_hardIndex_To]; const CUpdatePair2 &up2 = (*UpdatePairs)[pair.Value]; prop = DirItems->GetLogPath(up2.DirIndex); prop.Detach(value); return S_OK; } if (up.DirIndex >= 0) { prop.Detach(value); return S_OK; } } } if (up.IsAnti && propID != kpidIsDir && propID != kpidPath && propID != kpidIsAltStream) { switch (propID) { case kpidSize: prop = (UInt64)0; break; case kpidIsAnti: prop = true; break; } } else if (propID == kpidPath && up.NewNameIndex >= 0) prop = (*NewNames)[up.NewNameIndex]; else if (propID == kpidComment && CommentIndex >= 0 && (unsigned)CommentIndex == index && Comment) prop = *Comment; else if (propID == kpidShortName && up.NewNameIndex >= 0 && up.IsMainRenameItem) { // we can generate new ShortName here; } else if ((up.UseArcProps || (KeepOriginalItemNames && (propID == kpidPath || propID == kpidIsAltStream))) && up.ExistInArchive() && Archive) return Archive->GetProperty(ArcItems ? (*ArcItems)[up.ArcIndex].IndexInServer : up.ArcIndex, propID, value); else if (up.ExistOnDisk()) { const CDirItem &di = DirItems->Items[up.DirIndex]; switch (propID) { case kpidPath: prop = DirItems->GetLogPath(up.DirIndex); break; case kpidIsDir: prop = di.IsDir(); break; case kpidSize: prop = di.IsDir() ? (UInt64)0 : di.Size; break; case kpidAttrib: prop = di.Attrib; break; case kpidCTime: prop = di.CTime; break; case kpidATime: prop = di.ATime; break; case kpidMTime: prop = di.MTime; break; case kpidIsAltStream: prop = di.IsAltStream; break; #if defined(_WIN32) && !defined(UNDER_CE) // case kpidShortName: prop = di.ShortName; break; #endif } } prop.Detach(value); return S_OK; COM_TRY_END }