HRESULT - имхо отрыжка COMа.
Мы же пишем в С++, и enum'ы позволят объявить самоописывающийся интерфейс, что бы как раз не было
"Поскольку речь идет о межмодульном взаимодействии, не исключено, что мне будут неизвестны все возможные коды ошибок". Базовые общеупотребительные ошибки объявляются в IInterface, спецефические для интерфейса - в интерфейсе. Правда, очень жаль, что в С++ нельзя отнаследовать enum от enum'а.
GetLastError - ну либо надо ее надо тогда делать в самом базовом интерфейсе, либо отдельным интерфейсом, иначе она будет плодится в каждом интерфейсе. Возвращать LPCSTR имхо моветон. Либо я должен рассчитывать, что вызывающая сторона сразу скопирует строку куданить к себе, либо как-то обеспечивать "живость" этого указателя, причем не имея никакой инфы, а до каких пор этот указатель должен оставаться живым.
const CType& vs const CType* - имхо дело вкуса. Однако стоит заметить, что нетипизированных значений в 1С не бывает, ведь CValue отнаследована от CType. Хотя может быть, ты и прав - это позволит отличить "значения, принимающие тип 0" от "значения, тип которых оставлять как есть".
nextValues(CValue const* const* &ppVals)
Память должна выделятся источником. Освобождаться по done.
Я бы даже наверное переделал так:
virtual errCodes init(DWORD& cols, DWORD& rows, CValue const* const* &ppVals) = 0;
virtual errCodes nextValues() = 0;
virtual void done() = 0;