Converting decimal integers to a string representation in an arbitrary base between 2 and 26
The cardinal sin

An assignment tmp_string[tmp_string_i] = remainder; may write beyond an allocated memory. Consider a case of buffer_size being equal to 0. You must test tmp_string_i before the assignment. I don't know what exactly someone had in mind, but you are definitely committing one.
Unnecessary variables

decimal_number is passed by value; you can mutilate it as much as you want. There is no need to have dividend.

Reversal can be done in-place. There is no need for tmp_string at all. tmp_string_i shall also be gone.
Finding digits

Executing division dividend / base twice per iteration looks wrong; special-case of the last digit looks also wrong. Using do-while solves both wrongs:

    do {
        output[output_i++] = int_to_char(dividend % base);
        number = number / base;
    } while (number != 0);

No raw loops

Most loops represent an important algorithm, which deserves to be factored out in a function of its own, for further reuse and for giving it a name. In your case, the loop under the //copy tmp_string to output in reverse order comment implements an algorithm known as reverse.


All that said, this is 


Misc


The returned string should be terminated by '\0', or its actual length be returned.
The code happily converts numbers to a base up to 36 (10 digits and 26 letters). I see no reason to limit a base to 26.
Return codes 0,-1,-2 should be defined as named constants.
Size variables (e.g. buffer_size) should be unsigned, or better yet of type size_t.
The decimal_number parameter is not decimal. It is just number. Need to be renamed accordingly.