TransactedFileSink::TransactedFileSink(const KernelTransaction &tx, const wchar_t *path){ this->handle.reset(new HANDLE(nullptr), [](HANDLE *h){ CloseHandle(*h); delete h; }); static const DWORD open_modes[] = { OPEN_EXISTING, CREATE_ALWAYS, }; static USHORT TXFS_MINIVERSION_DEFAULT_VIEW = 0xFFFE; for (auto m : open_modes){ *this->handle = CreateFileTransactedW( path, GENERIC_WRITE, 0, nullptr, m, 0, nullptr, tx.get_handle(), &TXFS_MINIVERSION_DEFAULT_VIEW, nullptr ); if (*this->handle != INVALID_HANDLE_VALUE) break; } if (*this->handle == INVALID_HANDLE_VALUE){ auto error = GetLastError(); throw Win32Exception(error); } SetFilePointer(*this->handle, 0, 0, FILE_END); }
bool os_link_symbolic_junctions_raw(const std::string &target, const std::string &lname, void* transaction) { bool ret = false; HANDLE hJunc = INVALID_HANDLE_VALUE; char* buf = NULL; std::wstring wtarget = ConvertToWchar(target); std::wstring wlname = ConvertToWchar(lname); if (transaction != NULL) { if (!CreateDirectoryTransactedW(NULL, wlname.c_str(), NULL, transaction)) { goto cleanup; } } else { if (!CreateDirectoryW(wlname.c_str(), NULL)) { goto cleanup; } } if (transaction != NULL) { USHORT mversion = 0xFFFF; hJunc = CreateFileTransactedW(wlname.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL, transaction, &mversion, NULL); } else { hJunc = CreateFileW(wlname.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL); } if(hJunc==INVALID_HANDLE_VALUE) goto cleanup; size_t bsize=sizeof(REPARSE_MOUNTPOINT_DATA_BUFFER) + (wtarget.size()+1) * sizeof(wchar_t)+30; buf=new char[bsize]; memset(buf, 0, bsize); REPARSE_MOUNTPOINT_DATA_BUFFER *rb=(REPARSE_MOUNTPOINT_DATA_BUFFER*)buf; rb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; rb->ReparseTargetMaximumLength=(WORD)((wtarget.size()+1)*sizeof(wchar_t)); rb->ReparseTargetLength=rb->ReparseTargetMaximumLength-1*sizeof(wchar_t); rb->ReparseDataLength=rb->ReparseTargetLength+12; memcpy(rb->ReparseTarget, wtarget.c_str(), rb->ReparseTargetMaximumLength); DWORD bytes_ret; if(!DeviceIoControl(hJunc, FSCTL_SET_REPARSE_POINT, rb, rb->ReparseDataLength+REPARSE_MOUNTPOINT_HEADER_SIZE, NULL, 0, &bytes_ret, NULL) ) { goto cleanup; } ret=true; cleanup: DWORD lasterr; if(!ret) { lasterr = GetLastError(); Log("Creating junction failed. Last error="+convert((int)GetLastError()), LL_ERROR); } delete []buf; if(hJunc!=INVALID_HANDLE_VALUE) CloseHandle(hJunc); if(!ret) { if (transaction != NULL) RemoveDirectoryTransactedW(ConvertToWchar(lname).c_str(), transaction); else RemoveDirectoryW(ConvertToWchar(lname).c_str()); SetLastError(lasterr); } return ret; }