static bool GetREPARSE_DATA_BUFFER(const string& Object, REPARSE_DATA_BUFFER* rdb) { const auto FileAttr = os::fs::get_file_attributes(Object); if (FileAttr == INVALID_FILE_ATTRIBUTES || !(FileAttr & FILE_ATTRIBUTE_REPARSE_POINT)) return false; const os::fs::file fObject(Object, 0, 0, nullptr, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT); if (!fObject) return false; DWORD dwBytesReturned; return fObject.IoControl(FSCTL_GET_REPARSE_POINT, nullptr, 0, rdb, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &dwBytesReturned) && IsReparseTagValid(rdb->ReparseTag); }
bool DeleteReparsePoint(const string& Object) { block_ptr<REPARSE_DATA_BUFFER> rdb(MAXIMUM_REPARSE_DATA_BUFFER_SIZE); if (!GetREPARSE_DATA_BUFFER(Object, rdb.get())) return false; const os::fs::file fObject(Object, GetDesiredAccessForReparsePointChange(), 0, nullptr, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT); if (!fObject) return false; DWORD dwBytes; REPARSE_GUID_DATA_BUFFER rgdb{rdb->ReparseTag}; return fObject.IoControl(FSCTL_DELETE_REPARSE_POINT,&rgdb,REPARSE_GUID_DATA_BUFFER_HEADER_SIZE,nullptr,0,&dwBytes); }
static bool SetREPARSE_DATA_BUFFER(const string& Object, REPARSE_DATA_BUFFER* rdb) { if (!IsReparseTagValid(rdb->ReparseTag)) return false; SCOPED_ACTION(os::security::privilege){ SE_CREATE_SYMBOLIC_LINK_NAME }; const auto Attributes = os::fs::get_file_attributes(Object); if(Attributes&FILE_ATTRIBUTE_READONLY) { os::fs::set_file_attributes(Object, Attributes&~FILE_ATTRIBUTE_READONLY); } SCOPE_EXIT { if (Attributes&FILE_ATTRIBUTE_READONLY) os::fs::set_file_attributes(Object, Attributes); }; const auto& SetBuffer = [&](bool ForceElevation) { const os::fs::file fObject(Object, GetDesiredAccessForReparsePointChange(), 0, nullptr, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, nullptr, ForceElevation); DWORD dwBytesReturned; return fObject && fObject.IoControl(FSCTL_SET_REPARSE_POINT, rdb, rdb->ReparseDataLength + REPARSE_DATA_BUFFER_HEADER_SIZE, nullptr, 0, &dwBytesReturned); }; if (SetBuffer(false)) return true; if (ElevationRequired(ELEVATION_MODIFY_REQUEST)) { // Open() succeeded, but IoControl() failed. We can't handle this automatically :( return SetBuffer(true); } return false; }