pmg's answer will only work in case the top 9 bits already zero. If there were some bits set, your data will get ORed with them. So, to be sure you need to clear those bits first:
#define POS 23 // position at which to insert data
#define MASK ((1UL<<9)-1) // mask of nine 1s
word = (word & ~(MASK<<POS)) | ((data9 & MASK) << POS));
The first part will shift the mask to the target position, then invert it, so you'll have zeroes at the target top bits and ones for the rest of the word, thus the AND operation will clear the top 9 bits and leave the low bits unchanged. The second part will make sure we have only 9 bits set, then shift them into the target position. Finally, the two parts will be combined with the OR operations, and because of the masking they will not interfere.