// ke_settings.c - small system/settings.ini reader. // // This intentionally exposes generic string settings only. Subsystems and // drivers own the policy for interpreting their sections. #include #include #include #include #include #include #include #define KE_SETTINGS_MAX_FILE_BYTES (64u * 1024u) typedef struct KE_FIND_SETTING_CTX { const char* Section; const char* Key; char* Buffer; size_t BufferSize; KSTATUS Status; } KE_FIND_SETTING_CTX; static void KeFindSettingCallback(const char* section, const char* key, const char* value, void* userdata) { KE_FIND_SETTING_CTX* ctx = (KE_FIND_SETTING_CTX*)userdata; if (!ctx || ctx->Status != STATUS_NOT_FOUND) return; if (!section || !key || !value) return; if (strcmp(section, ctx->Section) != 0 || strcmp(key, ctx->Key) != 0) return; size_t len = strlen(value); if (len + 1 > ctx->BufferSize) { if (ctx->BufferSize) ctx->Buffer[0] = '\0'; ctx->Status = STATUS_BUFFER_TOO_SMALL; return; } memcpy(ctx->Buffer, value, len + 1); ctx->Status = STATUS_SUCCESS; } __declspec(dllexport) KSTATUS KeGetSettingString(const char* section, const char* key, char* buffer, size_t bufferSize) { if (!section || !*section || !key || !*key || !buffer || bufferSize == 0) return STATUS_INVALID_PARAMETER; buffer[0] = '\0'; FILE_OBJECT* file = NULL; KSTATUS st = IoOpenFile(SYS_SV_LITERAL(KE_SETTINGS_PATH), &file); if (!KSUCCESS(st)) return st; uint64_t fileSize64 = IoGetFileSize(file); if (fileSize64 >= KE_SETTINGS_MAX_FILE_BYTES) { IoCloseFile(file); return STATUS_BUFFER_TOO_SMALL; } size_t fileSize = (size_t)fileSize64; char* text = (char*)MmAllocatePool(fileSize + 1); if (!text) { IoCloseFile(file); return STATUS_NO_MEMORY; } size_t got = 0; st = IoReadFile(file, text, fileSize, &got); IoCloseFile(file); if (!KSUCCESS(st)) { MmFreePool(text); return st; } text[got] = '\0'; KE_FIND_SETTING_CTX ctx; ctx.Section = section; ctx.Key = key; ctx.Buffer = buffer; ctx.BufferSize = bufferSize; ctx.Status = STATUS_NOT_FOUND; IniParse(text, KeFindSettingCallback, &ctx); MmFreePool(text); return ctx.Status; }