mirror of
https://github.com/thunderbrewhq/squall.git
synced 2025-12-12 02:22:30 +00:00
feat(registry): add basic registry implementation
This commit is contained in:
parent
2ffa8217c0
commit
f8a7ac7001
20 changed files with 1318 additions and 73 deletions
|
|
@ -7,6 +7,7 @@ file(GLOB STORM_SOURCES
|
|||
"crypto/*.cpp"
|
||||
"error/*.cpp"
|
||||
"hash/*.cpp"
|
||||
"option*/*.cpp"
|
||||
"queue/*.cpp"
|
||||
"string/*.cpp"
|
||||
"thread/*.cpp"
|
||||
|
|
@ -17,6 +18,7 @@ if(WHOA_SYSTEM_WIN)
|
|||
"win/*.cpp"
|
||||
"error/win/*.cpp"
|
||||
"thread/win/*.cpp"
|
||||
"registry/win/*.cpp"
|
||||
)
|
||||
list(APPEND STORM_SOURCES ${STORM_WIN_SOURCES})
|
||||
endif()
|
||||
|
|
@ -28,6 +30,7 @@ if(WHOA_SYSTEM_MAC)
|
|||
"error/unix/*.cpp"
|
||||
"thread/mac/*.cpp"
|
||||
"thread/mac/*.mm"
|
||||
"registry/mac/*.mm"
|
||||
)
|
||||
list(APPEND STORM_SOURCES ${STORM_MAC_SOURCES})
|
||||
endif()
|
||||
|
|
@ -37,6 +40,7 @@ if(WHOA_SYSTEM_LINUX)
|
|||
"linux/*.cpp"
|
||||
"error/unix/*.cpp"
|
||||
"thread/linux/*.cpp"
|
||||
"registry/linux/*.cpp"
|
||||
)
|
||||
list(APPEND STORM_SOURCES ${STORM_LINUX_SOURCES})
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -3,8 +3,9 @@
|
|||
#include <cstring>
|
||||
|
||||
void SARC4PrepareKey(const void* data, uint32_t len, SARC4Key* key) {
|
||||
STORM_ASSERT(data);
|
||||
STORM_VALIDATE(data, ERROR_INVALID_PARAMETER);
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(data);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
key->x = 0;
|
||||
key->y = 0;
|
||||
|
|
|
|||
6
storm/Option.hpp
Normal file
6
storm/Option.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef STORM_OPTION_HPP
|
||||
#define STORM_OPTION_HPP
|
||||
|
||||
#include "storm/option/Option.hpp"
|
||||
|
||||
#endif
|
||||
6
storm/Registry.hpp
Normal file
6
storm/Registry.hpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef STORM_REGISTRY_HPP
|
||||
#define STORM_REGISTRY_HPP
|
||||
|
||||
#include "storm/registry/Registry.hpp"
|
||||
|
||||
#endif
|
||||
|
|
@ -21,6 +21,8 @@ int32_t SStrCmpI(const char* string1, const char* string2, size_t maxchars);
|
|||
|
||||
size_t SStrCopy(char* dest, const char* source, size_t destsize);
|
||||
|
||||
size_t SStrNCopy(char* dest, const char* source, size_t maxchars, size_t destsize);
|
||||
|
||||
char* SStrDupA(const char* string, const char* filename, uint32_t linenumber);
|
||||
|
||||
uint32_t SStrHashHT(const char* string);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,61 @@
|
|||
#include "storm/Unicode.hpp"
|
||||
#include "storm/String.hpp"
|
||||
|
||||
#include <limits>
|
||||
|
||||
static const uint32_t offsetsFromUTF8[] = {
|
||||
0x0,
|
||||
0x3080,
|
||||
0xE2080,
|
||||
0x3C82080,
|
||||
0xFA082080,
|
||||
0x82082080
|
||||
};
|
||||
|
||||
static const uint32_t firstByteMark[] = {
|
||||
0x0,
|
||||
0x0,
|
||||
0xC0,
|
||||
0xE0,
|
||||
0xF0,
|
||||
0xF8,
|
||||
0xFC
|
||||
};
|
||||
|
||||
static const uint8_t bytesFromUTF8[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
|
||||
0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05
|
||||
};
|
||||
|
||||
uint32_t SUniSGetUTF8(const uint8_t* strptr, int32_t* chars) {
|
||||
if (chars) {
|
||||
|
|
@ -111,3 +168,172 @@ void SUniSPutUTF8(uint32_t c, char* strptr) {
|
|||
*curstr++ = v3;
|
||||
*curstr = '\0';
|
||||
}
|
||||
|
||||
int32_t SUniConvertUTF16to8(uint8_t* dst, uint32_t dstmaxchars, const uint16_t* src, uint32_t srcmaxchars, uint32_t* dstchars, uint32_t* srcchars) {
|
||||
auto srcend = srcmaxchars == STORM_MAX_STR ? reinterpret_cast<const uint16_t*>(UINTPTR_MAX) : &src[srcmaxchars];
|
||||
auto dstend = &dst[dstmaxchars];
|
||||
auto dststart = dst;
|
||||
auto srcstart = src;
|
||||
|
||||
int32_t result;
|
||||
|
||||
while (src < srcend) {
|
||||
uint32_t widechars = 1;
|
||||
auto grapheme = static_cast<uint32_t>(src[0]);
|
||||
if (0xD7FF < grapheme && grapheme < 0xDC00) {
|
||||
if (src + 1 >= srcend) {
|
||||
goto fail;
|
||||
}
|
||||
auto char2 = static_cast<uint32_t>(src[1]);
|
||||
if (0xDBFF < char2 && char2 < 0xE000) {
|
||||
grapheme = ((grapheme - 0xD7F7) * 1024) + char2;
|
||||
widechars = 2;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t chars;
|
||||
|
||||
if (grapheme < 0x80) {
|
||||
chars = 1;
|
||||
if (grapheme == 0) {
|
||||
if (dst < dstend) {
|
||||
*dst++ = '\0';
|
||||
result = 0;
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
} else if (grapheme < 0x800) {
|
||||
chars = 2;
|
||||
} else if (grapheme < 0x10000) {
|
||||
chars = 3;
|
||||
} else if (grapheme < 0x200000) {
|
||||
chars = 4;
|
||||
} else if (grapheme < 0x4000000) {
|
||||
chars = 5;
|
||||
} else if (grapheme > 0x7FFFFFFF) {
|
||||
grapheme = 0xFFFD;
|
||||
chars = 2;
|
||||
} else {
|
||||
chars = 6;
|
||||
}
|
||||
|
||||
result = chars;
|
||||
|
||||
dst += chars;
|
||||
|
||||
if (dst > dstend) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
switch (chars) {
|
||||
case 6:
|
||||
*--dst = (grapheme & 0x3F) | 0x80;
|
||||
grapheme >>= 6;
|
||||
case 5:
|
||||
*--dst = (grapheme & 0x3F) | 0x80;
|
||||
grapheme >>= 6;
|
||||
case 4:
|
||||
*--dst = (grapheme & 0x3F) | 0x80;
|
||||
grapheme >>= 6;
|
||||
case 3:
|
||||
*--dst = (grapheme & 0x3F) | 0x80;
|
||||
grapheme >>= 6;
|
||||
case 2:
|
||||
*--dst = (grapheme & 0x3F) | 0x80;
|
||||
grapheme >>= 6;
|
||||
case 1:
|
||||
*--dst = grapheme | firstByteMark[chars];
|
||||
}
|
||||
|
||||
src += widechars;
|
||||
dst += chars;
|
||||
}
|
||||
|
||||
fail:
|
||||
result = -1;
|
||||
|
||||
done:
|
||||
if (srcchars) {
|
||||
*srcchars = src - srcstart;
|
||||
}
|
||||
|
||||
if (dstchars) {
|
||||
*dstchars = dst - dststart;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#include <cstdio>
|
||||
|
||||
int32_t SUniConvertUTF8to16(uint16_t* dst, uint32_t dstmaxchars, const uint8_t* src, uint32_t srcmaxchars, uint32_t* dstchars, uint32_t* srcchars) {
|
||||
auto srcend = srcmaxchars == STORM_MAX_STR ? reinterpret_cast<const uint8_t*>(UINTPTR_MAX) : src + srcmaxchars;
|
||||
auto dstend = dst + dstmaxchars;
|
||||
auto dststart = dst;
|
||||
auto srcstart = src;
|
||||
|
||||
int32_t result = 0;
|
||||
|
||||
while (src < srcend) {
|
||||
auto bytes = bytesFromUTF8[*src];
|
||||
if ((src + bytes) >= srcend) {
|
||||
result = -1 - bytes;
|
||||
goto done;
|
||||
}
|
||||
|
||||
uint32_t grapheme = 0;
|
||||
|
||||
int32_t width = 0;
|
||||
|
||||
switch (bytes) {
|
||||
case 5:
|
||||
grapheme = (grapheme + src[width++]) << 6;
|
||||
case 4:
|
||||
grapheme = (grapheme + src[width++]) << 6;
|
||||
case 3:
|
||||
grapheme = (grapheme + src[width++]) << 6;
|
||||
case 2:
|
||||
grapheme = (grapheme + src[width++]) << 6;
|
||||
case 1:
|
||||
grapheme = (grapheme + src[width++]) << 6;
|
||||
case 0:
|
||||
grapheme = (grapheme + src[width++]) - offsetsFromUTF8[bytes];
|
||||
}
|
||||
|
||||
if (dst >= dstend) {
|
||||
result = 1;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (grapheme < 0x10000) {
|
||||
*dst++ = static_cast<uint16_t>(grapheme);
|
||||
if (grapheme == 0x0) {
|
||||
goto done;
|
||||
}
|
||||
} else if (grapheme < 0x110000) {
|
||||
if (dst >= dstend) {
|
||||
result = 0;
|
||||
goto done;
|
||||
}
|
||||
auto v16 = grapheme - 0x10000;
|
||||
*dst++ = static_cast<uint16_t>(v16 >> 10) - 0x2800;
|
||||
*dst++ = static_cast<uint16_t>(v16 & 0x3FF) - 0x2400;
|
||||
} else {
|
||||
*dst++ = 0xFFFD;
|
||||
}
|
||||
|
||||
src += width;
|
||||
}
|
||||
|
||||
printf("fail yure %p %p\n", src, srcend);
|
||||
|
||||
result = -1;
|
||||
|
||||
done:
|
||||
if (srcchars) {
|
||||
*srcchars = src - srcstart;
|
||||
}
|
||||
|
||||
if (dstchars) {
|
||||
*dstchars = dst - dststart;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,8 @@ uint32_t SUniSGetUTF8(const uint8_t* strptr, int32_t* chars);
|
|||
|
||||
void SUniSPutUTF8(uint32_t c, char* strptr);
|
||||
|
||||
int32_t SUniConvertUTF16to8(uint8_t* dst, uint32_t dstmaxchars, const uint16_t* src, uint32_t srcmaxchars, uint32_t* dstchars, uint32_t* srcchars);
|
||||
|
||||
int32_t SUniConvertUTF8to16(uint16_t* dst, uint32_t dstmaxchars, const uint8_t* src, uint32_t srcmaxchars, uint32_t* dstchars, uint32_t* srcchars);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
#ifndef STORM_ERROR_CODES_HPP
|
||||
#define STORM_ERROR_CODES_HPP
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
#include "storm/error/win/Codes.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(WHOA_SYSTEM_MAC) || defined(WHOA_SYSTEM_LINUX)
|
||||
#include "storm/error/unix/Codes.hpp"
|
||||
#endif
|
||||
|
||||
#include "storm/error/Macro.hpp"
|
||||
|
||||
#define STORM_ERROR_APPLICATION_FATAL STORM_ERROR(0x84)
|
||||
|
||||
#define STORM_COMMAND_ERROR_BAD_ARGUMENT STORM_ERROR(0x65)
|
||||
#define STORM_COMMAND_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR(0x6D)
|
||||
#define STORM_COMMAND_ERROR_OPEN_FAILED 0x6E
|
||||
|
||||
#endif
|
||||
245
storm/error/Defines.hpp
Normal file
245
storm/error/Defines.hpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
#ifndef STORM_ERROR_DEFINES_HPP
|
||||
#define STORM_ERROR_DEFINES_HPP
|
||||
|
||||
// error codes
|
||||
|
||||
#if defined(WHOA_SYSTEM_WIN)
|
||||
|
||||
#include <winerror.h>
|
||||
|
||||
#else
|
||||
|
||||
#define ERROR_SUCCESS 0x0000
|
||||
#define ERROR_INVALID_FUNCTION 0x0001
|
||||
#define ERROR_FILE_NOT_FOUND 0x0002
|
||||
#define ERROR_PATH_NOT_FOUND 0x0003
|
||||
#define ERROR_TOO_MANY_OPEN_FILES 0x0004
|
||||
#define ERROR_ACCESS_DENIED 0x0005
|
||||
#define ERROR_INVALID_HANDLE 0x0006
|
||||
#define ERROR_ARENA_TRASHED 0x0007
|
||||
#define ERROR_NOT_ENOUGH_MEMORY 0x0008
|
||||
#define ERROR_INVALID_BLOCK 0x0009
|
||||
#define ERROR_BAD_ENVIRONMENT 0x000A
|
||||
#define ERROR_BAD_FORMAT 0x000B
|
||||
#define ERROR_INVALID_ACCESS 0x000C
|
||||
#define ERROR_INVALID_DATA 0x000D
|
||||
#define ERROR_INVALID_DRIVE 0x000F
|
||||
#define ERROR_CURRENT_DIRECTORY 0x0010
|
||||
#define ERROR_NOT_SAME_DEVICE 0x0011
|
||||
#define ERROR_NO_MORE_FILES 0x0012
|
||||
#define ERROR_WRITE_PROTECT 0x0013
|
||||
#define ERROR_BAD_UNIT 0x0014
|
||||
#define ERROR_NOT_READY 0x0015
|
||||
#define ERROR_BAD_COMMAND 0x0016
|
||||
#define ERROR_CRC 0x0017
|
||||
#define ERROR_BAD_LENGTH 0x0018
|
||||
#define ERROR_SEEK 0x0019
|
||||
#define ERROR_NOT_DOS_DISK 0x001A
|
||||
#define ERROR_SECTOR_NOT_FOUND 0x001B
|
||||
#define ERROR_OUT_OF_PAPER 0x001C
|
||||
#define ERROR_WRITE_FAULT 0x001D
|
||||
#define ERROR_READ_FAULT 0x001E
|
||||
#define ERROR_GEN_FAILURE 0x001F
|
||||
#define ERROR_SHARING_VIOLATION 0x0020
|
||||
#define ERROR_LOCK_VIOLATION 0x0021
|
||||
#define ERROR_WRONG_DISK 0x0022
|
||||
#define ERROR_FCB_UNAVAILABLE 0x0023
|
||||
#define ERROR_SHARING_BUFFER_EXCEEDED 0x0024
|
||||
#define ERROR_NOT_SUPPORTED 0x0032
|
||||
#define ERROR_FILE_EXISTS 0x0050
|
||||
#define ERROR_DUP_FCB 0x0051
|
||||
#define ERROR_CANNOT_MAKE 0x0052
|
||||
#define ERROR_FAIL_I24 0x0053
|
||||
#define ERROR_OUT_OF_STRUCTURES 0x0054
|
||||
#define ERROR_ALREADY_ASSIGNED 0x0055
|
||||
#define ERROR_INVALID_PASSWORD 0x0056
|
||||
#define ERROR_INVALID_PARAMETER 0x0057
|
||||
#define ERROR_NET_WRITE_FAULT 0x0058
|
||||
#define ERROR_NO_PROC_SLOTS 0x0059
|
||||
#define ERROR_NOT_FROZEN 0x005A
|
||||
#define ERR_TSTOVFL 0x005B
|
||||
#define ERR_TSTDUP 0x005C
|
||||
#define ERROR_NO_ITEMS 0x005D
|
||||
#define ERROR_INTERRUPT 0x005F
|
||||
#define ERROR_TOO_MANY_SEMAPHORES 0x0064
|
||||
#define ERROR_EXCL_SEM_ALREADY_OWNED 0x0065
|
||||
#define ERROR_SEM_IS_SET 0x0066
|
||||
#define ERROR_TOO_MANY_SEM_REQUESTS 0x0067
|
||||
#define ERROR_INVALID_AT_INTERRUPT_TIME 0x0068
|
||||
#define ERROR_SEM_OWNER_DIED 0x0069
|
||||
#define ERROR_SEM_USER_LIMIT 0x006A
|
||||
#define ERROR_DISK_CHANGE 0x006B
|
||||
#define ERROR_DRIVE_LOCKED 0x006C
|
||||
#define ERROR_BROKEN_PIPE 0x006D
|
||||
#define ERROR_OPEN_FAILED 0x006E
|
||||
#define ERROR_BUFFER_OVERFLOW 0x006F
|
||||
#define ERROR_DISK_FULL 0x0070
|
||||
#define ERROR_NO_MORE_SEARCH_HANDLES 0x0071
|
||||
#define ERROR_INVALID_TARGET_HANDLE 0x0072
|
||||
#define ERROR_PROTECTION_VIOLATION 0x0073
|
||||
#define ERROR_VIOKBD_REQUEST 0x0074
|
||||
#define ERROR_INVALID_CATEGORY 0x0075
|
||||
#define ERROR_INVALID_VERIFY_SWITCH 0x0076
|
||||
#define ERROR_BAD_DRIVER_LEVEL 0x0077
|
||||
#define ERROR_CALL_NOT_IMPLEMENTED 0x0078
|
||||
#define ERROR_SEM_TIMEOUT 0x0079
|
||||
#define ERROR_INSUFFICIENT_BUFFER 0x007A
|
||||
#define ERROR_INVALID_NAME 0x007B
|
||||
#define ERROR_INVALID_LEVEL 0x007C
|
||||
#define ERROR_NO_VOLUME_LABEL 0x007D
|
||||
#define ERROR_MOD_NOT_FOUND 0x007E
|
||||
#define ERROR_PROC_NOT_FOUND 0x007F
|
||||
#define ERROR_WAIT_NO_CHILDREN 0x0080
|
||||
#define ERROR_CHILD_NOT_COMPLETE 0x0081
|
||||
#define ERROR_DIRECT_ACCESS_HANDLE 0x0082
|
||||
#define ERROR_NEGATIVE_SEEK 0x0083
|
||||
#define ERROR_SEEK_ON_DEVICE 0x0084
|
||||
#define ERROR_IS_JOIN_TARGET 0x0085
|
||||
#define ERROR_IS_JOINED 0x0086
|
||||
#define ERROR_IS_SUBSTED 0x0087
|
||||
#define ERROR_NOT_JOINED 0x0088
|
||||
#define ERROR_NOT_SUBSTED 0x0089
|
||||
#define ERROR_JOIN_TO_JOIN 0x008A
|
||||
#define ERROR_SUBST_TO_SUBST 0x008B
|
||||
#define ERROR_JOIN_TO_SUBST 0x008C
|
||||
#define ERROR_SUBST_TO_JOIN 0x008D
|
||||
#define ERROR_BUSY_DRIVE 0x008E
|
||||
#define ERROR_SAME_DRIVE 0x008F
|
||||
#define ERROR_DIR_NOT_ROOT 0x0090
|
||||
#define ERROR_DIR_NOT_EMPTY 0x0091
|
||||
#define ERROR_IS_SUBST_PATH 0x0092
|
||||
#define ERROR_IS_JOIN_PATH 0x0093
|
||||
#define ERROR_PATH_BUSY 0x0094
|
||||
#define ERROR_IS_SUBST_TARGET 0x0095
|
||||
#define ERROR_SYSTEM_TRACE 0x0096
|
||||
#define ERROR_INVALID_EVENT_COUNT 0x0097
|
||||
#define ERROR_TOO_MANY_MUXWAITERS 0x0098
|
||||
#define ERROR_INVALID_LIST_FORMAT 0x0099
|
||||
#define ERROR_LABEL_TOO_LONG 0x009A
|
||||
#define ERROR_TOO_MANY_TCBS 0x009B
|
||||
#define ERROR_SIGNAL_REFUSED 0x009C
|
||||
#define ERROR_DISCARDED 0x009D
|
||||
#define ERROR_NOT_LOCKED 0x009E
|
||||
#define ERROR_BAD_THREADID_ADDR 0x009F
|
||||
#define ERROR_BAD_ARGUMENTS 0x00A0
|
||||
#define ERROR_BAD_PATHNAME 0x00A1
|
||||
#define ERROR_SIGNAL_PENDING 0x00A2
|
||||
#define ERROR_UNCERTAIN_MEDIA 0x00A3
|
||||
#define ERROR_MAX_THRDS_REACHED 0x00A4
|
||||
#define ERROR_MONITORS_NOT_SUPPORTED 0x00A5
|
||||
#define ERROR_INVALID_SEGMENT_NUMBER 0x00B4
|
||||
#define ERROR_INVALID_CALLGATE 0x00B5
|
||||
#define ERROR_INVALID_ORDINAL 0x00B6
|
||||
#define ERROR_ALREADY_EXISTS 0x00B7
|
||||
#define ERROR_NO_CHILD_PROCESS 0x00B8
|
||||
#define ERROR_CHILD_ALIVE_NOWAIT 0x00B9
|
||||
#define ERROR_INVALID_FLAG_NUMBER 0x00BA
|
||||
#define ERROR_SEM_NOT_FOUND 0x00BB
|
||||
#define ERROR_INVALID_STARTING_CODESEG 0x00BC
|
||||
#define ERROR_INVALID_STACKSEG 0x00BD
|
||||
#define ERROR_INVALID_MODULETYPE 0x00BE
|
||||
#define ERROR_INVALID_EXE_SIGNATURE 0x00BF
|
||||
#define ERROR_EXE_MARKED_INVALID 0x00C0
|
||||
#define ERROR_BAD_EXE_FORMAT 0x00C1
|
||||
#define ERROR_ITERATED_DATA_EXCEEDS_64k 0x00C2
|
||||
#define ERROR_INVALID_MINALLOCSIZE 0x00C3
|
||||
#define ERROR_DYNLINK_FROM_INVALID_RING 0x00C4
|
||||
#define ERROR_IOPL_NOT_ENABLED 0x00C5
|
||||
#define ERROR_INVALID_SEGDPL 0x00C6
|
||||
#define ERROR_AUTODATASEG_EXCEEDS_64k 0x00C7
|
||||
#define ERROR_RING2SEG_MUST_BE_MOVABLE 0x00C8
|
||||
#define ERROR_RELOC_CHAIN_XEEDS_SEGLIM 0x00C9
|
||||
#define ERROR_INFLOOP_IN_RELOC_CHAIN 0x00CA
|
||||
#define ERROR_ENVVAR_NOT_FOUND 0x00CB
|
||||
#define ERROR_NOT_CURRENT_CTRY 0x00CC
|
||||
#define ERROR_NO_SIGNAL_SENT 0x00CD
|
||||
#define ERROR_FILENAME_EXCED_RANGE 0x00CE
|
||||
#define ERROR_RING2_STACK_IN_USE 0x00CF
|
||||
#define ERROR_META_EXPANSION_TOO_LONG 0x00D0
|
||||
#define ERROR_INVALID_SIGNAL_NUMBER 0x00D1
|
||||
#define ERROR_THREAD_1_INACTIVE 0x00D2
|
||||
#define ERROR_INFO_NOT_AVAIL 0x00D3
|
||||
#define ERROR_LOCKED 0x00D4
|
||||
#define ERROR_BAD_DYNALINK 0x00D5
|
||||
#define ERROR_TOO_MANY_MODULES 0x00D6
|
||||
#define ERROR_NESTING_NOT_ALLOWED 0x00D7
|
||||
#define ERROR_INVALID_TOKEN 0x013B
|
||||
|
||||
#endif
|
||||
|
||||
#define STORM_NO_ERROR 0x85100000
|
||||
|
||||
#define STORM_ERROR(id) (STORM_NO_ERROR | (id & 0xFFFF))
|
||||
|
||||
#define STORM_ERROR_APPLICATION_FATAL STORM_ERROR(0x84)
|
||||
|
||||
#define STORM_COMMAND_ERROR_BAD_ARGUMENT STORM_ERROR(0x65)
|
||||
#define STORM_COMMAND_ERROR_NOT_ENOUGH_ARGUMENTS STORM_ERROR(0x6D)
|
||||
|
||||
// assertions
|
||||
|
||||
#if defined(WHOA_BUILD_ASSERTIONS)
|
||||
|
||||
#define STORM_ASSERT(x) \
|
||||
if (!(x)) { \
|
||||
SErrPrepareAppFatal(__FILE__, __LINE__); \
|
||||
SErrDisplayAppFatal(#x); \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
#else
|
||||
|
||||
#define STORM_ASSERT(x) \
|
||||
(void)0
|
||||
|
||||
#endif
|
||||
|
||||
// validation
|
||||
|
||||
#if defined(NDEBUG)
|
||||
|
||||
// (release) check all validation cases and return if any is false without displaying an error
|
||||
|
||||
#define STORM_VALIDATE_BEGIN \
|
||||
{ \
|
||||
bool intrn_valresult = true; \
|
||||
do {
|
||||
#define STORM_VALIDATE(x) \
|
||||
if (!(x)) { \
|
||||
intrn_valresult &= !!(x); \
|
||||
break; \
|
||||
}
|
||||
#define STORM_VALIDATE_END \
|
||||
} while(0); \
|
||||
if (!intrn_valresult) { \
|
||||
SErrSetLastError(ERROR_INVALID_PARAMETER); \
|
||||
return 0; \
|
||||
} \
|
||||
}
|
||||
#define STORM_VALIDATE_END_VOID \
|
||||
} while(0); \
|
||||
if (!intrn_valresult) { \
|
||||
SErrSetLastError(ERROR_INVALID_PARAMETER); \
|
||||
return; \
|
||||
} \
|
||||
}
|
||||
#else
|
||||
|
||||
// (debug) display any failed validation as you would a failed assertion
|
||||
|
||||
#define STORM_VALIDATE_BEGIN \
|
||||
do {
|
||||
#define STORM_VALIDATE(x) \
|
||||
if (!(x)) { \
|
||||
SErrPrepareAppFatal(__FILE__, __LINE__); \
|
||||
SErrDisplayAppFatal(#x); \
|
||||
} \
|
||||
(void)0
|
||||
#define STORM_VALIDATE_END \
|
||||
} while (0)
|
||||
#define STORM_VALIDATE_END_VOID \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
#include "storm/error/Error.hpp"
|
||||
#include "storm/error/Codes.hpp"
|
||||
#include "storm/error/Types.hpp"
|
||||
#include "storm/Thread.hpp"
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
|
||||
#include "storm/error/Macro.hpp"
|
||||
#include "storm/error/Codes.hpp"
|
||||
#include "storm/error/Defines.hpp"
|
||||
|
||||
[[noreturn]] void SErrDisplayAppFatal(const char* format, ...);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
#ifndef STORM_ERROR_MACRO_HPP
|
||||
#define STORM_ERROR_MACRO_HPP
|
||||
|
||||
#define STORM_NO_ERROR 0x85100000
|
||||
|
||||
#define STORM_ERROR(id) (STORM_NO_ERROR | (id & 0xFFFF))
|
||||
|
||||
// assertions
|
||||
#if defined(NDEBUG)
|
||||
#define STORM_ASSERT(x) \
|
||||
(void)0
|
||||
#else
|
||||
#define STORM_ASSERT(x) \
|
||||
if (!(x)) { \
|
||||
SErrPrepareAppFatal(__FILE__, __LINE__); \
|
||||
SErrDisplayAppFatal(#x); \
|
||||
} \
|
||||
(void)0
|
||||
#endif
|
||||
|
||||
#define STORM_VALIDATE(x, y, ...) \
|
||||
if (!(x)) { \
|
||||
SErrSetLastError(y); \
|
||||
return __VA_ARGS__; \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
#define STORM_VALIDATE_STRING(x, y, ...) STORM_VALIDATE(x && *x, y, __VA_ARGS__)
|
||||
|
||||
#define STORM_PANIC(...) \
|
||||
SErrPrepareAppFatal(__FILE__, __LINE__); \
|
||||
SErrDisplayAppFatal(__VA_ARGS__); \
|
||||
(void)0
|
||||
|
||||
#endif
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#ifndef STORM_ERROR_UNIX_CODES_HPP
|
||||
#define STORM_ERROR_UNIX_CODES_HPP
|
||||
|
||||
#define ERROR_INVALID_PARAMETER 0x57
|
||||
#define ERROR_SUCCESS 0x0
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef STORM_ERROR_WIN_CODES_HPP
|
||||
#define STORM_ERROR_WIN_CODES_HPP
|
||||
|
||||
#include <winerror.h>
|
||||
|
||||
#endif
|
||||
27
storm/registry/Registry.hpp
Normal file
27
storm/registry/Registry.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef STORM_REGISTRY_REGISTRY_HPP
|
||||
#define STORM_REGISTRY_REGISTRY_HPP
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#define STORM_REGISTRY_MAX_PATH 260
|
||||
#define STORM_REGISTRY_MAX_VALUE 16384
|
||||
|
||||
#define STORM_REGISTRY_BATTLENET 0x02
|
||||
#define STORM_REGISTRY_CURRENT_USER_ONLY 0x04
|
||||
#define STORM_REGISTRY_FLUSH_KEY 0x08
|
||||
#define STORM_REGISTRY_NO_BASE_KEY 0x10
|
||||
|
||||
#define STORM_REGISTRY_TYPE_STRING 1
|
||||
#define STORM_REGISTRY_TYPE_DWORD 4
|
||||
|
||||
int32_t SRegLoadString(const char* keyname, const char* valuename, uint32_t flags, char* buffer, uint32_t buffersize);
|
||||
|
||||
int32_t SRegLoadValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t* value);
|
||||
|
||||
int32_t SRegSaveString(const char* keyname, const char* valuename, uint32_t flags, const char* string);
|
||||
|
||||
int32_t SRegSaveValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t value);
|
||||
|
||||
void SRegDestroy();
|
||||
|
||||
#endif
|
||||
373
storm/registry/linux/Registry.cpp
Normal file
373
storm/registry/linux/Registry.cpp
Normal file
|
|
@ -0,0 +1,373 @@
|
|||
#include "storm/registry/Registry.hpp"
|
||||
#include "bc/file/Close.hpp"
|
||||
#include "bc/file/Defines.hpp"
|
||||
#include "bc/file/GetFileInfo.hpp"
|
||||
#include "bc/file/GetPos.hpp"
|
||||
#include "bc/file/Types.hpp"
|
||||
#include "bc/memory/Storm.hpp"
|
||||
#include "storm/String.hpp"
|
||||
#include "storm/Error.hpp"
|
||||
#include "storm/List.hpp"
|
||||
#include "bc/File.hpp"
|
||||
#include "bc/Memory.hpp"
|
||||
#include "storm/Thread.hpp"
|
||||
|
||||
#include <climits>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
|
||||
struct RegistryEntry : public TSLinkedNode<RegistryEntry> {
|
||||
char* name = nullptr;
|
||||
char* value = nullptr;
|
||||
|
||||
bool ParseLine(const char* line) {
|
||||
char buffer[STORM_MAX_PATH];
|
||||
auto b = buffer;
|
||||
auto end = buffer + sizeof(buffer);
|
||||
while (b < end && *line && *line != '=') {
|
||||
*b++ = *line++;
|
||||
}
|
||||
if (*line++ != '=') {
|
||||
return false;
|
||||
}
|
||||
if (b >= end) {
|
||||
return false;
|
||||
}
|
||||
*b = '\0';
|
||||
this->name = SStrDupA(buffer, __FILE__, __LINE__);
|
||||
|
||||
b = buffer;
|
||||
while (b < end && *line) {
|
||||
auto c = *line++;
|
||||
if (c == '\\') {
|
||||
if (*line == 'n') {
|
||||
*b++ = '\n';
|
||||
} else if (*line == '\\') {
|
||||
*b++ = '\\';
|
||||
} else {
|
||||
*b++ = *line;
|
||||
}
|
||||
line++;
|
||||
} else {
|
||||
*b++ = c;
|
||||
}
|
||||
}
|
||||
if (b >= end) {
|
||||
return false;
|
||||
}
|
||||
*b = '\0';
|
||||
|
||||
this->value = SStrDupA(buffer, __FILE__, __LINE__);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
~RegistryEntry() {
|
||||
if (this->name) {
|
||||
SMemFree(this->name, __FILE__, __LINE__, 0x0);
|
||||
}
|
||||
|
||||
if (this->value) {
|
||||
SMemFree(this->value, __FILE__, __LINE__, 0x0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static int32_t s_initregistry = 0;
|
||||
static STORM_LIST(RegistryEntry) s_registry;
|
||||
static SCritSect s_lockregistry;
|
||||
|
||||
Blizzard::File::StreamRecord* RegistryFileCreate(int32_t mode) {
|
||||
const char* basedir = getenv("XDG_CONFIG_HOME");
|
||||
if (!basedir) {
|
||||
basedir = getenv("HOME");
|
||||
if (!basedir) {
|
||||
basedir = ".";
|
||||
}
|
||||
}
|
||||
|
||||
char name[PATH_MAX];
|
||||
*name = '\0';
|
||||
SStrPack(name, basedir, sizeof(name));
|
||||
SStrPack(name, "/.whoa", sizeof(name));
|
||||
|
||||
if (!Blizzard::File::IsDirectory(name)) {
|
||||
if (!Blizzard::File::CreateDirectory(name, false)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
SStrPack(name, "/registry.txt", sizeof(name));
|
||||
|
||||
Blizzard::File::StreamRecord* file;
|
||||
if (!Blizzard::File::Open(name, mode, file)) {
|
||||
return nullptr;
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
int32_t RegistryFileWriteEntry(Blizzard::File::StreamRecord* file, RegistryEntry* entry) {
|
||||
char valuebuffer[STORM_REGISTRY_MAX_VALUE];
|
||||
auto source = reinterpret_cast<const char*>(entry->value);
|
||||
auto dest = reinterpret_cast<char*>(valuebuffer);
|
||||
auto sourceend = source + SStrLen(entry->value);
|
||||
auto destend = dest + sizeof(valuebuffer);
|
||||
|
||||
while (dest < destend && source < sourceend) {
|
||||
auto c = *source++;
|
||||
if (c == '\n' && (dest+1) < destend) {
|
||||
*dest++ = '\\';
|
||||
*dest++ = 'n';
|
||||
} else {
|
||||
*dest++ = c;
|
||||
}
|
||||
}
|
||||
valuebuffer[std::min(sizeof(valuebuffer)-1, static_cast<size_t>(dest-valuebuffer))] = '\0';
|
||||
|
||||
char linebuffer[STORM_REGISTRY_MAX_PATH + STORM_REGISTRY_MAX_VALUE + 2];
|
||||
SStrPrintf(linebuffer, sizeof(linebuffer), "%s=%s\n", entry->name, valuebuffer);
|
||||
|
||||
auto length = SStrLen(linebuffer);
|
||||
return Blizzard::File::Write(file, linebuffer, length);
|
||||
}
|
||||
|
||||
int32_t RegistryFileReadLine(Blizzard::File::StreamRecord* file, char* buffer, int32_t buffersize) {
|
||||
int64_t start;
|
||||
if (!Blizzard::File::GetPos(file, start)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto size = static_cast<int64_t>(Blizzard::File::GetFileInfo(file)->size);
|
||||
if (start == size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto count = static_cast<int32_t>(std::min(static_cast<int64_t>(buffersize), size-start));
|
||||
if (!Blizzard::File::Read(file, buffer, &count)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
auto p = buffer;
|
||||
auto end = buffer + std::min(buffersize-1, count);
|
||||
while (p < end && *p && *p != '\n') {
|
||||
p++;
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
|
||||
auto nextline = start + static_cast<int64_t>(p-buffer) + 1;
|
||||
|
||||
Blizzard::File::SetPos(file, nextline, BC_FILE_SEEK_START);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void RegistryInit() {
|
||||
s_initregistry = true;
|
||||
|
||||
auto file = RegistryFileCreate(Blizzard::File::Mode::mustexist|Blizzard::File::Mode::read);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[STORM_REGISTRY_MAX_PATH + STORM_REGISTRY_MAX_VALUE + 2];
|
||||
while (RegistryFileReadLine(file, buffer, sizeof(buffer))) {
|
||||
if (*buffer) {
|
||||
auto entry = s_registry.NewNode(1, 0, 0);
|
||||
|
||||
if (!entry->ParseLine(buffer)) {
|
||||
s_registry.DeleteNode(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Blizzard::File::Close(file);
|
||||
|
||||
}
|
||||
|
||||
void RegistryFlush(bool remove) {
|
||||
using Mode = Blizzard::File::Mode;
|
||||
auto file = RegistryFileCreate(Mode::create|Mode::write|Mode::truncate);
|
||||
if (!file) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto entry = s_registry.Head();
|
||||
while (entry) {
|
||||
auto curentry = entry;
|
||||
if (!RegistryFileWriteEntry(file, curentry)) {
|
||||
break;
|
||||
}
|
||||
entry = entry->Next();
|
||||
if (remove) {
|
||||
s_registry.DeleteNode(curentry);
|
||||
}
|
||||
}
|
||||
|
||||
Blizzard::File::Close(file);
|
||||
}
|
||||
|
||||
void RegistryShutdown() {
|
||||
s_initregistry = false;
|
||||
RegistryFlush(true);
|
||||
}
|
||||
|
||||
void BuildFullKeyName(const char* keyname, const char* valuename, char* buffer, uint32_t buffersize) {
|
||||
char key[STORM_MAX_PATH];
|
||||
auto k = key;
|
||||
auto keyend = (key + sizeof(key)) - 1;
|
||||
while (k < keyend && *keyname) {
|
||||
*k = *keyname == '\\' ? ':' : *keyname;
|
||||
k++;
|
||||
keyname++;
|
||||
}
|
||||
*k = '\0';
|
||||
SStrPrintf(buffer, buffersize, "%s:%s", key, valuename);
|
||||
}
|
||||
|
||||
int32_t InternalLoadEntry(const char* keyname, const char* valuename, uint32_t flags, char* buffer, uint32_t bytes, uint32_t* bytesread) {
|
||||
s_lockregistry.Enter();
|
||||
if (!s_initregistry) {
|
||||
RegistryInit();
|
||||
}
|
||||
|
||||
char fullkeyname[STORM_MAX_PATH];
|
||||
*fullkeyname = '\0';
|
||||
*bytesread = 0;
|
||||
|
||||
BuildFullKeyName(keyname, valuename, fullkeyname, STORM_MAX_PATH);
|
||||
|
||||
for (auto entry = s_registry.Head(); entry; entry = entry->Next()) {
|
||||
if (!SStrCmpI(fullkeyname, entry->name, STORM_MAX_PATH)) {
|
||||
auto valuelength = static_cast<uint32_t>(SStrLen(entry->value));
|
||||
*bytesread = std::min(valuelength, bytes);
|
||||
SStrCopy(buffer, entry->value, bytes);
|
||||
s_lockregistry.Leave();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
s_lockregistry.Leave();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t InternalSaveEntry(const char* keyname, const char* valuename, uint32_t flags, const char* value) {
|
||||
s_lockregistry.Enter();
|
||||
|
||||
if (!s_initregistry) {
|
||||
RegistryInit();
|
||||
}
|
||||
|
||||
char fullkeyname[STORM_MAX_PATH];
|
||||
*fullkeyname = '\0';
|
||||
BuildFullKeyName(keyname, valuename, fullkeyname, STORM_MAX_PATH);
|
||||
|
||||
auto entry = s_registry.Head();
|
||||
while (entry) {
|
||||
if (!SStrCmpI(fullkeyname, entry->name, STORM_MAX_PATH)) {
|
||||
auto curentry = entry;
|
||||
entry = entry->Next();
|
||||
s_registry.DeleteNode(curentry);
|
||||
} else {
|
||||
entry = entry->Next();
|
||||
}
|
||||
}
|
||||
|
||||
entry = s_registry.NewNode(1, 0, 0);
|
||||
if (!entry) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
entry->name = SStrDupA(fullkeyname, __FILE__, __LINE__);
|
||||
entry->value = SStrDupA(value, __FILE__, __LINE__);
|
||||
|
||||
if (flags & STORM_REGISTRY_FLUSH_KEY) {
|
||||
RegistryFlush(false);
|
||||
}
|
||||
|
||||
s_lockregistry.Leave();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SRegLoadString(const char* keyname, const char* valuename, uint32_t flags, char* buffer, uint32_t buffersize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(buffer);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint32_t bytesread;
|
||||
if (!InternalLoadEntry(keyname, valuename, flags, buffer, buffersize, &bytesread)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
buffer[std::min(buffersize - 1, bytesread)] = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SRegLoadValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t* value) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(value);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
char valuestring[11];
|
||||
|
||||
uint32_t datatype;
|
||||
uint32_t bytesread;
|
||||
if (!InternalLoadEntry(keyname, valuename, flags, valuestring, sizeof(valuestring), &bytesread)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*value = SStrToUnsigned(valuestring);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SRegSaveString(const char* keyname, const char* valuename, uint32_t flags, const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (!InternalSaveEntry(keyname, valuename, flags, string)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SRegSaveValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t value) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
char valuestring[11];
|
||||
SStrPrintf(valuestring, sizeof(valuestring), "%u", value);
|
||||
|
||||
if (!InternalSaveEntry(keyname, valuename, flags, valuestring)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void SRegDestroy() {
|
||||
s_lockregistry.Enter();
|
||||
RegistryShutdown();
|
||||
s_lockregistry.Leave();
|
||||
}
|
||||
161
storm/registry/mac/Registry.mm
Normal file
161
storm/registry/mac/Registry.mm
Normal file
|
|
@ -0,0 +1,161 @@
|
|||
#include "storm/Error.hpp"
|
||||
#include "storm/String.hpp"
|
||||
#include "storm/registry/Registry.hpp"
|
||||
#include "storm/registry/mac/Static.hpp"
|
||||
#include <cstring>
|
||||
|
||||
const char* NextComponent(const char* path, char* component, size_t size) {
|
||||
auto sep = SStrChrR(path, '\\');
|
||||
if (!sep) {
|
||||
return path + SStrCopy(component, path, size);
|
||||
} else {
|
||||
SStrNCopy(component, path, sep - path, size);
|
||||
return sep + 1;
|
||||
}
|
||||
}
|
||||
|
||||
bool GetDefaultsAndKeyPath(const char* key, const char* name, uint32_t flags, NSUserDefaults** defaults, char* path, size_t size) {
|
||||
STORM_ASSERT(key);
|
||||
STORM_ASSERT(*key);
|
||||
|
||||
id nextcomponent = NextComponent(key, path, size);
|
||||
|
||||
id prefix = @"com.blizzard";
|
||||
if ((flags & STORM_REGISTRY_BATTLENET)) {
|
||||
prefix = @"net.battle";
|
||||
}
|
||||
NSString* domain;
|
||||
if (!size || *path) {
|
||||
domain = [NSString stringWithFormat: @"%@.%s", prefix, path];
|
||||
} else {
|
||||
domain = prefix;
|
||||
}
|
||||
|
||||
id sregstatic = SRegStatic::Get();
|
||||
id hive = sregstatic->hives[domain];
|
||||
*defaults = hive;
|
||||
|
||||
if (hive == nullptr) {
|
||||
auto bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
|
||||
if ([bundleIdentifier isEqualToString: domain]) {
|
||||
hive = [NSUserDefaults standardUserDefaults];
|
||||
} else {
|
||||
hive = [[NSUserDefaults alloc] initWithSuiteName:domain];
|
||||
}
|
||||
*defaults = hive;
|
||||
sregstatic->hives[domain] = hive;
|
||||
}
|
||||
|
||||
int32_t length;
|
||||
|
||||
if (name && *name) {
|
||||
if (key && *key) {
|
||||
length = SStrPrintf(path, size, "%s/%s", key, name);
|
||||
} else {
|
||||
length = SStrCopy(path, name, size);
|
||||
}
|
||||
} else {
|
||||
length = SStrCopy(path, key, size);
|
||||
}
|
||||
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(length < size);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
for (id sep = path; ; *sep = '/') {
|
||||
sep = SStrChr(sep, '\\');
|
||||
if (!sep) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
NSObject* GetObject(const char* keyname, const char* valuename, uint32_t flags) {
|
||||
NSUserDefaults* defaults;
|
||||
char path[STORM_MAX_PATH];
|
||||
if (!GetDefaultsAndKeyPath(keyname, valuename, flags, &defaults, path, STORM_MAX_PATH)) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
id string = [NSString stringWithUTF8String: path];
|
||||
return [defaults objectForKey: string];
|
||||
}
|
||||
|
||||
bool SetObject(const char* key, const char* name, uint32_t flags, NSObject* object) {
|
||||
NSUserDefaults* defaults
|
||||
char path[STORM_MAX_PATH];
|
||||
if (!GetDefaultsAndKeyPath(keyname, valuename, flags, &defaults, path, STORM_MAX_PATH)) {
|
||||
return false;
|
||||
}
|
||||
id string = [NSString stringWithUTF8String:path];
|
||||
[defaults setObject:object forKey:string];
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t SRegLoadString(const char* keyname, const char* valuename, uint32_t flags, char* buffer, uint32_t buffersize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(buffer);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
@autoreleasepool {
|
||||
id string = GetObject(keyname, valuename, flags);
|
||||
if ([string isKindOfClass:[NSString class]) {
|
||||
return [string getCString buffer:buffer maxLength:buffersize encoding:NSUTF8StringEncoding];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SRegLoadValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t* value) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(value);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
@autoreleasepool {
|
||||
id num = GetObject(keyname, valuename, flags);
|
||||
if ([num isKindOfClass:[NSNumber class]) {
|
||||
*value = [num unsignedIntValue];
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SRegSaveString(const char* keyname, const char* valuename, uint32_t flags, const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
@autoreleasepool {
|
||||
return SetObject(keyname, valuename, flags, [NSString stringWithUTF8String:value]);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SRegSaveValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t value) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
@autoreleasepool {
|
||||
return SetObject(keyname, valuename, flags, [NSNumber numberWithUnsignedInt:value]);
|
||||
}
|
||||
}
|
||||
21
storm/registry/mac/Static.hpp
Normal file
21
storm/registry/mac/Static.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef STORM_REGISTRY_MAC_STATIC_HPP
|
||||
#define STORM_REGISTRY_MAC_STATIC_HPP
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
class SRegStatic {
|
||||
public:
|
||||
NSMutableDictionary<NSString*, NSUserDefaults*>* hives;
|
||||
|
||||
static SRegStatic Get();
|
||||
|
||||
SRegStatic() {
|
||||
this->hives = [NSMutableDictionary init];
|
||||
}
|
||||
|
||||
~SRegStatic() {
|
||||
this->hives = nil;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
14
storm/registry/mac/Static.mm
Normal file
14
storm/registry/mac/Static.mm
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include "storm/registry/mac/Static.hpp"
|
||||
|
||||
static SRegStatic* SRegStatic::Get() {
|
||||
static SRegStatic sregstatic;
|
||||
return &sregstatic;
|
||||
}
|
||||
|
||||
SRegStatic::SRegStatic() {
|
||||
this->hives = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
|
||||
SRegStatic::~SRegStatic() {
|
||||
this->hives = nil;
|
||||
}
|
||||
225
storm/registry/win/Registry.cpp
Normal file
225
storm/registry/win/Registry.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
|
||||
#include "storm/registry/Registry.hpp"
|
||||
#include "storm/Error.hpp"
|
||||
#include "storm/String.hpp"
|
||||
#include "storm/Unicode.hpp"
|
||||
#include "storm/option/Options.hpp"
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <windows.h>
|
||||
|
||||
int32_t ILoadValue(HKEY parentKey, const char* subKeyName, const char* valuename, uint32_t* datatype, uint8_t* buffer, uint32_t bytes, uint32_t* bytesread) {
|
||||
int32_t result;
|
||||
uint16_t wname[STORM_MAX_PATH];
|
||||
HKEY key;
|
||||
|
||||
if (g_opt.sregunicode) {
|
||||
SUniConvertUTF8to16(wname, STORM_MAX_PATH, reinterpret_cast<const uint8_t*>(subKeyName), STORM_MAX_STR, nullptr, nullptr);
|
||||
result = RegOpenKeyExW(parentKey, reinterpret_cast<LPWSTR>(wname), 0, KEY_EXECUTE, &key);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
*bytesread = bytes;
|
||||
SUniConvertUTF8to16(wname, STORM_MAX_PATH, reinterpret_cast<const uint8_t*>(valuename), STORM_MAX_STR, nullptr, nullptr);
|
||||
auto value = RegQueryValueExW(key, reinterpret_cast<LPWSTR>(wname), nullptr, reinterpret_cast<LPDWORD>(datatype), reinterpret_cast<LPBYTE>(buffer), reinterpret_cast<LPDWORD>(bytesread));
|
||||
RegCloseKey(key);
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
result = RegOpenKeyExA(parentKey, reinterpret_cast<LPCSTR>(subKeyName), 0, KEY_EXECUTE, &key);
|
||||
if (result == ERROR_SUCCESS) {
|
||||
*bytesread = bytes;
|
||||
auto value = RegQueryValueExA(key, reinterpret_cast<LPCSTR>(valuename), nullptr, reinterpret_cast<LPDWORD>(datatype), reinterpret_cast<LPBYTE>(buffer), reinterpret_cast<LPDWORD>(bytesread));
|
||||
RegCloseKey(key);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int32_t SRegGetBaseKey(uint8_t flags, char* buffer, uint32_t buffersize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(buffer);
|
||||
STORM_VALIDATE(buffersize);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (flags & STORM_REGISTRY_BATTLENET) {
|
||||
SStrCopy(buffer, "Software\\Battle.net\\", STORM_MAX_PATH);
|
||||
} else {
|
||||
SStrCopy(buffer, "Software\\Blizzard Entertainment\\", STORM_MAX_PATH);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BuildFullKeyName(const char* keyname, uint8_t flags, char* buffer, uint32_t buffersize) {
|
||||
*buffer = '\0';
|
||||
if (!(flags & STORM_REGISTRY_NO_BASE_KEY)) {
|
||||
SRegGetBaseKey(flags, buffer, buffersize);
|
||||
}
|
||||
SStrPack(buffer, keyname, buffersize);
|
||||
}
|
||||
|
||||
int32_t InternalLoadEntry(const char* keyname, const char* valuename, uint32_t flags, uint32_t* datatype, uint8_t* buffer, uint32_t bytes, uint32_t* bytesread) {
|
||||
char fullkeyname[STORM_MAX_PATH];
|
||||
*fullkeyname = '\0';
|
||||
*bytesread = 0;
|
||||
*datatype = 0;
|
||||
|
||||
BuildFullKeyName(keyname, flags, fullkeyname, STORM_MAX_PATH);
|
||||
|
||||
auto result = ILoadValue(flags & STORM_REGISTRY_CURRENT_USER_ONLY ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, fullkeyname, valuename, datatype, buffer, bytes, bytesread);
|
||||
if (result) {
|
||||
SetLastError(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t InternalSaveEntry(const char* keyname, const char* valuename, uint32_t flags, uint32_t datatype, const uint8_t* buffer, uint32_t bytes) {
|
||||
char fullkeyname[STORM_MAX_PATH];
|
||||
*fullkeyname = '\0';
|
||||
BuildFullKeyName(keyname, flags, fullkeyname, STORM_MAX_PATH);
|
||||
|
||||
HKEY key;
|
||||
DWORD disposition;
|
||||
int32_t result;
|
||||
uint16_t wname[STORM_MAX_PATH] = {0};
|
||||
|
||||
if (g_opt.sregunicode) {
|
||||
SUniConvertUTF8to16(wname, STORM_MAX_PATH, reinterpret_cast<const uint8_t*>(fullkeyname), STORM_MAX_STR, nullptr, nullptr);
|
||||
result = RegCreateKeyExW(flags & STORM_REGISTRY_CURRENT_USER_ONLY ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, reinterpret_cast<LPCWSTR>(wname), 0, nullptr, 0, KEY_WRITE, nullptr, &key, &disposition);
|
||||
} else {
|
||||
result = RegCreateKeyExA(flags & STORM_REGISTRY_CURRENT_USER_ONLY ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE, reinterpret_cast<LPCSTR>(fullkeyname), 0, nullptr, 0, KEY_WRITE, nullptr, &key, &disposition);
|
||||
}
|
||||
|
||||
if (result) {
|
||||
SetLastError(result);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (g_opt.sregunicode) {
|
||||
SUniConvertUTF8to16(wname, STORM_MAX_PATH, reinterpret_cast<const uint8_t*>(valuename), STORM_MAX_STR, nullptr, nullptr);
|
||||
result = RegSetValueExW(key, reinterpret_cast<LPCWSTR>(wname), 0, datatype, reinterpret_cast<const BYTE*>(buffer), bytes);
|
||||
} else {
|
||||
result = RegSetValueExA(key, reinterpret_cast<LPCSTR>(valuename), 0, datatype, reinterpret_cast<const BYTE*>(buffer), bytes);
|
||||
}
|
||||
if (!result && (flags & STORM_REGISTRY_FLUSH_KEY) != 0) {
|
||||
result = RegFlushKey(key);
|
||||
}
|
||||
|
||||
RegCloseKey(key);
|
||||
if (result) {
|
||||
SetLastError(result);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SRegLoadString(const char* keyname, const char* valuename, uint32_t flags, char* buffer, uint32_t buffersize) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(buffer);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint32_t datatype;
|
||||
uint16_t widecharstr[4096];
|
||||
uint32_t bytesread;
|
||||
|
||||
if (g_opt.sregunicode) {
|
||||
if (!InternalLoadEntry(keyname, valuename, flags, &datatype, reinterpret_cast<uint8_t*>(&widecharstr), sizeof(widecharstr), &bytesread)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (datatype == REG_SZ) {
|
||||
uint32_t dstchars;
|
||||
SUniConvertUTF16to8(reinterpret_cast<uint8_t*>(buffer), buffersize, widecharstr, bytesread / 2, &dstchars, nullptr);
|
||||
buffer[std::min(buffersize - 1, dstchars)] = '\0';
|
||||
return 1;
|
||||
} else if (datatype == REG_DWORD) {
|
||||
SStrPrintf(buffer, buffersize, "%u", (reinterpret_cast<uint32_t*>(widecharstr))[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
if (!InternalLoadEntry(keyname, valuename, flags, &datatype, reinterpret_cast<uint8_t*>(buffer), buffersize, &bytesread)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (datatype == REG_SZ) {
|
||||
buffer[std::min(buffersize - 1, bytesread)] = '\0';
|
||||
return 1;
|
||||
} else if (datatype == REG_DWORD) {
|
||||
SStrPrintf(buffer, buffersize, "%u", (reinterpret_cast<uint32_t*>(buffer))[0]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t SRegLoadValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t* value) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(value);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
uint8_t buffer[256];
|
||||
uint32_t bytesread;
|
||||
uint32_t datatype;
|
||||
if (!InternalLoadEntry(keyname, valuename, flags, &datatype, buffer, sizeof(buffer), &bytesread)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (datatype == REG_SZ) {
|
||||
*value = strtoul(reinterpret_cast<char*>(buffer), 0, 0);
|
||||
} else if (datatype == REG_DWORD) {
|
||||
*value = *reinterpret_cast<uint32_t*>(buffer);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int32_t SRegSaveString(const char* keyname, const char* valuename, uint32_t flags, const char* string) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE(string);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
if (g_opt.sregunicode) {
|
||||
uint16_t widecharstr[STORM_MAX_PATH];
|
||||
SUniConvertUTF8to16(widecharstr, STORM_MAX_PATH, reinterpret_cast<const uint8_t*>(string), STORM_MAX_STR, nullptr, nullptr);
|
||||
// ersatz wcslen()
|
||||
uint32_t length;
|
||||
auto p = widecharstr;
|
||||
while (*p) {
|
||||
++p;
|
||||
}
|
||||
length = p - widecharstr;
|
||||
return InternalSaveEntry(keyname, valuename, flags, REG_SZ, reinterpret_cast<const uint8_t*>(widecharstr), (length + 1) * 2);
|
||||
} else {
|
||||
return InternalSaveEntry(keyname, valuename, flags, REG_SZ, reinterpret_cast<const uint8_t*>(string), SStrLen(string) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SRegSaveValue(const char* keyname, const char* valuename, uint32_t flags, uint32_t value) {
|
||||
STORM_VALIDATE_BEGIN;
|
||||
STORM_VALIDATE(keyname);
|
||||
STORM_VALIDATE(*keyname);
|
||||
STORM_VALIDATE(valuename);
|
||||
STORM_VALIDATE(*valuename);
|
||||
STORM_VALIDATE_END;
|
||||
|
||||
return InternalSaveEntry(keyname, valuename, flags, REG_DWORD, reinterpret_cast<const uint8_t*>(&value), 4);
|
||||
}
|
||||
|
||||
void SRegDestroy() {
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue