Example #1
0
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;
}