From 1d7c807b8c354d281b6dc1d274a2e323bd6d457c Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 2 Jul 2017 10:48:36 +0300 Subject: [PATCH] Rewritten ini support, no more 64k section size limits. --- od-win32/registry.cpp | 343 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 280 insertions(+), 63 deletions(-) diff --git a/od-win32/registry.cpp b/od-win32/registry.cpp index 498dc6e8..93f1d1df 100644 --- a/od-win32/registry.cpp +++ b/od-win32/registry.cpp @@ -10,7 +10,262 @@ static int inimode = 0; static TCHAR *inipath; -#define PUPPA _T("eitätäoo") + +#define ROOT_TREE _T("WinUAE") + +static struct ini_line **inidata; +static int inilines; + +struct ini_line +{ + int section_order; + TCHAR *section; + TCHAR *key; + TCHAR *value; +}; + +static TCHAR *initrim(TCHAR *s) +{ + while (*s != 0 && *s <= 32) + s++; + TCHAR *s2 = s; + while (*s2) + s2++; + while (s2 > s) { + s2--; + if (*s2 > 32) + break; + *s2 = 0; + } + return s; +} + +static void ini_free(void) +{ + for(int c = 0; c < inilines; c++) { + struct ini_line *il = inidata[c]; + xfree(il->section); + xfree(il->key); + xfree(il->value); + xfree(il); + inidata[c] = NULL; + } +} + +static void ini_sort(void) +{ + for(int c1 = 0; c1 < inilines; c1++) { + struct ini_line *il1 = inidata[c1]; + if (il1 == NULL) + continue; + for (int c2 = c1 + 1; c2 < inilines; c2++) { + struct ini_line *il2 = inidata[c2]; + if (il2 == NULL) + continue; + int order = 0; + int sec = _tcsicmp(il1->section, il2->section); + if (sec) { + if (!il1->section_order && !il2->section_order) + order = sec; + else + order = il2->section_order - il1->section_order; + } else { + order = _tcsicmp(il1->key, il2->key); + } + if (order > 0) { + struct ini_line il; + memcpy(&il, il1, sizeof(struct ini_line)); + memcpy(il1, il2, sizeof(struct ini_line)); + memcpy(il2, &il, sizeof(struct ini_line)); + } + } + } +#if 0 + for(int c1 = 0; c1 < inilines; c1++) { + struct ini_line *il1 = inidata[c1]; + if (il1) + write_log(_T("[%s] %s %s\n"), il1->section, il1->key, il1->value); + } + write_log(_T("\n")); +#endif +} + +static void ini_addnewstring(const TCHAR *section, const TCHAR *key, const TCHAR *val) +{ + struct ini_line *il = xcalloc(struct ini_line, 1); + il->section = my_strdup(section); + if (!_tcsicmp(section, ROOT_TREE)) + il->section_order = 1; + il->key = my_strdup(key); + il->value = my_strdup(val); + int cnt = 0; + while (cnt < inilines && inidata[cnt]) + cnt++; + if (cnt == inilines) { + inilines += 10; + inidata = xrealloc(struct ini_line*, inidata, inilines); + int cnt2 = cnt; + while (cnt2 < inilines) { + inidata[cnt2++] = NULL; + } + } + inidata[cnt] = il; +} + +static const uae_u8 bom[3] = { 0xef, 0xbb, 0xbf }; + +static void ini_load(const TCHAR *path) +{ + bool utf8 = false; + TCHAR section[MAX_DPATH]; + uae_u8 tmp[3]; + + ini_free(); + + FILE *f = _tfopen(path, _T("rb")); + if (!f) + return; + int v = fread(tmp, 1, sizeof tmp, f); + fclose (f); + if (v == 3 && tmp[0] == 0xef && tmp[1] == 0xbb && tmp[2] == 0xbf) { + f = _tfopen (path, _T("rt, ccs=UTF-8")); + } else { + f = _tfopen (path, _T("rt")); + } + section[0] = 0; + for (;;) { + TCHAR tbuffer[MAX_DPATH]; + tbuffer[0] = 0; + if (!fgetws(tbuffer, MAX_DPATH, f)) + break; + TCHAR *s = initrim(tbuffer); + if (_tcslen(s) < 3) + continue; + if (s[0] == '[' && s[_tcslen(s) - 1] == ']') { + s[_tcslen(s) - 1] = 0; + _tcscpy(section, s + 1); + continue; + } + if (section[0] == 0) + continue; + TCHAR *s1 = _tcschr(s, '='); + if (s1) { + *s1++ = 0; + TCHAR *s2 = initrim(tbuffer); + TCHAR *s3 = initrim(s1); + ini_addnewstring(section, s2, s3); + } + } + fclose(f); + ini_sort(); +} + +static void ini_save(const TCHAR *path) +{ + TCHAR section[MAX_DPATH]; + TCHAR sep[2] = { '=', 0 }; + TCHAR lf[2] = { 10, 0 }; + TCHAR left[2] = { '[', 0 }; + TCHAR right[2] = { ']', 0 }; + + ini_sort(); + FILE *f = _tfopen(path, _T("wt, ccs=UTF-8")); + if (!f) + return; + section[0] = 0; + for (int c = 0; c < inilines; c++) { + TCHAR out[MAX_DPATH]; + struct ini_line *il = inidata[c]; + if (!il) + continue; + if (_tcscmp(il->section, section)) { + _tcscpy(out, lf); + _tcscat(out, left); + _tcscat(out, il->section); + _tcscat(out, right); + _tcscat(out, lf); + fputws(out, f); + _tcscpy(section, il->section); + } + _tcscpy(out, il->key); + _tcscat(out, sep); + _tcscat(out, il->value); + _tcscat(out, lf); + fputws(out, f); + } + fclose(f); +} + +static bool ini_getstring(const TCHAR *section, const TCHAR *key, TCHAR *out, int *max) +{ + for (int c = 0; c < inilines; c++) { + struct ini_line *il = inidata[c]; + if (il && !_tcscmp(section, il->section) && (key == NULL || !_tcscmp(key, il->key))) { + if (out) { + _tcsncpy(out, il->value, *max); + out[*max - 1] = 0; + *max = _tcslen(out); + } + return true; + } + } + return false; +} + +static bool ini_getsectionstring(const TCHAR *section, int idx, TCHAR *keyout, int *keysize, TCHAR *valout, int *valsize) +{ + for (int c = 0; c < inilines; c++) { + struct ini_line *il = inidata[c]; + if (il && !_tcscmp(section, il->section)) { + if (idx == 0) { + if (keyout) { + _tcsncpy(keyout, il->key, *keysize); + keyout[*keysize - 1] = 0; + *keysize = _tcslen(keyout); + } + if (valout) { + _tcsncpy(valout, il->value, *valsize); + valout[*valsize - 1] = 0; + *valsize = _tcslen(valout); + } + return true; + } + idx--; + } + } + return false; +} + +static bool ini_addstring(const TCHAR *section, const TCHAR *key, const TCHAR *val) +{ + for (int c = 0; c < inilines; c++) { + struct ini_line *il = inidata[c]; + if (il && !_tcscmp(section, il->section)) { + if (!_tcscmp(key, il->key)) { + xfree(il->value); + il->value = my_strdup(val); + return true; + } + } + } + ini_addnewstring(section, key, val); + return true; +} + +static void ini_delete(const TCHAR *section, const TCHAR *key) +{ + for (int c = 0; c < inilines; c++) { + struct ini_line *il = inidata[c]; + if (il && !_tcscmp(section, il->section) && (key == NULL || !_tcscmp(key, il->key))) { + xfree(il->section); + xfree(il->key); + xfree(il->value); + xfree(il); + inidata[c] = NULL; + } + } +} + static HKEY gr (UAEREG *root) { @@ -21,7 +276,7 @@ static HKEY gr (UAEREG *root) static TCHAR *gs (UAEREG *root) { if (!root) - return _T("WinUAE"); + return ROOT_TREE; return root->inipath; } static TCHAR *gsn (UAEREG *root, const TCHAR *name) @@ -38,8 +293,7 @@ static TCHAR *gsn (UAEREG *root, const TCHAR *name) int regsetstr (UAEREG *root, const TCHAR *name, const TCHAR *str) { if (inimode) { - DWORD ret; - ret = WritePrivateProfileString (gs (root), name, str, inipath); + int ret = ini_addstring(gs(root), name, str); return ret; } else { HKEY rk = gr (root); @@ -52,10 +306,10 @@ int regsetstr (UAEREG *root, const TCHAR *name, const TCHAR *str) int regsetint (UAEREG *root, const TCHAR *name, int val) { if (inimode) { - DWORD ret; + int ret; TCHAR tmp[100]; _stprintf (tmp, _T("%d"), val); - ret = WritePrivateProfileString (gs (root), name, tmp, inipath); + ret = ini_addstring(gs(root), name, tmp); return ret; } else { DWORD v = val; @@ -71,8 +325,8 @@ int regqueryint (UAEREG *root, const TCHAR *name, int *val) if (inimode) { int ret = 0; TCHAR tmp[100]; - GetPrivateProfileString (gs (root), name, PUPPA, tmp, sizeof (tmp) / sizeof (TCHAR), inipath); - if (_tcscmp (tmp, PUPPA)) { + int size = sizeof tmp / sizeof(TCHAR); + if (ini_getstring(gs(root), name, tmp, &size)) { *val = _tstol (tmp); ret = 1; } @@ -90,10 +344,10 @@ int regqueryint (UAEREG *root, const TCHAR *name, int *val) int regsetlonglong (UAEREG *root, const TCHAR *name, ULONGLONG val) { if (inimode) { - DWORD ret; + int ret; TCHAR tmp[100]; _stprintf (tmp, _T("%I64d"), val); - ret = WritePrivateProfileString (gs (root), name, tmp, inipath); + ret = ini_addstring(gs(root), name, tmp); return ret; } else { ULONGLONG v = val; @@ -110,8 +364,8 @@ int regquerylonglong (UAEREG *root, const TCHAR *name, ULONGLONG *val) if (inimode) { int ret = 0; TCHAR tmp[100]; - GetPrivateProfileString (gs (root), name, PUPPA, tmp, sizeof (tmp) / sizeof (TCHAR), inipath); - if (_tcscmp (tmp, PUPPA)) { + int size = sizeof tmp / sizeof(TCHAR); + if (ini_getstring(gs(root), name, tmp, &size)) { *val = _tstoi64 (tmp); ret = 1; } @@ -131,8 +385,7 @@ int regquerystr (UAEREG *root, const TCHAR *name, TCHAR *str, int *size) if (inimode) { int ret = 0; TCHAR *tmp = xmalloc (TCHAR, (*size) + 1); - GetPrivateProfileString (gs (root), name, PUPPA, tmp, *size, inipath); - if (_tcscmp (tmp, PUPPA)) { + if (ini_getstring(gs(root), name, tmp, size)) { _tcscpy (str, tmp); ret = 1; } @@ -154,28 +407,7 @@ int regenumstr (UAEREG *root, int idx, TCHAR *name, int *nsize, TCHAR *str, int name[0] = 0; str[0] = 0; if (inimode) { - int ret = 0; - int tmpsize = 65536; - TCHAR *tmp = xmalloc (TCHAR, tmpsize); - if (GetPrivateProfileSection (gs (root), tmp, tmpsize, inipath) > 0) { - int i; - TCHAR *p = tmp, *p2; - for (i = 0; i < idx; i++) { - if (p[0] == 0) - break; - p += _tcslen (p) + 1; - } - if (p[0]) { - p2 = _tcschr (p, '='); - if (p2) { - *p2++ = 0; - _tcscpy_s (name, *nsize, p); - _tcscpy_s (str, *size, p2); - ret = 1; - } - } - } - xfree (tmp); + int ret = ini_getsectionstring(gs(root), idx, name, nsize, str, size); return ret; } else { DWORD nsize2 = *nsize; @@ -217,12 +449,11 @@ int regsetdata (UAEREG *root, const TCHAR *name, const void *str, int size) { if (inimode) { uae_u8 *in = (uae_u8*)str; - DWORD ret; - int i; + int ret; TCHAR *tmp = xmalloc (TCHAR, size * 2 + 1); - for (i = 0; i < size; i++) + for (int i = 0; i < size; i++) _stprintf (tmp + i * 2, _T("%02X"), in[i]); - ret = WritePrivateProfileString (gs (root), name, tmp, inipath); + ret = ini_addstring(gs(root), name, tmp); xfree (tmp); return ret; } else { @@ -279,7 +510,7 @@ err: int regdelete (UAEREG *root, const TCHAR *name) { if (inimode) { - WritePrivateProfileString (gs (root), name, NULL, inipath); + ini_delete(gs(root), name); return 1; } else { HKEY rk = gr (root); @@ -292,13 +523,9 @@ int regdelete (UAEREG *root, const TCHAR *name) int regexists (UAEREG *root, const TCHAR *name) { if (inimode) { - int ret = 1; - TCHAR *tmp = xmalloc (TCHAR, _tcslen (PUPPA) + 1); - int size = _tcslen (PUPPA) + 1; - GetPrivateProfileString (gs (root), name, PUPPA, tmp, size, inipath); - if (!_tcscmp (tmp, PUPPA)) - ret = 0; - xfree (tmp); + if (!inilines) + return 0; + int ret = ini_getstring(gs(root), name, NULL, NULL); return ret; } else { HKEY rk = gr (root); @@ -314,7 +541,7 @@ void regdeletetree (UAEREG *root, const TCHAR *name) TCHAR *s = gsn (root, name); if (!s) return; - WritePrivateProfileSection (s, _T(""), inipath); + ini_delete(s, NULL); xfree (s); } else { HKEY rk = gr (root); @@ -328,23 +555,10 @@ int regexiststree (UAEREG *root, const TCHAR *name) { if (inimode) { int ret = 0; - int tmpsize = 65536; - TCHAR *p, *tmp; TCHAR *s = gsn (root, name); if (!s) return 0; - tmp = xmalloc (TCHAR, tmpsize / sizeof (TCHAR)); - tmp[0] = 0; - GetPrivateProfileSectionNames (tmp, tmpsize, inipath); - p = tmp; - while (p[0]) { - if (!_tcscmp (p, name)) { - ret = 1; - break; - } - p += _tcslen (p) + 1; - } - xfree (tmp); + ret = ini_getstring(s, NULL, NULL, 0); xfree (s); return ret; } else { @@ -402,6 +616,8 @@ void regclosetree (UAEREG *key) { if (!key) return; + if (inimode) + ini_save(inipath); if (key->fkey) RegCloseKey (key->fkey); xfree (key->inipath); @@ -446,6 +662,7 @@ int reginitializeinit (TCHAR **pppath) inimode = 1; inipath = my_strdup (fpath); + ini_load(inipath); if (!regexists (NULL, _T("Version"))) goto fail; return 1; -- 2.47.3