From 25105c0a75ba1d2a6e8486525744c3a57180157b Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 04:44:58 +0000 Subject: [PATCH 01/10] Use spaces instead of tabs and fix EOL whitespace --- configure.ac | 14 +- source_dist.sh | 6 +- src/bncsutil/bsha1.cpp | 156 +++---- src/bncsutil/bsha1.h | 2 +- src/bncsutil/cdkeydecoder.cpp | 236 +++++----- src/bncsutil/cdkeydecoder.h | 24 +- src/bncsutil/checkrevision.cpp | 766 +++++++++++++++---------------- src/bncsutil/checkrevision.h | 14 +- src/bncsutil/debug.c | 378 ++++++++-------- src/bncsutil/debug.h | 16 +- src/bncsutil/decodekey.cpp | 498 ++++++++++---------- src/bncsutil/decodekey.h | 8 +- src/bncsutil/file.cpp | 440 +++++++++--------- src/bncsutil/file.h | 6 +- src/bncsutil/keytables.h | 2 +- src/bncsutil/libinfo.cpp | 7 +- src/bncsutil/mutil.h | 24 +- src/bncsutil/nls.c | 474 +++++++++---------- src/bncsutil/nls.h | 280 ++++++------ src/bncsutil/oldauth.cpp | 16 +- src/bncsutil/oldauth.h | 2 +- src/bncsutil/pe.c | 806 ++++++++++++++++----------------- src/bncsutil/pe.h | 206 ++++----- src/bncsutil/sha1.h | 2 +- src/bncsutil/stack.c | 117 ++--- src/bncsutil/stack.h | 12 +- tests/checkrevision.c | 136 +++--- tests/nls.cpp | 44 +- vc8_build/BNCSutil.sln | 26 +- vc8_build/BNCSutil.vcproj | 802 ++++++++++++++++---------------- vc8_build/bncsutil.def | 96 ++-- 31 files changed, 2808 insertions(+), 2808 deletions(-) diff --git a/configure.ac b/configure.ac index eee56f2..15c9c51 100644 --- a/configure.ac +++ b/configure.ac @@ -21,23 +21,23 @@ AC_TRY_RUN([ #include int main() { - uint16_t s = 1; - uint16_t* ptr = &s; - uint8_t n = *((uint8_t*)ptr); - return n; + uint16_t s = 1; + uint16_t* ptr = &s; + uint8_t n = *((uint8_t*)ptr); + return n; } ] , AC_DEFINE([BIGENDIAN], [1], [Define to 1 if system is big endian]) [echo "big"] , AC_DEFINE([LITTLEENDIAN], [1], [Define to 1 if system is little endian]) - [echo "little"] + [echo "little"] ) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_FILES([ - Makefile - src/Makefile + Makefile + src/Makefile ]) AC_OUTPUT diff --git a/source_dist.sh b/source_dist.sh index 4ad32a8..f2ad313 100644 --- a/source_dist.sh +++ b/source_dist.sh @@ -7,10 +7,10 @@ rm -fr $PKGDIR mkdir $PKGDIR for b in config configure doc product_version src support tests vb6_example \ - vc7_build vc8_build windows_dist.bat source_dist.sh windows_dist.sh \ - README-Windows.txt + vc7_build vc8_build windows_dist.bat source_dist.sh windows_dist.sh \ + README-Windows.txt do - cp -R $SCRIPT_PATH/$b $PKGDIR + cp -R $SCRIPT_PATH/$b $PKGDIR done rm -f $PKGDIR.tar.bz2 diff --git a/src/bncsutil/bsha1.cpp b/src/bncsutil/bsha1.cpp index 6e5aa6b..6232f61 100644 --- a/src/bncsutil/bsha1.cpp +++ b/src/bncsutil/bsha1.cpp @@ -27,7 +27,7 @@ #include #include -#define USE_NEW_BSHA1 0 +#define USE_NEW_BSHA1 0 #define BSHA_IC1 0x67452301lu #define BSHA_IC2 0xEFCDAB89lu @@ -41,10 +41,10 @@ #define BSHA_OC4 0x359D3E2Alu #if !USE_NEW_BSHA1 -# define BSHA_COP e = d; d = c; c = ROL(b, 30); b = a; a = g; +# define BSHA_COP e = d; d = c; c = ROL(b, 30); b = a; a = g; #else -# define BSHA_N_COP t[4] = t[3]; t[3] = t[2]; t[2] = ROL(t[1], 30); \ - t[1] = t[0]; t[0] = x +# define BSHA_N_COP t[4] = t[3]; t[3] = t[2]; t[2] = ROL(t[1], 30); \ + t[1] = t[0]; t[0] = x #endif #if !USE_NEW_BSHA1 @@ -60,81 +60,81 @@ #else #define BSHA_N_OP1() x = LSB4(*p++) + ROL(t[0], 5) + t[4] + \ - ((t[1] & t[2]) | (~t[1] & t[3])) + BSHA_OC1; BSHA_N_COP + ((t[1] & t[2]) | (~t[1] & t[3])) + BSHA_OC1; BSHA_N_COP #define BSHA_N_OP2() x = (t[3] ^ t[2] ^ t[1]) + t[4] + ROL(x, 5) + \ - LSB4(*p++) + BSHA_OC2; BSHA_N_COP + LSB4(*p++) + BSHA_OC2; BSHA_N_COP #define BSHA_N_OP3() x = LSB4(*p++) + ROL(x, 5) + t[4] + \ - ((t[2] & t[1]) | (t[3] & t[2]) | (t[3] & t[1])) - BSHA_OC3; BSHA_N_COP + ((t[2] & t[1]) | (t[3] & t[2]) | (t[3] & t[1])) - BSHA_OC3; BSHA_N_COP #define BSHA_N_OP4() x = (t[3] ^ t[2] ^ t[1]) + t[4] + ROL(x, 5) + \ - LSB4(*p++) - BSHA_OC4; BSHA_N_COP + LSB4(*p++) - BSHA_OC4; BSHA_N_COP #endif #if USE_NEW_BSHA1 MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) { - uint32_t vals[5]; - uint32_t t[5]; // a, b, c, d, e - uint32_t buf[0x50]; - uint32_t* p; - uint32_t x; - const char* in = input; - unsigned int i, j; - unsigned int sub_length; - - /* Initializer Values */ - p = vals; - *p++ = BSHA_IC1; - *p++ = BSHA_IC2; - *p++ = BSHA_IC3; - *p++ = BSHA_IC4; - *p++ = BSHA_IC5; - - memset(buf, 0, 320); // zero buf - - /* Process input in chunks. */ - for (i = 0; i < length; i += 0x40) { - sub_length = length - i; - - /* Maximum chunk size is 0x40 (64) bytes. */ - if (sub_length > 0x40) - sub_length = 0x40; - - memcpy(buf, in, sub_length); - in += sub_length; - - /* If necessary, pad with zeroes to 64 bytes. */ - if (sub_length < 0x40) - memset(buf + sub_length, 0, 0x40 - sub_length); - - for (j = 0; j < 64; j++) { - buf[j + 16] = - LSB4(ROL(1, LSB4(buf[j] ^ buf[j+8] ^ buf[j+2] ^ buf[j+13]) % 32)); - } - - memcpy(t, vals, 20); - p = buf; - - /* It's a kind of magic. */ - BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); - BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); - - BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); - BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); - - BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); - BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); - - BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); - BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); - - vals[0] += t[0]; - vals[1] += t[1]; - vals[2] += t[2]; - vals[3] += t[3]; - vals[4] += t[4]; - } - - /* Return result. */ - memcpy(result, vals, 20); + uint32_t vals[5]; + uint32_t t[5]; // a, b, c, d, e + uint32_t buf[0x50]; + uint32_t* p; + uint32_t x; + const char* in = input; + unsigned int i, j; + unsigned int sub_length; + + /* Initializer Values */ + p = vals; + *p++ = BSHA_IC1; + *p++ = BSHA_IC2; + *p++ = BSHA_IC3; + *p++ = BSHA_IC4; + *p++ = BSHA_IC5; + + memset(buf, 0, 320); // zero buf + + /* Process input in chunks. */ + for (i = 0; i < length; i += 0x40) { + sub_length = length - i; + + /* Maximum chunk size is 0x40 (64) bytes. */ + if (sub_length > 0x40) + sub_length = 0x40; + + memcpy(buf, in, sub_length); + in += sub_length; + + /* If necessary, pad with zeroes to 64 bytes. */ + if (sub_length < 0x40) + memset(buf + sub_length, 0, 0x40 - sub_length); + + for (j = 0; j < 64; j++) { + buf[j + 16] = + LSB4(ROL(1, LSB4(buf[j] ^ buf[j+8] ^ buf[j+2] ^ buf[j+13]) % 32)); + } + + memcpy(t, vals, 20); + p = buf; + + /* It's a kind of magic. */ + BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); + BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); + + BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); + BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); + + BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); + BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); + + BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); + BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); + + vals[0] += t[0]; + vals[1] += t[1]; + vals[2] += t[2]; + vals[3] += t[3]; + vals[4] += t[4]; + } + + /* Return result. */ + memcpy(result, vals, 20); } #else @@ -142,26 +142,26 @@ MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) { MEXP(void) calcHashBuf(const char* input, size_t length, char* result) { int i; unsigned long a, b, c, d, e, g; - uint32_t* ldata; + uint32_t* ldata; char data[1024]; memset(data, 0, 1024); memcpy(data, input, length); ldata = (uint32_t*) data; - + for (i = 0; i < 64; i++) { ldata[i + 16] = LSB4(ROL(1, LSB4(ldata[i] ^ ldata[i+8] ^ ldata[i+2] ^ ldata[i+13]) % 32)); } - - //dumpbuf(data, 1024); - + + //dumpbuf(data, 1024); + a = BSHA_IC1; b = BSHA_IC2; c = BSHA_IC3; d = BSHA_IC4; e = BSHA_IC5; g = 0; - + // Loops unrolled. BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) diff --git a/src/bncsutil/bsha1.h b/src/bncsutil/bsha1.h index 6283c2e..71fb980 100644 --- a/src/bncsutil/bsha1.h +++ b/src/bncsutil/bsha1.h @@ -41,7 +41,7 @@ extern "C" { * hash: Buffer, at least 20 bytes in length, to receive the hash. */ MEXP(void) calcHashBuf(const char* data, size_t length, char* hash); - + /* * New implementation. Broken. No plans to fix. */ diff --git a/src/bncsutil/cdkeydecoder.cpp b/src/bncsutil/cdkeydecoder.cpp index 41c233e..4b3e97f 100644 --- a/src/bncsutil/cdkeydecoder.cpp +++ b/src/bncsutil/cdkeydecoder.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include #include #include // w2/d2 and w3 tables @@ -63,13 +63,13 @@ CDKeyDecoder::CDKeyDecoder() { initialized = 0; keyOK = 0; hashLen = 0; - cdkey = (char*) 0; - w3value2 = (char*) 0; - keyHash = (char*) 0; + cdkey = (char*) 0; + w3value2 = (char*) 0; + keyHash = (char*) 0; } CDKeyDecoder::CDKeyDecoder(const char* cd_key) { - CDKeyDecoder(cd_key, std::strlen(cd_key)); + CDKeyDecoder(cd_key, std::strlen(cd_key)); } /** @@ -80,19 +80,19 @@ CDKeyDecoder::CDKeyDecoder(const char* cd_key) { */ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { unsigned int i; - + initialized = 0; - product = 0; - value1 = 0; - value2 = 0; + product = 0; + value1 = 0; + value2 = 0; keyOK = 0; hashLen = 0; - cdkey = (char*) 0; - w3value2 = (char*) 0; - keyHash = (char*) 0; - + cdkey = (char*) 0; + w3value2 = (char*) 0; + keyHash = (char*) 0; + if (keyLength <= 0) return; - + // Initial sanity check if (keyLength == 13) { // StarCraft key @@ -101,9 +101,9 @@ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { } keyType = KEY_STARCRAFT; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with STAR key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with STAR key %s.", cdKey + ); #endif } else { // D2/W2/W3 key @@ -114,54 +114,54 @@ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { case 16: keyType = KEY_WARCRAFT2; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with W2/D2 key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with W2/D2 key %s.", cdKey + ); #endif break; case 26: keyType = KEY_WARCRAFT3; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with WAR3 key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with WAR3 key %s.", cdKey + ); #endif break; default: #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with unrecognized key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with unrecognized key %s.", cdKey + ); #endif return; } } - + cdkey = new char[keyLength + 1]; initialized = 1; keyLen = keyLength; strcpy(cdkey, cdKey); - + switch (keyType) { case KEY_STARCRAFT: keyOK = processStarCraftKey(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " - "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " + "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); #endif break; case KEY_WARCRAFT2: keyOK = processWarCraft2Key(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " - "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " + "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); #endif break; case KEY_WARCRAFT3: keyOK = processWarCraft3Key(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ", - cdkey, keyOK, getProduct(), getVal1()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ", + cdkey, keyOK, getProduct(), getVal1()); #endif break; default: @@ -174,8 +174,8 @@ CDKeyDecoder::~CDKeyDecoder() { delete [] cdkey; if (hashLen > 0 && keyHash != NULL) delete [] keyHash; - if (w3value2) - delete [] w3value2; + if (w3value2) + delete [] w3value2; } int CDKeyDecoder::isKeyValid() { @@ -187,27 +187,27 @@ int CDKeyDecoder::getVal2Length() { } uint32_t CDKeyDecoder::getProduct() { - switch (keyType) { - case KEY_STARCRAFT: - case KEY_WARCRAFT2: - return (uint32_t) LSB4(product); - case KEY_WARCRAFT3: - return (uint32_t) MSB4(product); - default: - return (uint32_t) -1; - } + switch (keyType) { + case KEY_STARCRAFT: + case KEY_WARCRAFT2: + return (uint32_t) LSB4(product); + case KEY_WARCRAFT3: + return (uint32_t) MSB4(product); + default: + return (uint32_t) -1; + } } uint32_t CDKeyDecoder::getVal1() { switch (keyType) { - case KEY_STARCRAFT: - case KEY_WARCRAFT2: - return (uint32_t) LSB4(value1); - case KEY_WARCRAFT3: - return (uint32_t) MSB4(value1); - default: - return (uint32_t) -1; - } + case KEY_STARCRAFT: + case KEY_WARCRAFT2: + return (uint32_t) LSB4(value1); + case KEY_WARCRAFT3: + return (uint32_t) MSB4(value1); + default: + return (uint32_t) -1; + } } uint32_t CDKeyDecoder::getVal2() { @@ -239,35 +239,35 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, { struct CDKEYHASH kh; SHA1Context sha; - + if (!initialized || !keyOK) return 0; hashLen = 0; - + kh.clientToken = clientToken; kh.serverToken = serverToken; - + switch (keyType) { case KEY_STARCRAFT: case KEY_WARCRAFT2: - kh.product = (uint32_t) LSB4(product); - kh.value1 = (uint32_t) LSB4(value1); + kh.product = (uint32_t) LSB4(product); + kh.value1 = (uint32_t) LSB4(value1); kh.value2.s.zero = 0; kh.value2.s.v = (uint32_t) LSB4(value2); - + keyHash = new char[20]; calcHashBuf((char*) &kh, 24, keyHash); hashLen = 20; #if DEBUG - bncsutil_debug_message_a("%s: Hash calculated.", cdkey); - bncsutil_debug_dump(keyHash, 20); + bncsutil_debug_message_a("%s: Hash calculated.", cdkey); + bncsutil_debug_dump(keyHash, 20); #endif return 20; case KEY_WARCRAFT3: - kh.product = (uint32_t) MSB4(product); - kh.value1 = (uint32_t) MSB4(value1); + kh.product = (uint32_t) MSB4(product); + kh.value1 = (uint32_t) MSB4(value1); memcpy(kh.value2.l.v, w3value2, 10); if (SHA1Reset(&sha)) @@ -281,10 +281,10 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, } SHA1Reset(&sha); hashLen = 20; - + #if DEBUG - bncsutil_debug_message_a("%s: Hash calculated.", cdkey); - bncsutil_debug_dump(keyHash, 20); + bncsutil_debug_message_a("%s: Hash calculated.", cdkey); + bncsutil_debug_dump(keyHash, 20); #endif return 20; @@ -300,7 +300,7 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, */ size_t CDKeyDecoder::getHash(char* outputBuffer) { if (hashLen == 0 || !keyHash || !outputBuffer) - return 0; + return 0; memcpy(outputBuffer, keyHash, hashLen); return hashLen; } @@ -318,21 +318,21 @@ int CDKeyDecoder::processStarCraftKey() { int accum, pos, i; char temp; int hashKey = 0x13AC9741; - char cdkey[14]; + char cdkey[14]; + + std::strcpy(cdkey, this->cdkey); - std::strcpy(cdkey, this->cdkey); - // Verification accum = 3; for (i = 0; i < (int) (keyLen - 1); i++) { accum += ((tolower(cdkey[i]) - '0') ^ (accum * 2)); } - - if ((accum % 10) != (cdkey[12] - '0')) { - bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey); + + if ((accum % 10) != (cdkey[12] - '0')) { + bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey); return 0; - } - + } + // Shuffling pos = 0x0B; for (i = 0xC2; i >= 7; i -= 0x11) { @@ -341,7 +341,7 @@ int CDKeyDecoder::processStarCraftKey() { cdkey[i % 0x0C] = temp; pos--; } - + // Final Value for (i = (int) (keyLen - 2); i >= 0; i--) { temp = toupper(cdkey[i]); @@ -353,10 +353,10 @@ int CDKeyDecoder::processStarCraftKey() { cdkey[i] ^= ((char) i & 1); } } - + // Final Calculations sscanf(cdkey, "%2ld%7ld%3ld", &product, &value1, &value2); - + return 1; } @@ -364,10 +364,10 @@ int CDKeyDecoder::processWarCraft2Key() { unsigned long r, n, n2, v, v2, checksum; int i; unsigned char c1, c2, c; - char cdkey[17]; + char cdkey[17]; + + std::strcpy(cdkey, this->cdkey); - std::strcpy(cdkey, this->cdkey); - r = 1; checksum = 0; for (i = 0; i < 16; i += 2) { @@ -375,7 +375,7 @@ int CDKeyDecoder::processWarCraft2Key() { n = c1 * 3; c2 = w2Map[(int) cdkey[i + 1]]; n = c2 + n * 8; - + if (n >= 0x100) { n -= 0x100; checksum |= r; @@ -387,7 +387,7 @@ int CDKeyDecoder::processWarCraft2Key() { cdkey[i + 1] = getHexValue(n); r <<= 1; } - + v = 3; for (i = 0; i < 16; i++) { c = cdkey[i]; @@ -397,11 +397,11 @@ int CDKeyDecoder::processWarCraft2Key() { v += n; } v &= 0xFF; - + if (v != checksum) { return 0; } - + n = 0; for (int j = 15; j >= 0; j--) { c = cdkey[j]; @@ -441,13 +441,13 @@ int CDKeyDecoder::processWarCraft3Key() { int a, b; int i; char decode; - + a = 0; b = 0x21; - + memset(table, 0, W3_BUFLEN); memset(values, 0, (sizeof(int) * 4)); - + for (i = 0; ((unsigned int) i) < keyLen; i++) { cdkey[i] = toupper(cdkey[i]); a = (b + 0x07B5) % W3_BUFLEN; @@ -456,40 +456,40 @@ int CDKeyDecoder::processWarCraft3Key() { table[a] = (decode / 5); table[b] = (decode % 5); } - + // Mult i = W3_BUFLEN; do { mult(4, 5, values + 3, table[i - 1]); } while (--i); - + decodeKeyTable(values); - - // 00 00 38 08 f0 64 18 6c 79 14 14 8E B9 49 1D BB - // -------- - // val1 - product = values[0] >> 0xA; - product = SWAP4(product); + // 00 00 38 08 f0 64 18 6c 79 14 14 8E B9 49 1D BB + // -------- + // val1 + + product = values[0] >> 0xA; + product = SWAP4(product); #if LITTLEENDIAN - for (i = 0; i < 4; i++) { - values[i] = MSB4(values[i]); - } + for (i = 0; i < 4; i++) { + values[i] = MSB4(values[i]); + } #endif - value1 = LSB4(*(uint32_t*) (((char*) values) + 2)) & 0xFFFFFF03; + value1 = LSB4(*(uint32_t*) (((char*) values) + 2)) & 0xFFFFFF03; - w3value2 = new char[10]; + w3value2 = new char[10]; #if LITTLEENDIAN - *((uint16_t*) w3value2) = MSB2(*(uint16_t*) (((char*) values) + 6)); - *((uint32_t*) ((char*) w3value2 + 2)) = MSB4(*(uint32_t*) (((char*) values) + 8)); - *((uint32_t*) ((char*) w3value2 + 6)) = MSB4(*(uint32_t*) (((char*) values) + 12)); + *((uint16_t*) w3value2) = MSB2(*(uint16_t*) (((char*) values) + 6)); + *((uint32_t*) ((char*) w3value2 + 2)) = MSB4(*(uint32_t*) (((char*) values) + 8)); + *((uint32_t*) ((char*) w3value2 + 6)) = MSB4(*(uint32_t*) (((char*) values) + 12)); #else - *((uint16_t*) w3value2) = LSB2(*(uint16_t*) (((char*) values) + 6)); - *((uint32_t*) ((char*) w3value2 + 2)) = LSB4(*(uint32_t*) (((char*) values) + 8)); - *((uint32_t*) ((char*) w3value2 + 6)) = LSB4(*(uint32_t*) (((char*) values) + 12)); + *((uint16_t*) w3value2) = LSB2(*(uint16_t*) (((char*) values) + 6)); + *((uint32_t*) ((char*) w3value2 + 2)) = LSB4(*(uint32_t*) (((char*) values) + 8)); + *((uint32_t*) ((char*) w3value2 + 6)) = LSB4(*(uint32_t*) (((char*) values) + 12)); #endif - return 1; + return 1; } inline void CDKeyDecoder::mult(int r, const int x, int* a, int dcByte) { @@ -510,7 +510,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { int ckt_temp; var8 = 29; int i = 464; - + // pass 1 do { int j; @@ -520,7 +520,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = keyTable[3 - var4]; varC &= (0xF << esi); varC = varC >> esi; - + if (i < 464) { for (j = 29; (unsigned int) j > var8; j--) { /* @@ -536,7 +536,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = w3TranslateMap[ebp ^ w3TranslateMap[varC + i] + i]; } } - + j = --var8; while (j >= 0) { ecx = (j & 7) << 2; @@ -547,12 +547,12 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = w3TranslateMap[ebp ^ w3TranslateMap[varC + i] + i]; j--; } - + j = 3 - var4; ebx = (w3TranslateMap[varC + i] & 0xF) << esi; keyTable[j] = (ebx | ~(0xF << esi) & ((int) keyTable[j])); } while ((i -= 16) >= 0); - + // pass 2 eax = 0; edx = 0; @@ -560,26 +560,26 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { edi = 0; esi = 0; ebp = 0; - + for (i = 0; i < 4; i++) { copy[i] = LSB4(keyTable[i]); } scopy = (unsigned char*) copy; - + for (edi = 0; edi < 120; edi++) { unsigned int location = 12; eax = edi & 0x1F; ecx = esi & 0x1F; edx = 3 - (edi >> 5); - + location -= ((esi >> 5) << 2); ebp = *(int*) (scopy + location); ebp = LSB4(ebp); - + //ebp = (ebp & (1 << ecx)) >> ecx; ebp &= (1 << ecx); ebp = ebp >> ecx; - + //keyTable[edx] = ((ebp & 1) << eax) | (~(1 << eax) & keyTable[edx]); ckt = (keyTable + edx); ckt_temp = *ckt; diff --git a/src/bncsutil/cdkeydecoder.h b/src/bncsutil/cdkeydecoder.h index cdf46bb..0f845f1 100644 --- a/src/bncsutil/cdkeydecoder.h +++ b/src/bncsutil/cdkeydecoder.h @@ -27,7 +27,7 @@ #define BNCSUTIL_CDKEYDECODER_H #include - + /** * Internal key type constants. */ @@ -49,18 +49,18 @@ MCEXP(CDKeyDecoder) { unsigned long value2; unsigned long product; char* w3value2; - + int processStarCraftKey(); int processWarCraft2Key(); int processWarCraft3Key(); - + void decodeKeyTable(int* keyTable); - + inline char getHexValue(int v); inline int getNumValue(char v); - + inline void mult(const int r, const int x, int* a, int dcByte); - + public: /** * Creates a new CD-key decoder object. @@ -68,8 +68,8 @@ MCEXP(CDKeyDecoder) { */ CDKeyDecoder(); - CDKeyDecoder(const char* cd_key); - + CDKeyDecoder(const char* cd_key); + /** * Creates a new CD-key decoder object, using the specified key. * keyLength should be the length of the key, NOT INCLUDING the @@ -77,16 +77,16 @@ MCEXP(CDKeyDecoder) { * this constructor to check the validity of the provided key. */ CDKeyDecoder(const char* cdKey, size_t keyLength); - + virtual ~CDKeyDecoder(); - + int isKeyValid(); int getVal2Length(); uint32_t getProduct(); uint32_t getVal1(); uint32_t getVal2(); int getLongVal2(char* out); - + /** * Calculates the CD-Key hash for use in SID_AUTH_CHECK (0x51) * Returns the length of the generated hash; call getHash and pass @@ -99,7 +99,7 @@ MCEXP(CDKeyDecoder) { * endianness is not a factor. */ size_t calculateHash(uint32_t clientToken, uint32_t serverToken); - + /** * Places the calculated CD-key hash in outputBuffer. You must call * calculateHash before getHash. Returns the length of the hash diff --git a/src/bncsutil/checkrevision.cpp b/src/bncsutil/checkrevision.cpp index 7708e06..039d1e7 100644 --- a/src/bncsutil/checkrevision.cpp +++ b/src/bncsutil/checkrevision.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include #include #include @@ -67,440 +67,440 @@ extern "C" { std::vector checkrevision_seeds; void initialize_checkrevision_seeds() { - static bool run = false; - - if (run) - return; - - run = true; - - checkrevision_seeds.reserve(8); - - checkrevision_seeds.push_back(0xE7F4CB62); - checkrevision_seeds.push_back(0xF6A14FFC); - checkrevision_seeds.push_back(0xAA5504AF); - checkrevision_seeds.push_back(0x871FCDC2); - checkrevision_seeds.push_back(0x11BF6A18); - checkrevision_seeds.push_back(0xC57292E6); - checkrevision_seeds.push_back(0x7927D27E); + static bool run = false; + + if (run) + return; + + run = true; + + checkrevision_seeds.reserve(8); + + checkrevision_seeds.push_back(0xE7F4CB62); + checkrevision_seeds.push_back(0xF6A14FFC); + checkrevision_seeds.push_back(0xAA5504AF); + checkrevision_seeds.push_back(0x871FCDC2); + checkrevision_seeds.push_back(0x11BF6A18); + checkrevision_seeds.push_back(0xC57292E6); + checkrevision_seeds.push_back(0x7927D27E); } MEXP(long) get_mpq_seed(int mpq_number) { - if (((size_t) mpq_number) >= checkrevision_seeds.size()) { - bncsutil_debug_message_a("error: no known revision check seed for " - "MPQ#%u", mpq_number); - return 0; - } - - return checkrevision_seeds[mpq_number]; + if (((size_t) mpq_number) >= checkrevision_seeds.size()) { + bncsutil_debug_message_a("error: no known revision check seed for " + "MPQ#%u", mpq_number); + return 0; + } + + return checkrevision_seeds[mpq_number]; } MEXP(long) set_mpq_seed(int mpq_number, long new_seed) { - long ret; - - if (((size_t) mpq_number) >= checkrevision_seeds.size()) { - ret = 0; - checkrevision_seeds.reserve((size_t) mpq_number); - } else { - ret = checkrevision_seeds[mpq_number]; - } - - checkrevision_seeds[mpq_number] = new_seed; - return ret; + long ret; + + if (((size_t) mpq_number) >= checkrevision_seeds.size()) { + ret = 0; + checkrevision_seeds.reserve((size_t) mpq_number); + } else { + ret = checkrevision_seeds[mpq_number]; + } + + checkrevision_seeds[mpq_number] = new_seed; + return ret; } MEXP(int) extractMPQNumber(const char* mpqName) { - const char* n; - int mpqNum; - if (mpqName == NULL) - return -1; - if ((n = (const char*) std::strchr(mpqName, '.')) == NULL) - return -1; - // extract int value of version number - mpqNum = atoi(n - 1); - return mpqNum; + const char* n; + int mpqNum; + if (mpqName == NULL) + return -1; + if ((n = (const char*) std::strchr(mpqName, '.')) == NULL) + return -1; + // extract int value of version number + mpqNum = atoi(n - 1); + return mpqNum; } const char* basename(const char* file_name) { - const char* base; - - for (base = (file_name + strlen(file_name)); base >= file_name; base--) { - if (*base == '\\' || *base == '/') - break; - } - - return ++base; + const char* base; + + for (base = (file_name + strlen(file_name)); base >= file_name; base--) { + if (*base == '\\' || *base == '/') + break; + } + + return ++base; } MEXP(int) checkRevision(const char* formula, const char* files[], int numFiles, - int mpqNumber, unsigned long* checksum) + int mpqNumber, unsigned long* checksum) { - long values[4], ovd[4], ovs1[4], ovs2[4]; - char ops[4]; - const char* token; - int curFormula = 0; - file_t f; - uint8_t* file_buffer; - uint32_t* dwBuf; - uint32_t* current; - size_t seed_count; - + long values[4], ovd[4], ovs1[4], ovs2[4]; + char ops[4]; + const char* token; + int curFormula = 0; + file_t f; + uint8_t* file_buffer; + uint32_t* dwBuf; + uint32_t* current; + size_t seed_count; + #if DEBUG - int i; - bncsutil_debug_message_a("checkRevision(\"%s\", {", formula); - for (i = 0; i < numFiles; i++) { - bncsutil_debug_message_a("\t\"%s\",", files[i]); - } - bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum); + int i; + bncsutil_debug_message_a("checkRevision(\"%s\", {", formula); + for (i = 0; i < numFiles; i++) { + bncsutil_debug_message_a("\t\"%s\",", files[i]); + } + bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum); #endif - - if (!formula || !files || numFiles == 0 || mpqNumber <= 0 || !checksum) { - bncsutil_debug_message("error: checkRevision() parameter sanity check " - "failed"); - return 0; - } - - seed_count = checkrevision_seeds.size(); - if (seed_count == 0) { - initialize_checkrevision_seeds(); - seed_count = checkrevision_seeds.size(); - } - - if (seed_count <= (size_t) mpqNumber) { - bncsutil_debug_message_a("error: no revision check seed value defined " - "for MPQ number %d", mpqNumber); - return 0; - } - - token = formula; - while (token && *token) { - if (*(token + 1) == '=') { - int variable = BUCR_GETNUM(*token); - if (variable < 0 || variable > 3) { - bncsutil_debug_message_a("error: Unknown revision check formula" - " variable %c", *token); - return 0; - } - - token += 2; // skip over equals sign - if (BUCR_ISNUM(*token)) { - values[variable] = atol(token); - } else { - if (curFormula > 3) { - // more than 4 operations? bloody hell. - bncsutil_debug_message("error: Revision check formula" - " contains more than 4 operations; unsupported."); - return 0; - } - ovd[curFormula] = variable; - ovs1[curFormula] = BUCR_GETNUM(*token); - ops[curFormula] = *(token + 1); - ovs2[curFormula] = BUCR_GETNUM(*(token + 2)); - curFormula++; - } - } - - for (; *token != 0; token++) { - if (*token == ' ') { - token++; - break; - } - } - } - - // Actual hashing (yay!) - // "hash A by the hashcode" - values[0] ^= checkrevision_seeds[mpqNumber]; - - for (int i = 0; i < numFiles; i++) { - size_t file_len, remainder, rounded_size, buffer_size; - - f = file_open(files[i], FILE_READ); - if (!f) { - bncsutil_debug_message_a("error: Failed to open file %s", - files[i]); - return 0; - } - - file_len = file_size(f); - remainder = file_len % 1024; - rounded_size = file_len - remainder; - - file_buffer = (uint8_t*) file_map(f, file_len, 0); - if (!file_buffer) { - file_close(f); - bncsutil_debug_message_a("error: Failed to map file %s into memory", - files[i]); - return 0; - } - - if (remainder == 0) { - // Mapped buffer may be used directly, without padding. - dwBuf = (uint32_t*) file_buffer; - buffer_size = file_len; - } else { - // Must be padded to nearest KB. - size_t extra = 1024 - remainder; - uint8_t pad = (uint8_t) 0xFF; - uint8_t* pad_dest; - - buffer_size = file_len + extra; - dwBuf = (uint32_t*) malloc(buffer_size); - if (!dwBuf) { - bncsutil_debug_message_a("error: Failed to allocate %d bytes " - "of memory as a temporary buffer", buffer_size); - file_unmap(f, file_buffer); - file_close(f); - return 0; - } - - memcpy(dwBuf, file_buffer, file_len); - file_unmap(f, file_buffer); - file_buffer = (uint8_t*) 0; - - pad_dest = ((uint8_t*) dwBuf) + file_len; - for (size_t j = file_len; j < buffer_size; j++) { - *pad_dest++ = pad--; - } - - } - - current = dwBuf; - for (size_t j = 0; j < buffer_size; j += 4) { - values[3] = LSB4(*(current++)); - for (int k = 0; k < curFormula; k++) { - switch (ops[k]) { - case '+': - values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]]; - break; - case '-': - values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]]; - break; - case '^': - values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]]; - break; - case '*': - // well, you never know - values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]]; - break; - case '/': - // well, you never know - values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]]; - break; - default: - // unrecognized operation - // shit - file_unmap(f, dwBuf); - file_close(f); - return 0; - } - } - } - - if (file_buffer) - file_unmap(f, file_buffer); - else if (dwBuf && file_buffer == 0) - free(dwBuf); // padded buffer - file_close(f); - } - - *checksum = (unsigned long) LSB4(values[2]); + + if (!formula || !files || numFiles == 0 || mpqNumber <= 0 || !checksum) { + bncsutil_debug_message("error: checkRevision() parameter sanity check " + "failed"); + return 0; + } + + seed_count = checkrevision_seeds.size(); + if (seed_count == 0) { + initialize_checkrevision_seeds(); + seed_count = checkrevision_seeds.size(); + } + + if (seed_count <= (size_t) mpqNumber) { + bncsutil_debug_message_a("error: no revision check seed value defined " + "for MPQ number %d", mpqNumber); + return 0; + } + + token = formula; + while (token && *token) { + if (*(token + 1) == '=') { + int variable = BUCR_GETNUM(*token); + if (variable < 0 || variable > 3) { + bncsutil_debug_message_a("error: Unknown revision check formula" + " variable %c", *token); + return 0; + } + + token += 2; // skip over equals sign + if (BUCR_ISNUM(*token)) { + values[variable] = atol(token); + } else { + if (curFormula > 3) { + // more than 4 operations? bloody hell. + bncsutil_debug_message("error: Revision check formula" + " contains more than 4 operations; unsupported."); + return 0; + } + ovd[curFormula] = variable; + ovs1[curFormula] = BUCR_GETNUM(*token); + ops[curFormula] = *(token + 1); + ovs2[curFormula] = BUCR_GETNUM(*(token + 2)); + curFormula++; + } + } + + for (; *token != 0; token++) { + if (*token == ' ') { + token++; + break; + } + } + } + + // Actual hashing (yay!) + // "hash A by the hashcode" + values[0] ^= checkrevision_seeds[mpqNumber]; + + for (int i = 0; i < numFiles; i++) { + size_t file_len, remainder, rounded_size, buffer_size; + + f = file_open(files[i], FILE_READ); + if (!f) { + bncsutil_debug_message_a("error: Failed to open file %s", + files[i]); + return 0; + } + + file_len = file_size(f); + remainder = file_len % 1024; + rounded_size = file_len - remainder; + + file_buffer = (uint8_t*) file_map(f, file_len, 0); + if (!file_buffer) { + file_close(f); + bncsutil_debug_message_a("error: Failed to map file %s into memory", + files[i]); + return 0; + } + + if (remainder == 0) { + // Mapped buffer may be used directly, without padding. + dwBuf = (uint32_t*) file_buffer; + buffer_size = file_len; + } else { + // Must be padded to nearest KB. + size_t extra = 1024 - remainder; + uint8_t pad = (uint8_t) 0xFF; + uint8_t* pad_dest; + + buffer_size = file_len + extra; + dwBuf = (uint32_t*) malloc(buffer_size); + if (!dwBuf) { + bncsutil_debug_message_a("error: Failed to allocate %d bytes " + "of memory as a temporary buffer", buffer_size); + file_unmap(f, file_buffer); + file_close(f); + return 0; + } + + memcpy(dwBuf, file_buffer, file_len); + file_unmap(f, file_buffer); + file_buffer = (uint8_t*) 0; + + pad_dest = ((uint8_t*) dwBuf) + file_len; + for (size_t j = file_len; j < buffer_size; j++) { + *pad_dest++ = pad--; + } + + } + + current = dwBuf; + for (size_t j = 0; j < buffer_size; j += 4) { + values[3] = LSB4(*(current++)); + for (int k = 0; k < curFormula; k++) { + switch (ops[k]) { + case '+': + values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]]; + break; + case '-': + values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]]; + break; + case '^': + values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]]; + break; + case '*': + // well, you never know + values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]]; + break; + case '/': + // well, you never know + values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]]; + break; + default: + // unrecognized operation + // shit + file_unmap(f, dwBuf); + file_close(f); + return 0; + } + } + } + + if (file_buffer) + file_unmap(f, file_buffer); + else if (dwBuf && file_buffer == 0) + free(dwBuf); // padded buffer + file_close(f); + } + + *checksum = (unsigned long) LSB4(values[2]); #if DEBUG - bncsutil_debug_message_a("\tChecksum = %lu", *checksum); + bncsutil_debug_message_a("\tChecksum = %lu", *checksum); #endif - return 1; + return 1; } MEXP(int) checkRevisionFlat(const char* valueString, const char* file1, const char* file2, const char* file3, int mpqNumber, unsigned long* checksum) { - const char* files[] = - {file1, file2, file3}; - return checkRevision(valueString, files, 3, mpqNumber, - checksum); + const char* files[] = + {file1, file2, file3}; + return checkRevision(valueString, files, 3, mpqNumber, + checksum); } MEXP(int) getExeInfo(const char* file_name, char* exe_info, - size_t exe_info_size, uint32_t* version, int platform) + size_t exe_info_size, uint32_t* version, int platform) { - const char* base = (char*) 0; - unsigned long file_size; - FILE* f = (FILE*) 0; - int ret; + const char* base = (char*) 0; + unsigned long file_size; + FILE* f = (FILE*) 0; + int ret; #ifdef MOS_WINDOWS - HANDLE hFile; - FILETIME ft; - SYSTEMTIME st; - LPBYTE buf; - VS_FIXEDFILEINFO* ffi; - DWORD infoSize, bytesRead; + HANDLE hFile; + FILETIME ft; + SYSTEMTIME st; + LPBYTE buf; + VS_FIXEDFILEINFO* ffi; + DWORD infoSize, bytesRead; #else - cm_pe_t pe; - cm_pe_resdir_t* root; - cm_pe_resdir_t* dir; - cm_pe_version_t ffi; - size_t i; - struct stat st; - struct tm* time; + cm_pe_t pe; + cm_pe_resdir_t* root; + cm_pe_resdir_t* dir; + cm_pe_version_t ffi; + size_t i; + struct stat st; + struct tm* time; #endif - - if (!file_name || !exe_info || !exe_info_size || !version) - return 0; - - base = basename(file_name); - - switch (platform) { - case BNCSUTIL_PLATFORM_X86: -#ifdef MOS_WINDOWS - infoSize = GetFileVersionInfoSize(file_name, &bytesRead); - if (infoSize == 0) - return 0; - buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, - PAGE_READWRITE); - if (buf == NULL) - return 0; - if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) - return 0; - if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) - return 0; - - *version = - ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | - ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | - ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | - (LOWORD(ffi->dwProductVersionLS) & 0xFF); + + if (!file_name || !exe_info || !exe_info_size || !version) + return 0; + + base = basename(file_name); + + switch (platform) { + case BNCSUTIL_PLATFORM_X86: +#ifdef MOS_WINDOWS + infoSize = GetFileVersionInfoSize(file_name, &bytesRead); + if (infoSize == 0) + return 0; + buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, + PAGE_READWRITE); + if (buf == NULL) + return 0; + if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) + return 0; + if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) + return 0; + + *version = + ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | + ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | + ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | + (LOWORD(ffi->dwProductVersionLS) & 0xFF); #if DEBUG - bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", - base, (HIWORD(ffi->dwProductVersionMS) & 0xFF), - (LOWORD(ffi->dwProductVersionMS) & 0xFF), - (HIWORD(ffi->dwProductVersionLS) & 0xFF), - (LOWORD(ffi->dwProductVersionLS) & 0xFF), - *version); + bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", + base, (HIWORD(ffi->dwProductVersionMS) & 0xFF), + (LOWORD(ffi->dwProductVersionMS) & 0xFF), + (HIWORD(ffi->dwProductVersionLS) & 0xFF), + (LOWORD(ffi->dwProductVersionLS) & 0xFF), + *version); #endif - VirtualFree(buf, 0lu, MEM_RELEASE); + VirtualFree(buf, 0lu, MEM_RELEASE); #else - pe = cm_pe_load(file_name); - if (!pe) - return 0; - root = cm_pe_load_resources(pe); - if (!root) { - cm_pe_unload(pe); - return 0; - } - - for (i = 0; i < root->subdir_count; i++) { - dir = (root->subdirs + i); - if (dir->name == 16) { - if (!cm_pe_fixed_version(pe, dir->subdirs->resources, - &ffi)) - { - cm_pe_unload_resources(root); - cm_pe_unload(pe); - return 0; - } - break; - } - } - *version = - ((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) | - ((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) | - ((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | - (LOWORD(ffi.dwProductVersionLS) & 0xFF); + pe = cm_pe_load(file_name); + if (!pe) + return 0; + root = cm_pe_load_resources(pe); + if (!root) { + cm_pe_unload(pe); + return 0; + } + + for (i = 0; i < root->subdir_count; i++) { + dir = (root->subdirs + i); + if (dir->name == 16) { + if (!cm_pe_fixed_version(pe, dir->subdirs->resources, + &ffi)) + { + cm_pe_unload_resources(root); + cm_pe_unload(pe); + return 0; + } + break; + } + } + *version = + ((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) | + ((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) | + ((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | + (LOWORD(ffi.dwProductVersionLS) & 0xFF); #if DEBUG - bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", - base, (HIWORD(ffi.dwProductVersionMS) & 0xFF), - (LOWORD(ffi.dwProductVersionMS) & 0xFF), - (HIWORD(ffi.dwProductVersionLS) & 0xFF), - (LOWORD(ffi.dwProductVersionLS) & 0xFF), - *version); + bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", + base, (HIWORD(ffi.dwProductVersionMS) & 0xFF), + (LOWORD(ffi.dwProductVersionMS) & 0xFF), + (HIWORD(ffi.dwProductVersionLS) & 0xFF), + (LOWORD(ffi.dwProductVersionLS) & 0xFF), + *version); #endif - - cm_pe_unload_resources(root); - cm_pe_unload(pe); + + cm_pe_unload_resources(root); + cm_pe_unload(pe); #endif - break; - case BNCSUTIL_PLATFORM_MAC: - case BNCSUTIL_PLATFORM_OSX: - f = fopen(file_name, "r"); - if (!f) - return 0; - if (fseek(f, -4, SEEK_END) != 0) { - fclose(f); - return 0; - } - if (fread(version, 4, 1, f) != 1) { - fclose(f); - return 0; - } + break; + case BNCSUTIL_PLATFORM_MAC: + case BNCSUTIL_PLATFORM_OSX: + f = fopen(file_name, "r"); + if (!f) + return 0; + if (fseek(f, -4, SEEK_END) != 0) { + fclose(f); + return 0; + } + if (fread(version, 4, 1, f) != 1) { + fclose(f); + return 0; + } #ifdef MOS_WINDOWS - fclose(f); + fclose(f); #endif - } - + } + #ifdef MOS_WINDOWS - hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return 0; - file_size = GetFileSize(hFile, NULL); - if (!GetFileTime(hFile, &ft, NULL, NULL)) { - CloseHandle(hFile); - return 0; - } - - if (!FileTimeToSystemTime(&ft, &st)) { - CloseHandle(hFile); - return 0; - } - CloseHandle(hFile); - - ret = snprintf(exe_info, exe_info_size, - "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth, - st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond, - file_size); + hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + file_size = GetFileSize(hFile, NULL); + if (!GetFileTime(hFile, &ft, NULL, NULL)) { + CloseHandle(hFile); + return 0; + } + + if (!FileTimeToSystemTime(&ft, &st)) { + CloseHandle(hFile); + return 0; + } + CloseHandle(hFile); + + ret = snprintf(exe_info, exe_info_size, + "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth, + st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond, + file_size); #else - if (!f) - f = fopen(file_name, "r"); - if (!f) - return 0; - if (fseek(f, 0, SEEK_END) == -1) { - fclose(f); - return 0; - } - file_size = ftell(f); - fclose(f); - - if (stat(file_name, &st) != 0) - return 0; - - time = gmtime(&st.st_mtime); - if (!time) - return 0; - - switch (platform) { - case BNCSUTIL_PLATFORM_MAC: - case BNCSUTIL_PLATFORM_OSX: - if (time->tm_year >= 100) // y2k - time->tm_year -= 100; - break; - } - - ret = (int) snprintf(exe_info, exe_info_size, - "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, - (time->tm_mon+1), time->tm_mday, time->tm_year, - time->tm_hour, time->tm_min, time->tm_sec, file_size); + if (!f) + f = fopen(file_name, "r"); + if (!f) + return 0; + if (fseek(f, 0, SEEK_END) == -1) { + fclose(f); + return 0; + } + file_size = ftell(f); + fclose(f); + + if (stat(file_name, &st) != 0) + return 0; + + time = gmtime(&st.st_mtime); + if (!time) + return 0; + + switch (platform) { + case BNCSUTIL_PLATFORM_MAC: + case BNCSUTIL_PLATFORM_OSX: + if (time->tm_year >= 100) // y2k + time->tm_year -= 100; + break; + } + + ret = (int) snprintf(exe_info, exe_info_size, + "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, + (time->tm_mon+1), time->tm_mday, time->tm_year, + time->tm_hour, time->tm_min, time->tm_sec, file_size); #endif #if DEBUG - bncsutil_debug_message(exe_info); + bncsutil_debug_message(exe_info); #endif - return ret; + return ret; } #ifdef __cplusplus diff --git a/src/bncsutil/checkrevision.h b/src/bncsutil/checkrevision.h index 1e42fe7..c31aa9f 100644 --- a/src/bncsutil/checkrevision.h +++ b/src/bncsutil/checkrevision.h @@ -71,8 +71,8 @@ MEXP(int) checkRevision( MEXP(int) checkRevisionFlat( const char* valueString, const char* file1, - const char* file2, - const char* file3, + const char* file2, + const char* file3, int mpqNumber, unsigned long* checksum ); @@ -87,11 +87,11 @@ MEXP(int) checkRevisionFlat( * necessary. */ MEXP(int) getExeInfo(const char* file_name, - char* exe_info, - size_t exe_info_size, - uint32_t* version, - int platform); - + char* exe_info, + size_t exe_info_size, + uint32_t* version, + int platform); + /** * Gets the seed value for the given MPQ file. If no seed value for the given * MPQ is registered with BNCSutil, returns 0. diff --git a/src/bncsutil/debug.c b/src/bncsutil/debug.c index 020a162..92fc499 100644 --- a/src/bncsutil/debug.c +++ b/src/bncsutil/debug.c @@ -20,14 +20,14 @@ struct _bncsutil_debug_env { - int enabled; + int enabled; #ifdef MOS_WINDOWS - HANDLE output; - BOOL console_was_created; - WORD orig_attributes; - WORD sans_foreground; + HANDLE output; + BOOL console_was_created; + WORD orig_attributes; + WORD sans_foreground; #else - FILE* output; + FILE* output; #endif }; @@ -36,109 +36,109 @@ const char default_err_msg[] = "[unknown error]"; #ifdef MOS_WINDOWS BOOL debug_set_color(debug_env_t env, WORD color) { - return SetConsoleTextAttribute(env->output, color | env->sans_foreground); + return SetConsoleTextAttribute(env->output, color | env->sans_foreground); } BOOL debug_restore_color(debug_env_t env) { - return SetConsoleTextAttribute(env->output, env->orig_attributes); + return SetConsoleTextAttribute(env->output, env->orig_attributes); } BOOL debug_intense_color(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env->output, &info)) - return FALSE; - return SetConsoleTextAttribute(env->output, info.wAttributes | - FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env->output, &info)) + return FALSE; + return SetConsoleTextAttribute(env->output, info.wAttributes | + FOREGROUND_INTENSITY); } BOOL debug_mellow_color(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env->output, &info)) - return FALSE; - return SetConsoleTextAttribute(env->output, info.wAttributes | - ~FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env->output, &info)) + return FALSE; + return SetConsoleTextAttribute(env->output, info.wAttributes | + ~FOREGROUND_INTENSITY); } void debug_setup_console(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (AllocConsole()) { - // only set title if new console was created - SetConsoleTitle("BNCSutil Debug Console"); - env->console_was_created = TRUE; - } else { - env->console_was_created = FALSE; - } - env->output = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(env->output, &info); - env->orig_attributes = info.wAttributes; - env->sans_foreground = info.wAttributes & - ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + + if (AllocConsole()) { + // only set title if new console was created + SetConsoleTitle("BNCSutil Debug Console"); + env->console_was_created = TRUE; + } else { + env->console_was_created = FALSE; + } + env->output = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(env->output, &info); + env->orig_attributes = info.wAttributes; + env->sans_foreground = info.wAttributes & + ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | + FOREGROUND_INTENSITY); } #endif size_t debug_write(debug_env_t env, const char* message) { #ifdef MOS_WINDOWS - DWORD chars_written; - BOOL res; - if (!env->output) - debug_setup_console(env); - res = WriteConsole(env->output, message, (DWORD) strlen(message), - &chars_written, (LPVOID) 0); - return (res) ? (size_t) chars_written : (size_t) -1; + DWORD chars_written; + BOOL res; + if (!env->output) + debug_setup_console(env); + res = WriteConsole(env->output, message, (DWORD) strlen(message), + &chars_written, (LPVOID) 0); + return (res) ? (size_t) chars_written : (size_t) -1; #else - return fwrite(message, 1, strlen(message), env->output); + return fwrite(message, 1, strlen(message), env->output); #endif } size_t get_console_width(debug_env_t env) { #ifdef MOS_WINDOWS - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env->output, &info)) - return (size_t) 0; - return (size_t) info.dwSize.X; + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env->output, &info)) + return (size_t) 0; + return (size_t) info.dwSize.X; #else - char* columns = getenv("COLUMNS"); - if (!columns) - return (size_t) 0; - return (size_t) strtol(columns, (char**) 0, 0); + char* columns = getenv("COLUMNS"); + if (!columns) + return (size_t) 0; + return (size_t) strtol(columns, (char**) 0, 0); #endif } char* produce_dump(const char* data, size_t length) { - return (char*) 0; + return (char*) 0; } debug_env_t get_debug_environment() { - static debug_env_t env = (debug_env_t) 0; - - if (!env) { - env = (debug_env_t) malloc(sizeof(struct _bncsutil_debug_env)); + static debug_env_t env = (debug_env_t) 0; + + if (!env) { + env = (debug_env_t) malloc(sizeof(struct _bncsutil_debug_env)); /*#if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES - env->enabled = 1; + env->enabled = 1; #else - env->enabled = 0; + env->enabled = 0; #endif*/ - env->enabled = 0; + env->enabled = 0; #ifdef MOS_WINDOWS - env->output = (HANDLE) NULL; - //debug_setup_console(env); + env->output = (HANDLE) NULL; + //debug_setup_console(env); #else - env->output = stderr; + env->output = stderr; #endif - } - - return env; + } + + return env; } /** @@ -146,8 +146,8 @@ debug_env_t get_debug_environment() */ MEXP(int) bncsutil_debug_status(void) { - debug_env_t env = get_debug_environment(); - return env->enabled; + debug_env_t env = get_debug_environment(); + return env->enabled; } /** * Set new_status to zero to turn debugging messages off or nonzero to turn @@ -155,197 +155,197 @@ MEXP(int) bncsutil_debug_status(void) */ MEXP(int) bncsutil_set_debug_status(int new_status) { - debug_env_t env = get_debug_environment(); - if (!env) { - return 0; - } + debug_env_t env = get_debug_environment(); + if (!env) { + return 0; + } #ifdef MOS_WINDOWS - if (env->enabled && !new_status && env->console_was_created) { - FreeConsole(); - } else if (!env->enabled && new_status) { - debug_setup_console(env); - } + if (env->enabled && !new_status && env->console_was_created) { + FreeConsole(); + } else if (!env->enabled && new_status) { + debug_setup_console(env); + } #endif - env->enabled = (new_status != 0) ? 1 : 0; - return 1; + env->enabled = (new_status != 0) ? 1 : 0; + return 1; } MEXP(int) bncsutil_internal_debug_messages() { #if DEBUG - return 1; + return 1; #else - return 0; + return 0; #endif } MEXP(void) bncsutil_debug_message(const char* message) { - debug_env_t env = get_debug_environment(); - char timestamp[12]; - /*size_t length;*/ + debug_env_t env = get_debug_environment(); + char timestamp[12]; + /*size_t length;*/ #ifdef MOS_WINDOWS - SYSTEMTIME local_time; + SYSTEMTIME local_time; #else - time_t unix_time; - struct tm* local_time; + time_t unix_time; + struct tm* local_time; #endif - if (!env->enabled) { - return; - } + if (!env->enabled) { + return; + } #ifdef MOS_WINDOWS - GetLocalTime(&local_time); - sprintf(timestamp, "[%02d:%02d:%02d] ", local_time.wHour, - local_time.wMinute, local_time.wSecond); - debug_set_color(env, FOREGROUND_RED | FOREGROUND_GREEN | - FOREGROUND_INTENSITY); -#else - time(&unix_time); - local_time = localtime(&unix_time); - sprintf(timestamp, "[%02d:%02d:%02d] ", local_time->tm_hour, - local_time->tm_min, local_time->tm_sec); + GetLocalTime(&local_time); + sprintf(timestamp, "[%02d:%02d:%02d] ", local_time.wHour, + local_time.wMinute, local_time.wSecond); + debug_set_color(env, FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_INTENSITY); +#else + time(&unix_time); + local_time = localtime(&unix_time); + sprintf(timestamp, "[%02d:%02d:%02d] ", local_time->tm_hour, + local_time->tm_min, local_time->tm_sec); #endif - debug_write(env, timestamp); + debug_write(env, timestamp); #ifdef MOS_WINDOWS - debug_restore_color(env); + debug_restore_color(env); #endif - - debug_write(env, message); - debug_write(env, "\r\n"); + + debug_write(env, message); + debug_write(env, "\r\n"); } MEXP(void) bncsutil_debug_message_a(const char* message, ...) { - char buf[4092]; - va_list args; - va_start(args, message); - - vsprintf(buf, message, args); - va_end(args); - - bncsutil_debug_message(buf); + char buf[4092]; + va_list args; + va_start(args, message); + + vsprintf(buf, message, args); + va_end(args); + + bncsutil_debug_message(buf); } MEXP(void) bncsutil_debug_dump(const void* data, size_t data_length) { - char ascii[] = " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - char hex[4]; - char pos_indicator[] = "0000 "; - debug_env_t env = get_debug_environment(); - size_t i; - size_t j = 2; /* printing to ASCII buffer skips over 2 spaces */ - size_t k; - char cur; - int on_boundary; - size_t current_string_length; - - if (!env->enabled) { - return; - } - - debug_intense_color(env); - for (i = 0; i < data_length; i++) { - on_boundary = ((i + 1) % 16 == 0); - - if ((i + 1) % 16 == 1) { + char ascii[] = " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + char hex[4]; + char pos_indicator[] = "0000 "; + debug_env_t env = get_debug_environment(); + size_t i; + size_t j = 2; /* printing to ASCII buffer skips over 2 spaces */ + size_t k; + char cur; + int on_boundary; + size_t current_string_length; + + if (!env->enabled) { + return; + } + + debug_intense_color(env); + for (i = 0; i < data_length; i++) { + on_boundary = ((i + 1) % 16 == 0); + + if ((i + 1) % 16 == 1) { #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_RED | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); + debug_set_color(env, FOREGROUND_RED | FOREGROUND_BLUE | + FOREGROUND_INTENSITY); #endif - debug_write(env, pos_indicator); + debug_write(env, pos_indicator); #ifdef MOS_WINDOWS - debug_restore_color(env); + debug_restore_color(env); #endif - } - - cur = *(((char*) data) + i); - /* The cast to unsigned char and then int is required to properly - * handle 8 bit characters. */ - ascii[j++] = (isprint((int) (unsigned char) cur)) ? cur : '.'; - sprintf(hex, "%02X ", (cur & 0xFF)); - debug_write(env, hex); - - if ((i + 1) % 8 == 0) { - debug_write(env, " "); - } - - if (on_boundary || (i + 1) == data_length) { - if (!on_boundary) { - current_string_length = 3 * (i % 16); - if ((i % 16) > 8) - current_string_length++; - - for (k = 0; k < (47 - current_string_length); k++) { - debug_write(env, " "); - } - } + } + + cur = *(((char*) data) + i); + /* The cast to unsigned char and then int is required to properly + * handle 8 bit characters. */ + ascii[j++] = (isprint((int) (unsigned char) cur)) ? cur : '.'; + sprintf(hex, "%02X ", (cur & 0xFF)); + debug_write(env, hex); + + if ((i + 1) % 8 == 0) { + debug_write(env, " "); + } + + if (on_boundary || (i + 1) == data_length) { + if (!on_boundary) { + current_string_length = 3 * (i % 16); + if ((i % 16) > 8) + current_string_length++; + + for (k = 0; k < (47 - current_string_length); k++) { + debug_write(env, " "); + } + } #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_GREEN | - FOREGROUND_INTENSITY); -#endif - ascii[j] = 0; - debug_write(env, ascii); - debug_write(env, "\r\n"); - j = 2; /* reset position in ASCII buffer */ + debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_INTENSITY); +#endif + ascii[j] = 0; + debug_write(env, ascii); + debug_write(env, "\r\n"); + j = 2; /* reset position in ASCII buffer */ #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_INTENSITY); + debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_INTENSITY); #endif - sprintf(pos_indicator, "%04X ", i + 1); + sprintf(pos_indicator, "%04X ", i + 1); #ifdef MOS_WINDOWS - debug_restore_color(env); -#endif - } - } + debug_restore_color(env); +#endif + } + } } #ifdef MOS_WINDOWS const char* sys_error_msg() { - const char* buffer; - DWORD res; - - res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - (const void*) 0, (DWORD) 0, (DWORD) 0, (LPTSTR) &buffer, (DWORD) 0, - (va_list*) 0); - if (!res) { - bncsutil_debug_message("error: Failed to get Windows error message."); - return default_err_msg; - } - - return buffer; + const char* buffer; + DWORD res; + + res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + (const void*) 0, (DWORD) 0, (DWORD) 0, (LPTSTR) &buffer, (DWORD) 0, + (va_list*) 0); + if (!res) { + bncsutil_debug_message("error: Failed to get Windows error message."); + return default_err_msg; + } + + return buffer; } void free_sys_err_msg(const char* message_pointer) { - if (message_pointer) - LocalFree(message_pointer); + if (message_pointer) + LocalFree(message_pointer); } #else const char* sys_error_msg() { - return (const char*) strerror(errno); + return (const char*) strerror(errno); } void free_sys_err_msg() { - /* Do nothing. */ + /* Do nothing. */ } #endif MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length) { - + } #ifdef MOS_WINDOWS MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, - size_t length) + size_t length) { - + } #endif diff --git a/src/bncsutil/debug.h b/src/bncsutil/debug.h index 0cbf7d1..930589a 100644 --- a/src/bncsutil/debug.h +++ b/src/bncsutil/debug.h @@ -11,13 +11,13 @@ #undef DEBUG #if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES -# define INTERNAL_DEBUG(msg) bncsutil_debug_message(msg) -# define INTERNAL_DUMP(data, length) bncsutil_debug_dump((data), (length)) -# define DEBUG 1 +# define INTERNAL_DEBUG(msg) bncsutil_debug_message(msg) +# define INTERNAL_DUMP(data, length) bncsutil_debug_dump((data), (length)) +# define DEBUG 1 #else -# define INTERNAL_DEBUG(msg) -# define INTERNAL_DUMP(data, length) -# define DEBUG 0 +# define INTERNAL_DEBUG(msg) +# define INTERNAL_DUMP(data, length) +# define DEBUG 0 #endif @@ -81,11 +81,11 @@ void free_sys_err_msg(const char* message_pointer); MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length); #ifdef MOS_WINDOWS //MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, -// size_t length); +// size_t length); #endif #ifdef __cplusplus } // extern "C" #endif -#endif /* DEBUG */ \ No newline at end of file +#endif /* DEBUG */ diff --git a/src/bncsutil/decodekey.cpp b/src/bncsutil/decodekey.cpp index 6caf08d..c38276e 100644 --- a/src/bncsutil/decodekey.cpp +++ b/src/bncsutil/decodekey.cpp @@ -32,11 +32,11 @@ #include #ifdef MOS_WINDOWS - #include + #include #else - #include - #include - #include + #include + #include + #include #endif #include #include @@ -61,37 +61,37 @@ unsigned int numDecoders = 0; unsigned int sizeDecoders = 0; #ifdef MOS_WINDOWS -// HANDLE mutex; - CRITICAL_SECTION kd_control; +// HANDLE mutex; + CRITICAL_SECTION kd_control; #else - pthread_mutex_t mutex; + pthread_mutex_t mutex; #endif int kd_lock_decoders() { #ifdef MOS_WINDOWS -/* DWORD dwWaitResult; - dwWaitResult = WaitForSingleObject(mutex, MUTEX_TIMEOUT_MS); - switch (dwWaitResult) { - case WAIT_OBJECT_0: - // success - break; - case WAIT_TIMEOUT: - return 0; - break; - case WAIT_ABANDONED: - // weird, but should be OK - break; - default: - return 0; - break; - }*/ - EnterCriticalSection(&kd_control); +/* DWORD dwWaitResult; + dwWaitResult = WaitForSingleObject(mutex, MUTEX_TIMEOUT_MS); + switch (dwWaitResult) { + case WAIT_OBJECT_0: + // success + break; + case WAIT_TIMEOUT: + return 0; + break; + case WAIT_ABANDONED: + // weird, but should be OK + break; + default: + return 0; + break; + }*/ + EnterCriticalSection(&kd_control); #else - int err = 0; - pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - struct timespec wait_time = {0, MUTEX_TIMEOUT_MS * 1000}; - - err = pthread_cond_timedwait(&cond, &mutex, &wait_time); + int err = 0; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + struct timespec wait_time = {0, MUTEX_TIMEOUT_MS * 1000}; + + err = pthread_cond_timedwait(&cond, &mutex, &wait_time); switch (err) { case 0: // success @@ -99,7 +99,7 @@ int kd_lock_decoders() { default: // error return 0; - } + } #endif return 1; } @@ -111,312 +111,312 @@ int kd_lock_decoders() { #endif MEXP(int) kd_quick(const char* cd_key, uint32_t client_token, - uint32_t server_token, uint32_t* public_value, - uint32_t* product, char* hash_buffer, size_t buffer_len) + uint32_t server_token, uint32_t* public_value, + uint32_t* product, char* hash_buffer, size_t buffer_len) { - CDKeyDecoder kd(cd_key, strlen(cd_key)); - size_t hash_len; - - if (!kd.isKeyValid()) - return 0; - - *public_value = kd.getVal1(); - *product = kd.getProduct(); - - hash_len = kd.calculateHash(client_token, server_token); - if (!hash_len || hash_len > buffer_len) - return 0; - - kd.getHash(hash_buffer); - return 1; + CDKeyDecoder kd(cd_key, strlen(cd_key)); + size_t hash_len; + + if (!kd.isKeyValid()) + return 0; + + *public_value = kd.getVal1(); + *product = kd.getProduct(); + + hash_len = kd.calculateHash(client_token, server_token); + if (!hash_len || hash_len > buffer_len) + return 0; + + kd.getHash(hash_buffer); + return 1; } MEXP(int) kd_init() { - static int has_run = 0; + static int has_run = 0; + + if (has_run) + return 1; - if (has_run) - return 1; - #ifdef MOS_WINDOWS - /*mutex = CreateMutex(NULL, FALSE, NULL); - if (mutex == NULL) - return 0;*/ - InitializeCriticalSection(&kd_control); + /*mutex = CreateMutex(NULL, FALSE, NULL); + if (mutex == NULL) + return 0;*/ + InitializeCriticalSection(&kd_control); #else - if (pthread_mutex_init(&mutex, NULL)) - return 0; + if (pthread_mutex_init(&mutex, NULL)) + return 0; #endif - numDecoders = 0; - sizeDecoders = 0; - decoders = (CDKeyDecoder**) 0; - has_run = 1; + numDecoders = 0; + sizeDecoders = 0; + decoders = (CDKeyDecoder**) 0; + has_run = 1; #if DEBUG - bncsutil_debug_message("Initialized key decoding C API."); + bncsutil_debug_message("Initialized key decoding C API."); #endif - return 1; + return 1; } unsigned int kd_findAvailable() { - unsigned int i; - CDKeyDecoder** d; - - d = decoders; - for (i = 0; i < sizeDecoders; i++) { - if (*d == (CDKeyDecoder*) 0) - return i; - d++; - } - - // no room available, must expand - decoders = (CDKeyDecoder**) realloc(decoders, sizeof(CDKeyDecoder*) * - (sizeDecoders + DEFAULT_DECODERS_SIZE)); - if (!decoders) - return (unsigned int) -1; - - memset(decoders + sizeDecoders, 0, - sizeof(CDKeyDecoder*) * DEFAULT_DECODERS_SIZE); // zero new memory - - i = sizeDecoders; - sizeDecoders += DEFAULT_DECODERS_SIZE; - return i; + unsigned int i; + CDKeyDecoder** d; + + d = decoders; + for (i = 0; i < sizeDecoders; i++) { + if (*d == (CDKeyDecoder*) 0) + return i; + d++; + } + + // no room available, must expand + decoders = (CDKeyDecoder**) realloc(decoders, sizeof(CDKeyDecoder*) * + (sizeDecoders + DEFAULT_DECODERS_SIZE)); + if (!decoders) + return (unsigned int) -1; + + memset(decoders + sizeDecoders, 0, + sizeof(CDKeyDecoder*) * DEFAULT_DECODERS_SIZE); // zero new memory + + i = sizeDecoders; + sizeDecoders += DEFAULT_DECODERS_SIZE; + return i; } MEXP(int) kd_create(const char* cdkey, int keyLength) { - unsigned int i; - CDKeyDecoder** d; - static int dcs_initialized = 0; - - if (!dcs_initialized) { - if (!kd_init()) - return -1; - dcs_initialized = 1; - } - - if (!kd_lock_decoders()) return -1; - - i = kd_findAvailable(); - if (i == (unsigned int) -1) - return -1; - - d = (decoders + i); - *d = new CDKeyDecoder(cdkey, keyLength); - if (!(**d).isKeyValid()) { - delete *d; - *d = (CDKeyDecoder*) 0; - return -1; - } - - numDecoders++; - - kd_unlock_decoders(); - return (int) i; + unsigned int i; + CDKeyDecoder** d; + static int dcs_initialized = 0; + + if (!dcs_initialized) { + if (!kd_init()) + return -1; + dcs_initialized = 1; + } + + if (!kd_lock_decoders()) return -1; + + i = kd_findAvailable(); + if (i == (unsigned int) -1) + return -1; + + d = (decoders + i); + *d = new CDKeyDecoder(cdkey, keyLength); + if (!(**d).isKeyValid()) { + delete *d; + *d = (CDKeyDecoder*) 0; + return -1; + } + + numDecoders++; + + kd_unlock_decoders(); + return (int) i; } /* MEXP(int) kd_create(char* cdkey, int keyLength) { if (!kd_lock_decoders()) return -1; - CDKeyDecoder* d; - unsigned int i; - if (numDecoders >= sizeDecoders) { - CDKeyDecoder** temp = new CDKeyDecoder*[sizeDecoders]; - for (unsigned int j = 0; j < sizeDecoders; j++) { - temp[j] = decoders[j]; - } - delete [] decoders; - decoders = new CDKeyDecoder*[sizeDecoders + DEFAULT_DECODERS_SIZE]; - - for (unsigned int j = 0; j < sizeDecoders; j++) { - decoders[j] = temp[j]; - } - delete [] temp; - sizeDecoders += DEFAULT_DECODERS_SIZE; - } - i = numDecoders++; - decoders[i] = new CDKeyDecoder(cdkey, keyLength); - d = decoders[i]; - if (!d->isKeyValid()) { - delete decoders[i]; - return -1; - } - kd_unlock_decoders(); - - d = NULL; - return (int) i; + CDKeyDecoder* d; + unsigned int i; + if (numDecoders >= sizeDecoders) { + CDKeyDecoder** temp = new CDKeyDecoder*[sizeDecoders]; + for (unsigned int j = 0; j < sizeDecoders; j++) { + temp[j] = decoders[j]; + } + delete [] decoders; + decoders = new CDKeyDecoder*[sizeDecoders + DEFAULT_DECODERS_SIZE]; + + for (unsigned int j = 0; j < sizeDecoders; j++) { + decoders[j] = temp[j]; + } + delete [] temp; + sizeDecoders += DEFAULT_DECODERS_SIZE; + } + i = numDecoders++; + decoders[i] = new CDKeyDecoder(cdkey, keyLength); + d = decoders[i]; + if (!d->isKeyValid()) { + delete decoders[i]; + return -1; + } + kd_unlock_decoders(); + + d = NULL; + return (int) i; }*/ MEXP(int) kd_free(int decoder) { - CDKeyDecoder* d; + CDKeyDecoder* d; + + if (!kd_lock_decoders()) return 0; - if (!kd_lock_decoders()) return 0; + if ((unsigned int) decoder >= sizeDecoders) + return 0; - if ((unsigned int) decoder >= sizeDecoders) - return 0; + d = *(decoders + decoder); + if (!d) + return 0; - d = *(decoders + decoder); - if (!d) - return 0; + delete d; + *(decoders + decoder) = (CDKeyDecoder*) 0; - delete d; - *(decoders + decoder) = (CDKeyDecoder*) 0; - - kd_unlock_decoders(); - return 1; + kd_unlock_decoders(); + return 1; } MEXP(int) kd_val2Length(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getVal2Length(); - value = d->getVal2Length(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_product(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getProduct(); - value = d->getProduct(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_val1(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getVal1(); - value = d->getVal1(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_val2(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; - if (!kd_lock_decoders()) return -1; + if (!kd_lock_decoders()) return -1; + + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getVal2(); - value = d->getVal2(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_longVal2(int decoder, char* out) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; - if (!kd_lock_decoders()) return -1; + if (!kd_lock_decoders()) return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - value = d->getLongVal2(out); - - kd_unlock_decoders(); - return value; + value = d->getLongVal2(out); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_calculateHash(int decoder, uint32_t clientToken, - uint32_t serverToken) + uint32_t serverToken) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = (int) d->calculateHash(clientToken, serverToken); - value = (int) d->calculateHash(clientToken, serverToken); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_getHash(int decoder, char* out) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = (int) d->getHash(out); - value = (int) d->getHash(out); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_isValid(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->isKeyValid(); - value = d->isKeyValid(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } #ifdef __cplusplus diff --git a/src/bncsutil/decodekey.h b/src/bncsutil/decodekey.h index dbade12..5dc8033 100644 --- a/src/bncsutil/decodekey.h +++ b/src/bncsutil/decodekey.h @@ -30,7 +30,7 @@ #ifdef __cplusplus extern "C" { #endif - + /** * Decodes a CD-key, retrieves its relevant values, and calculates a hash * suitable for SID_AUTH_CHECK (0x51) in one function call. Returns 1 on @@ -38,8 +38,8 @@ extern "C" { * calling this function. Available since BNCSutil 1.1.0. */ MEXP(int) kd_quick(const char* cd_key, uint32_t client_token, - uint32_t server_token, uint32_t* public_value, - uint32_t* product, char* hash_buffer, size_t buffer_len); + uint32_t server_token, uint32_t* public_value, + uint32_t* product, char* hash_buffer, size_t buffer_len); /** * Initializes the CD-key decoding C wrappers. @@ -96,7 +96,7 @@ MEXP(int) kd_longVal2(int decoder, char* out); * Returns the hash length or 0 on failure. */ MEXP(int) kd_calculateHash(int decoder, uint32_t clientToken, - uint32_t serverToken); + uint32_t serverToken); /** * Places the key hash in "out". The "out" buffer must be diff --git a/src/bncsutil/file.cpp b/src/bncsutil/file.cpp index 40fc9dc..a34fcca 100644 --- a/src/bncsutil/file.cpp +++ b/src/bncsutil/file.cpp @@ -21,12 +21,12 @@ typedef std::map mapping_map; struct _file { #if BWIN - HANDLE f; + HANDLE f; #else - FILE* f; + FILE* f; #endif - const char* filename; - mapping_map mappings; + const char* filename; + mapping_map mappings; }; #include @@ -39,276 +39,276 @@ extern "C" { file_t file_open(const char* filename, unsigned int mode) { - file_t data; - HANDLE file; - DWORD access; - DWORD share_mode; - DWORD open_mode; - const char* sys_err; - size_t filename_buf_len; - - if (mode & FILE_READ) { - access = GENERIC_READ; - share_mode = FILE_SHARE_READ; - open_mode = OPEN_EXISTING; - } else if (mode & FILE_WRITE) { - access = GENERIC_WRITE; - share_mode = 0; - open_mode = CREATE_ALWAYS; - } - - file = CreateFile(filename, access, share_mode, NULL, open_mode, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - sys_err = sys_error_msg(); - bncsutil_debug_message_a("Cannot open file \"%s\"; %s", filename, - sys_err); - free_sys_err_msg(sys_err); - return ((file_t) 0); - } - - try { - data = new _file; - } catch (std::bad_alloc) { - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "file structure.", sizeof(struct _file)); - CloseHandle(file); - return (file_t) 0; - } - - filename_buf_len = strlen(filename) + 1; - data->filename = (const char*) malloc(filename_buf_len); - if (!data->filename) { - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "filename.", filename_buf_len); - CloseHandle(file); - delete data; - return (file_t) 0; - } - strcpy_s((char*) data->filename, filename_buf_len, filename); - - data->f = file; - - return data; + file_t data; + HANDLE file; + DWORD access; + DWORD share_mode; + DWORD open_mode; + const char* sys_err; + size_t filename_buf_len; + + if (mode & FILE_READ) { + access = GENERIC_READ; + share_mode = FILE_SHARE_READ; + open_mode = OPEN_EXISTING; + } else if (mode & FILE_WRITE) { + access = GENERIC_WRITE; + share_mode = 0; + open_mode = CREATE_ALWAYS; + } + + file = CreateFile(filename, access, share_mode, NULL, open_mode, + FILE_ATTRIBUTE_NORMAL, NULL); + + if (file == INVALID_HANDLE_VALUE) { + sys_err = sys_error_msg(); + bncsutil_debug_message_a("Cannot open file \"%s\"; %s", filename, + sys_err); + free_sys_err_msg(sys_err); + return ((file_t) 0); + } + + try { + data = new _file; + } catch (std::bad_alloc) { + bncsutil_debug_message_a("Failed to allocate %u bytes to hold" + "file structure.", sizeof(struct _file)); + CloseHandle(file); + return (file_t) 0; + } + + filename_buf_len = strlen(filename) + 1; + data->filename = (const char*) malloc(filename_buf_len); + if (!data->filename) { + bncsutil_debug_message_a("Failed to allocate %u bytes to hold" + "filename.", filename_buf_len); + CloseHandle(file); + delete data; + return (file_t) 0; + } + strcpy_s((char*) data->filename, filename_buf_len, filename); + + data->f = file; + + return data; } void file_close(file_t file) { - mapping_map::iterator it; - - if (!file) { - bncsutil_debug_message_a("error: null pointer given to file_close"); - return; - } - - for (it = file->mappings.begin(); it != file->mappings.end(); it++) { - UnmapViewOfFile((*it).first); - CloseHandle((*it).second); - } - - CloseHandle((HANDLE) file->f); - free((void*) file->filename); - delete file; + mapping_map::iterator it; + + if (!file) { + bncsutil_debug_message_a("error: null pointer given to file_close"); + return; + } + + for (it = file->mappings.begin(); it != file->mappings.end(); it++) { + UnmapViewOfFile((*it).first); + CloseHandle((*it).second); + } + + CloseHandle((HANDLE) file->f); + free((void*) file->filename); + delete file; } size_t file_read(file_t file, void* ptr, size_t size, size_t count) { - DWORD bytes_read; - - if (!ReadFile(file->f, ptr, (DWORD) (size * count), &bytes_read, NULL)) { - return (size_t) 0; - } - - return (size_t) bytes_read; + DWORD bytes_read; + + if (!ReadFile(file->f, ptr, (DWORD) (size * count), &bytes_read, NULL)) { + return (size_t) 0; + } + + return (size_t) bytes_read; } size_t file_write(file_t file, const void* ptr, size_t size, - size_t count) + size_t count) { - DWORD bytes_written; - - if (!WriteFile(file->f, ptr, (DWORD) (size * count), &bytes_written, NULL)) - return (size_t) 0; - - return (size_t) bytes_written; + DWORD bytes_written; + + if (!WriteFile(file->f, ptr, (DWORD) (size * count), &bytes_written, NULL)) + return (size_t) 0; + + return (size_t) bytes_written; } size_t file_size(file_t file) { - return (size_t) GetFileSize(file->f, (LPDWORD) 0); + return (size_t) GetFileSize(file->f, (LPDWORD) 0); } void* file_map(file_t file, size_t len, off_t offset) { - HANDLE mapping = - CreateFileMapping((HANDLE) file->f, NULL, PAGE_READONLY, 0, 0, NULL); - void* base; - const char* err; - - if (!mapping) { - err = sys_error_msg(); - bncsutil_debug_message_a("Failed to create file mapping for \"%s\": %s", - file->filename, err); - free_sys_err_msg(err); - return (void*) 0; - } - - base = MapViewOfFile(mapping, FILE_MAP_READ, 0, (DWORD) offset, len); - if (!base) { - CloseHandle(mapping); - err = sys_error_msg(); - bncsutil_debug_message_a("Failed to map %u bytes of \"%s\" starting at " - "%u: %s", - len, file->filename, offset, err); - free_sys_err_msg(err); - return (void*) 0; - } - - file->mappings[base] = mapping; - - return base; + HANDLE mapping = + CreateFileMapping((HANDLE) file->f, NULL, PAGE_READONLY, 0, 0, NULL); + void* base; + const char* err; + + if (!mapping) { + err = sys_error_msg(); + bncsutil_debug_message_a("Failed to create file mapping for \"%s\": %s", + file->filename, err); + free_sys_err_msg(err); + return (void*) 0; + } + + base = MapViewOfFile(mapping, FILE_MAP_READ, 0, (DWORD) offset, len); + if (!base) { + CloseHandle(mapping); + err = sys_error_msg(); + bncsutil_debug_message_a("Failed to map %u bytes of \"%s\" starting at " + "%u: %s", + len, file->filename, offset, err); + free_sys_err_msg(err); + return (void*) 0; + } + + file->mappings[base] = mapping; + + return base; } void file_unmap(file_t file, const void* base) { - mapping_map::iterator item = file->mappings.find(base); - HANDLE mapping; - - if (item == file->mappings.end()) { - bncsutil_debug_message_a("warning: failed to unmap the block starting " - "at %p from %s; unknown block.", base, file->filename); - return; - } - - mapping = (*item).second; - - UnmapViewOfFile(base); - CloseHandle(mapping); - - file->mappings.erase(item); + mapping_map::iterator item = file->mappings.find(base); + HANDLE mapping; + + if (item == file->mappings.end()) { + bncsutil_debug_message_a("warning: failed to unmap the block starting " + "at %p from %s; unknown block.", base, file->filename); + return; + } + + mapping = (*item).second; + + UnmapViewOfFile(base); + CloseHandle(mapping); + + file->mappings.erase(item); } #else file_t file_open(const char* filename, unsigned int mode_flags) { - char mode[] = "rb"; - file_t data; - FILE* f; - size_t filename_buf_len; - const char* err; - - if (mode_flags & FILE_WRITE) - mode[0] = 'w'; - - f = fopen(filename, mode); - if (!f) { - return (file_t) 0; - } - - try { - data = new _file; - } catch (std::bad_alloc) { - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "file structure."), sizeof(struct _file)); - fclose(f); - return (file_t) 0; - } - - filename_buf_len = strlen(filename) + 1; - data->filename = (const char*) malloc(filename_buf_len); - if (!data->filename) { - err = sys_error_msg(); - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "filename; %s"), filename_buf_len); - free_sys_error_msg(err); - fclose(f); - delete data; - return (file_t) 0; - } - strcpy((char*) data->filename, filename); - - data->f = f; - - return data; + char mode[] = "rb"; + file_t data; + FILE* f; + size_t filename_buf_len; + const char* err; + + if (mode_flags & FILE_WRITE) + mode[0] = 'w'; + + f = fopen(filename, mode); + if (!f) { + return (file_t) 0; + } + + try { + data = new _file; + } catch (std::bad_alloc) { + bncsutil_debug_message_a("Failed to allocate %u bytes to hold" + "file structure."), sizeof(struct _file)); + fclose(f); + return (file_t) 0; + } + + filename_buf_len = strlen(filename) + 1; + data->filename = (const char*) malloc(filename_buf_len); + if (!data->filename) { + err = sys_error_msg(); + bncsutil_debug_message_a("Failed to allocate %u bytes to hold" + "filename; %s"), filename_buf_len); + free_sys_error_msg(err); + fclose(f); + delete data; + return (file_t) 0; + } + strcpy((char*) data->filename, filename); + + data->f = f; + + return data; } void file_close(file_t file) { - - if (!file) { - bncsutil_debug_message("error: null pointer given to file_close"); - return; - } - - for (it = file->mappings.begin(); it != file->mappings.end(); it++) { - munmap((void*) (*it).first, (*it).second); - } - - fclose(file->f); - delete file; + + if (!file) { + bncsutil_debug_message("error: null pointer given to file_close"); + return; + } + + for (it = file->mappings.begin(); it != file->mappings.end(); it++) { + munmap((void*) (*it).first, (*it).second); + } + + fclose(file->f); + delete file; } size_t file_read(file_t file, void* ptr, size_t size, size_t count) { - return fread(ptr, size, count, file->f); + return fread(ptr, size, count, file->f); } size_t file_write(file_t file, const void* ptr, size_t size, - size_t count) + size_t count) { - return fwrite(ptr, size, count, file->f); + return fwrite(ptr, size, count, file->f); } size_t file_size(file_t file) { - long cur_pos = ftell(file->f); - size_t size_of_file; - - fseek(file->f, 0, SEEK_END); - size_of_file = (size_t) ftell(file->f); - fseek(file->f, cur_pos, SEEK_SET); - - return size_of_file; + long cur_pos = ftell(file->f); + size_t size_of_file; + + fseek(file->f, 0, SEEK_END); + size_of_file = (size_t) ftell(file->f); + fseek(file->f, cur_pos, SEEK_SET); + + return size_of_file; } void* file_map(file_t file, size_t len, off_t offset) { - int fd = fileno(file->f); - void* base = mmap((void*) 0, len, PROT_READ, MAP_SHARED, fd, offset); - const char* err; - - if (!base) { - err = sys_error_msg(); - bncsutil_debug_message_a("error: failed to map %u bytes of %s " - "starting at %u into memory; %s", len, file->filename, offset, - err); - free_sys_error_msg(err); - return (void*) 0; - } - - file->mappings[base] = len; - - return base; + int fd = fileno(file->f); + void* base = mmap((void*) 0, len, PROT_READ, MAP_SHARED, fd, offset); + const char* err; + + if (!base) { + err = sys_error_msg(); + bncsutil_debug_message_a("error: failed to map %u bytes of %s " + "starting at %u into memory; %s", len, file->filename, offset, + err); + free_sys_error_msg(err); + return (void*) 0; + } + + file->mappings[base] = len; + + return base; } void file_unmap(file_t file, const void* base) { - mapping_map::iterator item = file->mappings.find(base); - size_t len; - - if (item == file->mappings.end()) { - bncsutil_debug_message_a("warning: failed to unmap the block starting " - "at %p from %s; unknown block.", base, file->filename); - return; - } - - len = (*item).second; - - munmap((void*) base, len); - - file->mappings.erase(item); + mapping_map::iterator item = file->mappings.find(base); + size_t len; + + if (item == file->mappings.end()) { + bncsutil_debug_message_a("warning: failed to unmap the block starting " + "at %p from %s; unknown block.", base, file->filename); + return; + } + + len = (*item).second; + + munmap((void*) base, len); + + file->mappings.erase(item); } #endif diff --git a/src/bncsutil/file.h b/src/bncsutil/file.h index 4721e28..3ff4bbd 100644 --- a/src/bncsutil/file.h +++ b/src/bncsutil/file.h @@ -41,15 +41,15 @@ extern "C" { typedef struct _file* file_t; -#define FILE_READ (0x01) -#define FILE_WRITE (0x02) +#define FILE_READ (0x01) +#define FILE_WRITE (0x02) file_t file_open(const char* filename, unsigned int mode); void file_close(file_t file); size_t file_read(file_t file, void* ptr, size_t size, size_t count); size_t file_write(file_t file, const void* ptr, size_t size, - size_t count); + size_t count); size_t file_size(file_t file); void* file_map(file_t file, size_t len, off_t offset); diff --git a/src/bncsutil/keytables.h b/src/bncsutil/keytables.h index e6cfe64..edb8e21 100644 --- a/src/bncsutil/keytables.h +++ b/src/bncsutil/keytables.h @@ -128,4 +128,4 @@ const unsigned char w3TranslateMap[] = { } // extern "C" #endif -#endif /* BNCSUTIL_KEYTABLES_H */ \ No newline at end of file +#endif /* BNCSUTIL_KEYTABLES_H */ diff --git a/src/bncsutil/libinfo.cpp b/src/bncsutil/libinfo.cpp index 99c4392..2a58a01 100644 --- a/src/bncsutil/libinfo.cpp +++ b/src/bncsutil/libinfo.cpp @@ -38,20 +38,19 @@ MEXP(int) bncsutil_getVersionString(char* outBuf) { // major major = (unsigned long) (BNCSUTIL_VERSION / 10000); if (major > 99 || major < 0) return 0; - + // minor ver -= (major * 10000); minor = (unsigned long) (ver / 100); if (minor > 99 || minor < 0) return 0; - + // revision ver -= (minor * 100); rev = ver; if (rev > 99 || rev < 0) return 0; - + printed = std::sprintf(outBuf, "%u.%u.%u", major, minor, rev); if (printed < 0) return 0; outBuf[8] = '\0'; return printed; } - \ No newline at end of file diff --git a/src/bncsutil/mutil.h b/src/bncsutil/mutil.h index aabdeac..6a346c8 100644 --- a/src/bncsutil/mutil.h +++ b/src/bncsutil/mutil.h @@ -33,12 +33,12 @@ /* Specific-Sized Integers */ #include "mutil_types.h" -#include +#include #ifdef _MSC_VER -#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */ -#define ROL(x,n) _lrotl((x),(n)) -#define ROR(x,n) _lrotr((x),(n)) +#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */ +#define ROL(x,n) _lrotl((x),(n)) +#define ROR(x,n) _lrotr((x),(n)) #else #ifndef ROL #define ROL(a,b) (((a) << (b)) | ((a) >> 32 - (b))) @@ -92,8 +92,8 @@ #define SWAP2(num) ((((num) >> 8) & 0x00FF) | (((num) << 8) & 0xFF00)) #define SWAP4(num) ((((num) >> 24) & 0x000000FF) | (((num) >> 8) & 0x0000FF00) | (((num) << 8) & 0x00FF0000) | (((num) << 24) & 0xFF000000)) -#define SWAP8(x) \ - (uint64_t)((((uint64_t)(x) & 0xff) << 56) | \ +#define SWAP8(x) \ + (uint64_t)((((uint64_t)(x) & 0xff) << 56) | \ ((uint64_t)(x) & 0xff00ULL) << 40 | \ ((uint64_t)(x) & 0xff0000ULL) << 24 | \ ((uint64_t)(x) & 0xff000000ULL) << 8 | \ @@ -119,17 +119,17 @@ #define MSB4(num) SWAP4(num) #endif /* (endianness) */ -#ifndef MOS_WINDOWS +#ifndef MOS_WINDOWS /* attempt automatic Windows detection */ - #ifdef _MSC_VER + #ifdef _MSC_VER /* Microsoft C++ compiler, has to be windows */ - #define MOS_WINDOWS - #else + #define MOS_WINDOWS + #else #if defined(_WIN) || defined(_WINDOWS) || defined(WINDOWS) || \ defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) #define MOS_WINDOWS - #endif - #endif + #endif + #endif #endif #if !(defined(MUTIL_LIB_BUILD)) && defined(BNCSUTIL_EXPORTS) diff --git a/src/bncsutil/nls.c b/src/bncsutil/nls.c index 997f06a..a765e02 100644 --- a/src/bncsutil/nls.c +++ b/src/bncsutil/nls.c @@ -36,17 +36,17 @@ struct _nls { const char* password; unsigned long username_len; unsigned long password_len; - + mpz_t n; mpz_t a; - + gmp_randstate_t rand; - char* A; - char* S; - char* K; - char* M1; - char* M2; + char* A; + char* S; + char* K; + char* M1; + char* M2; }; #ifdef MOS_WINDOWS @@ -95,7 +95,7 @@ uint32_t nls_get_u(const char* B); MEXP(nls_t*) nls_init(const char* username, const char* password) { return nls_init_l(username, (unsigned long) strlen(username), - password, (unsigned long) strlen(password)); + password, (unsigned long) strlen(password)); } MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, @@ -105,21 +105,21 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, char* d; /* destination */ const char* o; /* original */ nls_t* nls; - + nls = (nls_t*) malloc(sizeof(nls_t)); if (!nls) return (nls_t*) 0; - + nls->username_len = username_length; nls->password_len = password_length; - + nls->username = (char*) malloc(nls->username_len + 1); nls->password = (char*) malloc(nls->password_len + 1); if (!nls->username || !nls->password) { free(nls); return (nls_t*) 0; } - + d = (char*) nls->username; o = username; for (i = 0; i < nls->username_len; i++) { @@ -127,10 +127,10 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, d++; o++; } - + *((char*) nls->username + username_length) = 0; *((char*) nls->password + password_length) = 0; - + d = (char*) nls->password; o = password; for (i = 0; i < nls->password_len; i++) { @@ -138,9 +138,9 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, d++; o++; } - + mpz_init_set_str(nls->n, NLS_VAR_N_STR, 16); - + gmp_randinit_default(nls->rand); gmp_randseed_ui(nls->rand, nls_pre_seed()); mpz_init2(nls->a, 256); @@ -149,12 +149,12 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, /* The following line replaces preceding 2 lines during testing. */ /*mpz_init_set_str(nls->a, "1234", 10);*/ - nls->A = (char*) 0; - nls->S = (char*) 0; - nls->K = (char*) 0; - nls->M1 = (char*) 0; - nls->M2 = (char*) 0; - + nls->A = (char*) 0; + nls->S = (char*) 0; + nls->K = (char*) 0; + nls->M1 = (char*) 0; + nls->M2 = (char*) 0; + return nls; } @@ -167,63 +167,63 @@ MEXP(void) nls_free(nls_t* nls) { free((void*) nls->username); free((void*) nls->password); - if (nls->A) - free(nls->A); - if (nls->S) - free(nls->S); - if (nls->K) - free(nls->K); - if (nls->M1) - free(nls->M1); - if (nls->M2) - free(nls->M2); + if (nls->A) + free(nls->A); + if (nls->S) + free(nls->S); + if (nls->K) + free(nls->K); + if (nls->M1) + free(nls->M1); + if (nls->M2) + free(nls->M2); free(nls); } MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, - const char* password) + const char* password) { - return nls_reinit_l(nls, username, (unsigned long) strlen(username), - password, (unsigned long) strlen(password)); + return nls_reinit_l(nls, username, (unsigned long) strlen(username), + password, (unsigned long) strlen(password)); } MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, - unsigned long username_length, const char* password, - unsigned long password_length) + unsigned long username_length, const char* password, + unsigned long password_length) { - unsigned int i; + unsigned int i; char* d; /* destination */ const char* o; /* original */ - if (nls->A) - free(nls->A); - if (nls->S) - free(nls->S); - if (nls->K) - free(nls->K); - if (nls->M1) - free(nls->M1); - if (nls->M2) - free(nls->M2); - - nls->username_len = username_length; + if (nls->A) + free(nls->A); + if (nls->S) + free(nls->S); + if (nls->K) + free(nls->K); + if (nls->M1) + free(nls->M1); + if (nls->M2) + free(nls->M2); + + nls->username_len = username_length; nls->password_len = password_length; - - nls->username = (const char*) realloc((void*) nls->username, - nls->username_len + 1); - if (!nls->username) { + + nls->username = (const char*) realloc((void*) nls->username, + nls->username_len + 1); + if (!nls->username) { free(nls); return (nls_t*) 0; } nls->password = (const char*) realloc((void*) nls->password, - nls->password_len + 1); + nls->password_len + 1); if (!nls->password) { - free((void*) nls->username); + free((void*) nls->username); free(nls); return (nls_t*) 0; } - + d = (char*) nls->username; o = username; for (i = 0; i < nls->username_len; i++) { @@ -232,30 +232,30 @@ MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, o++; } - d = (char*) nls->password; + d = (char*) nls->password; o = password; for (i = 0; i < nls->password_len; i++) { *d = (char) toupper(*o); d++; o++; } - + *((char*) nls->username + username_length) = 0; *((char*) nls->password + password_length) = 0; - mpz_urandomm(nls->a, nls->rand, nls->n); /* generates the private key */ + mpz_urandomm(nls->a, nls->rand, nls->n); /* generates the private key */ - nls->A = (char*) 0; - nls->S = (char*) 0; - nls->K = (char*) 0; - nls->M1 = (char*) 0; - nls->M2 = (char*) 0; + nls->A = (char*) 0; + nls->S = (char*) 0; + nls->K = (char*) 0; + nls->M1 = (char*) 0; + nls->M2 = (char*) 0; - return nls; + return nls; } MEXP(unsigned long) nls_account_create(nls_t* nls, char* buf, unsigned long bufSize) { - mpz_t s; /* salt */ + mpz_t s; /* salt */ mpz_t v; mpz_t x; @@ -263,20 +263,20 @@ MEXP(unsigned long) nls_account_create(nls_t* nls, char* buf, unsigned long bufS return 0; if (bufSize < nls->username_len + 65) return 0; - + mpz_init2(s, 256); mpz_urandomb(s, nls->rand, 256); mpz_export(buf, (size_t*) 0, -1, 1, 0, 0, s); - /*memset(buf, 0, 32);*/ - + /*memset(buf, 0, 32);*/ + nls_get_x(nls, x, buf); nls_get_v_mpz(nls, v, x); mpz_export(buf + 32, (size_t*) 0, -1, 1, 0, 0, v); - - mpz_clear(x); + + mpz_clear(x); mpz_clear(v); mpz_clear(s); - + strcpy(buf + 64, nls->username); return nls->username_len + 65; } @@ -286,7 +286,7 @@ MEXP(unsigned long) nls_account_logon(nls_t* nls, char* buf, unsigned long bufSi return 0; if (bufSize < nls->username_len + 33) return 0; - + nls_get_A(nls, buf); strcpy(buf + 32, nls->username); return nls->username_len + 33; @@ -297,27 +297,27 @@ MEXP(nls_t*) nls_account_change_proof(nls_t* nls, char* buf, { nls_t* nouveau; mpz_t s; /* salt */ - + if (!nls) return (nls_t*) 0; - + /* create new nls_t */ nouveau = nls_init_l(nls->username, nls->username_len, new_password, (unsigned long) strlen(new_password)); if (!nouveau) return (nls_t*) 0; - + /* fill buf */ nls_get_M1(nls, buf, B, salt); - + mpz_init2(s, 256); mpz_urandomb(s, nouveau->rand, 256); mpz_export(buf + 20, (size_t*) 0, -1, 1, 0, 0, s); - - nls_get_v(nouveau, buf + 52, buf + 20); + + nls_get_v(nouveau, buf + 52, buf + 20); mpz_clear(s); - + return nouveau; } @@ -326,34 +326,34 @@ MEXP(void) nls_get_S(nls_t* nls, char* out, const char* B, const char* salt) { mpz_t S_base, S_exp; mpz_t x; mpz_t v; - + if (!nls) return; - if (nls->S) { - memcpy(out, nls->S, 32); - return; - } - + if (nls->S) { + memcpy(out, nls->S, 32); + return; + } + mpz_init2(temp, 256); mpz_import(temp, 32, -1, 1, 0, 0, B); - + nls_get_x(nls, x, salt); nls_get_v_mpz(nls, v, x); - + mpz_init_set(S_base, nls->n); mpz_add(S_base, S_base, temp); mpz_sub(S_base, S_base, v); mpz_mod(S_base, S_base, nls->n); - + mpz_init_set(S_exp, x); mpz_mul_ui(S_exp, S_exp, nls_get_u(B)); mpz_add(S_exp, S_exp, nls->a); - + mpz_clear(x); mpz_clear(v); mpz_clear(temp); - + mpz_init(temp); mpz_powm(temp, S_base, S_exp, nls->n); mpz_clear(S_base); @@ -361,25 +361,25 @@ MEXP(void) nls_get_S(nls_t* nls, char* out, const char* B, const char* salt) { mpz_export(out, (size_t*) 0, -1, 1, 0, 0, temp); mpz_clear(temp); - nls->S = (char*) malloc(32); - if (nls->S) - memcpy(nls->S, out, 32); + nls->S = (char*) malloc(32); + if (nls->S) + memcpy(nls->S, out, 32); } MEXP(void) nls_get_v(nls_t* nls, char* out, const char* salt) { mpz_t g; mpz_t v; mpz_t x; - + if (!nls) return; - + mpz_init_set_ui(g, NLS_VAR_g); mpz_init(v); nls_get_x(nls, x, salt); - + mpz_powm(v, g, x, nls->n); - + mpz_export(out, (size_t*) 0, -1, 1, 0, 0, v); mpz_clear(v); mpz_clear(g); @@ -391,62 +391,62 @@ MEXP(void) nls_get_A(nls_t* nls, char* out) { mpz_t g; mpz_t A; size_t o; - + if (!nls) return; - if (nls->A) { - memcpy(out, nls->A, 32); - return; - } - + if (nls->A) { + memcpy(out, nls->A, 32); + return; + } + mpz_init_set_ui(g, NLS_VAR_g); mpz_init2(A, 256); - + mpz_powm(A, g, nls->a, nls->n); mpz_export(out, &o, -1, 1, 0, 0, A); - + mpz_clear(A); mpz_clear(g); - nls->A = (char*) malloc(32); - if (nls->A) - memcpy(nls->A, out, 32); + nls->A = (char*) malloc(32); + if (nls->A) + memcpy(nls->A, out, 32); } MEXP(void) nls_get_K(nls_t* nls, char* out, const char* S) { char odd[16], even[16]; uint8_t odd_hash[20], even_hash[20]; - + char* Sp = (char*) S; char* op = odd; char* ep = even; unsigned int i; - + SHA1Context ctx; - if (!nls) - return; + if (!nls) + return; + + if (nls->K) { + memcpy(out, nls->K, 40); + return; + } - if (nls->K) { - memcpy(out, nls->K, 40); - return; - } - for (i = 0; i < 16; i++) { *(op++) = *(Sp++); *(ep++) = *(Sp++); } - + SHA1Reset(&ctx); SHA1Input(&ctx, (uint8_t*) odd, 16); SHA1Result(&ctx, odd_hash); - + SHA1Reset(&ctx); SHA1Input(&ctx, (uint8_t*) even, 16); SHA1Result(&ctx, even_hash); - + Sp = out; op = (char*) odd_hash; ep = (char*) even_hash; @@ -455,9 +455,9 @@ MEXP(void) nls_get_K(nls_t* nls, char* out, const char* S) { *(Sp++) = *(ep++); } - nls->K = (char*) malloc(40); - if (nls->K) - memcpy(nls->K, out, 40); + nls->K = (char*) malloc(40); + if (nls->K) + memcpy(nls->K, out, 40); } MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { @@ -467,21 +467,21 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { char S[32]; char K[40]; - if (!nls) - return; + if (!nls) + return; - if (nls->M1) { - nls_dbg("nls_get_M1(): Using cached M[1] value."); - memcpy(out, nls->M1, 20); - return; - } + if (nls->M1) { + nls_dbg("nls_get_M1(): Using cached M[1] value."); + memcpy(out, nls->M1, 20); + return; + } /* calculate SHA-1 hash of username */ SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); SHA1Result(&sha, username_hash); - + nls_get_A(nls, A); nls_get_S(nls, S, B, salt); nls_get_K(nls, K, S); @@ -496,9 +496,9 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { SHA1Input(&sha, (uint8_t*) K, 40); SHA1Result(&sha, (uint8_t*) out); - nls->M1 = (char*) malloc(20); - if (nls->M1) - memcpy(nls->M1, out, 20); + nls->M1 = (char*) malloc(20); + if (nls->M1) + memcpy(nls->M1, out, 20); } MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, @@ -506,66 +506,66 @@ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, { SHA1Context sha; char local_M2[20]; - char* A; - char S[32]; - char* K; - char* M1; + char* A; + char S[32]; + char* K; + char* M1; uint8_t username_hash[20]; - int res; - int mustFree = 0; - - if (!nls) - return 0; - - if (nls->M2) - return (memcmp(nls->M2, var_M2, 20) == 0); - - if (nls->A && nls->K && nls->M1) { - A = nls->A; - K = nls->K; - M1 = nls->M1; - } else { - if (!B || !salt) - return 0; - - A = (char*) malloc(32); - if (!A) - return 0; - K = (char*) malloc(40); - if (!K) { - free(A); - return 0; - } - M1 = (char*) malloc(20); - if (!M1) { - free(K); - free(A); - return 0; - } - - mustFree = 1; - - /* get the other values needed for the hash */ - nls_get_A(nls, A); - nls_get_S(nls, S, (char*) B, (char*) salt); - nls_get_K(nls, K, S); - - /* calculate SHA-1 hash of username */ - SHA1Reset(&sha); - SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); - SHA1Result(&sha, username_hash); - - /* calculate M[1] */ - SHA1Reset(&sha); - SHA1Input(&sha, (uint8_t*) bncsutil_NLS_I, 20); - SHA1Input(&sha, username_hash, 20); - SHA1Input(&sha, (uint8_t*) salt, 32); - SHA1Input(&sha, (uint8_t*) A, 32); - SHA1Input(&sha, (uint8_t*) B, 32); - SHA1Input(&sha, (uint8_t*) K, 40); - SHA1Result(&sha, (uint8_t*) M1); - } - + int res; + int mustFree = 0; + + if (!nls) + return 0; + + if (nls->M2) + return (memcmp(nls->M2, var_M2, 20) == 0); + + if (nls->A && nls->K && nls->M1) { + A = nls->A; + K = nls->K; + M1 = nls->M1; + } else { + if (!B || !salt) + return 0; + + A = (char*) malloc(32); + if (!A) + return 0; + K = (char*) malloc(40); + if (!K) { + free(A); + return 0; + } + M1 = (char*) malloc(20); + if (!M1) { + free(K); + free(A); + return 0; + } + + mustFree = 1; + + /* get the other values needed for the hash */ + nls_get_A(nls, A); + nls_get_S(nls, S, (char*) B, (char*) salt); + nls_get_K(nls, K, S); + + /* calculate SHA-1 hash of username */ + SHA1Reset(&sha); + SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); + SHA1Result(&sha, username_hash); + + /* calculate M[1] */ + SHA1Reset(&sha); + SHA1Input(&sha, (uint8_t*) bncsutil_NLS_I, 20); + SHA1Input(&sha, username_hash, 20); + SHA1Input(&sha, (uint8_t*) salt, 32); + SHA1Input(&sha, (uint8_t*) A, 32); + SHA1Input(&sha, (uint8_t*) B, 32); + SHA1Input(&sha, (uint8_t*) K, 40); + SHA1Result(&sha, (uint8_t*) M1); + } + /* calculate M[2] */ SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) A, 32); @@ -573,19 +573,19 @@ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, SHA1Input(&sha, (uint8_t*) K, 40); SHA1Result(&sha, (uint8_t*) local_M2); - res = (memcmp(local_M2, var_M2, 20) == 0); + res = (memcmp(local_M2, var_M2, 20) == 0); + + if (mustFree) { + free(A); + free(K); + free(M1); + } - if (mustFree) { - free(A); - free(K); - free(M1); - } + /* cache result */ + nls->M2 = (char*) malloc(20); + if (nls->M2) + memcpy(nls->M2, local_M2, 20); - /* cache result */ - nls->M2 = (char*) malloc(20); - if (nls->M2) - memcpy(nls->M2, local_M2, 20); - return res; } @@ -595,55 +595,55 @@ MEXP(int) nls_check_signature(uint32_t address, const char* signature_raw) { mpz_t result; mpz_t modulus; mpz_t signature; - size_t size, alloc_size; - int cmp_result; - + size_t size, alloc_size; + int cmp_result; + /* build the "check" array */ - memcpy(check, &address, 4); - memset(check + 4, 0xBB, 28); - + memcpy(check, &address, 4); + memset(check + 4, 0xBB, 28); + /* initialize the modulus */ mpz_init2(modulus, 1024); mpz_import(modulus, 128, -1, 1, 0, 0, bncsutil_NLS_sig_n); - + /* initialize the server signature */ mpz_init2(signature, 1024); mpz_import(signature, 128, -1, 1, 0, 0, signature_raw); - + /* initialize the result */ mpz_init2(result, 1024); - + /* calculate the result */ mpz_powm_ui(result, signature, NLS_SIGNATURE_KEY, modulus); - + /* clear (free) the intermediates */ mpz_clear(signature); mpz_clear(modulus); - /* allocate space for raw signature */ - alloc_size = mpz_size(result) * sizeof(mp_limb_t); - result_raw = (char*) malloc(alloc_size); - if (!result_raw) { - mpz_clear(result); - return 0; - } - + /* allocate space for raw signature */ + alloc_size = mpz_size(result) * sizeof(mp_limb_t); + result_raw = (char*) malloc(alloc_size); + if (!result_raw) { + mpz_clear(result); + return 0; + } + /* get a byte array of the signature */ mpz_export(result_raw, &size, -1, 1, 0, 0, result); - + /* clear (free) the result */ mpz_clear(result); - + /* check the result */ cmp_result = (memcmp(result_raw, check, 32) == 0); - /* free the result_raw buffer */ - free(result_raw); + /* free the result_raw buffer */ + free(result_raw); - /* return */ - return cmp_result; + /* return */ + return cmp_result; } - + unsigned long nls_pre_seed() { #ifdef MOS_WINDOWS return (unsigned long) GetTickCount(); @@ -673,28 +673,28 @@ void nls_get_x(nls_t* nls, mpz_t x_c, const char* raw_salt) { char* userpass; uint8_t hash[20], final_hash[20]; SHA1Context shac; - + // build the string Username:Password userpass = (char*) malloc(nls->username_len + nls->password_len + 2); memcpy(userpass, nls->username, nls->username_len); userpass[nls->username_len] = ':'; memcpy(userpass + nls->username_len + 1, nls->password, nls->password_len); userpass[nls->username_len + nls->password_len + 1] = 0; // null-terminator - + // get the SHA-1 hash of the string SHA1Reset(&shac); SHA1Input(&shac, (uint8_t*) userpass, (nls->username_len + nls->password_len + 1)); SHA1Result(&shac, hash); free(userpass); - + // get the SHA-1 hash of the salt and user:pass hash SHA1Reset(&shac); SHA1Input(&shac, (uint8_t*) raw_salt, 32); SHA1Input(&shac, hash, 20); SHA1Result(&shac, final_hash); SHA1Reset(&shac); - + // create an arbitrary-length integer from the hash and return it mpz_init2(x_c, 160); mpz_import(x_c, 20, -1, 1, 0, 0, (char*) final_hash); @@ -712,12 +712,12 @@ uint32_t nls_get_u(const char* B) { SHA1Context sha; uint8_t hash[20]; uint32_t u; - + SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) B, 32); SHA1Result(&sha, hash); SHA1Reset(&sha); - + u = *(uint32_t*) hash; u = MSB4(u); // needed? yes return u; diff --git a/src/bncsutil/nls.h b/src/bncsutil/nls.h index 3e94df1..f132559 100644 --- a/src/bncsutil/nls.h +++ b/src/bncsutil/nls.h @@ -72,7 +72,7 @@ MEXP(void) nls_free(nls_t* nls); * pointer on failure. */ MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, - const char* password); + const char* password); /** * Re-initializes an nls_t structure with a new username and @@ -80,8 +80,8 @@ MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, * on success or a NULL pointer on failure. */ MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, - unsigned long username_length, const char* password, - unsigned long password_length); + unsigned long username_length, const char* password, + unsigned long password_length); /* Packet Generation Functions */ @@ -161,8 +161,8 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt); * safely set to NULL. */ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, - const char* salt); - + const char* salt); + /** * Checks the server signature received in SID_AUTH_INFO (0x50). * Pass the IPv4 address of the server you're connecting to in the address @@ -188,142 +188,142 @@ MEXP(int) nls_check_signature(uint32_t address, const char* signature_raw); class NLS { public: - NLS(const char* username, const char* password) : n((nls_t*) 0) - { - n = nls_init(username, password); - } - - NLS(const char* username, size_t username_length, const char* password, - size_t password_length) - { - n = nls_init_l(username, username_length, password, password_length); - } - - NLS(const std::string& username, const std::string& password) - { - n = nls_init_l(username.c_str(), username.length(), - password.c_str(), password.length()); - } - - virtual ~NLS() - { - std::vector::iterator i; - - if (n) - nls_free(n); - - for (i = blocks.begin(); i != blocks.end(); i++) { - delete [] *i; - } - } - - void getSecret(char* out, const char* salt, const char* B) - { - nls_get_S(n, out, B, salt); - } - - const char* getSecret(const char* salt, const char* B) - { - char* buf = allocateBuffer(32); - getSecret(buf, salt, B); - return buf; - } - - void getVerifier(char* out, const char* salt) - { - nls_get_v(n, out, salt); - } - - const char* getVerifier(const char* salt) - { - char* buf = allocateBuffer(32); - getVerifier(buf, salt); - return buf; - } - - void getPublicKey(char* out) - { - nls_get_A(n, out); - } - - const char* getPublicKey(void) - { - char* buf = allocateBuffer(32); - getPublicKey(buf); - return buf; - } - - void getHashedSecret(char* out, const char* secret) - { - nls_get_K(n, out, secret); - } - - const char* getHashedSecret(const char* secret) - { - char* buf = allocateBuffer(40); - getHashedSecret(buf, secret); - return buf; - } - - void getClientSessionKey(char* out, const char* salt, const char* B) - { - nls_get_M1(n, out, B, salt); - } - - const char* getClientSessionKey(const char* salt, const char* B) - { - char* buf = allocateBuffer(20); - getClientSessionKey(buf, salt, B); - return buf; - } - - bool checkServerSessionKey(const char* key, const char* salt, - const char* B) - { - return (nls_check_M2(n, key, B, salt) != 0); - } - - NLS makeChangeProof(char* buf, const char* new_password, const char* salt, - const char* B) - { - return NLS(nls_account_change_proof(n, buf, new_password, B, salt)); - } - - NLS makeChangeProof(char* buf, const std::string& new_password, - const char* salt, const char* B) - { - return NLS(nls_account_change_proof(n, buf, new_password.c_str(), B, - salt)); - } - - std::pair makeChangeProof(const char* new_password, - const char* salt, const char* B) - { - char* buf = allocateBuffer(84); - NLS nls = NLS(nls_account_change_proof(n, buf, new_password, B, salt)); - return std::pair(nls, buf); - } - - std::pair makeChangeProof(const std::string& new_password, - const char* salt, const char* B) - { - return makeChangeProof(new_password.c_str(), salt, B); - } + NLS(const char* username, const char* password) : n((nls_t*) 0) + { + n = nls_init(username, password); + } + + NLS(const char* username, size_t username_length, const char* password, + size_t password_length) + { + n = nls_init_l(username, username_length, password, password_length); + } + + NLS(const std::string& username, const std::string& password) + { + n = nls_init_l(username.c_str(), username.length(), + password.c_str(), password.length()); + } + + virtual ~NLS() + { + std::vector::iterator i; + + if (n) + nls_free(n); + + for (i = blocks.begin(); i != blocks.end(); i++) { + delete [] *i; + } + } + + void getSecret(char* out, const char* salt, const char* B) + { + nls_get_S(n, out, B, salt); + } + + const char* getSecret(const char* salt, const char* B) + { + char* buf = allocateBuffer(32); + getSecret(buf, salt, B); + return buf; + } + + void getVerifier(char* out, const char* salt) + { + nls_get_v(n, out, salt); + } + + const char* getVerifier(const char* salt) + { + char* buf = allocateBuffer(32); + getVerifier(buf, salt); + return buf; + } + + void getPublicKey(char* out) + { + nls_get_A(n, out); + } + + const char* getPublicKey(void) + { + char* buf = allocateBuffer(32); + getPublicKey(buf); + return buf; + } + + void getHashedSecret(char* out, const char* secret) + { + nls_get_K(n, out, secret); + } + + const char* getHashedSecret(const char* secret) + { + char* buf = allocateBuffer(40); + getHashedSecret(buf, secret); + return buf; + } + + void getClientSessionKey(char* out, const char* salt, const char* B) + { + nls_get_M1(n, out, B, salt); + } + + const char* getClientSessionKey(const char* salt, const char* B) + { + char* buf = allocateBuffer(20); + getClientSessionKey(buf, salt, B); + return buf; + } + + bool checkServerSessionKey(const char* key, const char* salt, + const char* B) + { + return (nls_check_M2(n, key, B, salt) != 0); + } + + NLS makeChangeProof(char* buf, const char* new_password, const char* salt, + const char* B) + { + return NLS(nls_account_change_proof(n, buf, new_password, B, salt)); + } + + NLS makeChangeProof(char* buf, const std::string& new_password, + const char* salt, const char* B) + { + return NLS(nls_account_change_proof(n, buf, new_password.c_str(), B, + salt)); + } + + std::pair makeChangeProof(const char* new_password, + const char* salt, const char* B) + { + char* buf = allocateBuffer(84); + NLS nls = NLS(nls_account_change_proof(n, buf, new_password, B, salt)); + return std::pair(nls, buf); + } + + std::pair makeChangeProof(const std::string& new_password, + const char* salt, const char* B) + { + return makeChangeProof(new_password.c_str(), salt, B); + } private: - std::vector blocks; - nls_t* n; - - NLS(nls_t* nls) - { - n = nls; - } - - char* allocateBuffer(size_t length) - { - char* buf = new char[length]; - blocks.push_back(buf); - return buf; - } + std::vector blocks; + nls_t* n; + + NLS(nls_t* nls) + { + n = nls; + } + + char* allocateBuffer(size_t length) + { + char* buf = new char[length]; + blocks.push_back(buf); + return buf; + } }; #endif diff --git a/src/bncsutil/oldauth.cpp b/src/bncsutil/oldauth.cpp index 804634a..bde739d 100644 --- a/src/bncsutil/oldauth.cpp +++ b/src/bncsutil/oldauth.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include // for MEXP() #include #include @@ -44,11 +44,11 @@ uint32_t serverToken, char* outBuffer) { lp[0] = clientToken; lp[1] = serverToken; calcHashBuf(intermediate, 28, outBuffer); - + #if DEBUG - bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =", - password, clientToken, serverToken); - bncsutil_debug_dump(outBuffer, 20); + bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =", + password, clientToken, serverToken); + bncsutil_debug_dump(outBuffer, 20); #endif } @@ -61,7 +61,7 @@ MEXP(void) hashPassword(const char* password, char* outBuffer) { calcHashBuf(password, std::strlen(password), outBuffer); #if DEBUG - bncsutil_debug_message_a("hashPassword(\"%s\") =", password); - bncsutil_debug_dump(outBuffer, 20); + bncsutil_debug_message_a("hashPassword(\"%s\") =", password); + bncsutil_debug_dump(outBuffer, 20); #endif -} \ No newline at end of file +} diff --git a/src/bncsutil/oldauth.h b/src/bncsutil/oldauth.h index 95016ff..a0382cc 100644 --- a/src/bncsutil/oldauth.h +++ b/src/bncsutil/oldauth.h @@ -46,4 +46,4 @@ MEXP(void) hashPassword(const char* password, char* outBuffer); } // extern "C" #endif -#endif /* BNCSUTIL_OLDAUTH_H */ \ No newline at end of file +#endif /* BNCSUTIL_OLDAUTH_H */ diff --git a/src/bncsutil/pe.c b/src/bncsutil/pe.c index a762858..b83e321 100644 --- a/src/bncsutil/pe.c +++ b/src/bncsutil/pe.c @@ -32,453 +32,453 @@ int cm_pe_load_resdir(FILE* f, uint32_t offset, cm_pe_resdir_t* dir); MEXP(cm_pe_t) cm_pe_load(const char* filename) { - cm_pe_t pe; - cm_pe_header_t* header; - cm_pe_optional_header_t* opt_header; - cm_pe_windows_header_t* win_header; - long pe_offset = 0; - size_t i; - size_t count; - - pe = (cm_pe_t) malloc(sizeof(struct cm_pe)); - if (!pe) - return (cm_pe_t) 0; - - memset(pe, 0, sizeof(struct cm_pe)); - - pe->f = fopen(filename, "r"); - if (!pe->f) { - free(pe); - return (cm_pe_t) 0; - } - - if (fseek(pe->f, 0x3CL, SEEK_SET) == -1) - goto err_trap; - - if (fread(&pe_offset, 4, 1, pe->f) != 1) - goto err_trap; - + cm_pe_t pe; + cm_pe_header_t* header; + cm_pe_optional_header_t* opt_header; + cm_pe_windows_header_t* win_header; + long pe_offset = 0; + size_t i; + size_t count; + + pe = (cm_pe_t) malloc(sizeof(struct cm_pe)); + if (!pe) + return (cm_pe_t) 0; + + memset(pe, 0, sizeof(struct cm_pe)); + + pe->f = fopen(filename, "r"); + if (!pe->f) { + free(pe); + return (cm_pe_t) 0; + } + + if (fseek(pe->f, 0x3CL, SEEK_SET) == -1) + goto err_trap; + + if (fread(&pe_offset, 4, 1, pe->f) != 1) + goto err_trap; + #if BIG_ENDIAN - pe_offset = LSB4(pe_offset); + pe_offset = LSB4(pe_offset); #endif - - if (fseek(pe->f, pe_offset, SEEK_SET) == -1) - goto err_trap; - - if (fread(&pe->header, sizeof(cm_pe_header_t), 1, pe->f) != 1) - goto err_trap; - - header = &pe->header; + + if (fseek(pe->f, pe_offset, SEEK_SET) == -1) + goto err_trap; + + if (fread(&pe->header, sizeof(cm_pe_header_t), 1, pe->f) != 1) + goto err_trap; + + header = &pe->header; #if BIGENDIAN - /* Without regular expressions, this would've sucked. */ - header->signature = SWAP32(header->signature); - header->machine = SWAP16(header->machine); - header->section_count = SWAP16(header->section_count); - header->timestamp = SWAP32(header->timestamp); - header->symbol_table_offset = SWAP32(header->symbol_table_offset); - header->symbol_count = SWAP32(header->symbol_count); - header->optional_header_size = SWAP16(header->optional_header_size); - header->characteristics = SWAP16(header->characteristics); + /* Without regular expressions, this would've sucked. */ + header->signature = SWAP32(header->signature); + header->machine = SWAP16(header->machine); + header->section_count = SWAP16(header->section_count); + header->timestamp = SWAP32(header->timestamp); + header->symbol_table_offset = SWAP32(header->symbol_table_offset); + header->symbol_count = SWAP32(header->symbol_count); + header->optional_header_size = SWAP16(header->optional_header_size); + header->characteristics = SWAP16(header->characteristics); #endif - - if (header->optional_header_size > 0) { - if (fread(&pe->optional_header, PE_OPTIONAL_HEADER_MIN_SIZE, 1, pe->f) - != 1) - { - goto err_trap; - } - - opt_header = &pe->optional_header; - win_header = &pe->windows_header; - + + if (header->optional_header_size > 0) { + if (fread(&pe->optional_header, PE_OPTIONAL_HEADER_MIN_SIZE, 1, pe->f) + != 1) + { + goto err_trap; + } + + opt_header = &pe->optional_header; + win_header = &pe->windows_header; + #if BIGENDIAN - opt_header->magic = SWAP16(opt_header->magic); + opt_header->magic = SWAP16(opt_header->magic); #endif - - if (opt_header->magic == IMAGE_FORMAT_PE32) { - if (fread(&opt_header->data_base, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->image_base, 4, 1, pe->f) != 1) - goto err_trap; - // The 40 is not a typo. - if (fread(&win_header->section_alignment, 40, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->stack_reserve_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->stack_commit_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->heap_reserve_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->heap_commit_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->loader_flags, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->data_directory_count, 4, 1, pe->f) != 1) - goto err_trap; - } else if (opt_header->magic == IMAGE_FORMAT_PE32_PLUS) { - if (fread(win_header, sizeof(cm_pe_windows_header_t), 1, pe->f)!= 1) - goto err_trap; - } else { - goto err_trap; - } - + + if (opt_header->magic == IMAGE_FORMAT_PE32) { + if (fread(&opt_header->data_base, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->image_base, 4, 1, pe->f) != 1) + goto err_trap; + // The 40 is not a typo. + if (fread(&win_header->section_alignment, 40, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->stack_reserve_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->stack_commit_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->heap_reserve_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->heap_commit_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->loader_flags, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->data_directory_count, 4, 1, pe->f) != 1) + goto err_trap; + } else if (opt_header->magic == IMAGE_FORMAT_PE32_PLUS) { + if (fread(win_header, sizeof(cm_pe_windows_header_t), 1, pe->f)!= 1) + goto err_trap; + } else { + goto err_trap; + } + #if BIGENDIAN - opt_header->code_section_size = SWAP32(opt_header->code_section_size); - opt_header->initialized_data_size = - SWAP32(opt_header->initialized_data_size); - opt_header->uninitialized_data_size = - SWAP32(opt_header->uninitialized_data_size); - opt_header->entry_point = SWAP32(opt_header->entry_point); - opt_header->code_base = SWAP32(opt_header->code_base); - opt_header->data_base = SWAP32(opt_header->data_base); - - win_header->image_base = SWAP64(win_header->image_base); - win_header->section_alignment = SWAP32(win_header->section_alignment); - win_header->file_alignment = SWAP32(win_header->file_alignment); - win_header->major_os_version = SWAP16(win_header->major_os_version); - win_header->minor_os_version = SWAP16(win_header->minor_os_version); - win_header->major_image_version = - SWAP16(win_header->major_image_version); - win_header->minor_image_version = - SWAP16(win_header->minor_image_version); - win_header->major_subsystem_version = - SWAP16(win_header->major_subsystem_version); - win_header->minor_subsystem_version = - SWAP16(win_header->minor_subsystem_version); - win_header->reserved = SWAP32(win_header->reserved); - win_header->image_size = SWAP32(win_header->image_size); - win_header->headers_size = SWAP32(win_header->headers_size); - win_header->checksum = SWAP32(win_header->checksum); - win_header->subsystem = SWAP16(win_header->subsystem); - win_header->dll_characteristics = - SWAP16(win_header->dll_characteristics); - win_header->stack_reserve_size = SWAP64(win_header->stack_reserve_size); - win_header->stack_commit_size = SWAP64(win_header->stack_commit_size); - win_header->heap_reserve_size = SWAP64(win_header->heap_reserve_size); - win_header->heap_commit_size = SWAP64(win_header->heap_commit_size); - win_header->loader_flags = SWAP32(win_header->loader_flags); - win_header->data_directory_count = - SWAP32(win_header->data_directory_count); + opt_header->code_section_size = SWAP32(opt_header->code_section_size); + opt_header->initialized_data_size = + SWAP32(opt_header->initialized_data_size); + opt_header->uninitialized_data_size = + SWAP32(opt_header->uninitialized_data_size); + opt_header->entry_point = SWAP32(opt_header->entry_point); + opt_header->code_base = SWAP32(opt_header->code_base); + opt_header->data_base = SWAP32(opt_header->data_base); + + win_header->image_base = SWAP64(win_header->image_base); + win_header->section_alignment = SWAP32(win_header->section_alignment); + win_header->file_alignment = SWAP32(win_header->file_alignment); + win_header->major_os_version = SWAP16(win_header->major_os_version); + win_header->minor_os_version = SWAP16(win_header->minor_os_version); + win_header->major_image_version = + SWAP16(win_header->major_image_version); + win_header->minor_image_version = + SWAP16(win_header->minor_image_version); + win_header->major_subsystem_version = + SWAP16(win_header->major_subsystem_version); + win_header->minor_subsystem_version = + SWAP16(win_header->minor_subsystem_version); + win_header->reserved = SWAP32(win_header->reserved); + win_header->image_size = SWAP32(win_header->image_size); + win_header->headers_size = SWAP32(win_header->headers_size); + win_header->checksum = SWAP32(win_header->checksum); + win_header->subsystem = SWAP16(win_header->subsystem); + win_header->dll_characteristics = + SWAP16(win_header->dll_characteristics); + win_header->stack_reserve_size = SWAP64(win_header->stack_reserve_size); + win_header->stack_commit_size = SWAP64(win_header->stack_commit_size); + win_header->heap_reserve_size = SWAP64(win_header->heap_reserve_size); + win_header->heap_commit_size = SWAP64(win_header->heap_commit_size); + win_header->loader_flags = SWAP32(win_header->loader_flags); + win_header->data_directory_count = + SWAP32(win_header->data_directory_count); #endif - - if (win_header->data_directory_count > 0) { - count = win_header->data_directory_count; - pe->data_directories = (cm_pe_data_directory_t*) - calloc(sizeof(cm_pe_data_directory_t), count); - - if (!pe->data_directories) - goto err_trap; - - if (fread(pe->data_directories, sizeof(cm_pe_data_directory_t), - count, pe->f) != count) - { - goto dir_err_trap; - } - + + if (win_header->data_directory_count > 0) { + count = win_header->data_directory_count; + pe->data_directories = (cm_pe_data_directory_t*) + calloc(sizeof(cm_pe_data_directory_t), count); + + if (!pe->data_directories) + goto err_trap; + + if (fread(pe->data_directories, sizeof(cm_pe_data_directory_t), + count, pe->f) != count) + { + goto dir_err_trap; + } + #if BIGENDIAN - for (i = 0; i < count; i++) { - pe->data_directories[i].rva = - SWAP32(pe->data_directories[i].rva); - pe->data_directories[i].size = - SWAP32(pe->data_directories[i].size); - } + for (i = 0; i < count; i++) { + pe->data_directories[i].rva = + SWAP32(pe->data_directories[i].rva); + pe->data_directories[i].size = + SWAP32(pe->data_directories[i].size); + } #endif - } - - count = (size_t) header->section_count; - if (count) { - pe->sections = (cm_pe_section_t*) calloc(sizeof(cm_pe_section_t), - count); - - if (!pe->sections) - goto dir_err_trap; - - if (fread(pe->sections, sizeof(cm_pe_section_t), count, pe->f) - != count) - { - goto sect_err_trap; - } - } - + } + + count = (size_t) header->section_count; + if (count) { + pe->sections = (cm_pe_section_t*) calloc(sizeof(cm_pe_section_t), + count); + + if (!pe->sections) + goto dir_err_trap; + + if (fread(pe->sections, sizeof(cm_pe_section_t), count, pe->f) + != count) + { + goto sect_err_trap; + } + } + #if BIGENDIAN - for (i = 0; i < count; i++) { - pe->sections[i].virtual_size = SWAP32(pe->sections[i].virtual_size); - pe->sections[i].virtual_address = - SWAP32(pe->sections[i].virtual_address); - pe->sections[i].raw_data_size = - SWAP32(pe->sections[i].raw_data_size); - pe->sections[i].raw_data_offset = - SWAP32(pe->sections[i].raw_data_offset); - pe->sections[i].relocations_offset = - SWAP32(pe->sections[i].relocations_offset); - pe->sections[i].line_numbers_offset = - SWAP32(pe->sections[i].line_numbers_offset); - pe->sections[i].relocation_count = - SWAP16(pe->sections[i].relocation_count); - pe->sections[i].line_number_count = - SWAP16(pe->sections[i].line_number_count); - pe->sections[i].characteristics = - SWAP32(pe->sections[i].characteristics); - } + for (i = 0; i < count; i++) { + pe->sections[i].virtual_size = SWAP32(pe->sections[i].virtual_size); + pe->sections[i].virtual_address = + SWAP32(pe->sections[i].virtual_address); + pe->sections[i].raw_data_size = + SWAP32(pe->sections[i].raw_data_size); + pe->sections[i].raw_data_offset = + SWAP32(pe->sections[i].raw_data_offset); + pe->sections[i].relocations_offset = + SWAP32(pe->sections[i].relocations_offset); + pe->sections[i].line_numbers_offset = + SWAP32(pe->sections[i].line_numbers_offset); + pe->sections[i].relocation_count = + SWAP16(pe->sections[i].relocation_count); + pe->sections[i].line_number_count = + SWAP16(pe->sections[i].line_number_count); + pe->sections[i].characteristics = + SWAP32(pe->sections[i].characteristics); + } #endif - } - - return pe; + } + + return pe; sect_err_trap: - free(pe->sections); + free(pe->sections); dir_err_trap: - free(pe->data_directories); + free(pe->data_directories); err_trap: - fclose(pe->f); - free(pe); - return (cm_pe_t) 0; + fclose(pe->f); + free(pe); + return (cm_pe_t) 0; } MEXP(void) cm_pe_unload(cm_pe_t pe) { - if (pe->data_directories) - free(pe->data_directories); - if (pe->sections) - free(pe->sections); - if (pe->f) - fclose(pe->f); - free(pe); + if (pe->data_directories) + free(pe->data_directories); + if (pe->sections) + free(pe->sections); + if (pe->f) + fclose(pe->f); + free(pe); } MEXP(cm_pe_section_t*) cm_pe_get_section(cm_pe_t pe, const char* name) { - unsigned int i; - cm_pe_section_t* s; - uint32_t section_count = pe->header.section_count; - - if (!pe || !pe->sections) - return (cm_pe_section_t*) 0; - - for (i = 0, s = pe->sections; i < section_count; i++, s++) { - if (strcmp(s->name, name) == 0) - return s; - } - - return (cm_pe_section_t*) 0; + unsigned int i; + cm_pe_section_t* s; + uint32_t section_count = pe->header.section_count; + + if (!pe || !pe->sections) + return (cm_pe_section_t*) 0; + + for (i = 0, s = pe->sections; i < section_count; i++, s++) { + if (strcmp(s->name, name) == 0) + return s; + } + + return (cm_pe_section_t*) 0; } MEXP(cm_pe_resdir_t*) cm_pe_load_resources(cm_pe_t pe) { - cm_pe_section_t* sect; - cm_pe_resdir_t* root = (cm_pe_resdir_t*) 0; - cm_pe_resdir_t* dir; - cm_pe_resdir_t* subdirs; - cm_pe_res_t res; - cm_pe_res_t* resources; - cm_stack_t stack; - size_t i; - uint32_t base; - - // no need to check validity of pe pointer; cm_pe_get_section does this - sect = cm_pe_get_section(pe, ".rsrc"); - if (!sect) - return (cm_pe_resdir_t*) 0; - - root = (cm_pe_resdir_t*) malloc(sizeof(cm_pe_resdir_t)); - if (!root) - return (cm_pe_resdir_t*) 0; - - base = sect->raw_data_offset; - if (!cm_pe_load_resdir(pe->f, base, root)) { - free(root); - return (cm_pe_resdir_t*) 0; - } - - stack = cm_stack_create(); - if (!stack) { - free(root); - return (cm_pe_resdir_t*) 0; - } - - cm_stack_push(stack, root); - - while (dir = (cm_pe_resdir_t*) cm_stack_pop(stack)) { - while (dir->subdir_count + dir->resource_count < - dir->named_entry_count + dir->id_entry_count) - { - if (fseek(pe->f, dir->offset, SEEK_SET) == -1) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - - if (fread(&res, CM_RES_REAL_SIZE, 1, pe->f) != 1) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - - #if BIGENDIAN - res.name = SWAP4(res.name); - res.offset = SWAP4(res.offset); - #endif - if (res.offset & 0x80000000) { - // subdirectory - i = dir->subdir_count++; - subdirs = (cm_pe_resdir_t*) realloc(dir->subdirs, - sizeof(cm_pe_resdir_t) * dir->subdir_count); - if (!subdirs) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->subdirs = subdirs; - - cm_stack_push(stack, dir); - dir->offset += CM_RES_REAL_SIZE; - dir = (subdirs + i); - - res.offset &= 0x7FFFFFFF; - res.file_offset = base + res.offset; - - if (!cm_pe_load_resdir(pe->f, res.file_offset, dir)) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->name = res.name; - - cm_stack_push(stack, dir); - break; - } - // real resource - res.file_offset = base + res.offset; - i = dir->resource_count++; - resources = (cm_pe_res_t*) realloc(dir->resources, - sizeof(cm_pe_res_t) * dir->resource_count); - if (!resources) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->resources = resources; - memcpy(dir->resources + i, &res, sizeof(cm_pe_res_t)); - dir->offset += CM_RES_REAL_SIZE; - } - } - - cm_stack_destroy(stack); - return root; + cm_pe_section_t* sect; + cm_pe_resdir_t* root = (cm_pe_resdir_t*) 0; + cm_pe_resdir_t* dir; + cm_pe_resdir_t* subdirs; + cm_pe_res_t res; + cm_pe_res_t* resources; + cm_stack_t stack; + size_t i; + uint32_t base; + + // no need to check validity of pe pointer; cm_pe_get_section does this + sect = cm_pe_get_section(pe, ".rsrc"); + if (!sect) + return (cm_pe_resdir_t*) 0; + + root = (cm_pe_resdir_t*) malloc(sizeof(cm_pe_resdir_t)); + if (!root) + return (cm_pe_resdir_t*) 0; + + base = sect->raw_data_offset; + if (!cm_pe_load_resdir(pe->f, base, root)) { + free(root); + return (cm_pe_resdir_t*) 0; + } + + stack = cm_stack_create(); + if (!stack) { + free(root); + return (cm_pe_resdir_t*) 0; + } + + cm_stack_push(stack, root); + + while (dir = (cm_pe_resdir_t*) cm_stack_pop(stack)) { + while (dir->subdir_count + dir->resource_count < + dir->named_entry_count + dir->id_entry_count) + { + if (fseek(pe->f, dir->offset, SEEK_SET) == -1) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + + if (fread(&res, CM_RES_REAL_SIZE, 1, pe->f) != 1) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + + #if BIGENDIAN + res.name = SWAP4(res.name); + res.offset = SWAP4(res.offset); + #endif + if (res.offset & 0x80000000) { + // subdirectory + i = dir->subdir_count++; + subdirs = (cm_pe_resdir_t*) realloc(dir->subdirs, + sizeof(cm_pe_resdir_t) * dir->subdir_count); + if (!subdirs) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->subdirs = subdirs; + + cm_stack_push(stack, dir); + dir->offset += CM_RES_REAL_SIZE; + dir = (subdirs + i); + + res.offset &= 0x7FFFFFFF; + res.file_offset = base + res.offset; + + if (!cm_pe_load_resdir(pe->f, res.file_offset, dir)) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->name = res.name; + + cm_stack_push(stack, dir); + break; + } + // real resource + res.file_offset = base + res.offset; + i = dir->resource_count++; + resources = (cm_pe_res_t*) realloc(dir->resources, + sizeof(cm_pe_res_t) * dir->resource_count); + if (!resources) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->resources = resources; + memcpy(dir->resources + i, &res, sizeof(cm_pe_res_t)); + dir->offset += CM_RES_REAL_SIZE; + } + } + + cm_stack_destroy(stack); + return root; } MEXP(int) cm_pe_unload_resources(cm_pe_resdir_t* root) { - cm_pe_resdir_t* dir; - cm_stack_t stack; - - stack = cm_stack_create(); - if (!stack) - return 0; - - cm_stack_push(stack, root); - - while (dir = cm_stack_pop(stack)) { - if (dir->subdir_count) { - dir->subdir_count--; - cm_stack_push(stack, dir); - cm_stack_push(stack, (dir->subdirs + dir->subdir_count)); - continue; - } - - if (dir->subdirs) { - free(dir->subdirs); - dir->subdirs = (cm_pe_resdir_t*) 0; - } - - if (dir->resources) { - free(dir->resources); - dir->resource_count = 0; - } - } - - cm_stack_destroy(stack); - free(root); - return 1; + cm_pe_resdir_t* dir; + cm_stack_t stack; + + stack = cm_stack_create(); + if (!stack) + return 0; + + cm_stack_push(stack, root); + + while (dir = cm_stack_pop(stack)) { + if (dir->subdir_count) { + dir->subdir_count--; + cm_stack_push(stack, dir); + cm_stack_push(stack, (dir->subdirs + dir->subdir_count)); + continue; + } + + if (dir->subdirs) { + free(dir->subdirs); + dir->subdirs = (cm_pe_resdir_t*) 0; + } + + if (dir->resources) { + free(dir->resources); + dir->resource_count = 0; + } + } + + cm_stack_destroy(stack); + free(root); + return 1; } MEXP(int) cm_pe_fixed_version(cm_pe_t pe, cm_pe_res_t* res, - cm_pe_version_t* ver) + cm_pe_version_t* ver) { - cm_pe_section_t* sect = (pe->sections + 3); + cm_pe_section_t* sect = (pe->sections + 3); #if BIGENDIAN - uint32_t check = 0xBD04EFFE; + uint32_t check = 0xBD04EFFE; #else - uint32_t check = 0xFEEF04BD; + uint32_t check = 0xFEEF04BD; #endif - uint32_t rva; - uint32_t size; - uint32_t offset; - uint32_t align; - - if (!pe || !res || !ver) - return 0; - - if (fseek(pe->f, res->file_offset, SEEK_SET) == -1) - return 0; - if (fread(&rva, 4, 1, pe->f) != 1) - return 0; - if (fread(&size, 4, 1, pe->f) != 1) - return 0; + uint32_t rva; + uint32_t size; + uint32_t offset; + uint32_t align; + + if (!pe || !res || !ver) + return 0; + + if (fseek(pe->f, res->file_offset, SEEK_SET) == -1) + return 0; + if (fread(&rva, 4, 1, pe->f) != 1) + return 0; + if (fread(&size, 4, 1, pe->f) != 1) + return 0; #if BIGENDIAN - rva = SWAP4(rva); - size = SWAP4(size); + rva = SWAP4(rva); + size = SWAP4(size); #endif - - offset = sect->raw_data_offset + (rva - sect->virtual_address) + 0x26; - align = 4 -(offset & 0xF % 4); - if (align < 4) - offset += align; - if (fseek(pe->f, offset, SEEK_SET) == -1) - return 0; - if (fread(ver, sizeof(cm_pe_version_t), 1, pe->f) != 1) - return 0; - - if (ver->dwSignature != check) - return 0; - + + offset = sect->raw_data_offset + (rva - sect->virtual_address) + 0x26; + align = 4 -(offset & 0xF % 4); + if (align < 4) + offset += align; + if (fseek(pe->f, offset, SEEK_SET) == -1) + return 0; + if (fread(ver, sizeof(cm_pe_version_t), 1, pe->f) != 1) + return 0; + + if (ver->dwSignature != check) + return 0; + #if BIGENDIAN - ver->dwSignature = SWAP32(ver->dwSignature); - ver->dwStrucVersion = SWAP32(ver->dwStrucVersion); - ver->dwFileVersionMS = SWAP32(ver->dwFileVersionMS); - ver->dwFileVersionLS = SWAP32(ver->dwFileVersionLS); - ver->dwProductVersionMS = SWAP32(ver->dwProductVersionMS); - ver->dwProductVersionLS = SWAP32(ver->dwProductVersionLS); - ver->dwFileFlagsMask = SWAP32(ver->dwFileFlagsMask); - ver->dwFileFlags = SWAP32(ver->dwFileFlags); - ver->dwFileOS = SWAP32(ver->dwFileOS); - ver->dwFileType = SWAP32(ver->dwFileType); - ver->dwFileSubtype = SWAP32(ver->dwFileSubtype); - ver->dwFileDateMS = SWAP32(ver->dwFileDateMS); - ver->dwFileDateLS = SWAP32(ver->dwFileDateLS); + ver->dwSignature = SWAP32(ver->dwSignature); + ver->dwStrucVersion = SWAP32(ver->dwStrucVersion); + ver->dwFileVersionMS = SWAP32(ver->dwFileVersionMS); + ver->dwFileVersionLS = SWAP32(ver->dwFileVersionLS); + ver->dwProductVersionMS = SWAP32(ver->dwProductVersionMS); + ver->dwProductVersionLS = SWAP32(ver->dwProductVersionLS); + ver->dwFileFlagsMask = SWAP32(ver->dwFileFlagsMask); + ver->dwFileFlags = SWAP32(ver->dwFileFlags); + ver->dwFileOS = SWAP32(ver->dwFileOS); + ver->dwFileType = SWAP32(ver->dwFileType); + ver->dwFileSubtype = SWAP32(ver->dwFileSubtype); + ver->dwFileDateMS = SWAP32(ver->dwFileDateMS); + ver->dwFileDateLS = SWAP32(ver->dwFileDateLS); #endif - - return 1; + + return 1; } int cm_pe_load_resdir(FILE* f, uint32_t offset, cm_pe_resdir_t* dir) { - memset(dir, 0, sizeof(cm_pe_resdir_t)); - - if (fseek(f, offset, SEEK_SET) == -1) - return 0; - - if (fread(dir, 16, 1, f) != 1) - return 0; - + memset(dir, 0, sizeof(cm_pe_resdir_t)); + + if (fseek(f, offset, SEEK_SET) == -1) + return 0; + + if (fread(dir, 16, 1, f) != 1) + return 0; + #if BIGENDIAN - dir->characteristics = SWAP32(dir->characteristics); - dir->timestamp = SWAP32(dir->timestamp); - dir->major_version = SWAP16(dir->major_version); - dir->minor_version = SWAP16(dir->minor_version); - dir->named_entry_count = SWAP16(dir->named_entry_count); - dir->id_entry_count = SWAP16(dir->id_entry_count); + dir->characteristics = SWAP32(dir->characteristics); + dir->timestamp = SWAP32(dir->timestamp); + dir->major_version = SWAP16(dir->major_version); + dir->minor_version = SWAP16(dir->minor_version); + dir->named_entry_count = SWAP16(dir->named_entry_count); + dir->id_entry_count = SWAP16(dir->id_entry_count); #endif - - dir->offset = (uint32_t) ftell(f); - - return 1; -} \ No newline at end of file + + dir->offset = (uint32_t) ftell(f); + + return 1; +} diff --git a/src/bncsutil/pe.h b/src/bncsutil/pe.h index 9ff28d6..1795a10 100644 --- a/src/bncsutil/pe.h +++ b/src/bncsutil/pe.h @@ -34,135 +34,135 @@ extern "C" { #endif typedef struct cm_pe_header { - uint32_t signature; - uint16_t machine; // IMAGE_FILE_MACHINE_* - uint16_t section_count; - uint32_t timestamp; - uint32_t symbol_table_offset; - uint32_t symbol_count; - uint16_t optional_header_size; - uint16_t characteristics; + uint32_t signature; + uint16_t machine; // IMAGE_FILE_MACHINE_* + uint16_t section_count; + uint32_t timestamp; + uint32_t symbol_table_offset; + uint32_t symbol_count; + uint16_t optional_header_size; + uint16_t characteristics; } cm_pe_header_t; -#define IMAGE_FORMAT_PE32 0x10B -#define IMAGE_FORMAT_PE32_PLUS 0x20B +#define IMAGE_FORMAT_PE32 0x10B +#define IMAGE_FORMAT_PE32_PLUS 0x20B typedef struct cm_pe_optional_header { - uint16_t magic; // image format (PE32/PE32+) - uint8_t major_linker_version; - uint8_t minor_linker_version; - uint32_t code_section_size; - uint32_t initialized_data_size; - uint32_t uninitialized_data_size; - uint32_t entry_point; - uint32_t code_base; - uint32_t data_base; // not present in PE32+! + uint16_t magic; // image format (PE32/PE32+) + uint8_t major_linker_version; + uint8_t minor_linker_version; + uint32_t code_section_size; + uint32_t initialized_data_size; + uint32_t uninitialized_data_size; + uint32_t entry_point; + uint32_t code_base; + uint32_t data_base; // not present in PE32+! } cm_pe_optional_header_t; #define PE_OPTIONAL_HEADER_MIN_SIZE (sizeof(cm_pe_optional_header_t) - 4) typedef struct cm_pe_windows_header { - uint64_t image_base; - uint32_t section_alignment; - uint32_t file_alignment; - uint16_t major_os_version; - uint16_t minor_os_version; - uint16_t major_image_version; - uint16_t minor_image_version; - uint16_t major_subsystem_version; - uint16_t minor_subsystem_version; - uint32_t reserved; - uint32_t image_size; - uint32_t headers_size; - uint32_t checksum; - uint16_t subsystem; - uint16_t dll_characteristics; - uint64_t stack_reserve_size; - uint64_t stack_commit_size; - uint64_t heap_reserve_size; - uint64_t heap_commit_size; - uint32_t loader_flags; - uint32_t data_directory_count; + uint64_t image_base; + uint32_t section_alignment; + uint32_t file_alignment; + uint16_t major_os_version; + uint16_t minor_os_version; + uint16_t major_image_version; + uint16_t minor_image_version; + uint16_t major_subsystem_version; + uint16_t minor_subsystem_version; + uint32_t reserved; + uint32_t image_size; + uint32_t headers_size; + uint32_t checksum; + uint16_t subsystem; + uint16_t dll_characteristics; + uint64_t stack_reserve_size; + uint64_t stack_commit_size; + uint64_t heap_reserve_size; + uint64_t heap_commit_size; + uint32_t loader_flags; + uint32_t data_directory_count; } cm_pe_windows_header_t; typedef struct cm_pe_data_directory { - uint32_t rva; - uint32_t size; + uint32_t rva; + uint32_t size; } cm_pe_data_directory_t; typedef struct cm_pe_section { - char name[8]; - uint32_t virtual_size; - uint32_t virtual_address; - uint32_t raw_data_size; - uint32_t raw_data_offset; - uint32_t relocations_offset; - uint32_t line_numbers_offset; - uint16_t relocation_count; - uint16_t line_number_count; - uint32_t characteristics; + char name[8]; + uint32_t virtual_size; + uint32_t virtual_address; + uint32_t raw_data_size; + uint32_t raw_data_offset; + uint32_t relocations_offset; + uint32_t line_numbers_offset; + uint16_t relocation_count; + uint16_t line_number_count; + uint32_t characteristics; } cm_pe_section_t; -typedef struct VS_FIXEDFILEINFO { - uint32_t dwSignature; - uint32_t dwStrucVersion; - uint32_t dwFileVersionMS; - uint32_t dwFileVersionLS; - union { - struct { - uint32_t dwProductVersionMS; - uint32_t dwProductVersionLS; - }; - uint64_t qwProductVersion; - }; - uint32_t dwFileFlagsMask; - uint32_t dwFileFlags; - uint32_t dwFileOS; - uint32_t dwFileType; - uint32_t dwFileSubtype; - union { - struct { - uint32_t dwFileDateMS; - uint32_t dwFileDateLS; - }; - uint64_t qwFileDate; - }; +typedef struct VS_FIXEDFILEINFO { + uint32_t dwSignature; + uint32_t dwStrucVersion; + uint32_t dwFileVersionMS; + uint32_t dwFileVersionLS; + union { + struct { + uint32_t dwProductVersionMS; + uint32_t dwProductVersionLS; + }; + uint64_t qwProductVersion; + }; + uint32_t dwFileFlagsMask; + uint32_t dwFileFlags; + uint32_t dwFileOS; + uint32_t dwFileType; + uint32_t dwFileSubtype; + union { + struct { + uint32_t dwFileDateMS; + uint32_t dwFileDateLS; + }; + uint64_t qwFileDate; + }; } cm_pe_version_t; typedef struct cm_pe_resource { - uint32_t name; - uint32_t offset; - uint32_t file_offset; + uint32_t name; + uint32_t offset; + uint32_t file_offset; } cm_pe_res_t; -#define CM_RES_REAL_SIZE 8 +#define CM_RES_REAL_SIZE 8 typedef struct cm_pe_resdir { - uint32_t characteristics; - uint32_t timestamp; - uint16_t major_version; - uint16_t minor_version; - uint16_t named_entry_count; - uint16_t id_entry_count; - - size_t subdir_count; - struct cm_pe_resdir* subdirs; - size_t resource_count; - cm_pe_res_t* resources; - - uint32_t offset; - uint32_t name; + uint32_t characteristics; + uint32_t timestamp; + uint16_t major_version; + uint16_t minor_version; + uint16_t named_entry_count; + uint16_t id_entry_count; + + size_t subdir_count; + struct cm_pe_resdir* subdirs; + size_t resource_count; + cm_pe_res_t* resources; + + uint32_t offset; + uint32_t name; } cm_pe_resdir_t; typedef struct cm_pe { - FILE* f; - cm_pe_header_t header; - cm_pe_optional_header_t optional_header; - cm_pe_windows_header_t windows_header; - cm_pe_data_directory_t* data_directories; - cm_pe_section_t* sections; + FILE* f; + cm_pe_header_t header; + cm_pe_optional_header_t optional_header; + cm_pe_windows_header_t windows_header; + cm_pe_data_directory_t* data_directories; + cm_pe_section_t* sections; } *cm_pe_t; -#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 #define IMAGE_FILE_MACHINE_ALPHA 0x184 #define IMAGE_FILE_MACHINE_ARM 0x1c0 #define IMAGE_FILE_MACHINE_ALPHA64 0x284 @@ -171,7 +171,7 @@ typedef struct cm_pe { #define IMAGE_FILE_MACHINE_M68K 0x268 #define IMAGE_FILE_MACHINE_MIPS16 0x266 #define IMAGE_FILE_MACHINE_MIPSFPU 0x366 -#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 #define IMAGE_FILE_MACHINE_POWERPC 0x1f0 #define IMAGE_FILE_MACHINE_R3000 0x162 #define IMAGE_FILE_MACHINE_R4000 0x166 @@ -185,7 +185,7 @@ MEXP(void) cm_pe_unload(cm_pe_t pe); MEXP(cm_pe_resdir_t*) cm_pe_load_resources(cm_pe_t pe); MEXP(int) cm_pe_unload_resources(cm_pe_resdir_t* dir); MEXP(int) cm_pe_fixed_version(cm_pe_t pe, cm_pe_res_t* res, - cm_pe_version_t* ver); + cm_pe_version_t* ver); #ifdef __cplusplus } diff --git a/src/bncsutil/sha1.h b/src/bncsutil/sha1.h index e7753d4..23a3452 100644 --- a/src/bncsutil/sha1.h +++ b/src/bncsutil/sha1.h @@ -74,7 +74,7 @@ int SHA1Input( SHA1Context *, unsigned int); int SHA1Result( SHA1Context *, uint8_t Message_Digest[SHA1HashSize]); - + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/bncsutil/stack.c b/src/bncsutil/stack.c index 88edcd4..1b37f6d 100644 --- a/src/bncsutil/stack.c +++ b/src/bncsutil/stack.c @@ -20,9 +20,10 @@ * A copy of the GNU Lesser General Public License is included in the BNCSutil * distribution in the file COPYING. If you did not receive this copy, * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, + * Boston, MA 02111-1307 USA + */ -/* +/** * Mule Server * Copyright (c) 2004-2006 Eric Naeseth. * @@ -32,81 +33,81 @@ #include #include - + cm_stack_t cm_stack_create() { - cm_stack_t stack = (cm_stack_t) calloc(1, sizeof(struct cm_stack)); - if (!stack) - return (cm_stack_t) 0; - return stack; + cm_stack_t stack = (cm_stack_t) calloc(1, sizeof(struct cm_stack)); + if (!stack) + return (cm_stack_t) 0; + return stack; } void cm_stack_destroy(cm_stack_t stack) { - cm_stack_node_t* node; - cm_stack_node_t* next; - - if (!stack) - return; - - node = stack->top; - - while (node) { - next = node->next; - free(node); - node = next; - } - - free(stack); + cm_stack_node_t* node; + cm_stack_node_t* next; + + if (!stack) + return; + + node = stack->top; + + while (node) { + next = node->next; + free(node); + node = next; + } + + free(stack); } void cm_stack_push(cm_stack_t stack, void* item) { - cm_stack_node_t* new_node; - - if (!stack || !item) - return; - - new_node = (cm_stack_node_t*) malloc(sizeof(cm_stack_node_t)); - if (!new_node) - return; - new_node->next = stack->top; - new_node->value = item; - - stack->size++; - - stack->top = new_node; + cm_stack_node_t* new_node; + + if (!stack || !item) + return; + + new_node = (cm_stack_node_t*) malloc(sizeof(cm_stack_node_t)); + if (!new_node) + return; + new_node->next = stack->top; + new_node->value = item; + + stack->size++; + + stack->top = new_node; } void* cm_stack_pop(cm_stack_t stack) { - cm_stack_node_t* next; - void* value; - - if (!stack || !stack->top) - return (void*) 0; - - next = stack->top->next; - value = stack->top->value; - free(stack->top); - - stack->top = next; - stack->size--; - return value; + cm_stack_node_t* next; + void* value; + + if (!stack || !stack->top) + return (void*) 0; + + next = stack->top->next; + value = stack->top->value; + free(stack->top); + + stack->top = next; + stack->size--; + return value; } void* cm_stack_peek(cm_stack_t stack) { - if (!stack || !stack->top) - return (void*) 0; - - return stack->top->value; + if (!stack || !stack->top) + return (void*) 0; + + return stack->top->value; } unsigned int cm_stack_size(cm_stack_t stack) { - if (!stack) - return 0; - - return stack->size; -} \ No newline at end of file + if (!stack) + return 0; + + return stack->size; +} diff --git a/src/bncsutil/stack.h b/src/bncsutil/stack.h index c18197c..882b075 100644 --- a/src/bncsutil/stack.h +++ b/src/bncsutil/stack.h @@ -23,7 +23,7 @@ * Boston, MA 02111-1307 USA */ -/* +/** * Mule Server * Copyright (c) 2004-2006 Eric Naeseth. * @@ -35,13 +35,13 @@ #define CM_STACK_H_INCLUDED 1 typedef struct cm_stack_node { - void* value; - struct cm_stack_node* next; + void* value; + struct cm_stack_node* next; } cm_stack_node_t; typedef struct cm_stack { - unsigned int size; - cm_stack_node_t* top; + unsigned int size; + cm_stack_node_t* top; } *cm_stack_t; cm_stack_t cm_stack_create(); @@ -51,4 +51,4 @@ void* cm_stack_pop(cm_stack_t stack); void* cm_stack_peek(cm_stack_t stack); unsigned int cm_stack_size(cm_stack_t stack); -#endif \ No newline at end of file +#endif diff --git a/tests/checkrevision.c b/tests/checkrevision.c index fa1b95b..b17da36 100644 --- a/tests/checkrevision.c +++ b/tests/checkrevision.c @@ -1,69 +1,69 @@ -#include -#include - -typedef unsigned int uint32_t; - +#include +#include + +typedef unsigned int uint32_t; + typedef int (__stdcall *check_revision_t)(const char*, const char**, int, int, unsigned long*); -typedef int (__stdcall *exe_info_t)(const char*, char*, size_t, uint32_t*, int); -typedef int (__stdcall *ver_info_t)(char*); -typedef int (__stdcall *set_debug_t)(int); - -int main(int argc, char* argv[]) -{ - HMODULE lib; - check_revision_t check_revision; - exe_info_t exe_info; - ver_info_t ver_info; - set_debug_t set_debug; - const char* paths[] = { - "BNCSutil.dll", - "BNCSutil_1.1.dll" - }; - int has_debug[] = { 1, 0 }; - unsigned long checksum = 0; - uint32_t version = 0; - char exeInfo[1024]; - const unsigned long expectedChecksum = 0x98214637; - int i; - char lib_version[12]; - - const char formula[] = - "A=767237111 B=654373374 C=621868803 4 A=A+S B=B-C C=C-A A=A+B"; - - for (i = 0; i < 2; i++) { - lib = LoadLibrary(paths[i]); - if (!lib) { - printf("Failed to load \"%s\"\n", paths[i]); - continue; - } - - if (has_debug[i]) { - set_debug = (set_debug_t) GetProcAddress(lib, "bncsutil_set_debug_status"); - set_debug(0); - } - - ver_info = (ver_info_t) GetProcAddress(lib, "bncsutil_getVersionString"); - check_revision = (check_revision_t) GetProcAddress(lib, "checkRevision"); - exe_info = (exe_info_t) GetProcAddress(lib, "getExeInfo"); - - ver_info(lib_version); - printf("Using BNCSutil %s:\n", lib_version); - - if (!check_revision(formula, (argv + 1), (argc - 1), 7, &checksum)) { - printf("\tCheckRevision call failed.\n"); - continue; - } - printf("\tChecksum: 0x%08X\n", checksum); - - if (!exe_info(argv[1], exeInfo, 1024, &version, 1)) { - printf("\tGetExeInfo call failed.\n"); - continue; - } - printf("\tVersion: 0x%08X\n", version); - printf("\t%s\n", exeInfo); - - FreeLibrary(lib); - } - - return 0; -} +typedef int (__stdcall *exe_info_t)(const char*, char*, size_t, uint32_t*, int); +typedef int (__stdcall *ver_info_t)(char*); +typedef int (__stdcall *set_debug_t)(int); + +int main(int argc, char* argv[]) +{ + HMODULE lib; + check_revision_t check_revision; + exe_info_t exe_info; + ver_info_t ver_info; + set_debug_t set_debug; + const char* paths[] = { + "BNCSutil.dll", + "BNCSutil_1.1.dll" + }; + int has_debug[] = { 1, 0 }; + unsigned long checksum = 0; + uint32_t version = 0; + char exeInfo[1024]; + const unsigned long expectedChecksum = 0x98214637; + int i; + char lib_version[12]; + + const char formula[] = + "A=767237111 B=654373374 C=621868803 4 A=A+S B=B-C C=C-A A=A+B"; + + for (i = 0; i < 2; i++) { + lib = LoadLibrary(paths[i]); + if (!lib) { + printf("Failed to load \"%s\"\n", paths[i]); + continue; + } + + if (has_debug[i]) { + set_debug = (set_debug_t) GetProcAddress(lib, "bncsutil_set_debug_status"); + set_debug(0); + } + + ver_info = (ver_info_t) GetProcAddress(lib, "bncsutil_getVersionString"); + check_revision = (check_revision_t) GetProcAddress(lib, "checkRevision"); + exe_info = (exe_info_t) GetProcAddress(lib, "getExeInfo"); + + ver_info(lib_version); + printf("Using BNCSutil %s:\n", lib_version); + + if (!check_revision(formula, (argv + 1), (argc - 1), 7, &checksum)) { + printf("\tCheckRevision call failed.\n"); + continue; + } + printf("\tChecksum: 0x%08X\n", checksum); + + if (!exe_info(argv[1], exeInfo, 1024, &version, 1)) { + printf("\tGetExeInfo call failed.\n"); + continue; + } + printf("\tVersion: 0x%08X\n", version); + printf("\t%s\n", exeInfo); + + FreeLibrary(lib); + } + + return 0; +} diff --git a/tests/nls.cpp b/tests/nls.cpp index 1e8436a..d33d080 100644 --- a/tests/nls.cpp +++ b/tests/nls.cpp @@ -10,27 +10,27 @@ int main() { - char salt[32]; - char B[32]; - int i; - int j = 0; + char salt[32]; + char B[32]; + int i; + int j = 0; - for (i = 0; i < 32; i++) { - salt[i] = j++; - } - for (i = 0; i < 32; i++) { - B[i] = j++; - } + for (i = 0; i < 32; i++) { + salt[i] = j++; + } + for (i = 0; i < 32; i++) { + B[i] = j++; + } - NLS nls("Cloaked", "foo"); - bncsutil_debug_message("NLS Test"); - bncsutil_debug_message("Salt:"); - bncsutil_debug_dump(salt, 32); - bncsutil_debug_message("Client public key:"); - bncsutil_debug_dump(nls.getPublicKey(), 32); - bncsutil_debug_message("Server public key:"); - bncsutil_debug_dump(B, 32); - bncsutil_debug_message("Client session key:"); - bncsutil_debug_dump(nls.getClientSessionKey(salt, B), 20); - return 0; -} \ No newline at end of file + NLS nls("Cloaked", "foo"); + bncsutil_debug_message("NLS Test"); + bncsutil_debug_message("Salt:"); + bncsutil_debug_dump(salt, 32); + bncsutil_debug_message("Client public key:"); + bncsutil_debug_dump(nls.getPublicKey(), 32); + bncsutil_debug_message("Server public key:"); + bncsutil_debug_dump(B, 32); + bncsutil_debug_message("Client session key:"); + bncsutil_debug_dump(nls.getClientSessionKey(salt, B), 20); + return 0; +} diff --git a/vc8_build/BNCSutil.sln b/vc8_build/BNCSutil.sln index 8ca2162..fc19784 100644 --- a/vc8_build/BNCSutil.sln +++ b/vc8_build/BNCSutil.sln @@ -3,17 +3,17 @@ Microsoft Visual Studio Solution File, Format Version 9.00 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BNCSutil", "BNCSutil.vcproj", "{CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}" EndProject Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Debug|Win32.ActiveCfg = Debug|Win32 - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Debug|Win32.Build.0 = Debug|Win32 - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Release|Win32.ActiveCfg = Release|Win32 - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Debug|Win32.ActiveCfg = Debug|Win32 + {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Debug|Win32.Build.0 = Debug|Win32 + {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Release|Win32.ActiveCfg = Release|Win32 + {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection EndGlobal diff --git a/vc8_build/BNCSutil.vcproj b/vc8_build/BNCSutil.vcproj index ad37e93..ce6bfa0 100644 --- a/vc8_build/BNCSutil.vcproj +++ b/vc8_build/BNCSutil.vcproj @@ -1,404 +1,404 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="8.00" + Name="BNCSutil" + ProjectGUID="{CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}" + RootNamespace="BNCSutil" + Keyword="Win32Proj" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vc8_build/bncsutil.def b/vc8_build/bncsutil.def index ce3a416..d071cb0 100644 --- a/vc8_build/bncsutil.def +++ b/vc8_build/bncsutil.def @@ -1,52 +1,52 @@ -LIBRARY BNCSutil +LIBRARY BNCSutil VERSION 1.1 EXPORTS - bncsutil_getVersion=_bncsutil_getVersion@0 @1 - bncsutil_getVersionString=_bncsutil_getVersionString@4 @2 - - calcHashBuf=_calcHashBuf@12 @3 - doubleHashPassword=_doubleHashPassword@16 @4 - hashPassword=_hashPassword@8 @5 - - kd_quick=_kd_quick@28 - kd_init=_kd_init@0 @6 - kd_create=_kd_create@8 @7 - kd_free=_kd_free@4 @8 - kd_val2Length=_kd_val2Length@4 @9 - kd_product=_kd_product@4 @10 - kd_val1=_kd_val1@4 @11 - kd_val2=_kd_val2@4 @12 - kd_longVal2=_kd_longVal2@8 @13 - kd_calculateHash=_kd_calculateHash@12 @14 - kd_getHash=_kd_getHash@8 @15 - kd_isValid=_kd_isValid@4 @16 + bncsutil_getVersion=_bncsutil_getVersion@0 @1 + bncsutil_getVersionString=_bncsutil_getVersionString@4 @2 - checkRevision=_checkRevision@20 @17 - checkRevisionFlat=_checkRevisionFlat@24 @18 - getExeInfo=_getExeInfo@20 @19 + calcHashBuf=_calcHashBuf@12 @3 + doubleHashPassword=_doubleHashPassword@16 @4 + hashPassword=_hashPassword@8 @5 - extractMPQNumber=_extractMPQNumber@4 @20 - - nls_account_create=_nls_account_create@12 @21 - nls_account_logon=_nls_account_logon@12 @22 - nls_free=_nls_free@4 @23 - nls_get_A=_nls_get_A@8 @24 - nls_get_K=_nls_get_K@12 @25 - nls_get_M1=_nls_get_M1@16 @26 - nls_get_S=_nls_get_S@16 @27 - nls_get_v=_nls_get_v@12 @28 - nls_init=_nls_init@8 @29 - nls_init_l=_nls_init_l@16 @30 - nls_reinit=_nls_reinit@12 @31 - nls_reinit_l=_nls_reinit_l@20 @32 - nls_check_M2=_nls_check_M2@16 @33 - nls_check_signature=_nls_check_signature@8 @34 - nls_account_change_proof=_nls_account_change_proof@20 @35 - - bncsutil_debug_message=_bncsutil_debug_message@4 @36 - bncsutil_debug_dump=_bncsutil_debug_dump@8 @37 - bncsutil_print_dump=_bncsutil_print_dump@12 @38 - bncsutil_print_dump_win=_bncsutil_print_dump_win@12 @39 - bncsutil_debug_status=_bncsutil_debug_status@0 @40 - bncsutil_set_debug_status=_bncsutil_set_debug_status@4 @41 - bncsutil_internal_debug_messages=_bncsutil_internal_debug_messages@0 @42 \ No newline at end of file + kd_quick=_kd_quick@28 + kd_init=_kd_init@0 @6 + kd_create=_kd_create@8 @7 + kd_free=_kd_free@4 @8 + kd_val2Length=_kd_val2Length@4 @9 + kd_product=_kd_product@4 @10 + kd_val1=_kd_val1@4 @11 + kd_val2=_kd_val2@4 @12 + kd_longVal2=_kd_longVal2@8 @13 + kd_calculateHash=_kd_calculateHash@12 @14 + kd_getHash=_kd_getHash@8 @15 + kd_isValid=_kd_isValid@4 @16 + + checkRevision=_checkRevision@20 @17 + checkRevisionFlat=_checkRevisionFlat@24 @18 + getExeInfo=_getExeInfo@20 @19 + + extractMPQNumber=_extractMPQNumber@4 @20 + + nls_account_create=_nls_account_create@12 @21 + nls_account_logon=_nls_account_logon@12 @22 + nls_free=_nls_free@4 @23 + nls_get_A=_nls_get_A@8 @24 + nls_get_K=_nls_get_K@12 @25 + nls_get_M1=_nls_get_M1@16 @26 + nls_get_S=_nls_get_S@16 @27 + nls_get_v=_nls_get_v@12 @28 + nls_init=_nls_init@8 @29 + nls_init_l=_nls_init_l@16 @30 + nls_reinit=_nls_reinit@12 @31 + nls_reinit_l=_nls_reinit_l@20 @32 + nls_check_M2=_nls_check_M2@16 @33 + nls_check_signature=_nls_check_signature@8 @34 + nls_account_change_proof=_nls_account_change_proof@20 @35 + + bncsutil_debug_message=_bncsutil_debug_message@4 @36 + bncsutil_debug_dump=_bncsutil_debug_dump@8 @37 + bncsutil_print_dump=_bncsutil_print_dump@12 @38 + bncsutil_print_dump_win=_bncsutil_print_dump_win@12 @39 + bncsutil_debug_status=_bncsutil_debug_status@0 @40 + bncsutil_set_debug_status=_bncsutil_set_debug_status@4 @41 + bncsutil_internal_debug_messages=_bncsutil_internal_debug_messages@0 @42 From f0963d568f2ce20679945c0fc11ebbd11c7a573f Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:08:17 +0000 Subject: [PATCH 02/10] Add a gitignore file to hide build artifacts --- .gitignore | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0d75885 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +*.lo +*.o +.deps/ +.dirstamp +.libs/ +/aclocal.m4 +/autom4te.cache/ +/compile +/config.guess +/config.h +/config.h.in +/config.h.in~ +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/missing +/stamp-h1 +Makefile +Makefile.in From 0b6a99933500b68c24aae3608a14833a5031fe9d Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:08:36 +0000 Subject: [PATCH 03/10] Allow subdir-objects in configure.ac file --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 15c9c51..e8449e8 100644 --- a/configure.ac +++ b/configure.ac @@ -1,6 +1,6 @@ AC_INIT([bncsutil], [1.3.2], [bugs@example.com]) -AM_INIT_AUTOMAKE([-Wall -Werror foreign]) +AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AM_PROG_LIBTOOL AC_PROG_INSTALL From 56e4a3104dd64252f146f3686d119a6a324cdcff Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:17:52 +0000 Subject: [PATCH 04/10] Fix conflicting declaration of basename function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit error: conflicting declaration of ‘const char* basename(const char*)’ with ‘C’ linkage --- src/bncsutil/checkrevision.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/bncsutil/checkrevision.cpp b/src/bncsutil/checkrevision.cpp index 039d1e7..03675e7 100644 --- a/src/bncsutil/checkrevision.cpp +++ b/src/bncsutil/checkrevision.cpp @@ -124,6 +124,7 @@ MEXP(int) extractMPQNumber(const char* mpqName) return mpqNum; } +#if !__GNUC__ const char* basename(const char* file_name) { const char* base; @@ -135,6 +136,7 @@ const char* basename(const char* file_name) return ++base; } +#endif MEXP(int) checkRevision(const char* formula, const char* files[], int numFiles, int mpqNumber, unsigned long* checksum) From 49837bc9d773f6eb6fea0b9909c9d7a73efb663e Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:20:30 +0000 Subject: [PATCH 05/10] Fix error with extra parentheses --- src/bncsutil/file.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bncsutil/file.cpp b/src/bncsutil/file.cpp index a34fcca..27cde23 100644 --- a/src/bncsutil/file.cpp +++ b/src/bncsutil/file.cpp @@ -211,7 +211,7 @@ file_t file_open(const char* filename, unsigned int mode_flags) data = new _file; } catch (std::bad_alloc) { bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "file structure."), sizeof(struct _file)); + "file structure.", sizeof(struct _file)); fclose(f); return (file_t) 0; } @@ -221,7 +221,7 @@ file_t file_open(const char* filename, unsigned int mode_flags) if (!data->filename) { err = sys_error_msg(); bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "filename; %s"), filename_buf_len); + "filename; %s", filename_buf_len); free_sys_error_msg(err); fclose(f); delete data; From e7de02191182b8a542296f7eae1a7367c06c66e4 Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:21:12 +0000 Subject: [PATCH 06/10] Fix missing iterator declaration --- src/bncsutil/file.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bncsutil/file.cpp b/src/bncsutil/file.cpp index 27cde23..0295098 100644 --- a/src/bncsutil/file.cpp +++ b/src/bncsutil/file.cpp @@ -236,6 +236,7 @@ file_t file_open(const char* filename, unsigned int mode_flags) void file_close(file_t file) { + mapping_map::iterator it; if (!file) { bncsutil_debug_message("error: null pointer given to file_close"); From dad53ffd81109bac48b0ebfd2d1a39a75ed3147d Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:38:08 +0000 Subject: [PATCH 07/10] Merge with ghostplusplus updated copy of bncsutil --- .gitignore | 24 - Makefile.am | 1 - configure.ac | 43 - product_version | 2 +- source_dist.sh | 24 - src/Makefile.am | 34 - src/bncsutil/Makefile | 36 + src/bncsutil/bsha1.cpp | 158 +-- src/bncsutil/bsha1.h | 2 +- src/bncsutil/cdkeydecoder.cpp | 241 ++-- src/bncsutil/cdkeydecoder.h | 24 +- src/bncsutil/checkrevision.cpp | 772 +++++------ src/bncsutil/checkrevision.h | 14 +- src/bncsutil/debug.c | 382 +++--- src/bncsutil/debug.h | 173 +-- src/bncsutil/decodekey.cpp | 498 ++++---- src/bncsutil/decodekey.h | 8 +- src/bncsutil/file.cpp | 430 +++---- src/bncsutil/file.h | 6 +- src/bncsutil/gmp.h | 2189 ++++++++++++++++++++++++++++++++ src/bncsutil/libinfo.cpp | 8 +- src/bncsutil/ms_stdint.h | 232 ++++ src/bncsutil/mutil.h | 36 +- src/bncsutil/mutil_types.h | 6 + src/bncsutil/nls.c | 476 +++---- src/bncsutil/nls.h | 280 ++-- src/bncsutil/oldauth.cpp | 14 +- src/bncsutil/pe.c | 804 ++++++------ src/bncsutil/pe.h | 206 +-- src/bncsutil/sha1.h | 2 +- src/bncsutil/stack.c | 112 +- src/bncsutil/stack.h | 10 +- vc8_build/BNCSutil.sln | 19 - vc8_build/BNCSutil.vcproj | 1024 +++++++++------ vc8_build/BNCSutil1.aps | Bin 33780 -> 0 bytes vc8_build/BNCSutil1.rc | 102 -- vc8_build/bncsutil.def | 89 +- vc8_build/bncsutil.rc | 101 -- vc8_build/gmp.lib | Bin 0 -> 1659142 bytes vc8_build/manual_link.bat | 1 - vc8_build/resource.h | 1210 ------------------ vc8_build/resource1.h | 14 - windows_dist.bat | 19 - windows_dist.sh | 36 - 44 files changed, 5462 insertions(+), 4400 deletions(-) delete mode 100644 Makefile.am delete mode 100644 configure.ac delete mode 100644 source_dist.sh delete mode 100644 src/Makefile.am create mode 100644 src/bncsutil/Makefile create mode 100644 src/bncsutil/gmp.h create mode 100644 src/bncsutil/ms_stdint.h delete mode 100644 vc8_build/BNCSutil.sln delete mode 100644 vc8_build/BNCSutil1.aps delete mode 100644 vc8_build/BNCSutil1.rc delete mode 100644 vc8_build/bncsutil.rc create mode 100644 vc8_build/gmp.lib delete mode 100644 vc8_build/manual_link.bat delete mode 100644 vc8_build/resource.h delete mode 100644 vc8_build/resource1.h delete mode 100644 windows_dist.bat delete mode 100644 windows_dist.sh diff --git a/.gitignore b/.gitignore index 0d75885..e69de29 100644 --- a/.gitignore +++ b/.gitignore @@ -1,24 +0,0 @@ -*.lo -*.o -.deps/ -.dirstamp -.libs/ -/aclocal.m4 -/autom4te.cache/ -/compile -/config.guess -/config.h -/config.h.in -/config.h.in~ -/config.log -/config.status -/config.sub -/configure -/depcomp -/install-sh -/libtool -/ltmain.sh -/missing -/stamp-h1 -Makefile -Makefile.in diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index e785bfd..0000000 --- a/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = src/ diff --git a/configure.ac b/configure.ac deleted file mode 100644 index e8449e8..0000000 --- a/configure.ac +++ /dev/null @@ -1,43 +0,0 @@ -AC_INIT([bncsutil], [1.3.2], [bugs@example.com]) - -AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) -AM_PROG_LIBTOOL - -AC_PROG_INSTALL - -AC_LANG_C -AC_PROG_CC -AC_PROG_CXX -AC_PROG_INSTALL -AC_PROG_MAKE_SET - -AC_HEADER_STDC - -AC_CHECK_LIB(gmp, __gmpz_init,, AC_MSG_ERROR([ -bncsutil requires libgmp; see http://gmplib.org])) - -[echo -n "checking for little or big endian... " ] -AC_TRY_RUN([ -#include -int main() -{ - uint16_t s = 1; - uint16_t* ptr = &s; - uint8_t n = *((uint8_t*)ptr); - return n; -} - -] -, AC_DEFINE([BIGENDIAN], [1], [Define to 1 if system is big endian]) - [echo "big"] -, AC_DEFINE([LITTLEENDIAN], [1], [Define to 1 if system is little endian]) - [echo "little"] -) - -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_FILES([ - Makefile - src/Makefile -]) - -AC_OUTPUT diff --git a/product_version b/product_version index 3a3cd8c..1892b92 100644 --- a/product_version +++ b/product_version @@ -1 +1 @@ -1.3.1 +1.3.2 diff --git a/source_dist.sh b/source_dist.sh deleted file mode 100644 index f2ad313..0000000 --- a/source_dist.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/bin/sh - -SCRIPT_PATH=`dirname $0`; - -PKGDIR=bncsutil-`cat $SCRIPT_PATH/product_version` -rm -fr $PKGDIR -mkdir $PKGDIR - -for b in config configure doc product_version src support tests vb6_example \ - vc7_build vc8_build windows_dist.bat source_dist.sh windows_dist.sh \ - README-Windows.txt -do - cp -R $SCRIPT_PATH/$b $PKGDIR -done - -rm -f $PKGDIR.tar.bz2 -rm -f $PKGDIR.tar.gz - -tar --exclude=.svn -cjvf $PKGDIR.tar.bz2 $PKGDIR -tar --exclude=.svn -czvf $PKGDIR.tar.gz $PKGDIR - -rm -fr $PKGDIR - -scp $PKGDIR.tar.bz2 $PKGDIR.tar.gz "ionws.com:/home/ericn/public_html/code/bncsutil/static/releases" diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index ca1181f..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -AUTOMAKE_OPTIONS = gnu -AM_CPPFLAGS = -I@ROOTINCDIR@ -lib_LTLIBRARIES = libbncsutil.la -nobase_include_HEADERS = bncsutil/bncsutil.h \ - bncsutil/cdkeydecoder.h \ - bncsutil/decodekey.h \ - bncsutil/libinfo.h \ - bncsutil/nls.h \ - bncsutil/sha1.h \ - bncsutil/bsha1.h \ - bncsutil/checkrevision.h \ - bncsutil/file.h \ - bncsutil/mutil.h \ - bncsutil/oldauth.h \ - bncsutil/stack.h \ - bncsutil/buffer.h \ - bncsutil/debug.h \ - bncsutil/keytables.h \ - bncsutil/mutil_types.h \ - bncsutil/pe.h - -libbncsutil_la_SOURCES = bncsutil/nls.c \ - bncsutil/pe.c \ - bncsutil/sha1.c \ - bncsutil/stack.c \ - bncsutil/bsha1.cpp \ - bncsutil/checkrevision.cpp \ - bncsutil/file.cpp \ - bncsutil/oldauth.cpp \ - bncsutil/cdkeydecoder.cpp \ - bncsutil/decodekey.cpp \ - bncsutil/libinfo.cpp - -libbncsutil_la_LDFLAGS = -version-info 0:0:0 diff --git a/src/bncsutil/Makefile b/src/bncsutil/Makefile new file mode 100644 index 0000000..090fdbe --- /dev/null +++ b/src/bncsutil/Makefile @@ -0,0 +1,36 @@ +SHELL = /bin/sh +SYSTEM = $(shell uname) +CXX = g++ +CXXFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC +CXXOBJ = bsha1.o cdkeydecoder.o checkrevision.o decodekey.o file.o libinfo.o oldauth.o +CC = gcc +CCFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC +CCOBJ = nls.o pe.o sha1.o stack.o + +ifeq ($(SYSTEM),Darwin) +LDFLAGS = -dynamiclib -lgmp -L/opt/local/lib +TARGET = libbncsutil.dylib +else +LDFLAGS = -shared -lgmp +TARGET = libbncsutil.so +endif + +$(TARGET): $(CXXOBJ) $(CCOBJ) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(CXXOBJ) $(CCOBJ) -o $(TARGET) + +$(CXXOBJ): %.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(CCOBJ): %.o: %.c + $(CC) $(CCFLAGS) -c $< -o $@ + +clean: + rm -f $(CCOBJ) $(CXXOBJ) $(TARGET) *~ +all: + make $(TARGET) + +install: $(TARGET) + mkdir -p /usr/include/bncsutil + cp *.h /usr/include/bncsutil + cp $(TARGET) /usr/lib + ldconfig diff --git a/src/bncsutil/bsha1.cpp b/src/bncsutil/bsha1.cpp index 6232f61..4344f0f 100644 --- a/src/bncsutil/bsha1.cpp +++ b/src/bncsutil/bsha1.cpp @@ -27,7 +27,7 @@ #include #include -#define USE_NEW_BSHA1 0 +#define USE_NEW_BSHA1 0 #define BSHA_IC1 0x67452301lu #define BSHA_IC2 0xEFCDAB89lu @@ -41,10 +41,10 @@ #define BSHA_OC4 0x359D3E2Alu #if !USE_NEW_BSHA1 -# define BSHA_COP e = d; d = c; c = ROL(b, 30); b = a; a = g; +# define BSHA_COP e = d; d = c; c = ROL(b, 30); b = a; a = g; #else -# define BSHA_N_COP t[4] = t[3]; t[3] = t[2]; t[2] = ROL(t[1], 30); \ - t[1] = t[0]; t[0] = x +# define BSHA_N_COP t[4] = t[3]; t[3] = t[2]; t[2] = ROL(t[1], 30); \ + t[1] = t[0]; t[0] = x #endif #if !USE_NEW_BSHA1 @@ -60,108 +60,108 @@ #else #define BSHA_N_OP1() x = LSB4(*p++) + ROL(t[0], 5) + t[4] + \ - ((t[1] & t[2]) | (~t[1] & t[3])) + BSHA_OC1; BSHA_N_COP + ((t[1] & t[2]) | (~t[1] & t[3])) + BSHA_OC1; BSHA_N_COP #define BSHA_N_OP2() x = (t[3] ^ t[2] ^ t[1]) + t[4] + ROL(x, 5) + \ - LSB4(*p++) + BSHA_OC2; BSHA_N_COP + LSB4(*p++) + BSHA_OC2; BSHA_N_COP #define BSHA_N_OP3() x = LSB4(*p++) + ROL(x, 5) + t[4] + \ - ((t[2] & t[1]) | (t[3] & t[2]) | (t[3] & t[1])) - BSHA_OC3; BSHA_N_COP + ((t[2] & t[1]) | (t[3] & t[2]) | (t[3] & t[1])) - BSHA_OC3; BSHA_N_COP #define BSHA_N_OP4() x = (t[3] ^ t[2] ^ t[1]) + t[4] + ROL(x, 5) + \ - LSB4(*p++) - BSHA_OC4; BSHA_N_COP + LSB4(*p++) - BSHA_OC4; BSHA_N_COP #endif #if USE_NEW_BSHA1 MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) { - uint32_t vals[5]; - uint32_t t[5]; // a, b, c, d, e - uint32_t buf[0x50]; - uint32_t* p; - uint32_t x; - const char* in = input; - unsigned int i, j; - unsigned int sub_length; - - /* Initializer Values */ - p = vals; - *p++ = BSHA_IC1; - *p++ = BSHA_IC2; - *p++ = BSHA_IC3; - *p++ = BSHA_IC4; - *p++ = BSHA_IC5; - - memset(buf, 0, 320); // zero buf - - /* Process input in chunks. */ - for (i = 0; i < length; i += 0x40) { - sub_length = length - i; - - /* Maximum chunk size is 0x40 (64) bytes. */ - if (sub_length > 0x40) - sub_length = 0x40; - - memcpy(buf, in, sub_length); - in += sub_length; - - /* If necessary, pad with zeroes to 64 bytes. */ - if (sub_length < 0x40) - memset(buf + sub_length, 0, 0x40 - sub_length); - - for (j = 0; j < 64; j++) { - buf[j + 16] = - LSB4(ROL(1, LSB4(buf[j] ^ buf[j+8] ^ buf[j+2] ^ buf[j+13]) % 32)); - } - - memcpy(t, vals, 20); - p = buf; - - /* It's a kind of magic. */ - BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); - BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); - - BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); - BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); - - BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); - BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); - - BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); - BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); - - vals[0] += t[0]; - vals[1] += t[1]; - vals[2] += t[2]; - vals[3] += t[3]; - vals[4] += t[4]; - } - - /* Return result. */ - memcpy(result, vals, 20); + uint32_t vals[5]; + uint32_t t[5]; // a, b, c, d, e + uint32_t buf[0x50]; + uint32_t* p; + uint32_t x; + const char* in = input; + unsigned int i, j; + unsigned int sub_length; + + /* Initializer Values */ + p = vals; + *p++ = BSHA_IC1; + *p++ = BSHA_IC2; + *p++ = BSHA_IC3; + *p++ = BSHA_IC4; + *p++ = BSHA_IC5; + + memset(buf, 0, 320); // zero buf + + /* Process input in chunks. */ + for (i = 0; i < length; i += 0x40) { + sub_length = length - i; + + /* Maximum chunk size is 0x40 (64) bytes. */ + if (sub_length > 0x40) + sub_length = 0x40; + + memcpy(buf, in, sub_length); + in += sub_length; + + /* If necessary, pad with zeroes to 64 bytes. */ + if (sub_length < 0x40) + memset(buf + sub_length, 0, 0x40 - sub_length); + + for (j = 0; j < 64; j++) { + buf[j + 16] = + LSB4(ROL(1, LSB4(buf[j] ^ buf[j+8] ^ buf[j+2] ^ buf[j+13]) % 32)); + } + + memcpy(t, vals, 20); + p = buf; + + /* It's a kind of magic. */ + BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); + BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); + + BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); + BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); + + BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); + BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); + + BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); + BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); + + vals[0] += t[0]; + vals[1] += t[1]; + vals[2] += t[2]; + vals[3] += t[3]; + vals[4] += t[4]; + } + + /* Return result. */ + memcpy(result, vals, 20); } #else MEXP(void) calcHashBuf(const char* input, size_t length, char* result) { int i; - unsigned long a, b, c, d, e, g; - uint32_t* ldata; + uint32_t a, b, c, d, e, g; + uint32_t* ldata; char data[1024]; memset(data, 0, 1024); memcpy(data, input, length); ldata = (uint32_t*) data; - + for (i = 0; i < 64; i++) { ldata[i + 16] = LSB4(ROL(1, LSB4(ldata[i] ^ ldata[i+8] ^ ldata[i+2] ^ ldata[i+13]) % 32)); } - - //dumpbuf(data, 1024); - + + //dumpbuf(data, 1024); + a = BSHA_IC1; b = BSHA_IC2; c = BSHA_IC3; d = BSHA_IC4; e = BSHA_IC5; g = 0; - + // Loops unrolled. BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) diff --git a/src/bncsutil/bsha1.h b/src/bncsutil/bsha1.h index 71fb980..6283c2e 100644 --- a/src/bncsutil/bsha1.h +++ b/src/bncsutil/bsha1.h @@ -41,7 +41,7 @@ extern "C" { * hash: Buffer, at least 20 bytes in length, to receive the hash. */ MEXP(void) calcHashBuf(const char* data, size_t length, char* hash); - + /* * New implementation. Broken. No plans to fix. */ diff --git a/src/bncsutil/cdkeydecoder.cpp b/src/bncsutil/cdkeydecoder.cpp index 4b3e97f..6c4ff3b 100644 --- a/src/bncsutil/cdkeydecoder.cpp +++ b/src/bncsutil/cdkeydecoder.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include #include #include // w2/d2 and w3 tables @@ -31,7 +31,8 @@ #include // for isdigit(), isalnum(), and toupper() #include // for memcpy() #include // for sscanf() - +// #include + /** * Implementation-specific CD-key hash structure. */ @@ -63,13 +64,13 @@ CDKeyDecoder::CDKeyDecoder() { initialized = 0; keyOK = 0; hashLen = 0; - cdkey = (char*) 0; - w3value2 = (char*) 0; - keyHash = (char*) 0; + cdkey = (char*) 0; + w3value2 = (char*) 0; + keyHash = (char*) 0; } CDKeyDecoder::CDKeyDecoder(const char* cd_key) { - CDKeyDecoder(cd_key, std::strlen(cd_key)); + CDKeyDecoder(cd_key, std::strlen(cd_key)); } /** @@ -80,19 +81,19 @@ CDKeyDecoder::CDKeyDecoder(const char* cd_key) { */ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { unsigned int i; - + initialized = 0; - product = 0; - value1 = 0; - value2 = 0; + product = 0; + value1 = 0; + value2 = 0; keyOK = 0; hashLen = 0; - cdkey = (char*) 0; - w3value2 = (char*) 0; - keyHash = (char*) 0; - + cdkey = (char*) 0; + w3value2 = (char*) 0; + keyHash = (char*) 0; + if (keyLength <= 0) return; - + // Initial sanity check if (keyLength == 13) { // StarCraft key @@ -101,9 +102,9 @@ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { } keyType = KEY_STARCRAFT; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with STAR key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with STAR key %s.", cdKey + ); #endif } else { // D2/W2/W3 key @@ -114,54 +115,54 @@ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { case 16: keyType = KEY_WARCRAFT2; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with W2/D2 key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with W2/D2 key %s.", cdKey + ); #endif break; case 26: keyType = KEY_WARCRAFT3; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with WAR3 key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with WAR3 key %s.", cdKey + ); #endif break; default: #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with unrecognized key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with unrecognized key %s.", cdKey + ); #endif return; } } - + cdkey = new char[keyLength + 1]; initialized = 1; keyLen = keyLength; strcpy(cdkey, cdKey); - + switch (keyType) { case KEY_STARCRAFT: keyOK = processStarCraftKey(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " - "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " + "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); #endif break; case KEY_WARCRAFT2: keyOK = processWarCraft2Key(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " - "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " + "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); #endif break; case KEY_WARCRAFT3: keyOK = processWarCraft3Key(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ", - cdkey, keyOK, getProduct(), getVal1()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ", + cdkey, keyOK, getProduct(), getVal1()); #endif break; default: @@ -174,8 +175,8 @@ CDKeyDecoder::~CDKeyDecoder() { delete [] cdkey; if (hashLen > 0 && keyHash != NULL) delete [] keyHash; - if (w3value2) - delete [] w3value2; + if (w3value2) + delete [] w3value2; } int CDKeyDecoder::isKeyValid() { @@ -187,27 +188,27 @@ int CDKeyDecoder::getVal2Length() { } uint32_t CDKeyDecoder::getProduct() { - switch (keyType) { - case KEY_STARCRAFT: - case KEY_WARCRAFT2: - return (uint32_t) LSB4(product); - case KEY_WARCRAFT3: - return (uint32_t) MSB4(product); - default: - return (uint32_t) -1; - } + switch (keyType) { + case KEY_STARCRAFT: + case KEY_WARCRAFT2: + return (uint32_t) LSB4(product); + case KEY_WARCRAFT3: + return (uint32_t) MSB4(product); + default: + return (uint32_t) -1; + } } uint32_t CDKeyDecoder::getVal1() { switch (keyType) { - case KEY_STARCRAFT: - case KEY_WARCRAFT2: - return (uint32_t) LSB4(value1); - case KEY_WARCRAFT3: - return (uint32_t) MSB4(value1); - default: - return (uint32_t) -1; - } + case KEY_STARCRAFT: + case KEY_WARCRAFT2: + return (uint32_t) LSB4(value1); + case KEY_WARCRAFT3: + return (uint32_t) MSB4(value1); + default: + return (uint32_t) -1; + } } uint32_t CDKeyDecoder::getVal2() { @@ -239,35 +240,35 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, { struct CDKEYHASH kh; SHA1Context sha; - + if (!initialized || !keyOK) return 0; hashLen = 0; - + kh.clientToken = clientToken; kh.serverToken = serverToken; - + switch (keyType) { case KEY_STARCRAFT: case KEY_WARCRAFT2: - kh.product = (uint32_t) LSB4(product); - kh.value1 = (uint32_t) LSB4(value1); + kh.product = (uint32_t) LSB4(product); + kh.value1 = (uint32_t) LSB4(value1); kh.value2.s.zero = 0; kh.value2.s.v = (uint32_t) LSB4(value2); - + keyHash = new char[20]; calcHashBuf((char*) &kh, 24, keyHash); hashLen = 20; #if DEBUG - bncsutil_debug_message_a("%s: Hash calculated.", cdkey); - bncsutil_debug_dump(keyHash, 20); + bncsutil_debug_message_a("%s: Hash calculated.", cdkey); + bncsutil_debug_dump(keyHash, 20); #endif return 20; case KEY_WARCRAFT3: - kh.product = (uint32_t) MSB4(product); - kh.value1 = (uint32_t) MSB4(value1); + kh.product = (uint32_t) MSB4(product); + kh.value1 = (uint32_t) MSB4(value1); memcpy(kh.value2.l.v, w3value2, 10); if (SHA1Reset(&sha)) @@ -281,10 +282,10 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, } SHA1Reset(&sha); hashLen = 20; - + #if DEBUG - bncsutil_debug_message_a("%s: Hash calculated.", cdkey); - bncsutil_debug_dump(keyHash, 20); + bncsutil_debug_message_a("%s: Hash calculated.", cdkey); + bncsutil_debug_dump(keyHash, 20); #endif return 20; @@ -300,7 +301,7 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, */ size_t CDKeyDecoder::getHash(char* outputBuffer) { if (hashLen == 0 || !keyHash || !outputBuffer) - return 0; + return 0; memcpy(outputBuffer, keyHash, hashLen); return hashLen; } @@ -318,21 +319,21 @@ int CDKeyDecoder::processStarCraftKey() { int accum, pos, i; char temp; int hashKey = 0x13AC9741; - char cdkey[14]; - - std::strcpy(cdkey, this->cdkey); + char cdkey[14]; + std::strcpy(cdkey, this->cdkey); + // Verification accum = 3; for (i = 0; i < (int) (keyLen - 1); i++) { accum += ((tolower(cdkey[i]) - '0') ^ (accum * 2)); } - - if ((accum % 10) != (cdkey[12] - '0')) { - bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey); + + if ((accum % 10) != (cdkey[12] - '0')) { + // bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey); return 0; - } - + } + // Shuffling pos = 0x0B; for (i = 0xC2; i >= 7; i -= 0x11) { @@ -341,7 +342,7 @@ int CDKeyDecoder::processStarCraftKey() { cdkey[i % 0x0C] = temp; pos--; } - + // Final Value for (i = (int) (keyLen - 2); i >= 0; i--) { temp = toupper(cdkey[i]); @@ -353,10 +354,10 @@ int CDKeyDecoder::processStarCraftKey() { cdkey[i] ^= ((char) i & 1); } } - + // Final Calculations sscanf(cdkey, "%2ld%7ld%3ld", &product, &value1, &value2); - + return 1; } @@ -364,10 +365,10 @@ int CDKeyDecoder::processWarCraft2Key() { unsigned long r, n, n2, v, v2, checksum; int i; unsigned char c1, c2, c; - char cdkey[17]; - - std::strcpy(cdkey, this->cdkey); + char cdkey[17]; + std::strcpy(cdkey, this->cdkey); + r = 1; checksum = 0; for (i = 0; i < 16; i += 2) { @@ -375,7 +376,7 @@ int CDKeyDecoder::processWarCraft2Key() { n = c1 * 3; c2 = w2Map[(int) cdkey[i + 1]]; n = c2 + n * 8; - + if (n >= 0x100) { n -= 0x100; checksum |= r; @@ -387,7 +388,7 @@ int CDKeyDecoder::processWarCraft2Key() { cdkey[i + 1] = getHexValue(n); r <<= 1; } - + v = 3; for (i = 0; i < 16; i++) { c = cdkey[i]; @@ -397,11 +398,11 @@ int CDKeyDecoder::processWarCraft2Key() { v += n; } v &= 0xFF; - + if (v != checksum) { return 0; } - + n = 0; for (int j = 15; j >= 0; j--) { c = cdkey[j]; @@ -441,55 +442,55 @@ int CDKeyDecoder::processWarCraft3Key() { int a, b; int i; char decode; - + a = 0; b = 0x21; - + memset(table, 0, W3_BUFLEN); memset(values, 0, (sizeof(int) * 4)); - + for (i = 0; ((unsigned int) i) < keyLen; i++) { cdkey[i] = toupper(cdkey[i]); a = (b + 0x07B5) % W3_BUFLEN; b = (a + 0x07B5) % W3_BUFLEN; - decode = w3KeyMap[cdkey[i]]; + decode = w3KeyMap[(int)cdkey[i]]; table[a] = (decode / 5); table[b] = (decode % 5); } - + // Mult i = W3_BUFLEN; do { mult(4, 5, values + 3, table[i - 1]); } while (--i); - + decodeKeyTable(values); + + // 00 00 38 08 f0 64 18 6c 79 14 14 8E B9 49 1D BB + // -------- + // val1 - // 00 00 38 08 f0 64 18 6c 79 14 14 8E B9 49 1D BB - // -------- - // val1 - - product = values[0] >> 0xA; - product = SWAP4(product); + product = values[0] >> 0xA; + product = SWAP4(product); #if LITTLEENDIAN - for (i = 0; i < 4; i++) { - values[i] = MSB4(values[i]); - } + for (i = 0; i < 4; i++) { + values[i] = MSB4(values[i]); + } #endif - value1 = LSB4(*(uint32_t*) (((char*) values) + 2)) & 0xFFFFFF03; + value1 = LSB4(*(uint32_t*) (((char*) values) + 2)) & 0xFFFFFF00; - w3value2 = new char[10]; + w3value2 = new char[10]; #if LITTLEENDIAN - *((uint16_t*) w3value2) = MSB2(*(uint16_t*) (((char*) values) + 6)); - *((uint32_t*) ((char*) w3value2 + 2)) = MSB4(*(uint32_t*) (((char*) values) + 8)); - *((uint32_t*) ((char*) w3value2 + 6)) = MSB4(*(uint32_t*) (((char*) values) + 12)); + *((uint16_t*) w3value2) = MSB2(*(uint16_t*) (((char*) values) + 6)); + *((uint32_t*) ((char*) w3value2 + 2)) = MSB4(*(uint32_t*) (((char*) values) + 8)); + *((uint32_t*) ((char*) w3value2 + 6)) = MSB4(*(uint32_t*) (((char*) values) + 12)); #else - *((uint16_t*) w3value2) = LSB2(*(uint16_t*) (((char*) values) + 6)); - *((uint32_t*) ((char*) w3value2 + 2)) = LSB4(*(uint32_t*) (((char*) values) + 8)); - *((uint32_t*) ((char*) w3value2 + 6)) = LSB4(*(uint32_t*) (((char*) values) + 12)); + *((uint16_t*) w3value2) = LSB2(*(uint16_t*) (((char*) values) + 6)); + *((uint32_t*) ((char*) w3value2 + 2)) = LSB4(*(uint32_t*) (((char*) values) + 8)); + *((uint32_t*) ((char*) w3value2 + 6)) = LSB4(*(uint32_t*) (((char*) values) + 12)); #endif - return 1; + return 1; } inline void CDKeyDecoder::mult(int r, const int x, int* a, int dcByte) { @@ -510,7 +511,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { int ckt_temp; var8 = 29; int i = 464; - + // pass 1 do { int j; @@ -520,7 +521,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = keyTable[3 - var4]; varC &= (0xF << esi); varC = varC >> esi; - + if (i < 464) { for (j = 29; (unsigned int) j > var8; j--) { /* @@ -536,7 +537,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = w3TranslateMap[ebp ^ w3TranslateMap[varC + i] + i]; } } - + j = --var8; while (j >= 0) { ecx = (j & 7) << 2; @@ -547,12 +548,12 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = w3TranslateMap[ebp ^ w3TranslateMap[varC + i] + i]; j--; } - + j = 3 - var4; ebx = (w3TranslateMap[varC + i] & 0xF) << esi; keyTable[j] = (ebx | ~(0xF << esi) & ((int) keyTable[j])); } while ((i -= 16) >= 0); - + // pass 2 eax = 0; edx = 0; @@ -560,26 +561,26 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { edi = 0; esi = 0; ebp = 0; - + for (i = 0; i < 4; i++) { copy[i] = LSB4(keyTable[i]); } scopy = (unsigned char*) copy; - + for (edi = 0; edi < 120; edi++) { unsigned int location = 12; eax = edi & 0x1F; ecx = esi & 0x1F; edx = 3 - (edi >> 5); - + location -= ((esi >> 5) << 2); ebp = *(int*) (scopy + location); ebp = LSB4(ebp); - + //ebp = (ebp & (1 << ecx)) >> ecx; ebp &= (1 << ecx); ebp = ebp >> ecx; - + //keyTable[edx] = ((ebp & 1) << eax) | (~(1 << eax) & keyTable[edx]); ckt = (keyTable + edx); ckt_temp = *ckt; diff --git a/src/bncsutil/cdkeydecoder.h b/src/bncsutil/cdkeydecoder.h index 0f845f1..cdf46bb 100644 --- a/src/bncsutil/cdkeydecoder.h +++ b/src/bncsutil/cdkeydecoder.h @@ -27,7 +27,7 @@ #define BNCSUTIL_CDKEYDECODER_H #include - + /** * Internal key type constants. */ @@ -49,18 +49,18 @@ MCEXP(CDKeyDecoder) { unsigned long value2; unsigned long product; char* w3value2; - + int processStarCraftKey(); int processWarCraft2Key(); int processWarCraft3Key(); - + void decodeKeyTable(int* keyTable); - + inline char getHexValue(int v); inline int getNumValue(char v); - + inline void mult(const int r, const int x, int* a, int dcByte); - + public: /** * Creates a new CD-key decoder object. @@ -68,8 +68,8 @@ MCEXP(CDKeyDecoder) { */ CDKeyDecoder(); - CDKeyDecoder(const char* cd_key); - + CDKeyDecoder(const char* cd_key); + /** * Creates a new CD-key decoder object, using the specified key. * keyLength should be the length of the key, NOT INCLUDING the @@ -77,16 +77,16 @@ MCEXP(CDKeyDecoder) { * this constructor to check the validity of the provided key. */ CDKeyDecoder(const char* cdKey, size_t keyLength); - + virtual ~CDKeyDecoder(); - + int isKeyValid(); int getVal2Length(); uint32_t getProduct(); uint32_t getVal1(); uint32_t getVal2(); int getLongVal2(char* out); - + /** * Calculates the CD-Key hash for use in SID_AUTH_CHECK (0x51) * Returns the length of the generated hash; call getHash and pass @@ -99,7 +99,7 @@ MCEXP(CDKeyDecoder) { * endianness is not a factor. */ size_t calculateHash(uint32_t clientToken, uint32_t serverToken); - + /** * Places the calculated CD-key hash in outputBuffer. You must call * calculateHash before getHash. Returns the length of the hash diff --git a/src/bncsutil/checkrevision.cpp b/src/bncsutil/checkrevision.cpp index 03675e7..99819a6 100644 --- a/src/bncsutil/checkrevision.cpp +++ b/src/bncsutil/checkrevision.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include #include #include @@ -67,442 +67,442 @@ extern "C" { std::vector checkrevision_seeds; void initialize_checkrevision_seeds() { - static bool run = false; - - if (run) - return; - - run = true; - - checkrevision_seeds.reserve(8); - - checkrevision_seeds.push_back(0xE7F4CB62); - checkrevision_seeds.push_back(0xF6A14FFC); - checkrevision_seeds.push_back(0xAA5504AF); - checkrevision_seeds.push_back(0x871FCDC2); - checkrevision_seeds.push_back(0x11BF6A18); - checkrevision_seeds.push_back(0xC57292E6); - checkrevision_seeds.push_back(0x7927D27E); + static bool run = false; + + if (run) + return; + + run = true; + + checkrevision_seeds.reserve(8); + + checkrevision_seeds.push_back(0xE7F4CB62); + checkrevision_seeds.push_back(0xF6A14FFC); + checkrevision_seeds.push_back(0xAA5504AF); + checkrevision_seeds.push_back(0x871FCDC2); + checkrevision_seeds.push_back(0x11BF6A18); + checkrevision_seeds.push_back(0xC57292E6); + checkrevision_seeds.push_back(0x7927D27E); + checkrevision_seeds.push_back(0x2FEC8733); } MEXP(long) get_mpq_seed(int mpq_number) { - if (((size_t) mpq_number) >= checkrevision_seeds.size()) { - bncsutil_debug_message_a("error: no known revision check seed for " - "MPQ#%u", mpq_number); - return 0; - } - - return checkrevision_seeds[mpq_number]; + if (((size_t) mpq_number) >= checkrevision_seeds.size()) { + //bncsutil_debug_message_a("error: no known revision check seed for " + // "MPQ#%u", mpq_number); + return 0; + } + + return checkrevision_seeds[mpq_number]; } MEXP(long) set_mpq_seed(int mpq_number, long new_seed) { - long ret; - - if (((size_t) mpq_number) >= checkrevision_seeds.size()) { - ret = 0; - checkrevision_seeds.reserve((size_t) mpq_number); - } else { - ret = checkrevision_seeds[mpq_number]; - } - - checkrevision_seeds[mpq_number] = new_seed; - return ret; + long ret; + + if (((size_t) mpq_number) >= checkrevision_seeds.size()) { + ret = 0; + checkrevision_seeds.reserve((size_t) mpq_number); + } else { + ret = checkrevision_seeds[mpq_number]; + } + + checkrevision_seeds[mpq_number] = new_seed; + return ret; } MEXP(int) extractMPQNumber(const char* mpqName) { - const char* n; - int mpqNum; - if (mpqName == NULL) - return -1; - if ((n = (const char*) std::strchr(mpqName, '.')) == NULL) - return -1; - // extract int value of version number - mpqNum = atoi(n - 1); - return mpqNum; + const char* n; + int mpqNum; + if (mpqName == NULL) + return -1; + if ((n = (const char*) std::strchr(mpqName, '.')) == NULL) + return -1; + // extract int value of version number + mpqNum = atoi(n - 1); + return mpqNum; } -#if !__GNUC__ -const char* basename(const char* file_name) +const char* get_basename(const char* file_name) { - const char* base; - - for (base = (file_name + strlen(file_name)); base >= file_name; base--) { - if (*base == '\\' || *base == '/') - break; - } - - return ++base; + const char* base; + + for (base = (file_name + strlen(file_name)); base >= file_name; base--) { + if (*base == '\\' || *base == '/') + break; + } + + return ++base; } -#endif MEXP(int) checkRevision(const char* formula, const char* files[], int numFiles, - int mpqNumber, unsigned long* checksum) + int mpqNumber, unsigned long* checksum) { - long values[4], ovd[4], ovs1[4], ovs2[4]; - char ops[4]; - const char* token; - int curFormula = 0; - file_t f; - uint8_t* file_buffer; - uint32_t* dwBuf; - uint32_t* current; - size_t seed_count; - + uint64_t values[4]; + long ovd[4], ovs1[4], ovs2[4]; + char ops[4]; + const char* token; + int curFormula = 0; + file_t f; + uint8_t* file_buffer; + uint32_t* dwBuf; + uint32_t* current; + size_t seed_count; + #if DEBUG - int i; - bncsutil_debug_message_a("checkRevision(\"%s\", {", formula); - for (i = 0; i < numFiles; i++) { - bncsutil_debug_message_a("\t\"%s\",", files[i]); - } - bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum); + int i; + bncsutil_debug_message_a("checkRevision(\"%s\", {", formula); + for (i = 0; i < numFiles; i++) { + bncsutil_debug_message_a("\t\"%s\",", files[i]); + } + bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum); #endif - - if (!formula || !files || numFiles == 0 || mpqNumber <= 0 || !checksum) { - bncsutil_debug_message("error: checkRevision() parameter sanity check " - "failed"); - return 0; - } - - seed_count = checkrevision_seeds.size(); - if (seed_count == 0) { - initialize_checkrevision_seeds(); - seed_count = checkrevision_seeds.size(); - } - - if (seed_count <= (size_t) mpqNumber) { - bncsutil_debug_message_a("error: no revision check seed value defined " - "for MPQ number %d", mpqNumber); - return 0; - } - - token = formula; - while (token && *token) { - if (*(token + 1) == '=') { - int variable = BUCR_GETNUM(*token); - if (variable < 0 || variable > 3) { - bncsutil_debug_message_a("error: Unknown revision check formula" - " variable %c", *token); - return 0; - } - - token += 2; // skip over equals sign - if (BUCR_ISNUM(*token)) { - values[variable] = atol(token); - } else { - if (curFormula > 3) { - // more than 4 operations? bloody hell. - bncsutil_debug_message("error: Revision check formula" - " contains more than 4 operations; unsupported."); - return 0; - } - ovd[curFormula] = variable; - ovs1[curFormula] = BUCR_GETNUM(*token); - ops[curFormula] = *(token + 1); - ovs2[curFormula] = BUCR_GETNUM(*(token + 2)); - curFormula++; - } - } - - for (; *token != 0; token++) { - if (*token == ' ') { - token++; - break; - } - } - } - - // Actual hashing (yay!) - // "hash A by the hashcode" - values[0] ^= checkrevision_seeds[mpqNumber]; - - for (int i = 0; i < numFiles; i++) { - size_t file_len, remainder, rounded_size, buffer_size; - - f = file_open(files[i], FILE_READ); - if (!f) { - bncsutil_debug_message_a("error: Failed to open file %s", - files[i]); - return 0; - } - - file_len = file_size(f); - remainder = file_len % 1024; - rounded_size = file_len - remainder; - - file_buffer = (uint8_t*) file_map(f, file_len, 0); - if (!file_buffer) { - file_close(f); - bncsutil_debug_message_a("error: Failed to map file %s into memory", - files[i]); - return 0; - } - - if (remainder == 0) { - // Mapped buffer may be used directly, without padding. - dwBuf = (uint32_t*) file_buffer; - buffer_size = file_len; - } else { - // Must be padded to nearest KB. - size_t extra = 1024 - remainder; - uint8_t pad = (uint8_t) 0xFF; - uint8_t* pad_dest; - - buffer_size = file_len + extra; - dwBuf = (uint32_t*) malloc(buffer_size); - if (!dwBuf) { - bncsutil_debug_message_a("error: Failed to allocate %d bytes " - "of memory as a temporary buffer", buffer_size); - file_unmap(f, file_buffer); - file_close(f); - return 0; - } - - memcpy(dwBuf, file_buffer, file_len); - file_unmap(f, file_buffer); - file_buffer = (uint8_t*) 0; - - pad_dest = ((uint8_t*) dwBuf) + file_len; - for (size_t j = file_len; j < buffer_size; j++) { - *pad_dest++ = pad--; - } - - } - - current = dwBuf; - for (size_t j = 0; j < buffer_size; j += 4) { - values[3] = LSB4(*(current++)); - for (int k = 0; k < curFormula; k++) { - switch (ops[k]) { - case '+': - values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]]; - break; - case '-': - values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]]; - break; - case '^': - values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]]; - break; - case '*': - // well, you never know - values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]]; - break; - case '/': - // well, you never know - values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]]; - break; - default: - // unrecognized operation - // shit - file_unmap(f, dwBuf); - file_close(f); - return 0; - } - } - } - - if (file_buffer) - file_unmap(f, file_buffer); - else if (dwBuf && file_buffer == 0) - free(dwBuf); // padded buffer - file_close(f); - } - - *checksum = (unsigned long) LSB4(values[2]); + + if (!formula || !files || numFiles == 0 || mpqNumber < 0 || !checksum) { + //bncsutil_debug_message("error: checkRevision() parameter sanity check " + // "failed"); + return 0; + } + + seed_count = checkrevision_seeds.size(); + if (seed_count == 0) { + initialize_checkrevision_seeds(); + seed_count = checkrevision_seeds.size(); + } + + if (seed_count <= (size_t) mpqNumber) { + //bncsutil_debug_message_a("error: no revision check seed value defined " + // "for MPQ number %d", mpqNumber); + return 0; + } + + token = formula; + while (token && *token) { + if (*(token + 1) == '=') { + int variable = BUCR_GETNUM(*token); + if (variable < 0 || variable > 3) { + //bncsutil_debug_message_a("error: Unknown revision check formula" + // " variable %c", *token); + return 0; + } + + token += 2; // skip over equals sign + if (BUCR_ISNUM(*token)) { + values[variable] = ATOL64(token); + } else { + if (curFormula > 3) { + // more than 4 operations? bloody hell. + //bncsutil_debug_message("error: Revision check formula" + // " contains more than 4 operations; unsupported."); + return 0; + } + ovd[curFormula] = variable; + ovs1[curFormula] = BUCR_GETNUM(*token); + ops[curFormula] = *(token + 1); + ovs2[curFormula] = BUCR_GETNUM(*(token + 2)); + curFormula++; + } + } + + for (; *token != 0; token++) { + if (*token == ' ') { + token++; + break; + } + } + } + + // Actual hashing (yay!) + // "hash A by the hashcode" + values[0] ^= checkrevision_seeds[mpqNumber]; + + for (int i = 0; i < numFiles; i++) { + size_t file_len, remainder, rounded_size, buffer_size; + + f = file_open(files[i], FILE_READ); + if (!f) { + //bncsutil_debug_message_a("error: Failed to open file %s", + // files[i]); + return 0; + } + + file_len = file_size(f); + remainder = file_len % 1024; + rounded_size = file_len - remainder; + + file_buffer = (uint8_t*) file_map(f, file_len, 0); + if (!file_buffer) { + file_close(f); + //bncsutil_debug_message_a("error: Failed to map file %s into memory", + // files[i]); + return 0; + } + + if (remainder == 0) { + // Mapped buffer may be used directly, without padding. + dwBuf = (uint32_t*) file_buffer; + buffer_size = file_len; + } else { + // Must be padded to nearest KB. + size_t extra = 1024 - remainder; + uint8_t pad = (uint8_t) 0xFF; + uint8_t* pad_dest; + + buffer_size = file_len + extra; + dwBuf = (uint32_t*) malloc(buffer_size); + if (!dwBuf) { + //bncsutil_debug_message_a("error: Failed to allocate %d bytes " + // "of memory as a temporary buffer", buffer_size); + file_unmap(f, file_buffer); + file_close(f); + return 0; + } + + memcpy(dwBuf, file_buffer, file_len); + file_unmap(f, file_buffer); + file_buffer = (uint8_t*) 0; + + pad_dest = ((uint8_t*) dwBuf) + file_len; + for (size_t j = file_len; j < buffer_size; j++) { + *pad_dest++ = pad--; + } + + } + + current = dwBuf; + for (size_t j = 0; j < buffer_size; j += 4) { + values[3] = LSB4(*(current++)); + for (int k = 0; k < curFormula; k++) { + switch (ops[k]) { + case '+': + values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]]; + break; + case '-': + values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]]; + break; + case '^': + values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]]; + break; + case '*': + // well, you never know + values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]]; + break; + case '/': + // well, you never know + values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]]; + break; + default: + // unrecognized operation + // shit + file_unmap(f, dwBuf); + file_close(f); + return 0; + } + } + } + + if (file_buffer) + file_unmap(f, file_buffer); + else if (dwBuf && file_buffer == 0) + free(dwBuf); // padded buffer + file_close(f); + } + + *checksum = (unsigned long) LSB4(values[2]); #if DEBUG - bncsutil_debug_message_a("\tChecksum = %lu", *checksum); + bncsutil_debug_message_a("\tChecksum = %lu", *checksum); #endif - return 1; + return 1; } MEXP(int) checkRevisionFlat(const char* valueString, const char* file1, const char* file2, const char* file3, int mpqNumber, unsigned long* checksum) { - const char* files[] = - {file1, file2, file3}; - return checkRevision(valueString, files, 3, mpqNumber, - checksum); + const char* files[] = + {file1, file2, file3}; + return checkRevision(valueString, files, 3, mpqNumber, + checksum); } MEXP(int) getExeInfo(const char* file_name, char* exe_info, - size_t exe_info_size, uint32_t* version, int platform) + size_t exe_info_size, uint32_t* version, int platform) { - const char* base = (char*) 0; - unsigned long file_size; - FILE* f = (FILE*) 0; - int ret; + const char* base = (char*) 0; + unsigned long file_size; + FILE* f = (FILE*) 0; + int ret; #ifdef MOS_WINDOWS - HANDLE hFile; - FILETIME ft; - SYSTEMTIME st; - LPBYTE buf; - VS_FIXEDFILEINFO* ffi; - DWORD infoSize, bytesRead; + HANDLE hFile; + FILETIME ft; + SYSTEMTIME st; + LPBYTE buf; + VS_FIXEDFILEINFO* ffi; + DWORD infoSize, bytesRead; #else - cm_pe_t pe; - cm_pe_resdir_t* root; - cm_pe_resdir_t* dir; - cm_pe_version_t ffi; - size_t i; - struct stat st; - struct tm* time; + cm_pe_t pe; + cm_pe_resdir_t* root; + cm_pe_resdir_t* dir; + cm_pe_version_t ffi; + size_t i; + struct stat st; + struct tm* time; #endif - - if (!file_name || !exe_info || !exe_info_size || !version) - return 0; - - base = basename(file_name); - - switch (platform) { - case BNCSUTIL_PLATFORM_X86: -#ifdef MOS_WINDOWS - infoSize = GetFileVersionInfoSize(file_name, &bytesRead); - if (infoSize == 0) - return 0; - buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, - PAGE_READWRITE); - if (buf == NULL) - return 0; - if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) - return 0; - if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) - return 0; - - *version = - ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | - ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | - ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | - (LOWORD(ffi->dwProductVersionLS) & 0xFF); + + if (!file_name || !exe_info || !exe_info_size || !version) + return 0; + + base = get_basename(file_name); + + switch (platform) { + case BNCSUTIL_PLATFORM_X86: +#ifdef MOS_WINDOWS + infoSize = GetFileVersionInfoSize(file_name, &bytesRead); + if (infoSize == 0) + return 0; + buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, + PAGE_READWRITE); + if (buf == NULL) + return 0; + if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) + return 0; + if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) + return 0; + + *version = + ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | + ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | + ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | + (LOWORD(ffi->dwProductVersionLS) & 0xFF); #if DEBUG - bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", - base, (HIWORD(ffi->dwProductVersionMS) & 0xFF), - (LOWORD(ffi->dwProductVersionMS) & 0xFF), - (HIWORD(ffi->dwProductVersionLS) & 0xFF), - (LOWORD(ffi->dwProductVersionLS) & 0xFF), - *version); + bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", + base, (HIWORD(ffi->dwProductVersionMS) & 0xFF), + (LOWORD(ffi->dwProductVersionMS) & 0xFF), + (HIWORD(ffi->dwProductVersionLS) & 0xFF), + (LOWORD(ffi->dwProductVersionLS) & 0xFF), + *version); #endif - VirtualFree(buf, 0lu, MEM_RELEASE); + VirtualFree(buf, 0lu, MEM_RELEASE); #else - pe = cm_pe_load(file_name); - if (!pe) - return 0; - root = cm_pe_load_resources(pe); - if (!root) { - cm_pe_unload(pe); - return 0; - } - - for (i = 0; i < root->subdir_count; i++) { - dir = (root->subdirs + i); - if (dir->name == 16) { - if (!cm_pe_fixed_version(pe, dir->subdirs->resources, - &ffi)) - { - cm_pe_unload_resources(root); - cm_pe_unload(pe); - return 0; - } - break; - } - } - *version = - ((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) | - ((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) | - ((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | - (LOWORD(ffi.dwProductVersionLS) & 0xFF); + pe = cm_pe_load(file_name); + if (!pe) + return 0; + root = cm_pe_load_resources(pe); + if (!root) { + cm_pe_unload(pe); + return 0; + } + + for (i = 0; i < root->subdir_count; i++) { + dir = (root->subdirs + i); + if (dir->name == 16) { + if (!cm_pe_fixed_version(pe, dir->subdirs->resources, + &ffi)) + { + cm_pe_unload_resources(root); + cm_pe_unload(pe); + return 0; + } + break; + } + } + *version = + ((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) | + ((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) | + ((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | + (LOWORD(ffi.dwProductVersionLS) & 0xFF); #if DEBUG - bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", - base, (HIWORD(ffi.dwProductVersionMS) & 0xFF), - (LOWORD(ffi.dwProductVersionMS) & 0xFF), - (HIWORD(ffi.dwProductVersionLS) & 0xFF), - (LOWORD(ffi.dwProductVersionLS) & 0xFF), - *version); + bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", + base, (HIWORD(ffi.dwProductVersionMS) & 0xFF), + (LOWORD(ffi.dwProductVersionMS) & 0xFF), + (HIWORD(ffi.dwProductVersionLS) & 0xFF), + (LOWORD(ffi.dwProductVersionLS) & 0xFF), + *version); #endif - - cm_pe_unload_resources(root); - cm_pe_unload(pe); + + cm_pe_unload_resources(root); + cm_pe_unload(pe); #endif - break; - case BNCSUTIL_PLATFORM_MAC: - case BNCSUTIL_PLATFORM_OSX: - f = fopen(file_name, "r"); - if (!f) - return 0; - if (fseek(f, -4, SEEK_END) != 0) { - fclose(f); - return 0; - } - if (fread(version, 4, 1, f) != 1) { - fclose(f); - return 0; - } + break; + case BNCSUTIL_PLATFORM_MAC: + case BNCSUTIL_PLATFORM_OSX: + f = fopen(file_name, "r"); + if (!f) + return 0; + if (fseek(f, -4, SEEK_END) != 0) { + fclose(f); + return 0; + } + if (fread(version, 4, 1, f) != 1) { + fclose(f); + return 0; + } #ifdef MOS_WINDOWS - fclose(f); + fclose(f); #endif - } - + } + #ifdef MOS_WINDOWS - hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return 0; - file_size = GetFileSize(hFile, NULL); - if (!GetFileTime(hFile, &ft, NULL, NULL)) { - CloseHandle(hFile); - return 0; - } - - if (!FileTimeToSystemTime(&ft, &st)) { - CloseHandle(hFile); - return 0; - } - CloseHandle(hFile); - - ret = snprintf(exe_info, exe_info_size, - "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth, - st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond, - file_size); + hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + file_size = GetFileSize(hFile, NULL); + if (!GetFileTime(hFile, &ft, NULL, NULL)) { + CloseHandle(hFile); + return 0; + } + + if (!FileTimeToSystemTime(&ft, &st)) { + CloseHandle(hFile); + return 0; + } + CloseHandle(hFile); + + ret = snprintf(exe_info, exe_info_size, + "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth, + st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond, + file_size); #else - if (!f) - f = fopen(file_name, "r"); - if (!f) - return 0; - if (fseek(f, 0, SEEK_END) == -1) { - fclose(f); - return 0; - } - file_size = ftell(f); - fclose(f); - - if (stat(file_name, &st) != 0) - return 0; - - time = gmtime(&st.st_mtime); - if (!time) - return 0; - - switch (platform) { - case BNCSUTIL_PLATFORM_MAC: - case BNCSUTIL_PLATFORM_OSX: - if (time->tm_year >= 100) // y2k - time->tm_year -= 100; - break; - } - - ret = (int) snprintf(exe_info, exe_info_size, - "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, - (time->tm_mon+1), time->tm_mday, time->tm_year, - time->tm_hour, time->tm_min, time->tm_sec, file_size); + if (!f) + f = fopen(file_name, "r"); + if (!f) + return 0; + if (fseek(f, 0, SEEK_END) == -1) { + fclose(f); + return 0; + } + file_size = ftell(f); + fclose(f); + + if (stat(file_name, &st) != 0) + return 0; + + time = gmtime(&st.st_mtime); + if (!time) + return 0; + + switch (platform) { + case BNCSUTIL_PLATFORM_MAC: + case BNCSUTIL_PLATFORM_OSX: + if (time->tm_year >= 100) // y2k + time->tm_year -= 100; + break; + } + + ret = (int) snprintf(exe_info, exe_info_size, + "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, + (time->tm_mon+1), time->tm_mday, time->tm_year, + time->tm_hour, time->tm_min, time->tm_sec, file_size); #endif #if DEBUG - bncsutil_debug_message(exe_info); + bncsutil_debug_message(exe_info); #endif - return ret; + return ret; } #ifdef __cplusplus diff --git a/src/bncsutil/checkrevision.h b/src/bncsutil/checkrevision.h index c31aa9f..1e42fe7 100644 --- a/src/bncsutil/checkrevision.h +++ b/src/bncsutil/checkrevision.h @@ -71,8 +71,8 @@ MEXP(int) checkRevision( MEXP(int) checkRevisionFlat( const char* valueString, const char* file1, - const char* file2, - const char* file3, + const char* file2, + const char* file3, int mpqNumber, unsigned long* checksum ); @@ -87,11 +87,11 @@ MEXP(int) checkRevisionFlat( * necessary. */ MEXP(int) getExeInfo(const char* file_name, - char* exe_info, - size_t exe_info_size, - uint32_t* version, - int platform); - + char* exe_info, + size_t exe_info_size, + uint32_t* version, + int platform); + /** * Gets the seed value for the given MPQ file. If no seed value for the given * MPQ is registered with BNCSutil, returns 0. diff --git a/src/bncsutil/debug.c b/src/bncsutil/debug.c index 92fc499..5d07b62 100644 --- a/src/bncsutil/debug.c +++ b/src/bncsutil/debug.c @@ -18,127 +18,127 @@ #include #endif -struct _bncsutil_debug_env +typedef struct _bncsutil_debug_env { - int enabled; + int enabled; #ifdef MOS_WINDOWS - HANDLE output; - BOOL console_was_created; - WORD orig_attributes; - WORD sans_foreground; + HANDLE output; + BOOL console_was_created; + WORD orig_attributes; + WORD sans_foreground; #else - FILE* output; + FILE* output; #endif -}; +} debug_env_t; const char default_err_msg[] = "[unknown error]"; #ifdef MOS_WINDOWS BOOL debug_set_color(debug_env_t env, WORD color) { - return SetConsoleTextAttribute(env->output, color | env->sans_foreground); + return SetConsoleTextAttribute(env.output, color | env.sans_foreground); } BOOL debug_restore_color(debug_env_t env) { - return SetConsoleTextAttribute(env->output, env->orig_attributes); + return SetConsoleTextAttribute(env.output, env.orig_attributes); } BOOL debug_intense_color(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env->output, &info)) - return FALSE; - return SetConsoleTextAttribute(env->output, info.wAttributes | - FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env.output, &info)) + return FALSE; + return SetConsoleTextAttribute(env.output, info.wAttributes | + FOREGROUND_INTENSITY); } BOOL debug_mellow_color(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env->output, &info)) - return FALSE; - return SetConsoleTextAttribute(env->output, info.wAttributes | - ~FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env.output, &info)) + return FALSE; + return SetConsoleTextAttribute(env.output, info.wAttributes | + ~FOREGROUND_INTENSITY); } void debug_setup_console(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (AllocConsole()) { - // only set title if new console was created - SetConsoleTitle("BNCSutil Debug Console"); - env->console_was_created = TRUE; - } else { - env->console_was_created = FALSE; - } - env->output = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(env->output, &info); - env->orig_attributes = info.wAttributes; - env->sans_foreground = info.wAttributes & - ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + + if (AllocConsole()) { + // only set title if new console was created + SetConsoleTitle("BNCSutil Debug Console"); + env.console_was_created = TRUE; + } else { + env.console_was_created = FALSE; + } + env.output = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(env.output, &info); + env.orig_attributes = info.wAttributes; + env.sans_foreground = info.wAttributes & + ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | + FOREGROUND_INTENSITY); } #endif size_t debug_write(debug_env_t env, const char* message) { #ifdef MOS_WINDOWS - DWORD chars_written; - BOOL res; - if (!env->output) - debug_setup_console(env); - res = WriteConsole(env->output, message, (DWORD) strlen(message), - &chars_written, (LPVOID) 0); - return (res) ? (size_t) chars_written : (size_t) -1; + DWORD chars_written; + BOOL res; + if (!env.output) + debug_setup_console(env); + res = WriteConsole(env.output, message, (DWORD) strlen(message), + &chars_written, (LPVOID) 0); + return (res) ? (size_t) chars_written : (size_t) -1; #else - return fwrite(message, 1, strlen(message), env->output); + return fwrite(message, 1, strlen(message), env->output); #endif } size_t get_console_width(debug_env_t env) { #ifdef MOS_WINDOWS - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env->output, &info)) - return (size_t) 0; - return (size_t) info.dwSize.X; + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env.output, &info)) + return (size_t) 0; + return (size_t) info.dwSize.X; #else - char* columns = getenv("COLUMNS"); - if (!columns) - return (size_t) 0; - return (size_t) strtol(columns, (char**) 0, 0); + char* columns = getenv("COLUMNS"); + if (!columns) + return (size_t) 0; + return (size_t) strtol(columns, (char**) 0, 0); #endif } char* produce_dump(const char* data, size_t length) { - return (char*) 0; + return (char*) 0; } debug_env_t get_debug_environment() { - static debug_env_t env = (debug_env_t) 0; - - if (!env) { - env = (debug_env_t) malloc(sizeof(struct _bncsutil_debug_env)); + static debug_env_t env = (debug_env_t) 0; + + if (!env) { + env = (debug_env_t) malloc(sizeof(struct _bncsutil_debug_env)); /*#if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES - env->enabled = 1; + env->enabled = 1; #else - env->enabled = 0; + env->enabled = 0; #endif*/ - env->enabled = 0; + env->enabled = 0; #ifdef MOS_WINDOWS - env->output = (HANDLE) NULL; - //debug_setup_console(env); + env->output = (HANDLE) NULL; + //debug_setup_console(env); #else - env->output = stderr; + env->output = stderr; #endif - } - - return env; + } + + return env; } /** @@ -146,8 +146,8 @@ debug_env_t get_debug_environment() */ MEXP(int) bncsutil_debug_status(void) { - debug_env_t env = get_debug_environment(); - return env->enabled; + debug_env_t env = get_debug_environment(); + return env->enabled; } /** * Set new_status to zero to turn debugging messages off or nonzero to turn @@ -155,197 +155,197 @@ MEXP(int) bncsutil_debug_status(void) */ MEXP(int) bncsutil_set_debug_status(int new_status) { - debug_env_t env = get_debug_environment(); - if (!env) { - return 0; - } + debug_env_t env = get_debug_environment(); + if (!env) { + return 0; + } #ifdef MOS_WINDOWS - if (env->enabled && !new_status && env->console_was_created) { - FreeConsole(); - } else if (!env->enabled && new_status) { - debug_setup_console(env); - } + if (env->enabled && !new_status && env->console_was_created) { + FreeConsole(); + } else if (!env->enabled && new_status) { + debug_setup_console(env); + } #endif - env->enabled = (new_status != 0) ? 1 : 0; - return 1; + env->enabled = (new_status != 0) ? 1 : 0; + return 1; } MEXP(int) bncsutil_internal_debug_messages() { #if DEBUG - return 1; + return 1; #else - return 0; + return 0; #endif } MEXP(void) bncsutil_debug_message(const char* message) { - debug_env_t env = get_debug_environment(); - char timestamp[12]; - /*size_t length;*/ + debug_env_t env = get_debug_environment(); + char timestamp[12]; + /*size_t length;*/ #ifdef MOS_WINDOWS - SYSTEMTIME local_time; + SYSTEMTIME local_time; #else - time_t unix_time; - struct tm* local_time; + time_t unix_time; + struct tm* local_time; #endif - if (!env->enabled) { - return; - } + if (!env->enabled) { + return; + } #ifdef MOS_WINDOWS - GetLocalTime(&local_time); - sprintf(timestamp, "[%02d:%02d:%02d] ", local_time.wHour, - local_time.wMinute, local_time.wSecond); - debug_set_color(env, FOREGROUND_RED | FOREGROUND_GREEN | - FOREGROUND_INTENSITY); -#else - time(&unix_time); - local_time = localtime(&unix_time); - sprintf(timestamp, "[%02d:%02d:%02d] ", local_time->tm_hour, - local_time->tm_min, local_time->tm_sec); + GetLocalTime(&local_time); + sprintf(timestamp, "[%02d:%02d:%02d] ", local_time.wHour, + local_time.wMinute, local_time.wSecond); + debug_set_color(env, FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_INTENSITY); +#else + time(&unix_time); + local_time = localtime(&unix_time); + sprintf(timestamp, "[%02d:%02d:%02d] ", local_time->tm_hour, + local_time->tm_min, local_time->tm_sec); #endif - debug_write(env, timestamp); + debug_write(env, timestamp); #ifdef MOS_WINDOWS - debug_restore_color(env); + debug_restore_color(env); #endif - - debug_write(env, message); - debug_write(env, "\r\n"); + + debug_write(env, message); + debug_write(env, "\r\n"); } MEXP(void) bncsutil_debug_message_a(const char* message, ...) { - char buf[4092]; - va_list args; - va_start(args, message); - - vsprintf(buf, message, args); - va_end(args); - - bncsutil_debug_message(buf); + char buf[4092]; + va_list args; + va_start(args, message); + + vsprintf(buf, message, args); + va_end(args); + + bncsutil_debug_message(buf); } MEXP(void) bncsutil_debug_dump(const void* data, size_t data_length) { - char ascii[] = " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - char hex[4]; - char pos_indicator[] = "0000 "; - debug_env_t env = get_debug_environment(); - size_t i; - size_t j = 2; /* printing to ASCII buffer skips over 2 spaces */ - size_t k; - char cur; - int on_boundary; - size_t current_string_length; - - if (!env->enabled) { - return; - } - - debug_intense_color(env); - for (i = 0; i < data_length; i++) { - on_boundary = ((i + 1) % 16 == 0); - - if ((i + 1) % 16 == 1) { + char ascii[] = " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + char hex[4]; + char pos_indicator[] = "0000 "; + debug_env_t env = get_debug_environment(); + size_t i; + size_t j = 2; /* printing to ASCII buffer skips over 2 spaces */ + size_t k; + char cur; + int on_boundary; + size_t current_string_length; + + if (!env->enabled) { + return; + } + + debug_intense_color(env); + for (i = 0; i < data_length; i++) { + on_boundary = ((i + 1) % 16 == 0); + + if ((i + 1) % 16 == 1) { #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_RED | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); + debug_set_color(env, FOREGROUND_RED | FOREGROUND_BLUE | + FOREGROUND_INTENSITY); #endif - debug_write(env, pos_indicator); + debug_write(env, pos_indicator); #ifdef MOS_WINDOWS - debug_restore_color(env); + debug_restore_color(env); #endif - } - - cur = *(((char*) data) + i); - /* The cast to unsigned char and then int is required to properly - * handle 8 bit characters. */ - ascii[j++] = (isprint((int) (unsigned char) cur)) ? cur : '.'; - sprintf(hex, "%02X ", (cur & 0xFF)); - debug_write(env, hex); - - if ((i + 1) % 8 == 0) { - debug_write(env, " "); - } - - if (on_boundary || (i + 1) == data_length) { - if (!on_boundary) { - current_string_length = 3 * (i % 16); - if ((i % 16) > 8) - current_string_length++; - - for (k = 0; k < (47 - current_string_length); k++) { - debug_write(env, " "); - } - } + } + + cur = *(((char*) data) + i); + /* The cast to unsigned char and then int is required to properly + * handle 8 bit characters. */ + ascii[j++] = (isprint((int) (unsigned char) cur)) ? cur : '.'; + sprintf(hex, "%02X ", (cur & 0xFF)); + debug_write(env, hex); + + if ((i + 1) % 8 == 0) { + debug_write(env, " "); + } + + if (on_boundary || (i + 1) == data_length) { + if (!on_boundary) { + current_string_length = 3 * (i % 16); + if ((i % 16) > 8) + current_string_length++; + + for (k = 0; k < (47 - current_string_length); k++) { + debug_write(env, " "); + } + } #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_GREEN | - FOREGROUND_INTENSITY); -#endif - ascii[j] = 0; - debug_write(env, ascii); - debug_write(env, "\r\n"); - j = 2; /* reset position in ASCII buffer */ + debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_INTENSITY); +#endif + ascii[j] = 0; + debug_write(env, ascii); + debug_write(env, "\r\n"); + j = 2; /* reset position in ASCII buffer */ #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_INTENSITY); + debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_INTENSITY); #endif - sprintf(pos_indicator, "%04X ", i + 1); + sprintf(pos_indicator, "%04X ", i + 1); #ifdef MOS_WINDOWS - debug_restore_color(env); -#endif - } - } + debug_restore_color(env); +#endif + } + } } #ifdef MOS_WINDOWS const char* sys_error_msg() { - const char* buffer; - DWORD res; - - res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - (const void*) 0, (DWORD) 0, (DWORD) 0, (LPTSTR) &buffer, (DWORD) 0, - (va_list*) 0); - if (!res) { - bncsutil_debug_message("error: Failed to get Windows error message."); - return default_err_msg; - } - - return buffer; + const char* buffer; + DWORD res; + + res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + (const void*) 0, (DWORD) 0, (DWORD) 0, (LPTSTR) &buffer, (DWORD) 0, + (va_list*) 0); + if (!res) { + bncsutil_debug_message("error: Failed to get Windows error message."); + return default_err_msg; + } + + return buffer; } void free_sys_err_msg(const char* message_pointer) { - if (message_pointer) - LocalFree(message_pointer); + if (message_pointer) + LocalFree(message_pointer); } #else const char* sys_error_msg() { - return (const char*) strerror(errno); + return (const char*) strerror(errno); } void free_sys_err_msg() { - /* Do nothing. */ + /* Do nothing. */ } #endif MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length) { - + } #ifdef MOS_WINDOWS MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, - size_t length) + size_t length) { - + } #endif diff --git a/src/bncsutil/debug.h b/src/bncsutil/debug.h index 930589a..21c66f9 100644 --- a/src/bncsutil/debug.h +++ b/src/bncsutil/debug.h @@ -6,86 +6,99 @@ * April 1, 2006 */ -#ifndef _DEBUG_H_INCLUDED_ -#define _DEBUG_H_INCLUDED_ 1 - -#undef DEBUG -#if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES -# define INTERNAL_DEBUG(msg) bncsutil_debug_message(msg) -# define INTERNAL_DUMP(data, length) bncsutil_debug_dump((data), (length)) -# define DEBUG 1 -#else -# define INTERNAL_DEBUG(msg) -# define INTERNAL_DUMP(data, length) -# define DEBUG 0 -#endif - - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef MOS_WINDOWS -#include -#endif - -#include -#include - -typedef struct _bncsutil_debug_env* debug_env_t; - -debug_env_t get_debug_environment(); - -/** - * Returns nonzero if debugging messages are enabled or zero if disabled. - */ -MEXP(int) bncsutil_debug_status(void); -/** - * Set new_status to zero to turn debugging messages off or nonzero to turn - * them on. Returns nonzero on success and zero on failure. - */ -MEXP(int) bncsutil_set_debug_status(int new_status); - -/** - * Returns nonzero if internal debug messages were compiled in or zero if - * they were not. - */ -MEXP(int) bncsutil_internal_debug_messages(); - -/** - * Prints a debug message. - */ -MEXP(void) bncsutil_debug_message(const char* message); +/* #ifndef _DEBUG_H_INCLUDED_ */ +/* #define _DEBUG_H_INCLUDED_ 1 */ + +/* #undef DEBUG */ +/* #if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES */ +/* # define INTERNAL_DEBUG(msg) bncsutil_debug_message(msg) */ +/* # define INTERNAL_DUMP(data, length) bncsutil_debug_dump((data), (length)) */ +/* # define DEBUG 1 */ +/* #else */ +/* # define INTERNAL_DEBUG(msg) */ +/* # define INTERNAL_DUMP(data, length) */ +/* # define DEBUG 0 */ +/* #endif */ + +/* #undef DEBUG */ + +/* #ifdef __cplusplus */ +/* extern "C" { */ +/* #endif */ + +/* #ifdef MOS_WINDOWS */ +/* #include */ +/* #endif */ + +/* #include */ +/* #include */ + +/* typedef struct _bncsutil_debug_env* debug_env_t; */ + +/* debug_env_t get_debug_environment(); */ + +/* /\** */ +/* * Returns nonzero if debugging messages are enabled or zero if disabled. */ +/* *\/ */ +/* MEXP(int) bncsutil_debug_status(void); */ +/* /\** */ +/* * Set new_status to zero to turn debugging messages off or nonzero to turn */ +/* * them on. Returns nonzero on success and zero on failure. */ +/* *\/ */ +/* MEXP(int) bncsutil_set_debug_status(int new_status); */ + +/* /\** */ +/* * Returns nonzero if internal debug messages were compiled in or zero if */ +/* * they were not. */ +/* *\/ */ +/* MEXP(int) bncsutil_internal_debug_messages(); */ + +/* /\** */ +/* * Prints a debug message. */ +/* *\/ */ +/* MEXP(void) bncsutil_debug_message(const char* message); */ + +/* /\** */ +/* * Prints a debug message using a printf-style format string. */ +/* *\/ */ +/* MEXP(void) bncsutil_debug_message_a(const char* message, ...); */ + +/* /\** */ +/* * Prints a hex dump of data to the debug console. */ +/* *\/ */ +/* MEXP(void) bncsutil_debug_dump(const void* data, size_t data_length); */ + +/* /\** */ +/* * Returns a pointer to a message describing the last system error event. */ +/* *\/ */ +/* const char* sys_error_msg(); */ + +/* /\** */ +/* * Frees the pointer provided by sys_error_msg(). */ +/* *\/ */ +/* void free_sys_err_msg(const char* message_pointer); */ + +/* /\* Not implemented! *\/ */ +/* MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length); */ +/* #ifdef MOS_WINDOWS */ +/* //MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, */ +/* // size_t length); */ +/* #endif */ + +/* #ifdef __cplusplus */ +/* } // extern "C" */ +/* #endif */ + +/* #endif /\* DEBUG *\/ */ + + +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + +#define bncsutil_debug_message(x) +#define free_sys_err_msg(x) +#define bncsutil_debug_message_a(x, y) +#define sys_error_msg(x) -/** - * Prints a debug message using a printf-style format string. - */ -MEXP(void) bncsutil_debug_message_a(const char* message, ...); -/** - * Prints a hex dump of data to the debug console. - */ -MEXP(void) bncsutil_debug_dump(const void* data, size_t data_length); - -/** - * Returns a pointer to a message describing the last system error event. - */ -const char* sys_error_msg(); - -/** - * Frees the pointer provided by sys_error_msg(). - */ -void free_sys_err_msg(const char* message_pointer); - -/* Not implemented! */ -MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length); -#ifdef MOS_WINDOWS -//MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, -// size_t length); #endif - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* DEBUG */ diff --git a/src/bncsutil/decodekey.cpp b/src/bncsutil/decodekey.cpp index c38276e..6caf08d 100644 --- a/src/bncsutil/decodekey.cpp +++ b/src/bncsutil/decodekey.cpp @@ -32,11 +32,11 @@ #include #ifdef MOS_WINDOWS - #include + #include #else - #include - #include - #include + #include + #include + #include #endif #include #include @@ -61,37 +61,37 @@ unsigned int numDecoders = 0; unsigned int sizeDecoders = 0; #ifdef MOS_WINDOWS -// HANDLE mutex; - CRITICAL_SECTION kd_control; +// HANDLE mutex; + CRITICAL_SECTION kd_control; #else - pthread_mutex_t mutex; + pthread_mutex_t mutex; #endif int kd_lock_decoders() { #ifdef MOS_WINDOWS -/* DWORD dwWaitResult; - dwWaitResult = WaitForSingleObject(mutex, MUTEX_TIMEOUT_MS); - switch (dwWaitResult) { - case WAIT_OBJECT_0: - // success - break; - case WAIT_TIMEOUT: - return 0; - break; - case WAIT_ABANDONED: - // weird, but should be OK - break; - default: - return 0; - break; - }*/ - EnterCriticalSection(&kd_control); +/* DWORD dwWaitResult; + dwWaitResult = WaitForSingleObject(mutex, MUTEX_TIMEOUT_MS); + switch (dwWaitResult) { + case WAIT_OBJECT_0: + // success + break; + case WAIT_TIMEOUT: + return 0; + break; + case WAIT_ABANDONED: + // weird, but should be OK + break; + default: + return 0; + break; + }*/ + EnterCriticalSection(&kd_control); #else - int err = 0; - pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - struct timespec wait_time = {0, MUTEX_TIMEOUT_MS * 1000}; - - err = pthread_cond_timedwait(&cond, &mutex, &wait_time); + int err = 0; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + struct timespec wait_time = {0, MUTEX_TIMEOUT_MS * 1000}; + + err = pthread_cond_timedwait(&cond, &mutex, &wait_time); switch (err) { case 0: // success @@ -99,7 +99,7 @@ int kd_lock_decoders() { default: // error return 0; - } + } #endif return 1; } @@ -111,312 +111,312 @@ int kd_lock_decoders() { #endif MEXP(int) kd_quick(const char* cd_key, uint32_t client_token, - uint32_t server_token, uint32_t* public_value, - uint32_t* product, char* hash_buffer, size_t buffer_len) + uint32_t server_token, uint32_t* public_value, + uint32_t* product, char* hash_buffer, size_t buffer_len) { - CDKeyDecoder kd(cd_key, strlen(cd_key)); - size_t hash_len; - - if (!kd.isKeyValid()) - return 0; - - *public_value = kd.getVal1(); - *product = kd.getProduct(); - - hash_len = kd.calculateHash(client_token, server_token); - if (!hash_len || hash_len > buffer_len) - return 0; - - kd.getHash(hash_buffer); - return 1; + CDKeyDecoder kd(cd_key, strlen(cd_key)); + size_t hash_len; + + if (!kd.isKeyValid()) + return 0; + + *public_value = kd.getVal1(); + *product = kd.getProduct(); + + hash_len = kd.calculateHash(client_token, server_token); + if (!hash_len || hash_len > buffer_len) + return 0; + + kd.getHash(hash_buffer); + return 1; } MEXP(int) kd_init() { - static int has_run = 0; - - if (has_run) - return 1; + static int has_run = 0; + if (has_run) + return 1; + #ifdef MOS_WINDOWS - /*mutex = CreateMutex(NULL, FALSE, NULL); - if (mutex == NULL) - return 0;*/ - InitializeCriticalSection(&kd_control); + /*mutex = CreateMutex(NULL, FALSE, NULL); + if (mutex == NULL) + return 0;*/ + InitializeCriticalSection(&kd_control); #else - if (pthread_mutex_init(&mutex, NULL)) - return 0; + if (pthread_mutex_init(&mutex, NULL)) + return 0; #endif - numDecoders = 0; - sizeDecoders = 0; - decoders = (CDKeyDecoder**) 0; - has_run = 1; + numDecoders = 0; + sizeDecoders = 0; + decoders = (CDKeyDecoder**) 0; + has_run = 1; #if DEBUG - bncsutil_debug_message("Initialized key decoding C API."); + bncsutil_debug_message("Initialized key decoding C API."); #endif - return 1; + return 1; } unsigned int kd_findAvailable() { - unsigned int i; - CDKeyDecoder** d; - - d = decoders; - for (i = 0; i < sizeDecoders; i++) { - if (*d == (CDKeyDecoder*) 0) - return i; - d++; - } - - // no room available, must expand - decoders = (CDKeyDecoder**) realloc(decoders, sizeof(CDKeyDecoder*) * - (sizeDecoders + DEFAULT_DECODERS_SIZE)); - if (!decoders) - return (unsigned int) -1; - - memset(decoders + sizeDecoders, 0, - sizeof(CDKeyDecoder*) * DEFAULT_DECODERS_SIZE); // zero new memory - - i = sizeDecoders; - sizeDecoders += DEFAULT_DECODERS_SIZE; - return i; + unsigned int i; + CDKeyDecoder** d; + + d = decoders; + for (i = 0; i < sizeDecoders; i++) { + if (*d == (CDKeyDecoder*) 0) + return i; + d++; + } + + // no room available, must expand + decoders = (CDKeyDecoder**) realloc(decoders, sizeof(CDKeyDecoder*) * + (sizeDecoders + DEFAULT_DECODERS_SIZE)); + if (!decoders) + return (unsigned int) -1; + + memset(decoders + sizeDecoders, 0, + sizeof(CDKeyDecoder*) * DEFAULT_DECODERS_SIZE); // zero new memory + + i = sizeDecoders; + sizeDecoders += DEFAULT_DECODERS_SIZE; + return i; } MEXP(int) kd_create(const char* cdkey, int keyLength) { - unsigned int i; - CDKeyDecoder** d; - static int dcs_initialized = 0; - - if (!dcs_initialized) { - if (!kd_init()) - return -1; - dcs_initialized = 1; - } - - if (!kd_lock_decoders()) return -1; - - i = kd_findAvailable(); - if (i == (unsigned int) -1) - return -1; - - d = (decoders + i); - *d = new CDKeyDecoder(cdkey, keyLength); - if (!(**d).isKeyValid()) { - delete *d; - *d = (CDKeyDecoder*) 0; - return -1; - } - - numDecoders++; - - kd_unlock_decoders(); - return (int) i; + unsigned int i; + CDKeyDecoder** d; + static int dcs_initialized = 0; + + if (!dcs_initialized) { + if (!kd_init()) + return -1; + dcs_initialized = 1; + } + + if (!kd_lock_decoders()) return -1; + + i = kd_findAvailable(); + if (i == (unsigned int) -1) + return -1; + + d = (decoders + i); + *d = new CDKeyDecoder(cdkey, keyLength); + if (!(**d).isKeyValid()) { + delete *d; + *d = (CDKeyDecoder*) 0; + return -1; + } + + numDecoders++; + + kd_unlock_decoders(); + return (int) i; } /* MEXP(int) kd_create(char* cdkey, int keyLength) { if (!kd_lock_decoders()) return -1; - CDKeyDecoder* d; - unsigned int i; - if (numDecoders >= sizeDecoders) { - CDKeyDecoder** temp = new CDKeyDecoder*[sizeDecoders]; - for (unsigned int j = 0; j < sizeDecoders; j++) { - temp[j] = decoders[j]; - } - delete [] decoders; - decoders = new CDKeyDecoder*[sizeDecoders + DEFAULT_DECODERS_SIZE]; - - for (unsigned int j = 0; j < sizeDecoders; j++) { - decoders[j] = temp[j]; - } - delete [] temp; - sizeDecoders += DEFAULT_DECODERS_SIZE; - } - i = numDecoders++; - decoders[i] = new CDKeyDecoder(cdkey, keyLength); - d = decoders[i]; - if (!d->isKeyValid()) { - delete decoders[i]; - return -1; - } - kd_unlock_decoders(); - - d = NULL; - return (int) i; + CDKeyDecoder* d; + unsigned int i; + if (numDecoders >= sizeDecoders) { + CDKeyDecoder** temp = new CDKeyDecoder*[sizeDecoders]; + for (unsigned int j = 0; j < sizeDecoders; j++) { + temp[j] = decoders[j]; + } + delete [] decoders; + decoders = new CDKeyDecoder*[sizeDecoders + DEFAULT_DECODERS_SIZE]; + + for (unsigned int j = 0; j < sizeDecoders; j++) { + decoders[j] = temp[j]; + } + delete [] temp; + sizeDecoders += DEFAULT_DECODERS_SIZE; + } + i = numDecoders++; + decoders[i] = new CDKeyDecoder(cdkey, keyLength); + d = decoders[i]; + if (!d->isKeyValid()) { + delete decoders[i]; + return -1; + } + kd_unlock_decoders(); + + d = NULL; + return (int) i; }*/ MEXP(int) kd_free(int decoder) { - CDKeyDecoder* d; - - if (!kd_lock_decoders()) return 0; + CDKeyDecoder* d; - if ((unsigned int) decoder >= sizeDecoders) - return 0; + if (!kd_lock_decoders()) return 0; - d = *(decoders + decoder); - if (!d) - return 0; + if ((unsigned int) decoder >= sizeDecoders) + return 0; - delete d; - *(decoders + decoder) = (CDKeyDecoder*) 0; + d = *(decoders + decoder); + if (!d) + return 0; - kd_unlock_decoders(); - return 1; + delete d; + *(decoders + decoder) = (CDKeyDecoder*) 0; + + kd_unlock_decoders(); + return 1; } MEXP(int) kd_val2Length(int decoder) { - CDKeyDecoder* d; - int value; - - if (!kd_lock_decoders()) return -1; + CDKeyDecoder* d; + int value; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = d->getVal2Length(); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = d->getVal2Length(); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_product(int decoder) { - CDKeyDecoder* d; - int value; - - if (!kd_lock_decoders()) return -1; + CDKeyDecoder* d; + int value; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = d->getProduct(); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = d->getProduct(); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_val1(int decoder) { - CDKeyDecoder* d; - int value; - - if (!kd_lock_decoders()) return -1; + CDKeyDecoder* d; + int value; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = d->getVal1(); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = d->getVal1(); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_val2(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; - if (!kd_lock_decoders()) return -1; - - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = d->getVal2(); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = d->getVal2(); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_longVal2(int decoder, char* out) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; - if (!kd_lock_decoders()) return -1; + if (!kd_lock_decoders()) return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - value = d->getLongVal2(out); - - kd_unlock_decoders(); - return value; + value = d->getLongVal2(out); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_calculateHash(int decoder, uint32_t clientToken, - uint32_t serverToken) + uint32_t serverToken) { - CDKeyDecoder* d; - int value; - - if (!kd_lock_decoders()) return -1; + CDKeyDecoder* d; + int value; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = (int) d->calculateHash(clientToken, serverToken); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = (int) d->calculateHash(clientToken, serverToken); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_getHash(int decoder, char* out) { - CDKeyDecoder* d; - int value; - - if (!kd_lock_decoders()) return -1; + CDKeyDecoder* d; + int value; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = (int) d->getHash(out); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = (int) d->getHash(out); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_isValid(int decoder) { - CDKeyDecoder* d; - int value; - - if (!kd_lock_decoders()) return -1; + CDKeyDecoder* d; + int value; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if (!kd_lock_decoders()) return -1; - d = *(decoders + decoder); - if (!d) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - value = d->isKeyValid(); + d = *(decoders + decoder); + if (!d) + return -1; - kd_unlock_decoders(); - return value; + value = d->isKeyValid(); + + kd_unlock_decoders(); + return value; } #ifdef __cplusplus diff --git a/src/bncsutil/decodekey.h b/src/bncsutil/decodekey.h index 5dc8033..dbade12 100644 --- a/src/bncsutil/decodekey.h +++ b/src/bncsutil/decodekey.h @@ -30,7 +30,7 @@ #ifdef __cplusplus extern "C" { #endif - + /** * Decodes a CD-key, retrieves its relevant values, and calculates a hash * suitable for SID_AUTH_CHECK (0x51) in one function call. Returns 1 on @@ -38,8 +38,8 @@ extern "C" { * calling this function. Available since BNCSutil 1.1.0. */ MEXP(int) kd_quick(const char* cd_key, uint32_t client_token, - uint32_t server_token, uint32_t* public_value, - uint32_t* product, char* hash_buffer, size_t buffer_len); + uint32_t server_token, uint32_t* public_value, + uint32_t* product, char* hash_buffer, size_t buffer_len); /** * Initializes the CD-key decoding C wrappers. @@ -96,7 +96,7 @@ MEXP(int) kd_longVal2(int decoder, char* out); * Returns the hash length or 0 on failure. */ MEXP(int) kd_calculateHash(int decoder, uint32_t clientToken, - uint32_t serverToken); + uint32_t serverToken); /** * Places the key hash in "out". The "out" buffer must be diff --git a/src/bncsutil/file.cpp b/src/bncsutil/file.cpp index 0295098..2e4e783 100644 --- a/src/bncsutil/file.cpp +++ b/src/bncsutil/file.cpp @@ -21,12 +21,12 @@ typedef std::map mapping_map; struct _file { #if BWIN - HANDLE f; + HANDLE f; #else - FILE* f; + FILE* f; #endif - const char* filename; - mapping_map mappings; + const char* filename; + mapping_map mappings; }; #include @@ -39,277 +39,265 @@ extern "C" { file_t file_open(const char* filename, unsigned int mode) { - file_t data; - HANDLE file; - DWORD access; - DWORD share_mode; - DWORD open_mode; - const char* sys_err; - size_t filename_buf_len; - - if (mode & FILE_READ) { - access = GENERIC_READ; - share_mode = FILE_SHARE_READ; - open_mode = OPEN_EXISTING; - } else if (mode & FILE_WRITE) { - access = GENERIC_WRITE; - share_mode = 0; - open_mode = CREATE_ALWAYS; - } - - file = CreateFile(filename, access, share_mode, NULL, open_mode, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - sys_err = sys_error_msg(); - bncsutil_debug_message_a("Cannot open file \"%s\"; %s", filename, - sys_err); - free_sys_err_msg(sys_err); - return ((file_t) 0); - } - - try { - data = new _file; - } catch (std::bad_alloc) { - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "file structure.", sizeof(struct _file)); - CloseHandle(file); - return (file_t) 0; - } - - filename_buf_len = strlen(filename) + 1; - data->filename = (const char*) malloc(filename_buf_len); - if (!data->filename) { - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "filename.", filename_buf_len); - CloseHandle(file); - delete data; - return (file_t) 0; - } - strcpy_s((char*) data->filename, filename_buf_len, filename); - - data->f = file; - - return data; + file_t data; + HANDLE file; + DWORD access; + DWORD share_mode; + DWORD open_mode; + //const char* sys_err; + size_t filename_buf_len; + + if (mode & FILE_READ) { + access = GENERIC_READ; + share_mode = FILE_SHARE_READ; + open_mode = OPEN_EXISTING; + } else if (mode & FILE_WRITE) { + access = GENERIC_WRITE; + share_mode = 0; + open_mode = CREATE_ALWAYS; + } + + file = CreateFile(filename, access, share_mode, NULL, open_mode, + FILE_ATTRIBUTE_NORMAL, NULL); + + if (file == INVALID_HANDLE_VALUE) { + //sys_err = sys_error_msg(); + //bncsutil_debug_message_a("Cannot open file \"%s\"; %s", filename, sys_err); + //free_sys_err_msg(sys_err); + return ((file_t) 0); + } + + try { + data = new _file; + } catch (std::bad_alloc) { + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold file structure.", sizeof(struct _file)); + CloseHandle(file); + return (file_t) 0; + } + + filename_buf_len = strlen(filename) + 1; + data->filename = (const char*) malloc(filename_buf_len); + if (!data->filename) { + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold filename.", filename_buf_len); + CloseHandle(file); + delete data; + return (file_t) 0; + } + strcpy_s((char*) data->filename, filename_buf_len, filename); + + data->f = file; + + return data; } void file_close(file_t file) { - mapping_map::iterator it; - - if (!file) { - bncsutil_debug_message_a("error: null pointer given to file_close"); - return; - } - - for (it = file->mappings.begin(); it != file->mappings.end(); it++) { - UnmapViewOfFile((*it).first); - CloseHandle((*it).second); - } - - CloseHandle((HANDLE) file->f); - free((void*) file->filename); - delete file; + mapping_map::iterator it; + + if (!file) { + //bncsutil_debug_message_a("error: null pointer given to file_close"); + return; + } + + for (it = file->mappings.begin(); it != file->mappings.end(); it++) { + UnmapViewOfFile((*it).first); + CloseHandle((*it).second); + } + + CloseHandle((HANDLE) file->f); + free((void*) file->filename); + delete file; } size_t file_read(file_t file, void* ptr, size_t size, size_t count) { - DWORD bytes_read; - - if (!ReadFile(file->f, ptr, (DWORD) (size * count), &bytes_read, NULL)) { - return (size_t) 0; - } - - return (size_t) bytes_read; + DWORD bytes_read; + + if (!ReadFile(file->f, ptr, (DWORD) (size * count), &bytes_read, NULL)) { + return (size_t) 0; + } + + return (size_t) bytes_read; } size_t file_write(file_t file, const void* ptr, size_t size, - size_t count) + size_t count) { - DWORD bytes_written; - - if (!WriteFile(file->f, ptr, (DWORD) (size * count), &bytes_written, NULL)) - return (size_t) 0; - - return (size_t) bytes_written; + DWORD bytes_written; + + if (!WriteFile(file->f, ptr, (DWORD) (size * count), &bytes_written, NULL)) + return (size_t) 0; + + return (size_t) bytes_written; } size_t file_size(file_t file) { - return (size_t) GetFileSize(file->f, (LPDWORD) 0); + return (size_t) GetFileSize(file->f, (LPDWORD) 0); } void* file_map(file_t file, size_t len, off_t offset) { - HANDLE mapping = - CreateFileMapping((HANDLE) file->f, NULL, PAGE_READONLY, 0, 0, NULL); - void* base; - const char* err; - - if (!mapping) { - err = sys_error_msg(); - bncsutil_debug_message_a("Failed to create file mapping for \"%s\": %s", - file->filename, err); - free_sys_err_msg(err); - return (void*) 0; - } - - base = MapViewOfFile(mapping, FILE_MAP_READ, 0, (DWORD) offset, len); - if (!base) { - CloseHandle(mapping); - err = sys_error_msg(); - bncsutil_debug_message_a("Failed to map %u bytes of \"%s\" starting at " - "%u: %s", - len, file->filename, offset, err); - free_sys_err_msg(err); - return (void*) 0; - } - - file->mappings[base] = mapping; - - return base; + HANDLE mapping = + CreateFileMapping((HANDLE) file->f, NULL, PAGE_READONLY, 0, 0, NULL); + void* base; + //const char* err; + + if (!mapping) { + //err = sys_error_msg(); + //bncsutil_debug_message_a("Failed to create file mapping for \"%s\": %s", file->filename, err); + //free_sys_err_msg(err); + return (void*) 0; + } + + base = MapViewOfFile(mapping, FILE_MAP_READ, 0, (DWORD) offset, len); + if (!base) { + CloseHandle(mapping); + //err = sys_error_msg(); + //bncsutil_debug_message_a("Failed to map %u bytes of \"%s\" starting at %u: %s", len, file->filename, offset, err); + //free_sys_err_msg(err); + return (void*) 0; + } + + file->mappings[base] = mapping; + + return base; } void file_unmap(file_t file, const void* base) { - mapping_map::iterator item = file->mappings.find(base); - HANDLE mapping; - - if (item == file->mappings.end()) { - bncsutil_debug_message_a("warning: failed to unmap the block starting " - "at %p from %s; unknown block.", base, file->filename); - return; - } - - mapping = (*item).second; - - UnmapViewOfFile(base); - CloseHandle(mapping); - - file->mappings.erase(item); + mapping_map::iterator item = file->mappings.find(base); + HANDLE mapping; + + if (item == file->mappings.end()) { + //bncsutil_debug_message_a("warning: failed to unmap the block starting at %p from %s; unknown block.", base, file->filename); + return; + } + + mapping = (*item).second; + + UnmapViewOfFile(base); + CloseHandle(mapping); + + file->mappings.erase(item); } #else file_t file_open(const char* filename, unsigned int mode_flags) { - char mode[] = "rb"; - file_t data; - FILE* f; - size_t filename_buf_len; - const char* err; - - if (mode_flags & FILE_WRITE) - mode[0] = 'w'; - - f = fopen(filename, mode); - if (!f) { - return (file_t) 0; - } - - try { - data = new _file; - } catch (std::bad_alloc) { - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "file structure.", sizeof(struct _file)); - fclose(f); - return (file_t) 0; - } - - filename_buf_len = strlen(filename) + 1; - data->filename = (const char*) malloc(filename_buf_len); - if (!data->filename) { - err = sys_error_msg(); - bncsutil_debug_message_a("Failed to allocate %u bytes to hold" - "filename; %s", filename_buf_len); - free_sys_error_msg(err); - fclose(f); - delete data; - return (file_t) 0; - } - strcpy((char*) data->filename, filename); - - data->f = f; - - return data; + char mode[] = "rb"; + file_t data; + FILE* f; + size_t filename_buf_len; + //const char* err; + + if (mode_flags & FILE_WRITE) + mode[0] = 'w'; + + f = fopen(filename, mode); + if (!f) { + return (file_t) 0; + } + + try { + data = new _file; + } catch (std::bad_alloc) { + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold file structure.", sizeof(struct _file)); + fclose(f); + return (file_t) 0; + } + + filename_buf_len = strlen(filename) + 1; + data->filename = (const char*) malloc(filename_buf_len); + if (!data->filename) { + //err = sys_error_msg(); + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold filename; %s", filename_buf_len); + //free_sys_err_msg(err); + fclose(f); + delete data; + return (file_t) 0; + } + strcpy((char*) data->filename, filename); + + data->f = f; + + return data; } void file_close(file_t file) { - mapping_map::iterator it; - - if (!file) { - bncsutil_debug_message("error: null pointer given to file_close"); - return; - } - - for (it = file->mappings.begin(); it != file->mappings.end(); it++) { - munmap((void*) (*it).first, (*it).second); - } - - fclose(file->f); - delete file; + mapping_map::iterator it; + + if (!file) { + //bncsutil_debug_message("error: null pointer given to file_close"); + return; + } + + for (it = file->mappings.begin(); it != file->mappings.end(); it++) { + munmap((void*) (*it).first, (*it).second); + } + + fclose(file->f); + delete file; } size_t file_read(file_t file, void* ptr, size_t size, size_t count) { - return fread(ptr, size, count, file->f); + return fread(ptr, size, count, file->f); } size_t file_write(file_t file, const void* ptr, size_t size, - size_t count) + size_t count) { - return fwrite(ptr, size, count, file->f); + return fwrite(ptr, size, count, file->f); } size_t file_size(file_t file) { - long cur_pos = ftell(file->f); - size_t size_of_file; - - fseek(file->f, 0, SEEK_END); - size_of_file = (size_t) ftell(file->f); - fseek(file->f, cur_pos, SEEK_SET); - - return size_of_file; + long cur_pos = ftell(file->f); + size_t size_of_file; + + fseek(file->f, 0, SEEK_END); + size_of_file = (size_t) ftell(file->f); + fseek(file->f, cur_pos, SEEK_SET); + + return size_of_file; } void* file_map(file_t file, size_t len, off_t offset) { - int fd = fileno(file->f); - void* base = mmap((void*) 0, len, PROT_READ, MAP_SHARED, fd, offset); - const char* err; - - if (!base) { - err = sys_error_msg(); - bncsutil_debug_message_a("error: failed to map %u bytes of %s " - "starting at %u into memory; %s", len, file->filename, offset, - err); - free_sys_error_msg(err); - return (void*) 0; - } - - file->mappings[base] = len; - - return base; + int fd = fileno(file->f); + void* base = mmap((void*) 0, len, PROT_READ, MAP_SHARED, fd, offset); + //const char* err; + + if (!base) { + //err = sys_error_msg(); + //bncsutil_debug_message_a("error: failed to map %u bytes of %s starting at %u into memory; %s", len, file->filename, offset, err); + //free_sys_err_msg(err); + return (void*) 0; + } + + file->mappings[base] = len; + + return base; } void file_unmap(file_t file, const void* base) { - mapping_map::iterator item = file->mappings.find(base); - size_t len; - - if (item == file->mappings.end()) { - bncsutil_debug_message_a("warning: failed to unmap the block starting " - "at %p from %s; unknown block.", base, file->filename); - return; - } - - len = (*item).second; - - munmap((void*) base, len); - - file->mappings.erase(item); + mapping_map::iterator item = file->mappings.find(base); + size_t len; + + if (item == file->mappings.end()) { + //bncsutil_debug_message_a("warning: failed to unmap the block starting at %p from %s; unknown block.", base, file->filename); + return; + } + + len = (*item).second; + + munmap((void*) base, len); + + file->mappings.erase(item); } #endif diff --git a/src/bncsutil/file.h b/src/bncsutil/file.h index 3ff4bbd..4721e28 100644 --- a/src/bncsutil/file.h +++ b/src/bncsutil/file.h @@ -41,15 +41,15 @@ extern "C" { typedef struct _file* file_t; -#define FILE_READ (0x01) -#define FILE_WRITE (0x02) +#define FILE_READ (0x01) +#define FILE_WRITE (0x02) file_t file_open(const char* filename, unsigned int mode); void file_close(file_t file); size_t file_read(file_t file, void* ptr, size_t size, size_t count); size_t file_write(file_t file, const void* ptr, size_t size, - size_t count); + size_t count); size_t file_size(file_t file); void* file_map(file_t file, size_t len, off_t offset); diff --git a/src/bncsutil/gmp.h b/src/bncsutil/gmp.h new file mode 100644 index 0000000..0a8c32c --- /dev/null +++ b/src/bncsutil/gmp.h @@ -0,0 +1,2189 @@ +/* Definitions for GNU multiple precision functions. -*- mode: c -*- + +Copyright 1991, 1993, 1994, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, +2004, 2005, 2006, 2007 Free Software Foundation, Inc. + +This file is part of the GNU MP Library. + +The GNU MP Library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +The GNU MP Library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU Lesser General Public License +along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ + +#ifndef __GMP_H__ + +#if defined (__cplusplus) +#include /* for std::istream, std::ostream, std::string */ +#endif + + +#if ! defined (__GMP_WITHIN_CONFIGURE) +# if defined( _MSC_VER ) +# if defined( _WIN64 ) +# define __GMP_BITS_PER_MP_LIMB 64 +# define BITS_PER_MP_LIMB 64 +# define GMP_LIMB_BITS 64 +# define SIZEOF_MP_LIMB_T 8 +# define _LONG_LONG_LIMB 1 +# elif defined( _WIN32 ) +# define __GMP_BITS_PER_MP_LIMB 32 +# define BITS_PER_MP_LIMB 32 +# define GMP_LIMB_BITS 32 +# define SIZEOF_MP_LIMB_T 4 +# ifdef _LONG_LONG_LIMB +# undef _LONG_LONG_LIMB +# endif +# else +# error This is the wrong version of gmp.h +# endif +# endif +# define GMP_NAIL_BITS 0 +#endif +#define GMP_NUMB_BITS (GMP_LIMB_BITS - GMP_NAIL_BITS) +#define GMP_NUMB_MASK ((~ __GMP_CAST (mp_limb_t, 0)) >> GMP_NAIL_BITS) +#define GMP_NUMB_MAX GMP_NUMB_MASK +#define GMP_NAIL_MASK (~ GMP_NUMB_MASK) + + +/* The following (everything under ifndef __GNU_MP__) must be identical in + gmp.h and mp.h to allow both to be included in an application or during + the library build. */ +#ifndef __GNU_MP__ +#define __GNU_MP__ 4 + +#define __need_size_t /* tell gcc stddef.h we only want size_t */ +#if defined (__cplusplus) +#include /* for size_t */ +#else +#include /* for size_t */ +#endif +#undef __need_size_t + + + +/* __STDC__ - some ANSI compilers define this only to 0, hence the use of + "defined" and not "__STDC__-0". In particular Sun workshop C 5.0 + sets __STDC__ to 0, but requires "##" for token pasting. + + _AIX - gnu ansidecl.h asserts that all known AIX compilers are ANSI but + don't always define __STDC__. + + __DECC - current versions of DEC C (5.9 for instance) for alpha are ANSI, + but don't define __STDC__ in their default mode. Don't know if old + versions might have been K&R, but let's not worry about that unless + someone is still using one. + + _mips - gnu ansidecl.h says the RISC/OS MIPS compiler is ANSI in SVR4 + mode, but doesn't define __STDC__. + + _MSC_VER - Microsoft C is ANSI, but __STDC__ is undefined unless the /Za + option is given (in which case it's 1). + + _WIN32 - tested for by gnu ansidecl.h, no doubt on the assumption that + all w32 compilers are ansi. + + Note: This same set of tests is used by gen-psqr.c and + demos/expr/expr-impl.h, so if anything needs adding, then be sure to + update those too. */ + +#if defined (__STDC__) \ + || defined (__cplusplus) \ + || defined (_AIX) \ + || defined (__DECC) \ + || (defined (__mips) && defined (_SYSTYPE_SVR4)) \ + || defined (_MSC_VER) \ + || defined (_WIN32) +#define __GMP_HAVE_CONST 1 +#define __GMP_HAVE_PROTOTYPES 1 +#define __GMP_HAVE_TOKEN_PASTE 1 +#else +#define __GMP_HAVE_CONST 0 +#define __GMP_HAVE_PROTOTYPES 0 +#define __GMP_HAVE_TOKEN_PASTE 0 +#endif + + +#if __GMP_HAVE_CONST +#define __gmp_const const +#define __gmp_signed signed +#else +#define __gmp_const +#define __gmp_signed +#endif + + +/* __GMP_DECLSPEC supports Windows DLL versions of libgmp, and is empty in + all other circumstances. + + When compiling objects for libgmp, __GMP_DECLSPEC is an export directive, + or when compiling for an application it's an import directive. The two + cases are differentiated by __GMP_WITHIN_GMP defined by the GMP Makefiles + (and not defined from an application). + + __GMP_DECLSPEC_XX is similarly used for libgmpxx. __GMP_WITHIN_GMPXX + indicates when building libgmpxx, and in that case libgmpxx functions are + exports, but libgmp functions which might get called are imports. + + libmp.la uses __GMP_DECLSPEC, just as if it were libgmp.la. libgmp and + libmp don't call each other, so there's no conflict or confusion. + + Libtool DLL_EXPORT define is not used. + + There's no attempt to support GMP built both static and DLL. Doing so + would mean applications would have to tell us which of the two is going + to be used when linking, and that seems very tedious and error prone if + using GMP by hand, and equally tedious from a package since autoconf and + automake don't give much help. + + __GMP_DECLSPEC is required on all documented global functions and + variables, the various internals in gmp-impl.h etc can be left unadorned. + But internals used by the test programs or speed measuring programs + should have __GMP_DECLSPEC, and certainly constants or variables must + have it or the wrong address will be resolved. + + In gcc __declspec can go at either the start or end of a prototype. + + In Microsoft C __declspec must go at the start, or after the type like + void __declspec(...) *foo()". There's no __dllexport or anything to + guard against someone foolish #defining dllexport. _export used to be + available, but no longer. + + In Borland C _export still exists, but needs to go after the type, like + "void _export foo();". Would have to change the __GMP_DECLSPEC syntax to + make use of that. Probably more trouble than it's worth. */ + +#if defined (__GNUC__) +#define __GMP_DECLSPEC_EXPORT __declspec(__dllexport__) +#define __GMP_DECLSPEC_IMPORT __declspec(__dllimport__) +#endif +#if defined (_MSC_VER) || defined (__BORLANDC__) +#define __GMP_DECLSPEC_EXPORT __declspec(dllexport) +#define __GMP_DECLSPEC_IMPORT __declspec(dllimport) +#endif +#ifdef __WATCOMC__ +#define __GMP_DECLSPEC_EXPORT __export +#define __GMP_DECLSPEC_IMPORT __import +#endif +#ifdef __IBMC__ +#define __GMP_DECLSPEC_EXPORT _Export +#define __GMP_DECLSPEC_IMPORT _Import +#endif + +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMP +/* compiling to go into a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into an application which will link to a DLL libgmp */ +#define __GMP_DECLSPEC __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC +#endif + + +#ifdef __GMP_SHORT_LIMB +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; +#else +#ifdef _LONG_LONG_LIMB +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; +#else +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; +#endif +#endif + +/* For reference, note that the name __mpz_struct gets into C++ mangled + function names, which means although the "__" suggests an internal, we + must leave this name for binary compatibility. */ +typedef struct +{ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpz_struct; + +#endif /* __GNU_MP__ */ + + +typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ +typedef __mpz_struct mpz_t[1]; + +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; +#if defined (_CRAY) && ! defined (_CRAYMPP) +/* plain `int' is much faster (48 bits) */ +#define __GMP_MP_SIZE_T_INT 1 +typedef int mp_size_t; +typedef int mp_exp_t; +#else +#define __GMP_MP_SIZE_T_INT 0 +typedef long int mp_size_t; +typedef long int mp_exp_t; +#endif + +typedef struct +{ + __mpz_struct _mp_num; + __mpz_struct _mp_den; +} __mpq_struct; + +typedef __mpq_struct MP_RAT; /* gmp 1 source compatibility */ +typedef __mpq_struct mpq_t[1]; + +typedef struct +{ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to by the + _mp_d field contains `prec' + 1 limbs. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ +} __mpf_struct; + +/* typedef __mpf_struct MP_FLOAT; */ +typedef __mpf_struct mpf_t[1]; + +/* Available random number generation algorithms. */ +typedef enum +{ + GMP_RAND_ALG_DEFAULT = 0, + GMP_RAND_ALG_LC = GMP_RAND_ALG_DEFAULT /* Linear congruential. */ +} gmp_randalg_t; + +/* Random state struct. */ +typedef struct +{ + mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ + gmp_randalg_t _mp_alg; /* Currently unused. */ + union { + void *_mp_lc; /* Pointer to function pointers structure. */ + } _mp_algdata; +} __gmp_randstate_struct; +typedef __gmp_randstate_struct gmp_randstate_t[1]; + +/* Types for function declarations in gmp files. */ +/* ??? Should not pollute user name space with these ??? */ +typedef __gmp_const __mpz_struct *mpz_srcptr; +typedef __mpz_struct *mpz_ptr; +typedef __gmp_const __mpf_struct *mpf_srcptr; +typedef __mpf_struct *mpf_ptr; +typedef __gmp_const __mpq_struct *mpq_srcptr; +typedef __mpq_struct *mpq_ptr; + + +/* This is not wanted in mp.h, so put it outside the __GNU_MP__ common + section. */ +#if __GMP_LIBGMP_DLL +#if __GMP_WITHIN_GMPXX +/* compiling to go into a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_EXPORT +#else +/* compiling to go into a application which will link to a DLL libgmpxx */ +#define __GMP_DECLSPEC_XX __GMP_DECLSPEC_IMPORT +#endif +#else +/* all other cases */ +#define __GMP_DECLSPEC_XX +#endif + + +#if __GMP_HAVE_PROTOTYPES +#define __GMP_PROTO(x) x +#else +#define __GMP_PROTO(x) () +#endif + +#ifndef __MPN +#if __GMP_HAVE_TOKEN_PASTE +#define __MPN(x) __gmpn_##x +#else +#define __MPN(x) __gmpn_/**/x +#endif +#endif + +/* For reference, "defined(EOF)" cannot be used here. In g++ 2.95.4, + defines EOF but not FILE. */ +#if defined (FILE) \ + || defined (H_STDIO) \ + || defined (_H_STDIO) /* AIX */ \ + || defined (_STDIO_H) /* glibc, Sun, SCO */ \ + || defined (_STDIO_H_) /* BSD, OSF */ \ + || defined (__STDIO_H) /* Borland */ \ + || defined (__STDIO_H__) /* IRIX */ \ + || defined (_STDIO_INCLUDED) /* HPUX */ \ + || defined (__dj_include_stdio_h_) /* DJGPP */ \ + || defined (_FILE_DEFINED) /* Microsoft */ \ + || defined (__STDIO__) /* Apple MPW MrC */ \ + || defined (_MSL_STDIO_H) /* Metrowerks */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ +#define _GMP_H_HAVE_FILE 1 +#endif + +/* In ISO C, if a prototype involving "struct obstack *" is given without + that structure defined, then the struct is scoped down to just the + prototype, causing a conflict if it's subsequently defined for real. So + only give prototypes if we've got obstack.h. */ +#if defined (_OBSTACK_H) /* glibc */ +#define _GMP_H_HAVE_OBSTACK 1 +#endif + +/* The prototypes for gmp_vprintf etc are provided only if va_list is + available, via an application having included or . + Usually va_list is a typedef so can't be tested directly, but C99 + specifies that va_start is a macro (and it was normally a macro on past + systems too), so look for that. + + will define some sort of va_list for vprintf and vfprintf, but + let's not bother trying to use that since it's not standard and since + application uses for gmp_vprintf etc will almost certainly require the + whole or anyway. */ + +#ifdef va_start +#define _GMP_H_HAVE_VA_LIST 1 +#endif + +/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */ +#if defined (__GNUC__) && defined (__GNUC_MINOR__) +#define __GMP_GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +#else +#define __GMP_GNUC_PREREQ(maj, min) 0 +#endif + +/* "pure" is in gcc 2.96 and up, see "(gcc)Function Attributes". Basically + it means a function does nothing but examine its arguments and memory + (global or via arguments) to generate a return value, but changes nothing + and has no side-effects. __GMP_NO_ATTRIBUTE_CONST_PURE lets + tune/common.c etc turn this off when trying to write timing loops. */ +#if __GMP_GNUC_PREREQ (2,96) && ! defined (__GMP_NO_ATTRIBUTE_CONST_PURE) +#define __GMP_ATTRIBUTE_PURE __attribute__ ((__pure__)) +#else +#define __GMP_ATTRIBUTE_PURE +#endif + + +/* __GMP_CAST allows us to use static_cast in C++, so our macros are clean + to "g++ -Wold-style-cast". + + Casts in "extern inline" code within an extern "C" block don't induce + these warnings, so __GMP_CAST only needs to be used on documented + macros. */ + +#ifdef __cplusplus +#define __GMP_CAST(type, expr) (static_cast (expr)) +#else +#define __GMP_CAST(type, expr) ((type) (expr)) +#endif + + +/* An empty "throw ()" means the function doesn't throw any C++ exceptions, + this can save some stack frame info in applications. + + Currently it's given only on functions which never divide-by-zero etc, + don't allocate memory, and are expected to never need to allocate memory. + This leaves open the possibility of a C++ throw from a future GMP + exceptions scheme. + + mpz_set_ui etc are omitted to leave open the lazy allocation scheme + described in doc/tasks.html. mpz_get_d etc are omitted to leave open + exceptions for float overflows. + + Note that __GMP_NOTHROW must be given on any inlines the same as on their + prototypes (for g++ at least, where they're used together). Note also + that g++ 3.0 demands that __GMP_NOTHROW is before other attributes like + __GMP_ATTRIBUTE_PURE. */ + +#if defined (__cplusplus) +#define __GMP_NOTHROW throw () +#else +#define __GMP_NOTHROW +#endif + + +/* PORTME: What other compilers have a useful "extern inline"? "static + inline" would be an acceptable substitute if the compiler (or linker) + discards unused statics. */ + + /* gcc has __inline__ in all modes, including strict ansi. Give a prototype + for an inline too, so as to correctly specify "dllimport" on windows, in + case the function is called rather than inlined. + GCC 4.3 and above with -std=c99 or -std=gnu99 implements ISO C99 + inline semantics, unless -fgnu89-inline is used. */ +#ifdef __GNUC__ +#ifdef __GNUC_STDC_INLINE__ +#define __GMP_EXTERN_INLINE extern __inline__ __attribute__ ((__gnu_inline__)) +#else +#define __GMP_EXTERN_INLINE extern __inline__ +#endif +#define __GMP_INLINE_PROTOTYPES 1 +#endif + +/* DEC C (eg. version 5.9) supports "static __inline foo()", even in -std1 + strict ANSI mode. Inlining is done even when not optimizing (ie. -O0 + mode, which is the default), but an unnecessary local copy of foo is + emitted unless -O is used. "extern __inline" is accepted, but the + "extern" appears to be ignored, ie. it becomes a plain global function + but which is inlined within its file. Don't know if all old versions of + DEC C supported __inline, but as a start let's do the right thing for + current versions. */ +#ifdef __DECC +#define __GMP_EXTERN_INLINE static __inline +#endif + +/* SCO OpenUNIX 8 cc supports "static inline foo()" but not in -Xc strict + ANSI mode (__STDC__ is 1 in that mode). Inlining only actually takes + place under -O. Without -O "foo" seems to be emitted whether it's used + or not, which is wasteful. "extern inline foo()" isn't useful, the + "extern" is apparently ignored, so foo is inlined if possible but also + emitted as a global, which causes multiple definition errors when + building a shared libgmp. */ +#ifdef __SCO_VERSION__ +#if __SCO_VERSION__ > 400000000 && __STDC__ != 1 \ + && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE static inline +#endif +#endif + +/* C++ always has "inline" and since it's a normal feature the linker should + discard duplicate non-inlined copies, or if it doesn't then that's a + problem for everyone, not just GMP. */ +#if defined (__cplusplus) && ! defined (__GMP_EXTERN_INLINE) +#define __GMP_EXTERN_INLINE inline +#endif + +/* Don't do any inlining within a configure run, since if the compiler ends + up emitting copies of the code into the object file it can end up + demanding the various support routines (like mpn_popcount) for linking, + making the "alloca" test and perhaps others fail. And on hppa ia64 a + pre-release gcc 3.2 was seen not respecting the "extern" in "extern + __inline__", triggering this problem too. */ +#if defined (__GMP_WITHIN_CONFIGURE) && ! __GMP_WITHIN_CONFIGURE_INLINE +#undef __GMP_EXTERN_INLINE +#endif + +/* By default, don't give a prototype when there's going to be an inline + version. Note in particular that Cray C++ objects to the combination of + prototype and inline. */ +#ifdef __GMP_EXTERN_INLINE +#ifndef __GMP_INLINE_PROTOTYPES +#define __GMP_INLINE_PROTOTYPES 0 +#endif +#else +#define __GMP_INLINE_PROTOTYPES 1 +#endif + + +#define __GMP_ABS(x) ((x) >= 0 ? (x) : -(x)) +#define __GMP_MAX(h,i) ((h) > (i) ? (h) : (i)) + +/* __GMP_USHRT_MAX is not "~ (unsigned short) 0" because short is promoted + to int by "~". */ +#define __GMP_UINT_MAX (~ (unsigned) 0) +#define __GMP_ULONG_MAX (~ (unsigned long) 0) +#define __GMP_USHRT_MAX ((unsigned short) ~0) + + +/* __builtin_expect is in gcc 3.0, and not in 2.95. */ +#if __GMP_GNUC_PREREQ (3,0) +#define __GMP_LIKELY(cond) __builtin_expect ((cond) != 0, 1) +#define __GMP_UNLIKELY(cond) __builtin_expect ((cond) != 0, 0) +#else +#define __GMP_LIKELY(cond) (cond) +#define __GMP_UNLIKELY(cond) (cond) +#endif + +#ifdef _CRAY +#define __GMP_CRAY_Pragma(str) _Pragma (str) +#else +#define __GMP_CRAY_Pragma(str) +#endif + + +/* Allow direct user access to numerator and denominator of a mpq_t object. */ +#define mpq_numref(Q) (&((Q)->_mp_num)) +#define mpq_denref(Q) (&((Q)->_mp_den)) + + +#if defined (__cplusplus) +extern "C" { +#ifdef _GMP_H_HAVE_FILE +using std::FILE; +#endif +#endif + +#define mp_set_memory_functions __gmp_set_memory_functions +__GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))) __GMP_NOTHROW; + +#define mp_get_memory_functions __gmp_get_memory_functions +__GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), + void *(**) (void *, size_t, size_t), + void (**) (void *, size_t))) __GMP_NOTHROW; + +#define mp_bits_per_limb __gmp_bits_per_limb +__GMP_DECLSPEC extern __gmp_const int mp_bits_per_limb; + +#define gmp_errno __gmp_errno +__GMP_DECLSPEC extern int gmp_errno; + +#define gmp_version __gmp_version +__GMP_DECLSPEC extern __gmp_const char * __gmp_const gmp_version; + + +/**************** Random number routines. ****************/ + +/* obsolete */ +#define gmp_randinit __gmp_randinit +__GMP_DECLSPEC void gmp_randinit __GMP_PROTO ((gmp_randstate_t, gmp_randalg_t, ...)); + +#define gmp_randinit_default __gmp_randinit_default +__GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp +__GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, + mpz_srcptr, unsigned long int, + unsigned long int)); + +#define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size +__GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); + +#define gmp_randinit_mt __gmp_randinit_mt +__GMP_DECLSPEC void gmp_randinit_mt __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_randinit_set __gmp_randinit_set +void gmp_randinit_set __GMP_PROTO ((gmp_randstate_t, __gmp_const __gmp_randstate_struct *)); + +#define gmp_randseed __gmp_randseed +__GMP_DECLSPEC void gmp_randseed __GMP_PROTO ((gmp_randstate_t, mpz_srcptr)); + +#define gmp_randseed_ui __gmp_randseed_ui +__GMP_DECLSPEC void gmp_randseed_ui __GMP_PROTO ((gmp_randstate_t, unsigned long int)); + +#define gmp_randclear __gmp_randclear +__GMP_DECLSPEC void gmp_randclear __GMP_PROTO ((gmp_randstate_t)); + +#define gmp_urandomb_ui __gmp_urandomb_ui +unsigned long gmp_urandomb_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); + +#define gmp_urandomm_ui __gmp_urandomm_ui +unsigned long gmp_urandomm_ui __GMP_PROTO ((gmp_randstate_t, unsigned long)); + + +/**************** Formatted output routines. ****************/ + +#define gmp_asprintf __gmp_asprintf +__GMP_DECLSPEC int gmp_asprintf __GMP_PROTO ((char **, __gmp_const char *, ...)); + +#define gmp_fprintf __gmp_fprintf +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fprintf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +#endif + +#define gmp_obstack_printf __gmp_obstack_printf +#if defined (_GMP_H_HAVE_OBSTACK) +__GMP_DECLSPEC int gmp_obstack_printf __GMP_PROTO ((struct obstack *, __gmp_const char *, ...)); +#endif + +#define gmp_obstack_vprintf __gmp_obstack_vprintf +#if defined (_GMP_H_HAVE_OBSTACK) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_obstack_vprintf __GMP_PROTO ((struct obstack *, __gmp_const char *, va_list)); +#endif + +#define gmp_printf __gmp_printf +__GMP_DECLSPEC int gmp_printf __GMP_PROTO ((__gmp_const char *, ...)); + +#define gmp_snprintf __gmp_snprintf +__GMP_DECLSPEC int gmp_snprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, ...)); + +#define gmp_sprintf __gmp_sprintf +__GMP_DECLSPEC int gmp_sprintf __GMP_PROTO ((char *, __gmp_const char *, ...)); + +#define gmp_vasprintf __gmp_vasprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vasprintf __GMP_PROTO ((char **, __gmp_const char *, va_list)); +#endif + +#define gmp_vfprintf __gmp_vfprintf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vfprintf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +#endif + +#define gmp_vprintf __gmp_vprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vprintf __GMP_PROTO ((__gmp_const char *, va_list)); +#endif + +#define gmp_vsnprintf __gmp_vsnprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsnprintf __GMP_PROTO ((char *, size_t, __gmp_const char *, va_list)); +#endif + +#define gmp_vsprintf __gmp_vsprintf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsprintf __GMP_PROTO ((char *, __gmp_const char *, va_list)); +#endif + + +/**************** Formatted input routines. ****************/ + +#define gmp_fscanf __gmp_fscanf +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC int gmp_fscanf __GMP_PROTO ((FILE *, __gmp_const char *, ...)); +#endif + +#define gmp_scanf __gmp_scanf +__GMP_DECLSPEC int gmp_scanf __GMP_PROTO ((__gmp_const char *, ...)); + +#define gmp_sscanf __gmp_sscanf +__GMP_DECLSPEC int gmp_sscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, ...)); + +#define gmp_vfscanf __gmp_vfscanf +#if defined (_GMP_H_HAVE_FILE) && defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vfscanf __GMP_PROTO ((FILE *, __gmp_const char *, va_list)); +#endif + +#define gmp_vscanf __gmp_vscanf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vscanf __GMP_PROTO ((__gmp_const char *, va_list)); +#endif + +#define gmp_vsscanf __gmp_vsscanf +#if defined (_GMP_H_HAVE_VA_LIST) +__GMP_DECLSPEC int gmp_vsscanf __GMP_PROTO ((__gmp_const char *, __gmp_const char *, va_list)); +#endif + + +/**************** Integer (i.e. Z) routines. ****************/ + +#define _mpz_realloc __gmpz_realloc +#define mpz_realloc __gmpz_realloc +__GMP_DECLSPEC void *_mpz_realloc __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_abs __gmpz_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_abs) +__GMP_DECLSPEC void mpz_abs __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif + +#define mpz_add __gmpz_add +__GMP_DECLSPEC void mpz_add __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_add_ui __gmpz_add_ui +__GMP_DECLSPEC void mpz_add_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_addmul __gmpz_addmul +__GMP_DECLSPEC void mpz_addmul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_addmul_ui __gmpz_addmul_ui +__GMP_DECLSPEC void mpz_addmul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_and __gmpz_and +__GMP_DECLSPEC void mpz_and __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_array_init __gmpz_array_init +__GMP_DECLSPEC void mpz_array_init __GMP_PROTO ((mpz_ptr, mp_size_t, mp_size_t)); + +#define mpz_bin_ui __gmpz_bin_ui +__GMP_DECLSPEC void mpz_bin_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_bin_uiui __gmpz_bin_uiui +__GMP_DECLSPEC void mpz_bin_uiui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +#define mpz_cdiv_q __gmpz_cdiv_q +__GMP_DECLSPEC void mpz_cdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_q_2exp __gmpz_cdiv_q_2exp +__GMP_DECLSPEC void mpz_cdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_cdiv_q_ui __gmpz_cdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_qr __gmpz_cdiv_qr +__GMP_DECLSPEC void mpz_cdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_qr_ui __gmpz_cdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_r __gmpz_cdiv_r +__GMP_DECLSPEC void mpz_cdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_cdiv_r_2exp __gmpz_cdiv_r_2exp +__GMP_DECLSPEC void mpz_cdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_cdiv_r_ui __gmpz_cdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_cdiv_ui __gmpz_cdiv_ui +__GMP_DECLSPEC unsigned long int mpz_cdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_clear __gmpz_clear +__GMP_DECLSPEC void mpz_clear __GMP_PROTO ((mpz_ptr)); + +#define mpz_clrbit __gmpz_clrbit +__GMP_DECLSPEC void mpz_clrbit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_cmp __gmpz_cmp +__GMP_DECLSPEC int mpz_cmp __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmp_d __gmpz_cmp_d +__GMP_DECLSPEC int mpz_cmp_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_si __gmpz_cmp_si +__GMP_DECLSPEC int _mpz_cmp_si __GMP_PROTO ((mpz_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define _mpz_cmp_ui __gmpz_cmp_ui +__GMP_DECLSPEC int _mpz_cmp_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs __gmpz_cmpabs +__GMP_DECLSPEC int mpz_cmpabs __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_d __gmpz_cmpabs_d +__GMP_DECLSPEC int mpz_cmpabs_d __GMP_PROTO ((mpz_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define mpz_cmpabs_ui __gmpz_cmpabs_ui +__GMP_DECLSPEC int mpz_cmpabs_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_com __gmpz_com +__GMP_DECLSPEC void mpz_com __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_combit __gmpz_combit +__GMP_DECLSPEC void mpz_combit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_congruent_p __gmpz_congruent_p +__GMP_DECLSPEC int mpz_congruent_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_2exp_p __gmpz_congruent_2exp_p +__GMP_DECLSPEC int mpz_congruent_2exp_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_congruent_ui_p __gmpz_congruent_ui_p +__GMP_DECLSPEC int mpz_congruent_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divexact __gmpz_divexact +__GMP_DECLSPEC void mpz_divexact __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_divexact_ui __gmpz_divexact_ui +__GMP_DECLSPEC void mpz_divexact_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_divisible_p __gmpz_divisible_p +__GMP_DECLSPEC int mpz_divisible_p __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_ui_p __gmpz_divisible_ui_p +__GMP_DECLSPEC int mpz_divisible_ui_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_divisible_2exp_p __gmpz_divisible_2exp_p +__GMP_DECLSPEC int mpz_divisible_2exp_p __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_dump __gmpz_dump +__GMP_DECLSPEC void mpz_dump __GMP_PROTO ((mpz_srcptr)); + +#define mpz_export __gmpz_export +__GMP_DECLSPEC void *mpz_export __GMP_PROTO ((void *, size_t *, int, size_t, int, size_t, mpz_srcptr)); + +#define mpz_fac_ui __gmpz_fac_ui +__GMP_DECLSPEC void mpz_fac_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_fdiv_q __gmpz_fdiv_q +__GMP_DECLSPEC void mpz_fdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_q_2exp __gmpz_fdiv_q_2exp +__GMP_DECLSPEC void mpz_fdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_q_ui __gmpz_fdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_qr __gmpz_fdiv_qr +__GMP_DECLSPEC void mpz_fdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_qr_ui __gmpz_fdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_r __gmpz_fdiv_r +__GMP_DECLSPEC void mpz_fdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_fdiv_r_2exp __gmpz_fdiv_r_2exp +__GMP_DECLSPEC void mpz_fdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_r_ui __gmpz_fdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_fdiv_ui __gmpz_fdiv_ui +__GMP_DECLSPEC unsigned long int mpz_fdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_fib_ui __gmpz_fib_ui +__GMP_DECLSPEC void mpz_fib_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_fib2_ui __gmpz_fib2_ui +__GMP_DECLSPEC void mpz_fib2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); + +#define mpz_fits_sint_p __gmpz_fits_sint_p +__GMP_DECLSPEC int mpz_fits_sint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_slong_p __gmpz_fits_slong_p +__GMP_DECLSPEC int mpz_fits_slong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_sshort_p __gmpz_fits_sshort_p +__GMP_DECLSPEC int mpz_fits_sshort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_fits_uint_p __gmpz_fits_uint_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_uint_p) +__GMP_DECLSPEC int mpz_fits_uint_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ulong_p __gmpz_fits_ulong_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ulong_p) +__GMP_DECLSPEC int mpz_fits_ulong_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_fits_ushort_p __gmpz_fits_ushort_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_fits_ushort_p) +__GMP_DECLSPEC int mpz_fits_ushort_p __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_gcd __gmpz_gcd +__GMP_DECLSPEC void mpz_gcd __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_gcd_ui __gmpz_gcd_ui +__GMP_DECLSPEC unsigned long int mpz_gcd_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_gcdext __gmpz_gcdext +__GMP_DECLSPEC void mpz_gcdext __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_get_d __gmpz_get_d +__GMP_DECLSPEC double mpz_get_d __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_get_d_2exp __gmpz_get_d_2exp +__GMP_DECLSPEC double mpz_get_d_2exp __GMP_PROTO ((signed long int *, mpz_srcptr)); + +#define mpz_get_si __gmpz_get_si +__GMP_DECLSPEC /* signed */ long int mpz_get_si __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_get_str __gmpz_get_str +__GMP_DECLSPEC char *mpz_get_str __GMP_PROTO ((char *, int, mpz_srcptr)); + +#define mpz_get_ui __gmpz_get_ui +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_get_ui) +__GMP_DECLSPEC unsigned long int mpz_get_ui __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_getlimbn __gmpz_getlimbn +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_getlimbn) +__GMP_DECLSPEC mp_limb_t mpz_getlimbn __GMP_PROTO ((mpz_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_hamdist __gmpz_hamdist +__GMP_DECLSPEC unsigned long int mpz_hamdist __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_import __gmpz_import +__GMP_DECLSPEC void mpz_import __GMP_PROTO ((mpz_ptr, size_t, int, size_t, int, size_t, __gmp_const void *)); + +#define mpz_init __gmpz_init +__GMP_DECLSPEC void mpz_init __GMP_PROTO ((mpz_ptr)); + +#define mpz_init2 __gmpz_init2 +__GMP_DECLSPEC void mpz_init2 __GMP_PROTO ((mpz_ptr, unsigned long)); + +#define mpz_init_set __gmpz_init_set +__GMP_DECLSPEC void mpz_init_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_init_set_d __gmpz_init_set_d +__GMP_DECLSPEC void mpz_init_set_d __GMP_PROTO ((mpz_ptr, double)); + +#define mpz_init_set_si __gmpz_init_set_si +__GMP_DECLSPEC void mpz_init_set_si __GMP_PROTO ((mpz_ptr, signed long int)); + +#define mpz_init_set_str __gmpz_init_set_str +__GMP_DECLSPEC int mpz_init_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); + +#define mpz_init_set_ui __gmpz_init_set_ui +__GMP_DECLSPEC void mpz_init_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_inp_raw __gmpz_inp_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_raw __GMP_PROTO ((mpz_ptr, FILE *)); +#endif + +#define mpz_inp_str __gmpz_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_inp_str __GMP_PROTO ((mpz_ptr, FILE *, int)); +#endif + +#define mpz_invert __gmpz_invert +__GMP_DECLSPEC int mpz_invert __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_ior __gmpz_ior +__GMP_DECLSPEC void mpz_ior __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_jacobi __gmpz_jacobi +__GMP_DECLSPEC int mpz_jacobi __GMP_PROTO ((mpz_srcptr, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker mpz_jacobi /* alias */ + +#define mpz_kronecker_si __gmpz_kronecker_si +__GMP_DECLSPEC int mpz_kronecker_si __GMP_PROTO ((mpz_srcptr, long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_kronecker_ui __gmpz_kronecker_ui +__GMP_DECLSPEC int mpz_kronecker_ui __GMP_PROTO ((mpz_srcptr, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define mpz_si_kronecker __gmpz_si_kronecker +__GMP_DECLSPEC int mpz_si_kronecker __GMP_PROTO ((long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_kronecker __gmpz_ui_kronecker +__GMP_DECLSPEC int mpz_ui_kronecker __GMP_PROTO ((unsigned long, mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_lcm __gmpz_lcm +__GMP_DECLSPEC void mpz_lcm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_lcm_ui __gmpz_lcm_ui +__GMP_DECLSPEC void mpz_lcm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long)); + +#define mpz_legendre mpz_jacobi /* alias */ + +#define mpz_lucnum_ui __gmpz_lucnum_ui +__GMP_DECLSPEC void mpz_lucnum_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_lucnum2_ui __gmpz_lucnum2_ui +__GMP_DECLSPEC void mpz_lucnum2_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, unsigned long int)); + +#define mpz_millerrabin __gmpz_millerrabin +__GMP_DECLSPEC int mpz_millerrabin __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_mod __gmpz_mod +__GMP_DECLSPEC void mpz_mod __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_mod_ui mpz_fdiv_r_ui /* same as fdiv_r because divisor unsigned */ + +#define mpz_mul __gmpz_mul +__GMP_DECLSPEC void mpz_mul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_mul_2exp __gmpz_mul_2exp +__GMP_DECLSPEC void mpz_mul_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_mul_si __gmpz_mul_si +__GMP_DECLSPEC void mpz_mul_si __GMP_PROTO ((mpz_ptr, mpz_srcptr, long int)); + +#define mpz_mul_ui __gmpz_mul_ui +__GMP_DECLSPEC void mpz_mul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_neg __gmpz_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_neg) +__GMP_DECLSPEC void mpz_neg __GMP_PROTO ((mpz_ptr, mpz_srcptr)); +#endif + +#define mpz_nextprime __gmpz_nextprime +__GMP_DECLSPEC void mpz_nextprime __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_out_raw __gmpz_out_raw +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_raw __GMP_PROTO ((FILE *, mpz_srcptr)); +#endif + +#define mpz_out_str __gmpz_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpz_out_str __GMP_PROTO ((FILE *, int, mpz_srcptr)); +#endif + +#define mpz_perfect_power_p __gmpz_perfect_power_p +__GMP_DECLSPEC int mpz_perfect_power_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpz_perfect_square_p __gmpz_perfect_square_p +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_perfect_square_p) +__GMP_DECLSPEC int mpz_perfect_square_p __GMP_PROTO ((mpz_srcptr)) __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_popcount __gmpz_popcount +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_popcount) +__GMP_DECLSPEC unsigned long int mpz_popcount __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_pow_ui __gmpz_pow_ui +__GMP_DECLSPEC void mpz_pow_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_powm __gmpz_powm +__GMP_DECLSPEC void mpz_powm __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_powm_ui __gmpz_powm_ui +__GMP_DECLSPEC void mpz_powm_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int, mpz_srcptr)); + +#define mpz_probab_prime_p __gmpz_probab_prime_p +__GMP_DECLSPEC int mpz_probab_prime_p __GMP_PROTO ((mpz_srcptr, int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_random __gmpz_random +__GMP_DECLSPEC void mpz_random __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_random2 __gmpz_random2 +__GMP_DECLSPEC void mpz_random2 __GMP_PROTO ((mpz_ptr, mp_size_t)); + +#define mpz_realloc2 __gmpz_realloc2 +__GMP_DECLSPEC void mpz_realloc2 __GMP_PROTO ((mpz_ptr, unsigned long)); + +#define mpz_remove __gmpz_remove +__GMP_DECLSPEC unsigned long int mpz_remove __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_root __gmpz_root +__GMP_DECLSPEC int mpz_root __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_rootrem __gmpz_rootrem +__GMP_DECLSPEC void mpz_rootrem __GMP_PROTO ((mpz_ptr,mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_rrandomb __gmpz_rrandomb +__GMP_DECLSPEC void mpz_rrandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); + +#define mpz_scan0 __gmpz_scan0 +__GMP_DECLSPEC unsigned long int mpz_scan0 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_scan1 __gmpz_scan1 +__GMP_DECLSPEC unsigned long int mpz_scan1 __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_set __gmpz_set +__GMP_DECLSPEC void mpz_set __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_set_d __gmpz_set_d +__GMP_DECLSPEC void mpz_set_d __GMP_PROTO ((mpz_ptr, double)); + +#define mpz_set_f __gmpz_set_f +__GMP_DECLSPEC void mpz_set_f __GMP_PROTO ((mpz_ptr, mpf_srcptr)); + +#define mpz_set_q __gmpz_set_q +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_set_q) +__GMP_DECLSPEC void mpz_set_q __GMP_PROTO ((mpz_ptr, mpq_srcptr)); +#endif + +#define mpz_set_si __gmpz_set_si +__GMP_DECLSPEC void mpz_set_si __GMP_PROTO ((mpz_ptr, signed long int)); + +#define mpz_set_str __gmpz_set_str +__GMP_DECLSPEC int mpz_set_str __GMP_PROTO ((mpz_ptr, __gmp_const char *, int)); + +#define mpz_set_ui __gmpz_set_ui +__GMP_DECLSPEC void mpz_set_ui __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_setbit __gmpz_setbit +__GMP_DECLSPEC void mpz_setbit __GMP_PROTO ((mpz_ptr, unsigned long int)); + +#define mpz_size __gmpz_size +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpz_size) +__GMP_DECLSPEC size_t mpz_size __GMP_PROTO ((mpz_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpz_sizeinbase __gmpz_sizeinbase +__GMP_DECLSPEC size_t mpz_sizeinbase __GMP_PROTO ((mpz_srcptr, int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_sqrt __gmpz_sqrt +__GMP_DECLSPEC void mpz_sqrt __GMP_PROTO ((mpz_ptr, mpz_srcptr)); + +#define mpz_sqrtrem __gmpz_sqrtrem +__GMP_DECLSPEC void mpz_sqrtrem __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr)); + +#define mpz_sub __gmpz_sub +__GMP_DECLSPEC void mpz_sub __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_sub_ui __gmpz_sub_ui +__GMP_DECLSPEC void mpz_sub_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_ui_sub __gmpz_ui_sub +__GMP_DECLSPEC void mpz_ui_sub __GMP_PROTO ((mpz_ptr, unsigned long int, mpz_srcptr)); + +#define mpz_submul __gmpz_submul +__GMP_DECLSPEC void mpz_submul __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_submul_ui __gmpz_submul_ui +__GMP_DECLSPEC void mpz_submul_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_swap __gmpz_swap +__GMP_DECLSPEC void mpz_swap __GMP_PROTO ((mpz_ptr, mpz_ptr)) __GMP_NOTHROW; + +#define mpz_tdiv_ui __gmpz_tdiv_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_ui __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpz_tdiv_q __gmpz_tdiv_q +__GMP_DECLSPEC void mpz_tdiv_q __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_q_2exp __gmpz_tdiv_q_2exp +__GMP_DECLSPEC void mpz_tdiv_q_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_q_ui __gmpz_tdiv_q_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_q_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_qr __gmpz_tdiv_qr +__GMP_DECLSPEC void mpz_tdiv_qr __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_qr_ui __gmpz_tdiv_qr_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_qr_ui __GMP_PROTO ((mpz_ptr, mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_r __gmpz_tdiv_r +__GMP_DECLSPEC void mpz_tdiv_r __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + +#define mpz_tdiv_r_2exp __gmpz_tdiv_r_2exp +__GMP_DECLSPEC void mpz_tdiv_r_2exp __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tdiv_r_ui __gmpz_tdiv_r_ui +__GMP_DECLSPEC unsigned long int mpz_tdiv_r_ui __GMP_PROTO ((mpz_ptr, mpz_srcptr, unsigned long int)); + +#define mpz_tstbit __gmpz_tstbit +__GMP_DECLSPEC int mpz_tstbit __GMP_PROTO ((mpz_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpz_ui_pow_ui __gmpz_ui_pow_ui +__GMP_DECLSPEC void mpz_ui_pow_ui __GMP_PROTO ((mpz_ptr, unsigned long int, unsigned long int)); + +#define mpz_urandomb __gmpz_urandomb +__GMP_DECLSPEC void mpz_urandomb __GMP_PROTO ((mpz_ptr, gmp_randstate_t, unsigned long int)); + +#define mpz_urandomm __gmpz_urandomm +__GMP_DECLSPEC void mpz_urandomm __GMP_PROTO ((mpz_ptr, gmp_randstate_t, mpz_srcptr)); + +#define mpz_xor __gmpz_xor +#define mpz_eor __gmpz_xor +__GMP_DECLSPEC void mpz_xor __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr)); + + +/**************** Rational (i.e. Q) routines. ****************/ + +#define mpq_abs __gmpq_abs +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_abs) +__GMP_DECLSPEC void mpq_abs __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif + +#define mpq_add __gmpq_add +__GMP_DECLSPEC void mpq_add __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_canonicalize __gmpq_canonicalize +__GMP_DECLSPEC void mpq_canonicalize __GMP_PROTO ((mpq_ptr)); + +#define mpq_clear __gmpq_clear +__GMP_DECLSPEC void mpq_clear __GMP_PROTO ((mpq_ptr)); + +#define mpq_cmp __gmpq_cmp +__GMP_DECLSPEC int mpq_cmp __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_si __gmpq_cmp_si +__GMP_DECLSPEC int _mpq_cmp_si __GMP_PROTO ((mpq_srcptr, long, unsigned long)) __GMP_ATTRIBUTE_PURE; + +#define _mpq_cmp_ui __gmpq_cmp_ui +__GMP_DECLSPEC int _mpq_cmp_ui __GMP_PROTO ((mpq_srcptr, unsigned long int, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpq_div __gmpq_div +__GMP_DECLSPEC void mpq_div __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_div_2exp __gmpq_div_2exp +__GMP_DECLSPEC void mpq_div_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); + +#define mpq_equal __gmpq_equal +__GMP_DECLSPEC int mpq_equal __GMP_PROTO ((mpq_srcptr, mpq_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpq_get_num __gmpq_get_num +__GMP_DECLSPEC void mpq_get_num __GMP_PROTO ((mpz_ptr, mpq_srcptr)); + +#define mpq_get_den __gmpq_get_den +__GMP_DECLSPEC void mpq_get_den __GMP_PROTO ((mpz_ptr, mpq_srcptr)); + +#define mpq_get_d __gmpq_get_d +__GMP_DECLSPEC double mpq_get_d __GMP_PROTO ((mpq_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpq_get_str __gmpq_get_str +__GMP_DECLSPEC char *mpq_get_str __GMP_PROTO ((char *, int, mpq_srcptr)); + +#define mpq_init __gmpq_init +__GMP_DECLSPEC void mpq_init __GMP_PROTO ((mpq_ptr)); + +#define mpq_inp_str __gmpq_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_inp_str __GMP_PROTO ((mpq_ptr, FILE *, int)); +#endif + +#define mpq_inv __gmpq_inv +__GMP_DECLSPEC void mpq_inv __GMP_PROTO ((mpq_ptr, mpq_srcptr)); + +#define mpq_mul __gmpq_mul +__GMP_DECLSPEC void mpq_mul __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_mul_2exp __gmpq_mul_2exp +__GMP_DECLSPEC void mpq_mul_2exp __GMP_PROTO ((mpq_ptr, mpq_srcptr, unsigned long)); + +#define mpq_neg __gmpq_neg +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpq_neg) +__GMP_DECLSPEC void mpq_neg __GMP_PROTO ((mpq_ptr, mpq_srcptr)); +#endif + +#define mpq_out_str __gmpq_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpq_out_str __GMP_PROTO ((FILE *, int, mpq_srcptr)); +#endif + +#define mpq_set __gmpq_set +__GMP_DECLSPEC void mpq_set __GMP_PROTO ((mpq_ptr, mpq_srcptr)); + +#define mpq_set_d __gmpq_set_d +__GMP_DECLSPEC void mpq_set_d __GMP_PROTO ((mpq_ptr, double)); + +#define mpq_set_den __gmpq_set_den +__GMP_DECLSPEC void mpq_set_den __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_set_f __gmpq_set_f +__GMP_DECLSPEC void mpq_set_f __GMP_PROTO ((mpq_ptr, mpf_srcptr)); + +#define mpq_set_num __gmpq_set_num +__GMP_DECLSPEC void mpq_set_num __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_set_si __gmpq_set_si +__GMP_DECLSPEC void mpq_set_si __GMP_PROTO ((mpq_ptr, signed long int, unsigned long int)); + +#define mpq_set_str __gmpq_set_str +__GMP_DECLSPEC int mpq_set_str __GMP_PROTO ((mpq_ptr, __gmp_const char *, int)); + +#define mpq_set_ui __gmpq_set_ui +__GMP_DECLSPEC void mpq_set_ui __GMP_PROTO ((mpq_ptr, unsigned long int, unsigned long int)); + +#define mpq_set_z __gmpq_set_z +__GMP_DECLSPEC void mpq_set_z __GMP_PROTO ((mpq_ptr, mpz_srcptr)); + +#define mpq_sub __gmpq_sub +__GMP_DECLSPEC void mpq_sub __GMP_PROTO ((mpq_ptr, mpq_srcptr, mpq_srcptr)); + +#define mpq_swap __gmpq_swap +__GMP_DECLSPEC void mpq_swap __GMP_PROTO ((mpq_ptr, mpq_ptr)) __GMP_NOTHROW; + + +/**************** Float (i.e. F) routines. ****************/ + +#define mpf_abs __gmpf_abs +__GMP_DECLSPEC void mpf_abs __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_add __gmpf_add +__GMP_DECLSPEC void mpf_add __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_add_ui __gmpf_add_ui +__GMP_DECLSPEC void mpf_add_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); +#define mpf_ceil __gmpf_ceil +__GMP_DECLSPEC void mpf_ceil __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_clear __gmpf_clear +__GMP_DECLSPEC void mpf_clear __GMP_PROTO ((mpf_ptr)); + +#define mpf_cmp __gmpf_cmp +__GMP_DECLSPEC int mpf_cmp __GMP_PROTO ((mpf_srcptr, mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_d __gmpf_cmp_d +__GMP_DECLSPEC int mpf_cmp_d __GMP_PROTO ((mpf_srcptr, double)) __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_si __gmpf_cmp_si +__GMP_DECLSPEC int mpf_cmp_si __GMP_PROTO ((mpf_srcptr, signed long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_cmp_ui __gmpf_cmp_ui +__GMP_DECLSPEC int mpf_cmp_ui __GMP_PROTO ((mpf_srcptr, unsigned long int)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_div __gmpf_div +__GMP_DECLSPEC void mpf_div __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_div_2exp __gmpf_div_2exp +__GMP_DECLSPEC void mpf_div_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_div_ui __gmpf_div_ui +__GMP_DECLSPEC void mpf_div_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_dump __gmpf_dump +__GMP_DECLSPEC void mpf_dump __GMP_PROTO ((mpf_srcptr)); + +#define mpf_eq __gmpf_eq +__GMP_DECLSPEC int mpf_eq __GMP_PROTO ((mpf_srcptr, mpf_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sint_p __gmpf_fits_sint_p +__GMP_DECLSPEC int mpf_fits_sint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_slong_p __gmpf_fits_slong_p +__GMP_DECLSPEC int mpf_fits_slong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_sshort_p __gmpf_fits_sshort_p +__GMP_DECLSPEC int mpf_fits_sshort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_uint_p __gmpf_fits_uint_p +__GMP_DECLSPEC int mpf_fits_uint_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ulong_p __gmpf_fits_ulong_p +__GMP_DECLSPEC int mpf_fits_ulong_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_fits_ushort_p __gmpf_fits_ushort_p +__GMP_DECLSPEC int mpf_fits_ushort_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_floor __gmpf_floor +__GMP_DECLSPEC void mpf_floor __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_get_d __gmpf_get_d +__GMP_DECLSPEC double mpf_get_d __GMP_PROTO ((mpf_srcptr)) __GMP_ATTRIBUTE_PURE; + +#define mpf_get_d_2exp __gmpf_get_d_2exp +__GMP_DECLSPEC double mpf_get_d_2exp __GMP_PROTO ((signed long int *, mpf_srcptr)); + +#define mpf_get_default_prec __gmpf_get_default_prec +__GMP_DECLSPEC unsigned long int mpf_get_default_prec __GMP_PROTO ((void)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_prec __gmpf_get_prec +__GMP_DECLSPEC unsigned long int mpf_get_prec __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_si __gmpf_get_si +__GMP_DECLSPEC long mpf_get_si __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_get_str __gmpf_get_str +__GMP_DECLSPEC char *mpf_get_str __GMP_PROTO ((char *, mp_exp_t *, int, size_t, mpf_srcptr)); + +#define mpf_get_ui __gmpf_get_ui +__GMP_DECLSPEC unsigned long mpf_get_ui __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_init __gmpf_init +__GMP_DECLSPEC void mpf_init __GMP_PROTO ((mpf_ptr)); + +#define mpf_init2 __gmpf_init2 +__GMP_DECLSPEC void mpf_init2 __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_init_set __gmpf_init_set +__GMP_DECLSPEC void mpf_init_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_init_set_d __gmpf_init_set_d +__GMP_DECLSPEC void mpf_init_set_d __GMP_PROTO ((mpf_ptr, double)); + +#define mpf_init_set_si __gmpf_init_set_si +__GMP_DECLSPEC void mpf_init_set_si __GMP_PROTO ((mpf_ptr, signed long int)); + +#define mpf_init_set_str __gmpf_init_set_str +__GMP_DECLSPEC int mpf_init_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); + +#define mpf_init_set_ui __gmpf_init_set_ui +__GMP_DECLSPEC void mpf_init_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_inp_str __gmpf_inp_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_inp_str __GMP_PROTO ((mpf_ptr, FILE *, int)); +#endif + +#define mpf_integer_p __gmpf_integer_p +__GMP_DECLSPEC int mpf_integer_p __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_mul __gmpf_mul +__GMP_DECLSPEC void mpf_mul __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_mul_2exp __gmpf_mul_2exp +__GMP_DECLSPEC void mpf_mul_2exp __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_mul_ui __gmpf_mul_ui +__GMP_DECLSPEC void mpf_mul_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_neg __gmpf_neg +__GMP_DECLSPEC void mpf_neg __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_out_str __gmpf_out_str +#ifdef _GMP_H_HAVE_FILE +__GMP_DECLSPEC size_t mpf_out_str __GMP_PROTO ((FILE *, int, size_t, mpf_srcptr)); +#endif + +#define mpf_pow_ui __gmpf_pow_ui +__GMP_DECLSPEC void mpf_pow_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_random2 __gmpf_random2 +__GMP_DECLSPEC void mpf_random2 __GMP_PROTO ((mpf_ptr, mp_size_t, mp_exp_t)); + +#define mpf_reldiff __gmpf_reldiff +__GMP_DECLSPEC void mpf_reldiff __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_set __gmpf_set +__GMP_DECLSPEC void mpf_set __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_set_d __gmpf_set_d +__GMP_DECLSPEC void mpf_set_d __GMP_PROTO ((mpf_ptr, double)); + +#define mpf_set_default_prec __gmpf_set_default_prec +__GMP_DECLSPEC void mpf_set_default_prec __GMP_PROTO ((unsigned long int)) __GMP_NOTHROW; + +#define mpf_set_prec __gmpf_set_prec +__GMP_DECLSPEC void mpf_set_prec __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_set_prec_raw __gmpf_set_prec_raw +__GMP_DECLSPEC void mpf_set_prec_raw __GMP_PROTO ((mpf_ptr, unsigned long int)) __GMP_NOTHROW; + +#define mpf_set_q __gmpf_set_q +__GMP_DECLSPEC void mpf_set_q __GMP_PROTO ((mpf_ptr, mpq_srcptr)); + +#define mpf_set_si __gmpf_set_si +__GMP_DECLSPEC void mpf_set_si __GMP_PROTO ((mpf_ptr, signed long int)); + +#define mpf_set_str __gmpf_set_str +__GMP_DECLSPEC int mpf_set_str __GMP_PROTO ((mpf_ptr, __gmp_const char *, int)); + +#define mpf_set_ui __gmpf_set_ui +__GMP_DECLSPEC void mpf_set_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_set_z __gmpf_set_z +__GMP_DECLSPEC void mpf_set_z __GMP_PROTO ((mpf_ptr, mpz_srcptr)); + +#define mpf_size __gmpf_size +__GMP_DECLSPEC size_t mpf_size __GMP_PROTO ((mpf_srcptr)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpf_sqrt __gmpf_sqrt +__GMP_DECLSPEC void mpf_sqrt __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_sqrt_ui __gmpf_sqrt_ui +__GMP_DECLSPEC void mpf_sqrt_ui __GMP_PROTO ((mpf_ptr, unsigned long int)); + +#define mpf_sub __gmpf_sub +__GMP_DECLSPEC void mpf_sub __GMP_PROTO ((mpf_ptr, mpf_srcptr, mpf_srcptr)); + +#define mpf_sub_ui __gmpf_sub_ui +__GMP_DECLSPEC void mpf_sub_ui __GMP_PROTO ((mpf_ptr, mpf_srcptr, unsigned long int)); + +#define mpf_swap __gmpf_swap +__GMP_DECLSPEC void mpf_swap __GMP_PROTO ((mpf_ptr, mpf_ptr)) __GMP_NOTHROW; + +#define mpf_trunc __gmpf_trunc +__GMP_DECLSPEC void mpf_trunc __GMP_PROTO ((mpf_ptr, mpf_srcptr)); + +#define mpf_ui_div __gmpf_ui_div +__GMP_DECLSPEC void mpf_ui_div __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); + +#define mpf_ui_sub __gmpf_ui_sub +__GMP_DECLSPEC void mpf_ui_sub __GMP_PROTO ((mpf_ptr, unsigned long int, mpf_srcptr)); + +#define mpf_urandomb __gmpf_urandomb +__GMP_DECLSPEC void mpf_urandomb __GMP_PROTO ((mpf_t, gmp_randstate_t, unsigned long int)); + + +/************ Low level positive-integer (i.e. N) routines. ************/ + +/* This is ugly, but we need to make user calls reach the prefixed function. */ + +#define mpn_add __MPN(add) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add) +__GMP_DECLSPEC mp_limb_t mpn_add __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif + +#define mpn_add_1 __MPN(add_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_add_1) +__GMP_DECLSPEC mp_limb_t mpn_add_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif + +#define mpn_add_n __MPN(add_n) +__GMP_DECLSPEC mp_limb_t mpn_add_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_addmul_1 __MPN(addmul_1) +__GMP_DECLSPEC mp_limb_t mpn_addmul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_bdivmod __MPN(bdivmod) +__GMP_DECLSPEC mp_limb_t mpn_bdivmod __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, unsigned long int)); + +#define mpn_cmp __MPN(cmp) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_cmp) +__GMP_DECLSPEC int mpn_cmp __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; +#endif + +#define mpn_divexact_by3(dst,src,size) \ + mpn_divexact_by3c (dst, src, size, __GMP_CAST (mp_limb_t, 0)) + +#define mpn_divexact_by3c __MPN(divexact_by3c) +__GMP_DECLSPEC mp_limb_t mpn_divexact_by3c __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_divmod_1(qp,np,nsize,dlimb) \ + mpn_divrem_1 (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dlimb) + +#define mpn_divrem __MPN(divrem) +__GMP_DECLSPEC mp_limb_t mpn_divrem __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr, mp_size_t)); + +#define mpn_divrem_1 __MPN(divrem_1) +__GMP_DECLSPEC mp_limb_t mpn_divrem_1 __GMP_PROTO ((mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_divrem_2 __MPN(divrem_2) +__GMP_DECLSPEC mp_limb_t mpn_divrem_2 __GMP_PROTO ((mp_ptr, mp_size_t, mp_ptr, mp_size_t, mp_srcptr)); + +#define mpn_gcd __MPN(gcd) +__GMP_DECLSPEC mp_size_t mpn_gcd __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); + +#define mpn_gcd_1 __MPN(gcd_1) +__GMP_DECLSPEC mp_limb_t mpn_gcd_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_gcdext __MPN(gcdext) +__GMP_DECLSPEC mp_size_t mpn_gcdext __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t *, mp_ptr, mp_size_t, mp_ptr, mp_size_t)); + +#define mpn_get_str __MPN(get_str) +__GMP_DECLSPEC size_t mpn_get_str __GMP_PROTO ((unsigned char *, int, mp_ptr, mp_size_t)); + +#define mpn_hamdist __MPN(hamdist) +__GMP_DECLSPEC unsigned long int mpn_hamdist __GMP_PROTO ((mp_srcptr, mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_lshift __MPN(lshift) +__GMP_DECLSPEC mp_limb_t mpn_lshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); + +#define mpn_mod_1 __MPN(mod_1) +__GMP_DECLSPEC mp_limb_t mpn_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_mul __MPN(mul) +__GMP_DECLSPEC mp_limb_t mpn_mul __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); + +#define mpn_mul_1 __MPN(mul_1) +__GMP_DECLSPEC mp_limb_t mpn_mul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_mul_n __MPN(mul_n) +__GMP_DECLSPEC void mpn_mul_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_perfect_square_p __MPN(perfect_square_p) +__GMP_DECLSPEC int mpn_perfect_square_p __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_popcount __MPN(popcount) +__GMP_DECLSPEC unsigned long int mpn_popcount __GMP_PROTO ((mp_srcptr, mp_size_t)) __GMP_NOTHROW __GMP_ATTRIBUTE_PURE; + +#define mpn_pow_1 __MPN(pow_1) +__GMP_DECLSPEC mp_size_t mpn_pow_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t, mp_ptr)); + +/* undocumented now, but retained here for upward compatibility */ +#define mpn_preinv_mod_1 __MPN(preinv_mod_1) +__GMP_DECLSPEC mp_limb_t mpn_preinv_mod_1 __GMP_PROTO ((mp_srcptr, mp_size_t, mp_limb_t, mp_limb_t)) __GMP_ATTRIBUTE_PURE; + +#define mpn_random __MPN(random) +__GMP_DECLSPEC void mpn_random __GMP_PROTO ((mp_ptr, mp_size_t)); + +#define mpn_random2 __MPN(random2) +__GMP_DECLSPEC void mpn_random2 __GMP_PROTO ((mp_ptr, mp_size_t)); + +#define mpn_rshift __MPN(rshift) +__GMP_DECLSPEC mp_limb_t mpn_rshift __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, unsigned int)); + +#define mpn_scan0 __MPN(scan0) +__GMP_DECLSPEC unsigned long int mpn_scan0 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpn_scan1 __MPN(scan1) +__GMP_DECLSPEC unsigned long int mpn_scan1 __GMP_PROTO ((mp_srcptr, unsigned long int)) __GMP_ATTRIBUTE_PURE; + +#define mpn_set_str __MPN(set_str) +__GMP_DECLSPEC mp_size_t mpn_set_str __GMP_PROTO ((mp_ptr, __gmp_const unsigned char *, size_t, int)); + +#define mpn_sqrtrem __MPN(sqrtrem) +__GMP_DECLSPEC mp_size_t mpn_sqrtrem __GMP_PROTO ((mp_ptr, mp_ptr, mp_srcptr, mp_size_t)); + +#define mpn_sub __MPN(sub) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub) +__GMP_DECLSPEC mp_limb_t mpn_sub __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_srcptr,mp_size_t)); +#endif + +#define mpn_sub_1 __MPN(sub_1) +#if __GMP_INLINE_PROTOTYPES || defined (__GMP_FORCE_mpn_sub_1) +__GMP_DECLSPEC mp_limb_t mpn_sub_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)) __GMP_NOTHROW; +#endif + +#define mpn_sub_n __MPN(sub_n) +__GMP_DECLSPEC mp_limb_t mpn_sub_n __GMP_PROTO ((mp_ptr, mp_srcptr, mp_srcptr, mp_size_t)); + +#define mpn_submul_1 __MPN(submul_1) +__GMP_DECLSPEC mp_limb_t mpn_submul_1 __GMP_PROTO ((mp_ptr, mp_srcptr, mp_size_t, mp_limb_t)); + +#define mpn_tdiv_qr __MPN(tdiv_qr) +__GMP_DECLSPEC void mpn_tdiv_qr __GMP_PROTO ((mp_ptr, mp_ptr, mp_size_t, mp_srcptr, mp_size_t, mp_srcptr, mp_size_t)); + + +/**************** mpz inlines ****************/ + +/* The following are provided as inlines where possible, but always exist as + library functions too, for binary compatibility. + + Within gmp itself this inlining generally isn't relied on, since it + doesn't get done for all compilers, whereas if something is worth + inlining then it's worth arranging always. + + There are two styles of inlining here. When the same bit of code is + wanted for the inline as for the library version, then __GMP_FORCE_foo + arranges for that code to be emitted and the __GMP_EXTERN_INLINE + directive suppressed, eg. mpz_fits_uint_p. When a different bit of code + is wanted for the inline than for the library version, then + __GMP_FORCE_foo arranges the inline to be suppressed, eg. mpz_abs. */ + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_abs) +__GMP_EXTERN_INLINE void +mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = __GMP_ABS (__gmp_w->_mp_size); +} +#endif + +#if GMP_NAIL_BITS == 0 +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); +#else +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ + || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) +#if ! defined (__GMP_FORCE_mpz_fits_uint_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_uint_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_UINT_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ulong_p) +#if ! defined (__GMP_FORCE_mpz_fits_ulong_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ulong_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_ULONG_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_ushort_p) +#if ! defined (__GMP_FORCE_mpz_fits_ushort_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_fits_ushort_p (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + __GMPZ_FITS_UTYPE_P (__gmp_z, __GMP_USHRT_MAX); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_get_ui) +#if ! defined (__GMP_FORCE_mpz_get_ui) +__GMP_EXTERN_INLINE +#endif +unsigned long +mpz_get_ui (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + mp_ptr __gmp_p = __gmp_z->_mp_d; + mp_size_t __gmp_n = __gmp_z->_mp_size; + mp_limb_t __gmp_l = __gmp_p[0]; + /* This is a "#if" rather than a plain "if" so as to avoid gcc warnings + about "<< GMP_NUMB_BITS" exceeding the type size, and to avoid Borland + C++ 6.0 warnings about condition always true for something like + "__GMP_ULONG_MAX < GMP_NUMB_MASK". */ +#if GMP_NAIL_BITS == 0 || defined (_LONG_LONG_LIMB) + /* limb==long and no nails, or limb==longlong, one limb is enough */ + return (__gmp_n != 0 ? __gmp_l : 0); +#else + /* limb==long and nails, need two limbs when available */ + __gmp_n = __GMP_ABS (__gmp_n); + if (__gmp_n <= 1) + return (__gmp_n != 0 ? __gmp_l : 0); + else + return __gmp_l + (__gmp_p[1] << GMP_NUMB_BITS); +#endif +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_getlimbn) +#if ! defined (__GMP_FORCE_mpz_getlimbn) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpz_getlimbn (mpz_srcptr __gmp_z, mp_size_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_result = 0; + if (__GMP_LIKELY (__gmp_n >= 0 && __gmp_n < __GMP_ABS (__gmp_z->_mp_size))) + __gmp_result = __gmp_z->_mp_d[__gmp_n]; + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpz_neg) +__GMP_EXTERN_INLINE void +mpz_neg (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpz_set (__gmp_w, __gmp_u); + __gmp_w->_mp_size = - __gmp_w->_mp_size; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_perfect_square_p) +#if ! defined (__GMP_FORCE_mpz_perfect_square_p) +__GMP_EXTERN_INLINE +#endif +int +mpz_perfect_square_p (mpz_srcptr __gmp_a) +{ + mp_size_t __gmp_asize; + int __gmp_result; + + __gmp_asize = __gmp_a->_mp_size; + __gmp_result = (__gmp_asize >= 0); /* zero is a square, negatives are not */ + if (__GMP_LIKELY (__gmp_asize > 0)) + __gmp_result = mpn_perfect_square_p (__gmp_a->_mp_d, __gmp_asize); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_popcount) +#if ! defined (__GMP_FORCE_mpz_popcount) +__GMP_EXTERN_INLINE +#endif +unsigned long +mpz_popcount (mpz_srcptr __gmp_u) __GMP_NOTHROW +{ + mp_size_t __gmp_usize; + unsigned long __gmp_result; + + __gmp_usize = __gmp_u->_mp_size; + __gmp_result = (__gmp_usize < 0 ? __GMP_ULONG_MAX : 0); + if (__GMP_LIKELY (__gmp_usize > 0)) + __gmp_result = mpn_popcount (__gmp_u->_mp_d, __gmp_usize); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_set_q) +#if ! defined (__GMP_FORCE_mpz_set_q) +__GMP_EXTERN_INLINE +#endif +void +mpz_set_q (mpz_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + mpz_tdiv_q (__gmp_w, mpq_numref (__gmp_u), mpq_denref (__gmp_u)); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_size) +#if ! defined (__GMP_FORCE_mpz_size) +__GMP_EXTERN_INLINE +#endif +size_t +mpz_size (mpz_srcptr __gmp_z) __GMP_NOTHROW +{ + return __GMP_ABS (__gmp_z->_mp_size); +} +#endif + + +/**************** mpq inlines ****************/ + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_abs) +__GMP_EXTERN_INLINE void +mpq_abs (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = __GMP_ABS (__gmp_w->_mp_num._mp_size); +} +#endif + +#if defined (__GMP_EXTERN_INLINE) && ! defined (__GMP_FORCE_mpq_neg) +__GMP_EXTERN_INLINE void +mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) +{ + if (__gmp_w != __gmp_u) + mpq_set (__gmp_w, __gmp_u); + __gmp_w->_mp_num._mp_size = - __gmp_w->_mp_num._mp_size; +} +#endif + + +/**************** mpn inlines ****************/ + +/* The comments with __GMPN_ADD_1 below apply here too. + + The test for FUNCTION returning 0 should predict well. If it's assumed + {yp,ysize} will usually have a random number of bits then the high limb + won't be full and a carry out will occur a good deal less than 50% of the + time. + + ysize==0 isn't a documented feature, but is used internally in a few + places. + + Producing cout last stops it using up a register during the main part of + the calculation, though gcc (as of 3.0) on an "if (mpn_add (...))" + doesn't seem able to move the true and false legs of the conditional up + to the two places cout is generated. */ + +#define __GMPN_AORS(cout, wp, xp, xsize, yp, ysize, FUNCTION, TEST) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x; \ + \ + /* ASSERT ((ysize) >= 0); */ \ + /* ASSERT ((xsize) >= (ysize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, xp, xsize)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE2_P (wp, xsize, yp, ysize)); */ \ + \ + __gmp_i = (ysize); \ + if (__gmp_i != 0) \ + { \ + if (FUNCTION (wp, xp, yp, __gmp_i)) \ + { \ + do \ + { \ + if (__gmp_i >= (xsize)) \ + { \ + (cout) = 1; \ + goto __gmp_done; \ + } \ + __gmp_x = (xp)[__gmp_i]; \ + } \ + while (TEST); \ + } \ + } \ + if ((wp) != (xp)) \ + __GMPN_COPY_REST (wp, xp, xsize, __gmp_i); \ + (cout) = 0; \ + __gmp_done: \ + ; \ + } while (0) + +#define __GMPN_ADD(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_add_n, \ + (((wp)[__gmp_i++] = (__gmp_x + 1) & GMP_NUMB_MASK) == 0)) +#define __GMPN_SUB(cout, wp, xp, xsize, yp, ysize) \ + __GMPN_AORS (cout, wp, xp, xsize, yp, ysize, mpn_sub_n, \ + (((wp)[__gmp_i++] = (__gmp_x - 1) & GMP_NUMB_MASK), __gmp_x == 0)) + + +/* The use of __gmp_i indexing is designed to ensure a compile time src==dst + remains nice and clear to the compiler, so that __GMPN_COPY_REST can + disappear, and the load/add/store gets a chance to become a + read-modify-write on CISC CPUs. + + Alternatives: + + Using a pair of pointers instead of indexing would be possible, but gcc + isn't able to recognise compile-time src==dst in that case, even when the + pointers are incremented more or less together. Other compilers would + very likely have similar difficulty. + + gcc could use "if (__builtin_constant_p(src==dst) && src==dst)" or + similar to detect a compile-time src==dst. This works nicely on gcc + 2.95.x, it's not good on gcc 3.0 where __builtin_constant_p(p==p) seems + to be always false, for a pointer p. But the current code form seems + good enough for src==dst anyway. + + gcc on x86 as usual doesn't give particularly good flags handling for the + carry/borrow detection. It's tempting to want some multi instruction asm + blocks to help it, and this was tried, but in truth there's only a few + instructions to save and any gain is all too easily lost by register + juggling setting up for the asm. */ + +#if GMP_NAIL_BITS == 0 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r; \ + if (CB (__gmp_r, __gmp_x, (v))) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r; \ + ++__gmp_i; \ + if (!CB (__gmp_r, __gmp_x, 1)) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#if GMP_NAIL_BITS >= 1 +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ + if (__gmp_r >> GMP_NUMB_BITS != 0) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ + ++__gmp_i; \ + if (__gmp_r >> GMP_NUMB_BITS == 0) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ + } while (0) +#endif + +#define __GMPN_ADDCB(r,x,y) ((r) < (y)) +#define __GMPN_SUBCB(r,x,y) ((x) < (y)) + +#define __GMPN_ADD_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) +#define __GMPN_SUB_1(cout, dst, src, n, v) \ + __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) + + +/* Compare {xp,size} and {yp,size}, setting "result" to positive, zero or + negative. size==0 is allowed. On random data usually only one limb will + need to be examined to get a result, so it's worth having it inline. */ +#define __GMPN_CMP(result, xp, yp, size) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_y; \ + \ + /* ASSERT ((size) >= 0); */ \ + \ + (result) = 0; \ + __gmp_i = (size); \ + while (--__gmp_i >= 0) \ + { \ + __gmp_x = (xp)[__gmp_i]; \ + __gmp_y = (yp)[__gmp_i]; \ + if (__gmp_x != __gmp_y) \ + { \ + /* Cannot use __gmp_x - __gmp_y, may overflow an "int" */ \ + (result) = (__gmp_x > __gmp_y ? 1 : -1); \ + break; \ + } \ + } \ + } while (0) + + +#if defined (__GMPN_COPY) && ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + __GMPN_COPY ((dst)+(start), (src)+(start), (size)-(start)); \ + } while (0) +#endif + +/* Copy {src,size} to {dst,size}, starting at "start". This is designed to + keep the indexing dst[j] and src[j] nice and simple for __GMPN_ADD_1, + __GMPN_ADD, etc. */ +#if ! defined (__GMPN_COPY_REST) +#define __GMPN_COPY_REST(dst, src, size, start) \ + do { \ + mp_size_t __gmp_j; \ + /* ASSERT ((size) >= 0); */ \ + /* ASSERT ((start) >= 0); */ \ + /* ASSERT ((start) <= (size)); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, size)); */ \ + __GMP_CRAY_Pragma ("_CRI ivdep"); \ + for (__gmp_j = (start); __gmp_j < (size); __gmp_j++) \ + (dst)[__gmp_j] = (src)[__gmp_j]; \ + } while (0) +#endif + +/* Enhancement: Use some of the smarter code from gmp-impl.h. Maybe use + mpn_copyi if there's a native version, and if we don't mind demanding + binary compatibility for it (on targets which use it). */ + +#if ! defined (__GMPN_COPY) +#define __GMPN_COPY(dst, src, size) __GMPN_COPY_REST (dst, src, size, 0) +#endif + + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add) +#if ! defined (__GMP_FORCE_mpn_add) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_ADD (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_add_1) +#if ! defined (__GMP_FORCE_mpn_add_1) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_add_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_ADD_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_cmp) +#if ! defined (__GMP_FORCE_mpn_cmp) +__GMP_EXTERN_INLINE +#endif +int +mpn_cmp (mp_srcptr __gmp_xp, mp_srcptr __gmp_yp, mp_size_t __gmp_size) __GMP_NOTHROW +{ + int __gmp_result; + __GMPN_CMP (__gmp_result, __gmp_xp, __gmp_yp, __gmp_size); + return __gmp_result; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub) +#if ! defined (__GMP_FORCE_mpn_sub) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub (mp_ptr __gmp_wp, mp_srcptr __gmp_xp, mp_size_t __gmp_xsize, mp_srcptr __gmp_yp, mp_size_t __gmp_ysize) +{ + mp_limb_t __gmp_c; + __GMPN_SUB (__gmp_c, __gmp_wp, __gmp_xp, __gmp_xsize, __gmp_yp, __gmp_ysize); + return __gmp_c; +} +#endif + +#if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpn_sub_1) +#if ! defined (__GMP_FORCE_mpn_sub_1) +__GMP_EXTERN_INLINE +#endif +mp_limb_t +mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_t __gmp_n) __GMP_NOTHROW +{ + mp_limb_t __gmp_c; + __GMPN_SUB_1 (__gmp_c, __gmp_dst, __gmp_src, __gmp_size, __gmp_n); + return __gmp_c; +} +#endif + +#if defined (__cplusplus) +} +#endif + + +/* Allow faster testing for negative, zero, and positive. */ +#define mpz_sgn(Z) ((Z)->_mp_size < 0 ? -1 : (Z)->_mp_size > 0) +#define mpf_sgn(F) ((F)->_mp_size < 0 ? -1 : (F)->_mp_size > 0) +#define mpq_sgn(Q) ((Q)->_mp_num._mp_size < 0 ? -1 : (Q)->_mp_num._mp_size > 0) + +/* When using GCC, optimize certain common comparisons. */ +#if defined (__GNUC__) +#define mpz_cmp_ui(Z,UI) \ + (__builtin_constant_p (UI) && (UI) == 0 \ + ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) +#define mpz_cmp_si(Z,SI) \ + (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (SI) && (SI) > 0 \ + ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ + : _mpz_cmp_si (Z,SI)) +#define mpq_cmp_ui(Q,NUI,DUI) \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ + ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) +#define mpq_cmp_si(q,n,d) \ + (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ + ? mpq_cmp_ui (q, __GMP_CAST (unsigned long, n), d) \ + : _mpq_cmp_si (q, n, d)) +#else +#define mpz_cmp_ui(Z,UI) _mpz_cmp_ui (Z,UI) +#define mpz_cmp_si(Z,UI) _mpz_cmp_si (Z,UI) +#define mpq_cmp_ui(Q,NUI,DUI) _mpq_cmp_ui (Q,NUI,DUI) +#define mpq_cmp_si(q,n,d) _mpq_cmp_si(q,n,d) +#endif + + +/* Using "&" rather than "&&" means these can come out branch-free. Every + mpz_t has at least one limb allocated, so fetching the low limb is always + allowed. */ +#define mpz_odd_p(z) (((z)->_mp_size != 0) & __GMP_CAST (int, (z)->_mp_d[0])) +#define mpz_even_p(z) (! mpz_odd_p (z)) + + +/**************** C++ routines ****************/ + +#ifdef __cplusplus +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpz_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpq_srcptr); +__GMP_DECLSPEC_XX std::ostream& operator<< (std::ostream &, mpf_srcptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpz_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpq_ptr); +__GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); +#endif + + +/* Source-level compatibility with GMP 2 and earlier. */ +#define mpn_divmod(qp,np,nsize,dp,dsize) \ + mpn_divrem (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dp, dsize) + +/* Source-level compatibility with GMP 1. */ +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdivmod_ui(q,r,n,d) \ + (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) +#define mpz_mmod_ui(r,n,d) \ + (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) + +/* Useful synonyms, but not quite compatible with GMP 1. */ +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp + +enum +{ + GMP_ERROR_NONE = 0, + GMP_ERROR_UNSUPPORTED_ARGUMENT = 1, + GMP_ERROR_DIVISION_BY_ZERO = 2, + GMP_ERROR_SQRT_OF_NEGATIVE = 4, + GMP_ERROR_INVALID_ARGUMENT = 8 +}; + +/* Major version number is the value of __GNU_MP__ too, above and in mp.h. */ +#define __GNU_MP_VERSION 4 +#define __GNU_MP_VERSION_MINOR 2 +#define __GNU_MP_VERSION_PATCHLEVEL 2 + +#define __GMP_H__ +#endif /* __GMP_H__ */ diff --git a/src/bncsutil/libinfo.cpp b/src/bncsutil/libinfo.cpp index 2a58a01..4fc032e 100644 --- a/src/bncsutil/libinfo.cpp +++ b/src/bncsutil/libinfo.cpp @@ -38,18 +38,18 @@ MEXP(int) bncsutil_getVersionString(char* outBuf) { // major major = (unsigned long) (BNCSUTIL_VERSION / 10000); if (major > 99 || major < 0) return 0; - + // minor ver -= (major * 10000); minor = (unsigned long) (ver / 100); if (minor > 99 || minor < 0) return 0; - + // revision ver -= (minor * 100); rev = ver; if (rev > 99 || rev < 0) return 0; - - printed = std::sprintf(outBuf, "%u.%u.%u", major, minor, rev); + + printed = std::sprintf(outBuf, "%lu.%lu.%lu", major, minor, rev); if (printed < 0) return 0; outBuf[8] = '\0'; return printed; diff --git a/src/bncsutil/ms_stdint.h b/src/bncsutil/ms_stdint.h new file mode 100644 index 0000000..e032ff1 --- /dev/null +++ b/src/bncsutil/ms_stdint.h @@ -0,0 +1,232 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#if (_MSC_VER < 1300) && defined(__cplusplus) + extern "C++" { +#endif +# include +#if (_MSC_VER < 1300) && defined(__cplusplus) + } +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef __int64 int64_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; +typedef unsigned __int64 uint64_t; + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/src/bncsutil/mutil.h b/src/bncsutil/mutil.h index 6a346c8..e6316b7 100644 --- a/src/bncsutil/mutil.h +++ b/src/bncsutil/mutil.h @@ -27,18 +27,28 @@ #ifndef MUTIL_H #define MUTIL_H +#define LITTLEENDIAN 1 + + #ifdef HAVE_CONFIG_H #include #endif /* Specific-Sized Integers */ #include "mutil_types.h" -#include +#include + +// functions for converting a string to a 64-bit number. +#if defined(_MSC_VER) +#define ATOL64(x) _atoi64(x) +#else +#define ATOL64(x) atoll(x) +#endif #ifdef _MSC_VER -#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */ -#define ROL(x,n) _lrotl((x),(n)) -#define ROR(x,n) _lrotr((x),(n)) +#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */ +#define ROL(x,n) _lrotl((x),(n)) +#define ROR(x,n) _lrotr((x),(n)) #else #ifndef ROL #define ROL(a,b) (((a) << (b)) | ((a) >> 32 - (b))) @@ -92,8 +102,8 @@ #define SWAP2(num) ((((num) >> 8) & 0x00FF) | (((num) << 8) & 0xFF00)) #define SWAP4(num) ((((num) >> 24) & 0x000000FF) | (((num) >> 8) & 0x0000FF00) | (((num) << 8) & 0x00FF0000) | (((num) << 24) & 0xFF000000)) -#define SWAP8(x) \ - (uint64_t)((((uint64_t)(x) & 0xff) << 56) | \ +#define SWAP8(x) \ + (uint64_t)((((uint64_t)(x) & 0xff) << 56) | \ ((uint64_t)(x) & 0xff00ULL) << 40 | \ ((uint64_t)(x) & 0xff0000ULL) << 24 | \ ((uint64_t)(x) & 0xff000000ULL) << 8 | \ @@ -119,17 +129,17 @@ #define MSB4(num) SWAP4(num) #endif /* (endianness) */ -#ifndef MOS_WINDOWS +#ifndef MOS_WINDOWS /* attempt automatic Windows detection */ - #ifdef _MSC_VER + #ifdef _MSC_VER /* Microsoft C++ compiler, has to be windows */ - #define MOS_WINDOWS - #else + #define MOS_WINDOWS + #else #if defined(_WIN) || defined(_WINDOWS) || defined(WINDOWS) || \ defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) #define MOS_WINDOWS - #endif - #endif + #endif + #endif #endif #if !(defined(MUTIL_LIB_BUILD)) && defined(BNCSUTIL_EXPORTS) @@ -163,6 +173,6 @@ #define NULL 0 #endif /* NULL */ -#include +// #include #endif /* MUTIL_H */ diff --git a/src/bncsutil/mutil_types.h b/src/bncsutil/mutil_types.h index a52b100..aec9a3d 100644 --- a/src/bncsutil/mutil_types.h +++ b/src/bncsutil/mutil_types.h @@ -26,6 +26,10 @@ #ifndef BNCSUTIL_MUTIL_TYPES_H_INCLUDED #define BNCSUTIL_MUTIL_TYPES_H_INCLUDED +#ifdef WIN32 + #include "ms_stdint.h" +#else + #if defined(_MSC_VER) || (defined(HAVE_STDINT_H) && !HAVE_STDINT_H) // no stdint.h available // so just wing it @@ -136,4 +140,6 @@ typedef unsigned long long uintmax_t; #include #endif +#endif /* WIN32 */ + #endif /* BNCSUTIL_MUTIL_TYPES_H_INCLUDED */ diff --git a/src/bncsutil/nls.c b/src/bncsutil/nls.c index a765e02..8d19cd0 100644 --- a/src/bncsutil/nls.c +++ b/src/bncsutil/nls.c @@ -29,24 +29,24 @@ #include #include #include -#include +#include "gmp.h" struct _nls { const char* username; const char* password; unsigned long username_len; unsigned long password_len; - + mpz_t n; mpz_t a; - + gmp_randstate_t rand; - char* A; - char* S; - char* K; - char* M1; - char* M2; + char* A; + char* S; + char* K; + char* M1; + char* M2; }; #ifdef MOS_WINDOWS @@ -95,7 +95,7 @@ uint32_t nls_get_u(const char* B); MEXP(nls_t*) nls_init(const char* username, const char* password) { return nls_init_l(username, (unsigned long) strlen(username), - password, (unsigned long) strlen(password)); + password, (unsigned long) strlen(password)); } MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, @@ -105,21 +105,21 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, char* d; /* destination */ const char* o; /* original */ nls_t* nls; - + nls = (nls_t*) malloc(sizeof(nls_t)); if (!nls) return (nls_t*) 0; - + nls->username_len = username_length; nls->password_len = password_length; - + nls->username = (char*) malloc(nls->username_len + 1); nls->password = (char*) malloc(nls->password_len + 1); if (!nls->username || !nls->password) { free(nls); return (nls_t*) 0; } - + d = (char*) nls->username; o = username; for (i = 0; i < nls->username_len; i++) { @@ -127,10 +127,10 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, d++; o++; } - + *((char*) nls->username + username_length) = 0; *((char*) nls->password + password_length) = 0; - + d = (char*) nls->password; o = password; for (i = 0; i < nls->password_len; i++) { @@ -138,9 +138,9 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, d++; o++; } - + mpz_init_set_str(nls->n, NLS_VAR_N_STR, 16); - + gmp_randinit_default(nls->rand); gmp_randseed_ui(nls->rand, nls_pre_seed()); mpz_init2(nls->a, 256); @@ -149,12 +149,12 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, /* The following line replaces preceding 2 lines during testing. */ /*mpz_init_set_str(nls->a, "1234", 10);*/ - nls->A = (char*) 0; - nls->S = (char*) 0; - nls->K = (char*) 0; - nls->M1 = (char*) 0; - nls->M2 = (char*) 0; - + nls->A = (char*) 0; + nls->S = (char*) 0; + nls->K = (char*) 0; + nls->M1 = (char*) 0; + nls->M2 = (char*) 0; + return nls; } @@ -167,63 +167,63 @@ MEXP(void) nls_free(nls_t* nls) { free((void*) nls->username); free((void*) nls->password); - if (nls->A) - free(nls->A); - if (nls->S) - free(nls->S); - if (nls->K) - free(nls->K); - if (nls->M1) - free(nls->M1); - if (nls->M2) - free(nls->M2); + if (nls->A) + free(nls->A); + if (nls->S) + free(nls->S); + if (nls->K) + free(nls->K); + if (nls->M1) + free(nls->M1); + if (nls->M2) + free(nls->M2); free(nls); } MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, - const char* password) + const char* password) { - return nls_reinit_l(nls, username, (unsigned long) strlen(username), - password, (unsigned long) strlen(password)); + return nls_reinit_l(nls, username, (unsigned long) strlen(username), + password, (unsigned long) strlen(password)); } MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, - unsigned long username_length, const char* password, - unsigned long password_length) + unsigned long username_length, const char* password, + unsigned long password_length) { - unsigned int i; + unsigned int i; char* d; /* destination */ const char* o; /* original */ - if (nls->A) - free(nls->A); - if (nls->S) - free(nls->S); - if (nls->K) - free(nls->K); - if (nls->M1) - free(nls->M1); - if (nls->M2) - free(nls->M2); - - nls->username_len = username_length; + if (nls->A) + free(nls->A); + if (nls->S) + free(nls->S); + if (nls->K) + free(nls->K); + if (nls->M1) + free(nls->M1); + if (nls->M2) + free(nls->M2); + + nls->username_len = username_length; nls->password_len = password_length; - - nls->username = (const char*) realloc((void*) nls->username, - nls->username_len + 1); - if (!nls->username) { + + nls->username = (const char*) realloc((void*) nls->username, + nls->username_len + 1); + if (!nls->username) { free(nls); return (nls_t*) 0; } nls->password = (const char*) realloc((void*) nls->password, - nls->password_len + 1); + nls->password_len + 1); if (!nls->password) { - free((void*) nls->username); + free((void*) nls->username); free(nls); return (nls_t*) 0; } - + d = (char*) nls->username; o = username; for (i = 0; i < nls->username_len; i++) { @@ -232,30 +232,30 @@ MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, o++; } - d = (char*) nls->password; + d = (char*) nls->password; o = password; for (i = 0; i < nls->password_len; i++) { *d = (char) toupper(*o); d++; o++; } - + *((char*) nls->username + username_length) = 0; *((char*) nls->password + password_length) = 0; - mpz_urandomm(nls->a, nls->rand, nls->n); /* generates the private key */ + mpz_urandomm(nls->a, nls->rand, nls->n); /* generates the private key */ - nls->A = (char*) 0; - nls->S = (char*) 0; - nls->K = (char*) 0; - nls->M1 = (char*) 0; - nls->M2 = (char*) 0; + nls->A = (char*) 0; + nls->S = (char*) 0; + nls->K = (char*) 0; + nls->M1 = (char*) 0; + nls->M2 = (char*) 0; - return nls; + return nls; } MEXP(unsigned long) nls_account_create(nls_t* nls, char* buf, unsigned long bufSize) { - mpz_t s; /* salt */ + mpz_t s; /* salt */ mpz_t v; mpz_t x; @@ -263,20 +263,20 @@ MEXP(unsigned long) nls_account_create(nls_t* nls, char* buf, unsigned long bufS return 0; if (bufSize < nls->username_len + 65) return 0; - + mpz_init2(s, 256); mpz_urandomb(s, nls->rand, 256); mpz_export(buf, (size_t*) 0, -1, 1, 0, 0, s); - /*memset(buf, 0, 32);*/ - + /*memset(buf, 0, 32);*/ + nls_get_x(nls, x, buf); nls_get_v_mpz(nls, v, x); mpz_export(buf + 32, (size_t*) 0, -1, 1, 0, 0, v); - - mpz_clear(x); + + mpz_clear(x); mpz_clear(v); mpz_clear(s); - + strcpy(buf + 64, nls->username); return nls->username_len + 65; } @@ -286,7 +286,7 @@ MEXP(unsigned long) nls_account_logon(nls_t* nls, char* buf, unsigned long bufSi return 0; if (bufSize < nls->username_len + 33) return 0; - + nls_get_A(nls, buf); strcpy(buf + 32, nls->username); return nls->username_len + 33; @@ -297,27 +297,27 @@ MEXP(nls_t*) nls_account_change_proof(nls_t* nls, char* buf, { nls_t* nouveau; mpz_t s; /* salt */ - + if (!nls) return (nls_t*) 0; - + /* create new nls_t */ nouveau = nls_init_l(nls->username, nls->username_len, new_password, (unsigned long) strlen(new_password)); if (!nouveau) return (nls_t*) 0; - + /* fill buf */ nls_get_M1(nls, buf, B, salt); - + mpz_init2(s, 256); mpz_urandomb(s, nouveau->rand, 256); mpz_export(buf + 20, (size_t*) 0, -1, 1, 0, 0, s); - - nls_get_v(nouveau, buf + 52, buf + 20); + + nls_get_v(nouveau, buf + 52, buf + 20); mpz_clear(s); - + return nouveau; } @@ -326,34 +326,34 @@ MEXP(void) nls_get_S(nls_t* nls, char* out, const char* B, const char* salt) { mpz_t S_base, S_exp; mpz_t x; mpz_t v; - + if (!nls) return; - if (nls->S) { - memcpy(out, nls->S, 32); - return; - } - + if (nls->S) { + memcpy(out, nls->S, 32); + return; + } + mpz_init2(temp, 256); mpz_import(temp, 32, -1, 1, 0, 0, B); - + nls_get_x(nls, x, salt); nls_get_v_mpz(nls, v, x); - + mpz_init_set(S_base, nls->n); mpz_add(S_base, S_base, temp); mpz_sub(S_base, S_base, v); mpz_mod(S_base, S_base, nls->n); - + mpz_init_set(S_exp, x); mpz_mul_ui(S_exp, S_exp, nls_get_u(B)); mpz_add(S_exp, S_exp, nls->a); - + mpz_clear(x); mpz_clear(v); mpz_clear(temp); - + mpz_init(temp); mpz_powm(temp, S_base, S_exp, nls->n); mpz_clear(S_base); @@ -361,25 +361,25 @@ MEXP(void) nls_get_S(nls_t* nls, char* out, const char* B, const char* salt) { mpz_export(out, (size_t*) 0, -1, 1, 0, 0, temp); mpz_clear(temp); - nls->S = (char*) malloc(32); - if (nls->S) - memcpy(nls->S, out, 32); + nls->S = (char*) malloc(32); + if (nls->S) + memcpy(nls->S, out, 32); } MEXP(void) nls_get_v(nls_t* nls, char* out, const char* salt) { mpz_t g; mpz_t v; mpz_t x; - + if (!nls) return; - + mpz_init_set_ui(g, NLS_VAR_g); mpz_init(v); nls_get_x(nls, x, salt); - + mpz_powm(v, g, x, nls->n); - + mpz_export(out, (size_t*) 0, -1, 1, 0, 0, v); mpz_clear(v); mpz_clear(g); @@ -391,62 +391,62 @@ MEXP(void) nls_get_A(nls_t* nls, char* out) { mpz_t g; mpz_t A; size_t o; - + if (!nls) return; - if (nls->A) { - memcpy(out, nls->A, 32); - return; - } - + if (nls->A) { + memcpy(out, nls->A, 32); + return; + } + mpz_init_set_ui(g, NLS_VAR_g); mpz_init2(A, 256); - + mpz_powm(A, g, nls->a, nls->n); mpz_export(out, &o, -1, 1, 0, 0, A); - + mpz_clear(A); mpz_clear(g); - nls->A = (char*) malloc(32); - if (nls->A) - memcpy(nls->A, out, 32); + nls->A = (char*) malloc(32); + if (nls->A) + memcpy(nls->A, out, 32); } MEXP(void) nls_get_K(nls_t* nls, char* out, const char* S) { char odd[16], even[16]; uint8_t odd_hash[20], even_hash[20]; - + char* Sp = (char*) S; char* op = odd; char* ep = even; unsigned int i; - + SHA1Context ctx; - if (!nls) - return; - - if (nls->K) { - memcpy(out, nls->K, 40); - return; - } + if (!nls) + return; + if (nls->K) { + memcpy(out, nls->K, 40); + return; + } + for (i = 0; i < 16; i++) { *(op++) = *(Sp++); *(ep++) = *(Sp++); } - + SHA1Reset(&ctx); SHA1Input(&ctx, (uint8_t*) odd, 16); SHA1Result(&ctx, odd_hash); - + SHA1Reset(&ctx); SHA1Input(&ctx, (uint8_t*) even, 16); SHA1Result(&ctx, even_hash); - + Sp = out; op = (char*) odd_hash; ep = (char*) even_hash; @@ -455,9 +455,9 @@ MEXP(void) nls_get_K(nls_t* nls, char* out, const char* S) { *(Sp++) = *(ep++); } - nls->K = (char*) malloc(40); - if (nls->K) - memcpy(nls->K, out, 40); + nls->K = (char*) malloc(40); + if (nls->K) + memcpy(nls->K, out, 40); } MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { @@ -467,21 +467,21 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { char S[32]; char K[40]; - if (!nls) - return; + if (!nls) + return; - if (nls->M1) { - nls_dbg("nls_get_M1(): Using cached M[1] value."); - memcpy(out, nls->M1, 20); - return; - } + if (nls->M1) { + nls_dbg("nls_get_M1(): Using cached M[1] value."); + memcpy(out, nls->M1, 20); + return; + } /* calculate SHA-1 hash of username */ SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); SHA1Result(&sha, username_hash); - + nls_get_A(nls, A); nls_get_S(nls, S, B, salt); nls_get_K(nls, K, S); @@ -496,9 +496,9 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { SHA1Input(&sha, (uint8_t*) K, 40); SHA1Result(&sha, (uint8_t*) out); - nls->M1 = (char*) malloc(20); - if (nls->M1) - memcpy(nls->M1, out, 20); + nls->M1 = (char*) malloc(20); + if (nls->M1) + memcpy(nls->M1, out, 20); } MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, @@ -506,66 +506,66 @@ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, { SHA1Context sha; char local_M2[20]; - char* A; - char S[32]; - char* K; - char* M1; + char* A; + char S[32]; + char* K; + char* M1; uint8_t username_hash[20]; - int res; - int mustFree = 0; - - if (!nls) - return 0; - - if (nls->M2) - return (memcmp(nls->M2, var_M2, 20) == 0); - - if (nls->A && nls->K && nls->M1) { - A = nls->A; - K = nls->K; - M1 = nls->M1; - } else { - if (!B || !salt) - return 0; - - A = (char*) malloc(32); - if (!A) - return 0; - K = (char*) malloc(40); - if (!K) { - free(A); - return 0; - } - M1 = (char*) malloc(20); - if (!M1) { - free(K); - free(A); - return 0; - } - - mustFree = 1; - - /* get the other values needed for the hash */ - nls_get_A(nls, A); - nls_get_S(nls, S, (char*) B, (char*) salt); - nls_get_K(nls, K, S); - - /* calculate SHA-1 hash of username */ - SHA1Reset(&sha); - SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); - SHA1Result(&sha, username_hash); - - /* calculate M[1] */ - SHA1Reset(&sha); - SHA1Input(&sha, (uint8_t*) bncsutil_NLS_I, 20); - SHA1Input(&sha, username_hash, 20); - SHA1Input(&sha, (uint8_t*) salt, 32); - SHA1Input(&sha, (uint8_t*) A, 32); - SHA1Input(&sha, (uint8_t*) B, 32); - SHA1Input(&sha, (uint8_t*) K, 40); - SHA1Result(&sha, (uint8_t*) M1); - } - + int res; + int mustFree = 0; + + if (!nls) + return 0; + + if (nls->M2) + return (memcmp(nls->M2, var_M2, 20) == 0); + + if (nls->A && nls->K && nls->M1) { + A = nls->A; + K = nls->K; + M1 = nls->M1; + } else { + if (!B || !salt) + return 0; + + A = (char*) malloc(32); + if (!A) + return 0; + K = (char*) malloc(40); + if (!K) { + free(A); + return 0; + } + M1 = (char*) malloc(20); + if (!M1) { + free(K); + free(A); + return 0; + } + + mustFree = 1; + + /* get the other values needed for the hash */ + nls_get_A(nls, A); + nls_get_S(nls, S, (char*) B, (char*) salt); + nls_get_K(nls, K, S); + + /* calculate SHA-1 hash of username */ + SHA1Reset(&sha); + SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); + SHA1Result(&sha, username_hash); + + /* calculate M[1] */ + SHA1Reset(&sha); + SHA1Input(&sha, (uint8_t*) bncsutil_NLS_I, 20); + SHA1Input(&sha, username_hash, 20); + SHA1Input(&sha, (uint8_t*) salt, 32); + SHA1Input(&sha, (uint8_t*) A, 32); + SHA1Input(&sha, (uint8_t*) B, 32); + SHA1Input(&sha, (uint8_t*) K, 40); + SHA1Result(&sha, (uint8_t*) M1); + } + /* calculate M[2] */ SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) A, 32); @@ -573,19 +573,19 @@ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, SHA1Input(&sha, (uint8_t*) K, 40); SHA1Result(&sha, (uint8_t*) local_M2); - res = (memcmp(local_M2, var_M2, 20) == 0); - - if (mustFree) { - free(A); - free(K); - free(M1); - } + res = (memcmp(local_M2, var_M2, 20) == 0); - /* cache result */ - nls->M2 = (char*) malloc(20); - if (nls->M2) - memcpy(nls->M2, local_M2, 20); + if (mustFree) { + free(A); + free(K); + free(M1); + } + /* cache result */ + nls->M2 = (char*) malloc(20); + if (nls->M2) + memcpy(nls->M2, local_M2, 20); + return res; } @@ -595,55 +595,55 @@ MEXP(int) nls_check_signature(uint32_t address, const char* signature_raw) { mpz_t result; mpz_t modulus; mpz_t signature; - size_t size, alloc_size; - int cmp_result; - + size_t size, alloc_size; + int cmp_result; + /* build the "check" array */ - memcpy(check, &address, 4); - memset(check + 4, 0xBB, 28); - + memcpy(check, &address, 4); + memset(check + 4, 0xBB, 28); + /* initialize the modulus */ mpz_init2(modulus, 1024); mpz_import(modulus, 128, -1, 1, 0, 0, bncsutil_NLS_sig_n); - + /* initialize the server signature */ mpz_init2(signature, 1024); mpz_import(signature, 128, -1, 1, 0, 0, signature_raw); - + /* initialize the result */ mpz_init2(result, 1024); - + /* calculate the result */ mpz_powm_ui(result, signature, NLS_SIGNATURE_KEY, modulus); - + /* clear (free) the intermediates */ mpz_clear(signature); mpz_clear(modulus); - /* allocate space for raw signature */ - alloc_size = mpz_size(result) * sizeof(mp_limb_t); - result_raw = (char*) malloc(alloc_size); - if (!result_raw) { - mpz_clear(result); - return 0; - } - + /* allocate space for raw signature */ + alloc_size = mpz_size(result) * sizeof(mp_limb_t); + result_raw = (char*) malloc(alloc_size); + if (!result_raw) { + mpz_clear(result); + return 0; + } + /* get a byte array of the signature */ mpz_export(result_raw, &size, -1, 1, 0, 0, result); - + /* clear (free) the result */ mpz_clear(result); - + /* check the result */ cmp_result = (memcmp(result_raw, check, 32) == 0); - /* free the result_raw buffer */ - free(result_raw); + /* free the result_raw buffer */ + free(result_raw); - /* return */ - return cmp_result; + /* return */ + return cmp_result; } - + unsigned long nls_pre_seed() { #ifdef MOS_WINDOWS return (unsigned long) GetTickCount(); @@ -673,28 +673,28 @@ void nls_get_x(nls_t* nls, mpz_t x_c, const char* raw_salt) { char* userpass; uint8_t hash[20], final_hash[20]; SHA1Context shac; - + // build the string Username:Password userpass = (char*) malloc(nls->username_len + nls->password_len + 2); memcpy(userpass, nls->username, nls->username_len); userpass[nls->username_len] = ':'; memcpy(userpass + nls->username_len + 1, nls->password, nls->password_len); userpass[nls->username_len + nls->password_len + 1] = 0; // null-terminator - + // get the SHA-1 hash of the string SHA1Reset(&shac); SHA1Input(&shac, (uint8_t*) userpass, (nls->username_len + nls->password_len + 1)); SHA1Result(&shac, hash); free(userpass); - + // get the SHA-1 hash of the salt and user:pass hash SHA1Reset(&shac); SHA1Input(&shac, (uint8_t*) raw_salt, 32); SHA1Input(&shac, hash, 20); SHA1Result(&shac, final_hash); SHA1Reset(&shac); - + // create an arbitrary-length integer from the hash and return it mpz_init2(x_c, 160); mpz_import(x_c, 20, -1, 1, 0, 0, (char*) final_hash); @@ -712,12 +712,12 @@ uint32_t nls_get_u(const char* B) { SHA1Context sha; uint8_t hash[20]; uint32_t u; - + SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) B, 32); SHA1Result(&sha, hash); SHA1Reset(&sha); - + u = *(uint32_t*) hash; u = MSB4(u); // needed? yes return u; diff --git a/src/bncsutil/nls.h b/src/bncsutil/nls.h index f132559..3e94df1 100644 --- a/src/bncsutil/nls.h +++ b/src/bncsutil/nls.h @@ -72,7 +72,7 @@ MEXP(void) nls_free(nls_t* nls); * pointer on failure. */ MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, - const char* password); + const char* password); /** * Re-initializes an nls_t structure with a new username and @@ -80,8 +80,8 @@ MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, * on success or a NULL pointer on failure. */ MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, - unsigned long username_length, const char* password, - unsigned long password_length); + unsigned long username_length, const char* password, + unsigned long password_length); /* Packet Generation Functions */ @@ -161,8 +161,8 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt); * safely set to NULL. */ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, - const char* salt); - + const char* salt); + /** * Checks the server signature received in SID_AUTH_INFO (0x50). * Pass the IPv4 address of the server you're connecting to in the address @@ -188,142 +188,142 @@ MEXP(int) nls_check_signature(uint32_t address, const char* signature_raw); class NLS { public: - NLS(const char* username, const char* password) : n((nls_t*) 0) - { - n = nls_init(username, password); - } - - NLS(const char* username, size_t username_length, const char* password, - size_t password_length) - { - n = nls_init_l(username, username_length, password, password_length); - } - - NLS(const std::string& username, const std::string& password) - { - n = nls_init_l(username.c_str(), username.length(), - password.c_str(), password.length()); - } - - virtual ~NLS() - { - std::vector::iterator i; - - if (n) - nls_free(n); - - for (i = blocks.begin(); i != blocks.end(); i++) { - delete [] *i; - } - } - - void getSecret(char* out, const char* salt, const char* B) - { - nls_get_S(n, out, B, salt); - } - - const char* getSecret(const char* salt, const char* B) - { - char* buf = allocateBuffer(32); - getSecret(buf, salt, B); - return buf; - } - - void getVerifier(char* out, const char* salt) - { - nls_get_v(n, out, salt); - } - - const char* getVerifier(const char* salt) - { - char* buf = allocateBuffer(32); - getVerifier(buf, salt); - return buf; - } - - void getPublicKey(char* out) - { - nls_get_A(n, out); - } - - const char* getPublicKey(void) - { - char* buf = allocateBuffer(32); - getPublicKey(buf); - return buf; - } - - void getHashedSecret(char* out, const char* secret) - { - nls_get_K(n, out, secret); - } - - const char* getHashedSecret(const char* secret) - { - char* buf = allocateBuffer(40); - getHashedSecret(buf, secret); - return buf; - } - - void getClientSessionKey(char* out, const char* salt, const char* B) - { - nls_get_M1(n, out, B, salt); - } - - const char* getClientSessionKey(const char* salt, const char* B) - { - char* buf = allocateBuffer(20); - getClientSessionKey(buf, salt, B); - return buf; - } - - bool checkServerSessionKey(const char* key, const char* salt, - const char* B) - { - return (nls_check_M2(n, key, B, salt) != 0); - } - - NLS makeChangeProof(char* buf, const char* new_password, const char* salt, - const char* B) - { - return NLS(nls_account_change_proof(n, buf, new_password, B, salt)); - } - - NLS makeChangeProof(char* buf, const std::string& new_password, - const char* salt, const char* B) - { - return NLS(nls_account_change_proof(n, buf, new_password.c_str(), B, - salt)); - } - - std::pair makeChangeProof(const char* new_password, - const char* salt, const char* B) - { - char* buf = allocateBuffer(84); - NLS nls = NLS(nls_account_change_proof(n, buf, new_password, B, salt)); - return std::pair(nls, buf); - } - - std::pair makeChangeProof(const std::string& new_password, - const char* salt, const char* B) - { - return makeChangeProof(new_password.c_str(), salt, B); - } + NLS(const char* username, const char* password) : n((nls_t*) 0) + { + n = nls_init(username, password); + } + + NLS(const char* username, size_t username_length, const char* password, + size_t password_length) + { + n = nls_init_l(username, username_length, password, password_length); + } + + NLS(const std::string& username, const std::string& password) + { + n = nls_init_l(username.c_str(), username.length(), + password.c_str(), password.length()); + } + + virtual ~NLS() + { + std::vector::iterator i; + + if (n) + nls_free(n); + + for (i = blocks.begin(); i != blocks.end(); i++) { + delete [] *i; + } + } + + void getSecret(char* out, const char* salt, const char* B) + { + nls_get_S(n, out, B, salt); + } + + const char* getSecret(const char* salt, const char* B) + { + char* buf = allocateBuffer(32); + getSecret(buf, salt, B); + return buf; + } + + void getVerifier(char* out, const char* salt) + { + nls_get_v(n, out, salt); + } + + const char* getVerifier(const char* salt) + { + char* buf = allocateBuffer(32); + getVerifier(buf, salt); + return buf; + } + + void getPublicKey(char* out) + { + nls_get_A(n, out); + } + + const char* getPublicKey(void) + { + char* buf = allocateBuffer(32); + getPublicKey(buf); + return buf; + } + + void getHashedSecret(char* out, const char* secret) + { + nls_get_K(n, out, secret); + } + + const char* getHashedSecret(const char* secret) + { + char* buf = allocateBuffer(40); + getHashedSecret(buf, secret); + return buf; + } + + void getClientSessionKey(char* out, const char* salt, const char* B) + { + nls_get_M1(n, out, B, salt); + } + + const char* getClientSessionKey(const char* salt, const char* B) + { + char* buf = allocateBuffer(20); + getClientSessionKey(buf, salt, B); + return buf; + } + + bool checkServerSessionKey(const char* key, const char* salt, + const char* B) + { + return (nls_check_M2(n, key, B, salt) != 0); + } + + NLS makeChangeProof(char* buf, const char* new_password, const char* salt, + const char* B) + { + return NLS(nls_account_change_proof(n, buf, new_password, B, salt)); + } + + NLS makeChangeProof(char* buf, const std::string& new_password, + const char* salt, const char* B) + { + return NLS(nls_account_change_proof(n, buf, new_password.c_str(), B, + salt)); + } + + std::pair makeChangeProof(const char* new_password, + const char* salt, const char* B) + { + char* buf = allocateBuffer(84); + NLS nls = NLS(nls_account_change_proof(n, buf, new_password, B, salt)); + return std::pair(nls, buf); + } + + std::pair makeChangeProof(const std::string& new_password, + const char* salt, const char* B) + { + return makeChangeProof(new_password.c_str(), salt, B); + } private: - std::vector blocks; - nls_t* n; - - NLS(nls_t* nls) - { - n = nls; - } - - char* allocateBuffer(size_t length) - { - char* buf = new char[length]; - blocks.push_back(buf); - return buf; - } + std::vector blocks; + nls_t* n; + + NLS(nls_t* nls) + { + n = nls; + } + + char* allocateBuffer(size_t length) + { + char* buf = new char[length]; + blocks.push_back(buf); + return buf; + } }; #endif diff --git a/src/bncsutil/oldauth.cpp b/src/bncsutil/oldauth.cpp index bde739d..308d823 100644 --- a/src/bncsutil/oldauth.cpp +++ b/src/bncsutil/oldauth.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include // for MEXP() #include #include @@ -44,11 +44,11 @@ uint32_t serverToken, char* outBuffer) { lp[0] = clientToken; lp[1] = serverToken; calcHashBuf(intermediate, 28, outBuffer); - + #if DEBUG - bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =", - password, clientToken, serverToken); - bncsutil_debug_dump(outBuffer, 20); + bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =", + password, clientToken, serverToken); + bncsutil_debug_dump(outBuffer, 20); #endif } @@ -61,7 +61,7 @@ MEXP(void) hashPassword(const char* password, char* outBuffer) { calcHashBuf(password, std::strlen(password), outBuffer); #if DEBUG - bncsutil_debug_message_a("hashPassword(\"%s\") =", password); - bncsutil_debug_dump(outBuffer, 20); + bncsutil_debug_message_a("hashPassword(\"%s\") =", password); + bncsutil_debug_dump(outBuffer, 20); #endif } diff --git a/src/bncsutil/pe.c b/src/bncsutil/pe.c index b83e321..0c35ada 100644 --- a/src/bncsutil/pe.c +++ b/src/bncsutil/pe.c @@ -32,453 +32,453 @@ int cm_pe_load_resdir(FILE* f, uint32_t offset, cm_pe_resdir_t* dir); MEXP(cm_pe_t) cm_pe_load(const char* filename) { - cm_pe_t pe; - cm_pe_header_t* header; - cm_pe_optional_header_t* opt_header; - cm_pe_windows_header_t* win_header; - long pe_offset = 0; - size_t i; - size_t count; - - pe = (cm_pe_t) malloc(sizeof(struct cm_pe)); - if (!pe) - return (cm_pe_t) 0; - - memset(pe, 0, sizeof(struct cm_pe)); - - pe->f = fopen(filename, "r"); - if (!pe->f) { - free(pe); - return (cm_pe_t) 0; - } - - if (fseek(pe->f, 0x3CL, SEEK_SET) == -1) - goto err_trap; - - if (fread(&pe_offset, 4, 1, pe->f) != 1) - goto err_trap; - + cm_pe_t pe; + cm_pe_header_t* header; + cm_pe_optional_header_t* opt_header; + cm_pe_windows_header_t* win_header; + long pe_offset = 0; + //size_t i; + size_t count; + + pe = (cm_pe_t) malloc(sizeof(struct cm_pe)); + if (!pe) + return (cm_pe_t) 0; + + memset(pe, 0, sizeof(struct cm_pe)); + + pe->f = fopen(filename, "r"); + if (!pe->f) { + free(pe); + return (cm_pe_t) 0; + } + + if (fseek(pe->f, 0x3CL, SEEK_SET) == -1) + goto err_trap; + + if (fread(&pe_offset, 4, 1, pe->f) != 1) + goto err_trap; + #if BIG_ENDIAN - pe_offset = LSB4(pe_offset); + pe_offset = LSB4(pe_offset); #endif - - if (fseek(pe->f, pe_offset, SEEK_SET) == -1) - goto err_trap; - - if (fread(&pe->header, sizeof(cm_pe_header_t), 1, pe->f) != 1) - goto err_trap; - - header = &pe->header; + + if (fseek(pe->f, pe_offset, SEEK_SET) == -1) + goto err_trap; + + if (fread(&pe->header, sizeof(cm_pe_header_t), 1, pe->f) != 1) + goto err_trap; + + header = &pe->header; #if BIGENDIAN - /* Without regular expressions, this would've sucked. */ - header->signature = SWAP32(header->signature); - header->machine = SWAP16(header->machine); - header->section_count = SWAP16(header->section_count); - header->timestamp = SWAP32(header->timestamp); - header->symbol_table_offset = SWAP32(header->symbol_table_offset); - header->symbol_count = SWAP32(header->symbol_count); - header->optional_header_size = SWAP16(header->optional_header_size); - header->characteristics = SWAP16(header->characteristics); + /* Without regular expressions, this would've sucked. */ + header->signature = SWAP32(header->signature); + header->machine = SWAP16(header->machine); + header->section_count = SWAP16(header->section_count); + header->timestamp = SWAP32(header->timestamp); + header->symbol_table_offset = SWAP32(header->symbol_table_offset); + header->symbol_count = SWAP32(header->symbol_count); + header->optional_header_size = SWAP16(header->optional_header_size); + header->characteristics = SWAP16(header->characteristics); #endif - - if (header->optional_header_size > 0) { - if (fread(&pe->optional_header, PE_OPTIONAL_HEADER_MIN_SIZE, 1, pe->f) - != 1) - { - goto err_trap; - } - - opt_header = &pe->optional_header; - win_header = &pe->windows_header; - + + if (header->optional_header_size > 0) { + if (fread(&pe->optional_header, PE_OPTIONAL_HEADER_MIN_SIZE, 1, pe->f) + != 1) + { + goto err_trap; + } + + opt_header = &pe->optional_header; + win_header = &pe->windows_header; + #if BIGENDIAN - opt_header->magic = SWAP16(opt_header->magic); + opt_header->magic = SWAP16(opt_header->magic); #endif - - if (opt_header->magic == IMAGE_FORMAT_PE32) { - if (fread(&opt_header->data_base, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->image_base, 4, 1, pe->f) != 1) - goto err_trap; - // The 40 is not a typo. - if (fread(&win_header->section_alignment, 40, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->stack_reserve_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->stack_commit_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->heap_reserve_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->heap_commit_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->loader_flags, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->data_directory_count, 4, 1, pe->f) != 1) - goto err_trap; - } else if (opt_header->magic == IMAGE_FORMAT_PE32_PLUS) { - if (fread(win_header, sizeof(cm_pe_windows_header_t), 1, pe->f)!= 1) - goto err_trap; - } else { - goto err_trap; - } - + + if (opt_header->magic == IMAGE_FORMAT_PE32) { + if (fread(&opt_header->data_base, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->image_base, 4, 1, pe->f) != 1) + goto err_trap; + // The 40 is not a typo. + if (fread(&win_header->section_alignment, 40, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->stack_reserve_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->stack_commit_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->heap_reserve_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->heap_commit_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->loader_flags, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->data_directory_count, 4, 1, pe->f) != 1) + goto err_trap; + } else if (opt_header->magic == IMAGE_FORMAT_PE32_PLUS) { + if (fread(win_header, sizeof(cm_pe_windows_header_t), 1, pe->f)!= 1) + goto err_trap; + } else { + goto err_trap; + } + #if BIGENDIAN - opt_header->code_section_size = SWAP32(opt_header->code_section_size); - opt_header->initialized_data_size = - SWAP32(opt_header->initialized_data_size); - opt_header->uninitialized_data_size = - SWAP32(opt_header->uninitialized_data_size); - opt_header->entry_point = SWAP32(opt_header->entry_point); - opt_header->code_base = SWAP32(opt_header->code_base); - opt_header->data_base = SWAP32(opt_header->data_base); - - win_header->image_base = SWAP64(win_header->image_base); - win_header->section_alignment = SWAP32(win_header->section_alignment); - win_header->file_alignment = SWAP32(win_header->file_alignment); - win_header->major_os_version = SWAP16(win_header->major_os_version); - win_header->minor_os_version = SWAP16(win_header->minor_os_version); - win_header->major_image_version = - SWAP16(win_header->major_image_version); - win_header->minor_image_version = - SWAP16(win_header->minor_image_version); - win_header->major_subsystem_version = - SWAP16(win_header->major_subsystem_version); - win_header->minor_subsystem_version = - SWAP16(win_header->minor_subsystem_version); - win_header->reserved = SWAP32(win_header->reserved); - win_header->image_size = SWAP32(win_header->image_size); - win_header->headers_size = SWAP32(win_header->headers_size); - win_header->checksum = SWAP32(win_header->checksum); - win_header->subsystem = SWAP16(win_header->subsystem); - win_header->dll_characteristics = - SWAP16(win_header->dll_characteristics); - win_header->stack_reserve_size = SWAP64(win_header->stack_reserve_size); - win_header->stack_commit_size = SWAP64(win_header->stack_commit_size); - win_header->heap_reserve_size = SWAP64(win_header->heap_reserve_size); - win_header->heap_commit_size = SWAP64(win_header->heap_commit_size); - win_header->loader_flags = SWAP32(win_header->loader_flags); - win_header->data_directory_count = - SWAP32(win_header->data_directory_count); + opt_header->code_section_size = SWAP32(opt_header->code_section_size); + opt_header->initialized_data_size = + SWAP32(opt_header->initialized_data_size); + opt_header->uninitialized_data_size = + SWAP32(opt_header->uninitialized_data_size); + opt_header->entry_point = SWAP32(opt_header->entry_point); + opt_header->code_base = SWAP32(opt_header->code_base); + opt_header->data_base = SWAP32(opt_header->data_base); + + win_header->image_base = SWAP64(win_header->image_base); + win_header->section_alignment = SWAP32(win_header->section_alignment); + win_header->file_alignment = SWAP32(win_header->file_alignment); + win_header->major_os_version = SWAP16(win_header->major_os_version); + win_header->minor_os_version = SWAP16(win_header->minor_os_version); + win_header->major_image_version = + SWAP16(win_header->major_image_version); + win_header->minor_image_version = + SWAP16(win_header->minor_image_version); + win_header->major_subsystem_version = + SWAP16(win_header->major_subsystem_version); + win_header->minor_subsystem_version = + SWAP16(win_header->minor_subsystem_version); + win_header->reserved = SWAP32(win_header->reserved); + win_header->image_size = SWAP32(win_header->image_size); + win_header->headers_size = SWAP32(win_header->headers_size); + win_header->checksum = SWAP32(win_header->checksum); + win_header->subsystem = SWAP16(win_header->subsystem); + win_header->dll_characteristics = + SWAP16(win_header->dll_characteristics); + win_header->stack_reserve_size = SWAP64(win_header->stack_reserve_size); + win_header->stack_commit_size = SWAP64(win_header->stack_commit_size); + win_header->heap_reserve_size = SWAP64(win_header->heap_reserve_size); + win_header->heap_commit_size = SWAP64(win_header->heap_commit_size); + win_header->loader_flags = SWAP32(win_header->loader_flags); + win_header->data_directory_count = + SWAP32(win_header->data_directory_count); #endif - - if (win_header->data_directory_count > 0) { - count = win_header->data_directory_count; - pe->data_directories = (cm_pe_data_directory_t*) - calloc(sizeof(cm_pe_data_directory_t), count); - - if (!pe->data_directories) - goto err_trap; - - if (fread(pe->data_directories, sizeof(cm_pe_data_directory_t), - count, pe->f) != count) - { - goto dir_err_trap; - } - + + if (win_header->data_directory_count > 0) { + count = win_header->data_directory_count; + pe->data_directories = (cm_pe_data_directory_t*) + calloc(sizeof(cm_pe_data_directory_t), count); + + if (!pe->data_directories) + goto err_trap; + + if (fread(pe->data_directories, sizeof(cm_pe_data_directory_t), + count, pe->f) != count) + { + goto dir_err_trap; + } + #if BIGENDIAN - for (i = 0; i < count; i++) { - pe->data_directories[i].rva = - SWAP32(pe->data_directories[i].rva); - pe->data_directories[i].size = - SWAP32(pe->data_directories[i].size); - } + for (i = 0; i < count; i++) { + pe->data_directories[i].rva = + SWAP32(pe->data_directories[i].rva); + pe->data_directories[i].size = + SWAP32(pe->data_directories[i].size); + } #endif - } - - count = (size_t) header->section_count; - if (count) { - pe->sections = (cm_pe_section_t*) calloc(sizeof(cm_pe_section_t), - count); - - if (!pe->sections) - goto dir_err_trap; - - if (fread(pe->sections, sizeof(cm_pe_section_t), count, pe->f) - != count) - { - goto sect_err_trap; - } - } - + } + + count = (size_t) header->section_count; + if (count) { + pe->sections = (cm_pe_section_t*) calloc(sizeof(cm_pe_section_t), + count); + + if (!pe->sections) + goto dir_err_trap; + + if (fread(pe->sections, sizeof(cm_pe_section_t), count, pe->f) + != count) + { + goto sect_err_trap; + } + } + #if BIGENDIAN - for (i = 0; i < count; i++) { - pe->sections[i].virtual_size = SWAP32(pe->sections[i].virtual_size); - pe->sections[i].virtual_address = - SWAP32(pe->sections[i].virtual_address); - pe->sections[i].raw_data_size = - SWAP32(pe->sections[i].raw_data_size); - pe->sections[i].raw_data_offset = - SWAP32(pe->sections[i].raw_data_offset); - pe->sections[i].relocations_offset = - SWAP32(pe->sections[i].relocations_offset); - pe->sections[i].line_numbers_offset = - SWAP32(pe->sections[i].line_numbers_offset); - pe->sections[i].relocation_count = - SWAP16(pe->sections[i].relocation_count); - pe->sections[i].line_number_count = - SWAP16(pe->sections[i].line_number_count); - pe->sections[i].characteristics = - SWAP32(pe->sections[i].characteristics); - } + for (i = 0; i < count; i++) { + pe->sections[i].virtual_size = SWAP32(pe->sections[i].virtual_size); + pe->sections[i].virtual_address = + SWAP32(pe->sections[i].virtual_address); + pe->sections[i].raw_data_size = + SWAP32(pe->sections[i].raw_data_size); + pe->sections[i].raw_data_offset = + SWAP32(pe->sections[i].raw_data_offset); + pe->sections[i].relocations_offset = + SWAP32(pe->sections[i].relocations_offset); + pe->sections[i].line_numbers_offset = + SWAP32(pe->sections[i].line_numbers_offset); + pe->sections[i].relocation_count = + SWAP16(pe->sections[i].relocation_count); + pe->sections[i].line_number_count = + SWAP16(pe->sections[i].line_number_count); + pe->sections[i].characteristics = + SWAP32(pe->sections[i].characteristics); + } #endif - } - - return pe; + } + + return pe; sect_err_trap: - free(pe->sections); + free(pe->sections); dir_err_trap: - free(pe->data_directories); + free(pe->data_directories); err_trap: - fclose(pe->f); - free(pe); - return (cm_pe_t) 0; + fclose(pe->f); + free(pe); + return (cm_pe_t) 0; } MEXP(void) cm_pe_unload(cm_pe_t pe) { - if (pe->data_directories) - free(pe->data_directories); - if (pe->sections) - free(pe->sections); - if (pe->f) - fclose(pe->f); - free(pe); + if (pe->data_directories) + free(pe->data_directories); + if (pe->sections) + free(pe->sections); + if (pe->f) + fclose(pe->f); + free(pe); } MEXP(cm_pe_section_t*) cm_pe_get_section(cm_pe_t pe, const char* name) { - unsigned int i; - cm_pe_section_t* s; - uint32_t section_count = pe->header.section_count; - - if (!pe || !pe->sections) - return (cm_pe_section_t*) 0; - - for (i = 0, s = pe->sections; i < section_count; i++, s++) { - if (strcmp(s->name, name) == 0) - return s; - } - - return (cm_pe_section_t*) 0; + unsigned int i; + cm_pe_section_t* s; + uint32_t section_count = pe->header.section_count; + + if (!pe || !pe->sections) + return (cm_pe_section_t*) 0; + + for (i = 0, s = pe->sections; i < section_count; i++, s++) { + if (strcmp(s->name, name) == 0) + return s; + } + + return (cm_pe_section_t*) 0; } MEXP(cm_pe_resdir_t*) cm_pe_load_resources(cm_pe_t pe) { - cm_pe_section_t* sect; - cm_pe_resdir_t* root = (cm_pe_resdir_t*) 0; - cm_pe_resdir_t* dir; - cm_pe_resdir_t* subdirs; - cm_pe_res_t res; - cm_pe_res_t* resources; - cm_stack_t stack; - size_t i; - uint32_t base; - - // no need to check validity of pe pointer; cm_pe_get_section does this - sect = cm_pe_get_section(pe, ".rsrc"); - if (!sect) - return (cm_pe_resdir_t*) 0; - - root = (cm_pe_resdir_t*) malloc(sizeof(cm_pe_resdir_t)); - if (!root) - return (cm_pe_resdir_t*) 0; - - base = sect->raw_data_offset; - if (!cm_pe_load_resdir(pe->f, base, root)) { - free(root); - return (cm_pe_resdir_t*) 0; - } - - stack = cm_stack_create(); - if (!stack) { - free(root); - return (cm_pe_resdir_t*) 0; - } - - cm_stack_push(stack, root); - - while (dir = (cm_pe_resdir_t*) cm_stack_pop(stack)) { - while (dir->subdir_count + dir->resource_count < - dir->named_entry_count + dir->id_entry_count) - { - if (fseek(pe->f, dir->offset, SEEK_SET) == -1) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - - if (fread(&res, CM_RES_REAL_SIZE, 1, pe->f) != 1) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - - #if BIGENDIAN - res.name = SWAP4(res.name); - res.offset = SWAP4(res.offset); - #endif - if (res.offset & 0x80000000) { - // subdirectory - i = dir->subdir_count++; - subdirs = (cm_pe_resdir_t*) realloc(dir->subdirs, - sizeof(cm_pe_resdir_t) * dir->subdir_count); - if (!subdirs) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->subdirs = subdirs; - - cm_stack_push(stack, dir); - dir->offset += CM_RES_REAL_SIZE; - dir = (subdirs + i); - - res.offset &= 0x7FFFFFFF; - res.file_offset = base + res.offset; - - if (!cm_pe_load_resdir(pe->f, res.file_offset, dir)) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->name = res.name; - - cm_stack_push(stack, dir); - break; - } - // real resource - res.file_offset = base + res.offset; - i = dir->resource_count++; - resources = (cm_pe_res_t*) realloc(dir->resources, - sizeof(cm_pe_res_t) * dir->resource_count); - if (!resources) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->resources = resources; - memcpy(dir->resources + i, &res, sizeof(cm_pe_res_t)); - dir->offset += CM_RES_REAL_SIZE; - } - } - - cm_stack_destroy(stack); - return root; + cm_pe_section_t* sect; + cm_pe_resdir_t* root = (cm_pe_resdir_t*) 0; + cm_pe_resdir_t* dir; + cm_pe_resdir_t* subdirs; + cm_pe_res_t res; + cm_pe_res_t* resources; + cm_stack_t stack; + size_t i; + uint32_t base; + + // no need to check validity of pe pointer; cm_pe_get_section does this + sect = cm_pe_get_section(pe, ".rsrc"); + if (!sect) + return (cm_pe_resdir_t*) 0; + + root = (cm_pe_resdir_t*) malloc(sizeof(cm_pe_resdir_t)); + if (!root) + return (cm_pe_resdir_t*) 0; + + base = sect->raw_data_offset; + if (!cm_pe_load_resdir(pe->f, base, root)) { + free(root); + return (cm_pe_resdir_t*) 0; + } + + stack = cm_stack_create(); + if (!stack) { + free(root); + return (cm_pe_resdir_t*) 0; + } + + cm_stack_push(stack, root); + + while ( (dir = (cm_pe_resdir_t*) cm_stack_pop(stack)) ) { + while (dir->subdir_count + dir->resource_count < + dir->named_entry_count + dir->id_entry_count) + { + if (fseek(pe->f, dir->offset, SEEK_SET) == -1) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + + if (fread(&res, CM_RES_REAL_SIZE, 1, pe->f) != 1) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + + #if BIGENDIAN + res.name = SWAP4(res.name); + res.offset = SWAP4(res.offset); + #endif + if (res.offset & 0x80000000) { + // subdirectory + i = dir->subdir_count++; + subdirs = (cm_pe_resdir_t*) realloc(dir->subdirs, + sizeof(cm_pe_resdir_t) * dir->subdir_count); + if (!subdirs) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->subdirs = subdirs; + + cm_stack_push(stack, dir); + dir->offset += CM_RES_REAL_SIZE; + dir = (subdirs + i); + + res.offset &= 0x7FFFFFFF; + res.file_offset = base + res.offset; + + if (!cm_pe_load_resdir(pe->f, res.file_offset, dir)) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->name = res.name; + + cm_stack_push(stack, dir); + break; + } + // real resource + res.file_offset = base + res.offset; + i = dir->resource_count++; + resources = (cm_pe_res_t*) realloc(dir->resources, + sizeof(cm_pe_res_t) * dir->resource_count); + if (!resources) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->resources = resources; + memcpy(dir->resources + i, &res, sizeof(cm_pe_res_t)); + dir->offset += CM_RES_REAL_SIZE; + } + } + + cm_stack_destroy(stack); + return root; } MEXP(int) cm_pe_unload_resources(cm_pe_resdir_t* root) { - cm_pe_resdir_t* dir; - cm_stack_t stack; - - stack = cm_stack_create(); - if (!stack) - return 0; - - cm_stack_push(stack, root); - - while (dir = cm_stack_pop(stack)) { - if (dir->subdir_count) { - dir->subdir_count--; - cm_stack_push(stack, dir); - cm_stack_push(stack, (dir->subdirs + dir->subdir_count)); - continue; - } - - if (dir->subdirs) { - free(dir->subdirs); - dir->subdirs = (cm_pe_resdir_t*) 0; - } - - if (dir->resources) { - free(dir->resources); - dir->resource_count = 0; - } - } - - cm_stack_destroy(stack); - free(root); - return 1; + cm_pe_resdir_t* dir; + cm_stack_t stack; + + stack = cm_stack_create(); + if (!stack) + return 0; + + cm_stack_push(stack, root); + + while ( (dir = cm_stack_pop(stack)) ) { + if (dir->subdir_count) { + dir->subdir_count--; + cm_stack_push(stack, dir); + cm_stack_push(stack, (dir->subdirs + dir->subdir_count)); + continue; + } + + if (dir->subdirs) { + free(dir->subdirs); + dir->subdirs = (cm_pe_resdir_t*) 0; + } + + if (dir->resources) { + free(dir->resources); + dir->resource_count = 0; + } + } + + cm_stack_destroy(stack); + free(root); + return 1; } MEXP(int) cm_pe_fixed_version(cm_pe_t pe, cm_pe_res_t* res, - cm_pe_version_t* ver) + cm_pe_version_t* ver) { - cm_pe_section_t* sect = (pe->sections + 3); + cm_pe_section_t* sect = (pe->sections + 3); #if BIGENDIAN - uint32_t check = 0xBD04EFFE; + uint32_t check = 0xBD04EFFE; #else - uint32_t check = 0xFEEF04BD; + uint32_t check = 0xFEEF04BD; #endif - uint32_t rva; - uint32_t size; - uint32_t offset; - uint32_t align; - - if (!pe || !res || !ver) - return 0; - - if (fseek(pe->f, res->file_offset, SEEK_SET) == -1) - return 0; - if (fread(&rva, 4, 1, pe->f) != 1) - return 0; - if (fread(&size, 4, 1, pe->f) != 1) - return 0; + uint32_t rva; + uint32_t size; + uint32_t offset; + uint32_t align; + + if (!pe || !res || !ver) + return 0; + + if (fseek(pe->f, res->file_offset, SEEK_SET) == -1) + return 0; + if (fread(&rva, 4, 1, pe->f) != 1) + return 0; + if (fread(&size, 4, 1, pe->f) != 1) + return 0; #if BIGENDIAN - rva = SWAP4(rva); - size = SWAP4(size); + rva = SWAP4(rva); + size = SWAP4(size); #endif - - offset = sect->raw_data_offset + (rva - sect->virtual_address) + 0x26; - align = 4 -(offset & 0xF % 4); - if (align < 4) - offset += align; - if (fseek(pe->f, offset, SEEK_SET) == -1) - return 0; - if (fread(ver, sizeof(cm_pe_version_t), 1, pe->f) != 1) - return 0; - - if (ver->dwSignature != check) - return 0; - + + offset = sect->raw_data_offset + (rva - sect->virtual_address) + 0x26; + align = 4 -(offset & 0xF % 4); + if (align < 4) + offset += align; + if (fseek(pe->f, offset, SEEK_SET) == -1) + return 0; + if (fread(ver, sizeof(cm_pe_version_t), 1, pe->f) != 1) + return 0; + + if (ver->dwSignature != check) + return 0; + #if BIGENDIAN - ver->dwSignature = SWAP32(ver->dwSignature); - ver->dwStrucVersion = SWAP32(ver->dwStrucVersion); - ver->dwFileVersionMS = SWAP32(ver->dwFileVersionMS); - ver->dwFileVersionLS = SWAP32(ver->dwFileVersionLS); - ver->dwProductVersionMS = SWAP32(ver->dwProductVersionMS); - ver->dwProductVersionLS = SWAP32(ver->dwProductVersionLS); - ver->dwFileFlagsMask = SWAP32(ver->dwFileFlagsMask); - ver->dwFileFlags = SWAP32(ver->dwFileFlags); - ver->dwFileOS = SWAP32(ver->dwFileOS); - ver->dwFileType = SWAP32(ver->dwFileType); - ver->dwFileSubtype = SWAP32(ver->dwFileSubtype); - ver->dwFileDateMS = SWAP32(ver->dwFileDateMS); - ver->dwFileDateLS = SWAP32(ver->dwFileDateLS); + ver->dwSignature = SWAP32(ver->dwSignature); + ver->dwStrucVersion = SWAP32(ver->dwStrucVersion); + ver->dwFileVersionMS = SWAP32(ver->dwFileVersionMS); + ver->dwFileVersionLS = SWAP32(ver->dwFileVersionLS); + ver->dwProductVersionMS = SWAP32(ver->dwProductVersionMS); + ver->dwProductVersionLS = SWAP32(ver->dwProductVersionLS); + ver->dwFileFlagsMask = SWAP32(ver->dwFileFlagsMask); + ver->dwFileFlags = SWAP32(ver->dwFileFlags); + ver->dwFileOS = SWAP32(ver->dwFileOS); + ver->dwFileType = SWAP32(ver->dwFileType); + ver->dwFileSubtype = SWAP32(ver->dwFileSubtype); + ver->dwFileDateMS = SWAP32(ver->dwFileDateMS); + ver->dwFileDateLS = SWAP32(ver->dwFileDateLS); #endif - - return 1; + + return 1; } int cm_pe_load_resdir(FILE* f, uint32_t offset, cm_pe_resdir_t* dir) { - memset(dir, 0, sizeof(cm_pe_resdir_t)); - - if (fseek(f, offset, SEEK_SET) == -1) - return 0; - - if (fread(dir, 16, 1, f) != 1) - return 0; - + memset(dir, 0, sizeof(cm_pe_resdir_t)); + + if (fseek(f, offset, SEEK_SET) == -1) + return 0; + + if (fread(dir, 16, 1, f) != 1) + return 0; + #if BIGENDIAN - dir->characteristics = SWAP32(dir->characteristics); - dir->timestamp = SWAP32(dir->timestamp); - dir->major_version = SWAP16(dir->major_version); - dir->minor_version = SWAP16(dir->minor_version); - dir->named_entry_count = SWAP16(dir->named_entry_count); - dir->id_entry_count = SWAP16(dir->id_entry_count); + dir->characteristics = SWAP32(dir->characteristics); + dir->timestamp = SWAP32(dir->timestamp); + dir->major_version = SWAP16(dir->major_version); + dir->minor_version = SWAP16(dir->minor_version); + dir->named_entry_count = SWAP16(dir->named_entry_count); + dir->id_entry_count = SWAP16(dir->id_entry_count); #endif - - dir->offset = (uint32_t) ftell(f); - - return 1; + + dir->offset = (uint32_t) ftell(f); + + return 1; } diff --git a/src/bncsutil/pe.h b/src/bncsutil/pe.h index 1795a10..9ff28d6 100644 --- a/src/bncsutil/pe.h +++ b/src/bncsutil/pe.h @@ -34,135 +34,135 @@ extern "C" { #endif typedef struct cm_pe_header { - uint32_t signature; - uint16_t machine; // IMAGE_FILE_MACHINE_* - uint16_t section_count; - uint32_t timestamp; - uint32_t symbol_table_offset; - uint32_t symbol_count; - uint16_t optional_header_size; - uint16_t characteristics; + uint32_t signature; + uint16_t machine; // IMAGE_FILE_MACHINE_* + uint16_t section_count; + uint32_t timestamp; + uint32_t symbol_table_offset; + uint32_t symbol_count; + uint16_t optional_header_size; + uint16_t characteristics; } cm_pe_header_t; -#define IMAGE_FORMAT_PE32 0x10B -#define IMAGE_FORMAT_PE32_PLUS 0x20B +#define IMAGE_FORMAT_PE32 0x10B +#define IMAGE_FORMAT_PE32_PLUS 0x20B typedef struct cm_pe_optional_header { - uint16_t magic; // image format (PE32/PE32+) - uint8_t major_linker_version; - uint8_t minor_linker_version; - uint32_t code_section_size; - uint32_t initialized_data_size; - uint32_t uninitialized_data_size; - uint32_t entry_point; - uint32_t code_base; - uint32_t data_base; // not present in PE32+! + uint16_t magic; // image format (PE32/PE32+) + uint8_t major_linker_version; + uint8_t minor_linker_version; + uint32_t code_section_size; + uint32_t initialized_data_size; + uint32_t uninitialized_data_size; + uint32_t entry_point; + uint32_t code_base; + uint32_t data_base; // not present in PE32+! } cm_pe_optional_header_t; #define PE_OPTIONAL_HEADER_MIN_SIZE (sizeof(cm_pe_optional_header_t) - 4) typedef struct cm_pe_windows_header { - uint64_t image_base; - uint32_t section_alignment; - uint32_t file_alignment; - uint16_t major_os_version; - uint16_t minor_os_version; - uint16_t major_image_version; - uint16_t minor_image_version; - uint16_t major_subsystem_version; - uint16_t minor_subsystem_version; - uint32_t reserved; - uint32_t image_size; - uint32_t headers_size; - uint32_t checksum; - uint16_t subsystem; - uint16_t dll_characteristics; - uint64_t stack_reserve_size; - uint64_t stack_commit_size; - uint64_t heap_reserve_size; - uint64_t heap_commit_size; - uint32_t loader_flags; - uint32_t data_directory_count; + uint64_t image_base; + uint32_t section_alignment; + uint32_t file_alignment; + uint16_t major_os_version; + uint16_t minor_os_version; + uint16_t major_image_version; + uint16_t minor_image_version; + uint16_t major_subsystem_version; + uint16_t minor_subsystem_version; + uint32_t reserved; + uint32_t image_size; + uint32_t headers_size; + uint32_t checksum; + uint16_t subsystem; + uint16_t dll_characteristics; + uint64_t stack_reserve_size; + uint64_t stack_commit_size; + uint64_t heap_reserve_size; + uint64_t heap_commit_size; + uint32_t loader_flags; + uint32_t data_directory_count; } cm_pe_windows_header_t; typedef struct cm_pe_data_directory { - uint32_t rva; - uint32_t size; + uint32_t rva; + uint32_t size; } cm_pe_data_directory_t; typedef struct cm_pe_section { - char name[8]; - uint32_t virtual_size; - uint32_t virtual_address; - uint32_t raw_data_size; - uint32_t raw_data_offset; - uint32_t relocations_offset; - uint32_t line_numbers_offset; - uint16_t relocation_count; - uint16_t line_number_count; - uint32_t characteristics; + char name[8]; + uint32_t virtual_size; + uint32_t virtual_address; + uint32_t raw_data_size; + uint32_t raw_data_offset; + uint32_t relocations_offset; + uint32_t line_numbers_offset; + uint16_t relocation_count; + uint16_t line_number_count; + uint32_t characteristics; } cm_pe_section_t; -typedef struct VS_FIXEDFILEINFO { - uint32_t dwSignature; - uint32_t dwStrucVersion; - uint32_t dwFileVersionMS; - uint32_t dwFileVersionLS; - union { - struct { - uint32_t dwProductVersionMS; - uint32_t dwProductVersionLS; - }; - uint64_t qwProductVersion; - }; - uint32_t dwFileFlagsMask; - uint32_t dwFileFlags; - uint32_t dwFileOS; - uint32_t dwFileType; - uint32_t dwFileSubtype; - union { - struct { - uint32_t dwFileDateMS; - uint32_t dwFileDateLS; - }; - uint64_t qwFileDate; - }; +typedef struct VS_FIXEDFILEINFO { + uint32_t dwSignature; + uint32_t dwStrucVersion; + uint32_t dwFileVersionMS; + uint32_t dwFileVersionLS; + union { + struct { + uint32_t dwProductVersionMS; + uint32_t dwProductVersionLS; + }; + uint64_t qwProductVersion; + }; + uint32_t dwFileFlagsMask; + uint32_t dwFileFlags; + uint32_t dwFileOS; + uint32_t dwFileType; + uint32_t dwFileSubtype; + union { + struct { + uint32_t dwFileDateMS; + uint32_t dwFileDateLS; + }; + uint64_t qwFileDate; + }; } cm_pe_version_t; typedef struct cm_pe_resource { - uint32_t name; - uint32_t offset; - uint32_t file_offset; + uint32_t name; + uint32_t offset; + uint32_t file_offset; } cm_pe_res_t; -#define CM_RES_REAL_SIZE 8 +#define CM_RES_REAL_SIZE 8 typedef struct cm_pe_resdir { - uint32_t characteristics; - uint32_t timestamp; - uint16_t major_version; - uint16_t minor_version; - uint16_t named_entry_count; - uint16_t id_entry_count; - - size_t subdir_count; - struct cm_pe_resdir* subdirs; - size_t resource_count; - cm_pe_res_t* resources; - - uint32_t offset; - uint32_t name; + uint32_t characteristics; + uint32_t timestamp; + uint16_t major_version; + uint16_t minor_version; + uint16_t named_entry_count; + uint16_t id_entry_count; + + size_t subdir_count; + struct cm_pe_resdir* subdirs; + size_t resource_count; + cm_pe_res_t* resources; + + uint32_t offset; + uint32_t name; } cm_pe_resdir_t; typedef struct cm_pe { - FILE* f; - cm_pe_header_t header; - cm_pe_optional_header_t optional_header; - cm_pe_windows_header_t windows_header; - cm_pe_data_directory_t* data_directories; - cm_pe_section_t* sections; + FILE* f; + cm_pe_header_t header; + cm_pe_optional_header_t optional_header; + cm_pe_windows_header_t windows_header; + cm_pe_data_directory_t* data_directories; + cm_pe_section_t* sections; } *cm_pe_t; -#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 #define IMAGE_FILE_MACHINE_ALPHA 0x184 #define IMAGE_FILE_MACHINE_ARM 0x1c0 #define IMAGE_FILE_MACHINE_ALPHA64 0x284 @@ -171,7 +171,7 @@ typedef struct cm_pe { #define IMAGE_FILE_MACHINE_M68K 0x268 #define IMAGE_FILE_MACHINE_MIPS16 0x266 #define IMAGE_FILE_MACHINE_MIPSFPU 0x366 -#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 #define IMAGE_FILE_MACHINE_POWERPC 0x1f0 #define IMAGE_FILE_MACHINE_R3000 0x162 #define IMAGE_FILE_MACHINE_R4000 0x166 @@ -185,7 +185,7 @@ MEXP(void) cm_pe_unload(cm_pe_t pe); MEXP(cm_pe_resdir_t*) cm_pe_load_resources(cm_pe_t pe); MEXP(int) cm_pe_unload_resources(cm_pe_resdir_t* dir); MEXP(int) cm_pe_fixed_version(cm_pe_t pe, cm_pe_res_t* res, - cm_pe_version_t* ver); + cm_pe_version_t* ver); #ifdef __cplusplus } diff --git a/src/bncsutil/sha1.h b/src/bncsutil/sha1.h index 23a3452..e7753d4 100644 --- a/src/bncsutil/sha1.h +++ b/src/bncsutil/sha1.h @@ -74,7 +74,7 @@ int SHA1Input( SHA1Context *, unsigned int); int SHA1Result( SHA1Context *, uint8_t Message_Digest[SHA1HashSize]); - + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/bncsutil/stack.c b/src/bncsutil/stack.c index 1b37f6d..0525209 100644 --- a/src/bncsutil/stack.c +++ b/src/bncsutil/stack.c @@ -23,7 +23,7 @@ * Boston, MA 02111-1307 USA */ -/** +/* * Mule Server * Copyright (c) 2004-2006 Eric Naeseth. * @@ -33,81 +33,81 @@ #include #include - + cm_stack_t cm_stack_create() { - cm_stack_t stack = (cm_stack_t) calloc(1, sizeof(struct cm_stack)); - if (!stack) - return (cm_stack_t) 0; - return stack; + cm_stack_t stack = (cm_stack_t) calloc(1, sizeof(struct cm_stack)); + if (!stack) + return (cm_stack_t) 0; + return stack; } void cm_stack_destroy(cm_stack_t stack) { - cm_stack_node_t* node; - cm_stack_node_t* next; - - if (!stack) - return; - - node = stack->top; - - while (node) { - next = node->next; - free(node); - node = next; - } - - free(stack); + cm_stack_node_t* node; + cm_stack_node_t* next; + + if (!stack) + return; + + node = stack->top; + + while (node) { + next = node->next; + free(node); + node = next; + } + + free(stack); } void cm_stack_push(cm_stack_t stack, void* item) { - cm_stack_node_t* new_node; - - if (!stack || !item) - return; - - new_node = (cm_stack_node_t*) malloc(sizeof(cm_stack_node_t)); - if (!new_node) - return; - new_node->next = stack->top; - new_node->value = item; - - stack->size++; - - stack->top = new_node; + cm_stack_node_t* new_node; + + if (!stack || !item) + return; + + new_node = (cm_stack_node_t*) malloc(sizeof(cm_stack_node_t)); + if (!new_node) + return; + new_node->next = stack->top; + new_node->value = item; + + stack->size++; + + stack->top = new_node; } void* cm_stack_pop(cm_stack_t stack) { - cm_stack_node_t* next; - void* value; - - if (!stack || !stack->top) - return (void*) 0; - - next = stack->top->next; - value = stack->top->value; - free(stack->top); - - stack->top = next; - stack->size--; - return value; + cm_stack_node_t* next; + void* value; + + if (!stack || !stack->top) + return (void*) 0; + + next = stack->top->next; + value = stack->top->value; + free(stack->top); + + stack->top = next; + stack->size--; + return value; } void* cm_stack_peek(cm_stack_t stack) { - if (!stack || !stack->top) - return (void*) 0; - - return stack->top->value; + if (!stack || !stack->top) + return (void*) 0; + + return stack->top->value; } unsigned int cm_stack_size(cm_stack_t stack) { - if (!stack) - return 0; - - return stack->size; + if (!stack) + return 0; + + return stack->size; } diff --git a/src/bncsutil/stack.h b/src/bncsutil/stack.h index 882b075..82a0ba5 100644 --- a/src/bncsutil/stack.h +++ b/src/bncsutil/stack.h @@ -23,7 +23,7 @@ * Boston, MA 02111-1307 USA */ -/** +/* * Mule Server * Copyright (c) 2004-2006 Eric Naeseth. * @@ -35,13 +35,13 @@ #define CM_STACK_H_INCLUDED 1 typedef struct cm_stack_node { - void* value; - struct cm_stack_node* next; + void* value; + struct cm_stack_node* next; } cm_stack_node_t; typedef struct cm_stack { - unsigned int size; - cm_stack_node_t* top; + unsigned int size; + cm_stack_node_t* top; } *cm_stack_t; cm_stack_t cm_stack_create(); diff --git a/vc8_build/BNCSutil.sln b/vc8_build/BNCSutil.sln deleted file mode 100644 index fc19784..0000000 --- a/vc8_build/BNCSutil.sln +++ /dev/null @@ -1,19 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BNCSutil", "BNCSutil.vcproj", "{CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Debug|Win32.ActiveCfg = Debug|Win32 - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Debug|Win32.Build.0 = Debug|Win32 - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Release|Win32.ActiveCfg = Release|Win32 - {CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/vc8_build/BNCSutil.vcproj b/vc8_build/BNCSutil.vcproj index ce6bfa0..8c04042 100644 --- a/vc8_build/BNCSutil.vcproj +++ b/vc8_build/BNCSutil.vcproj @@ -1,404 +1,626 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + ProjectType="Visual C++" + Version="9.00" + Name="BNCSutil" + ProjectGUID="{CFB9AEE6-C0BB-49B0-B0F5-F564975202B8}" + RootNamespace="BNCSutil" + Keyword="Win32Proj" + TargetFrameworkVersion="131072" + > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/vc8_build/BNCSutil1.aps b/vc8_build/BNCSutil1.aps deleted file mode 100644 index a042a20ca4392a963b194d16f036e9875c47b5de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33780 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 Ef6PV#L;wH) diff --git a/vc8_build/BNCSutil1.rc b/vc8_build/BNCSutil1.rc deleted file mode 100644 index 8dd58cc..0000000 --- a/vc8_build/BNCSutil1.rc +++ /dev/null @@ -1,102 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource1.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource1.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,2,0,0 - PRODUCTVERSION 1,2,0,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x2L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "CompanyName", "Cloaked" - VALUE "FileDescription", "BNCSutil Library" - VALUE "FileVersion", "1, 2, 0, 0" - VALUE "InternalName", "BNCSutil" - VALUE "LegalCopyright", "Copyright © 2004-2006 Eric Naeseth." - VALUE "OriginalFilename", "bncsutil.dll" - VALUE "ProductName", " BNCSutil Library" - VALUE "ProductVersion", "1, 2, 0, 0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/vc8_build/bncsutil.def b/vc8_build/bncsutil.def index d071cb0..32db61d 100644 --- a/vc8_build/bncsutil.def +++ b/vc8_build/bncsutil.def @@ -1,52 +1,45 @@ -LIBRARY BNCSutil +LIBRARY BNCSutil VERSION 1.1 EXPORTS - bncsutil_getVersion=_bncsutil_getVersion@0 @1 - bncsutil_getVersionString=_bncsutil_getVersionString@4 @2 + bncsutil_getVersion=_bncsutil_getVersion@0 @1 + bncsutil_getVersionString=_bncsutil_getVersionString@4 @2 + + calcHashBuf=_calcHashBuf@12 @3 + doubleHashPassword=_doubleHashPassword@16 @4 + hashPassword=_hashPassword@8 @5 + + kd_quick=_kd_quick@28 + kd_init=_kd_init@0 @6 + kd_create=_kd_create@8 @7 + kd_free=_kd_free@4 @8 + kd_val2Length=_kd_val2Length@4 @9 + kd_product=_kd_product@4 @10 + kd_val1=_kd_val1@4 @11 + kd_val2=_kd_val2@4 @12 + kd_longVal2=_kd_longVal2@8 @13 + kd_calculateHash=_kd_calculateHash@12 @14 + kd_getHash=_kd_getHash@8 @15 + kd_isValid=_kd_isValid@4 @16 - calcHashBuf=_calcHashBuf@12 @3 - doubleHashPassword=_doubleHashPassword@16 @4 - hashPassword=_hashPassword@8 @5 + checkRevision=_checkRevision@20 @17 + checkRevisionFlat=_checkRevisionFlat@24 @18 + getExeInfo=_getExeInfo@20 @19 - kd_quick=_kd_quick@28 - kd_init=_kd_init@0 @6 - kd_create=_kd_create@8 @7 - kd_free=_kd_free@4 @8 - kd_val2Length=_kd_val2Length@4 @9 - kd_product=_kd_product@4 @10 - kd_val1=_kd_val1@4 @11 - kd_val2=_kd_val2@4 @12 - kd_longVal2=_kd_longVal2@8 @13 - kd_calculateHash=_kd_calculateHash@12 @14 - kd_getHash=_kd_getHash@8 @15 - kd_isValid=_kd_isValid@4 @16 - - checkRevision=_checkRevision@20 @17 - checkRevisionFlat=_checkRevisionFlat@24 @18 - getExeInfo=_getExeInfo@20 @19 - - extractMPQNumber=_extractMPQNumber@4 @20 - - nls_account_create=_nls_account_create@12 @21 - nls_account_logon=_nls_account_logon@12 @22 - nls_free=_nls_free@4 @23 - nls_get_A=_nls_get_A@8 @24 - nls_get_K=_nls_get_K@12 @25 - nls_get_M1=_nls_get_M1@16 @26 - nls_get_S=_nls_get_S@16 @27 - nls_get_v=_nls_get_v@12 @28 - nls_init=_nls_init@8 @29 - nls_init_l=_nls_init_l@16 @30 - nls_reinit=_nls_reinit@12 @31 - nls_reinit_l=_nls_reinit_l@20 @32 - nls_check_M2=_nls_check_M2@16 @33 - nls_check_signature=_nls_check_signature@8 @34 - nls_account_change_proof=_nls_account_change_proof@20 @35 - - bncsutil_debug_message=_bncsutil_debug_message@4 @36 - bncsutil_debug_dump=_bncsutil_debug_dump@8 @37 - bncsutil_print_dump=_bncsutil_print_dump@12 @38 - bncsutil_print_dump_win=_bncsutil_print_dump_win@12 @39 - bncsutil_debug_status=_bncsutil_debug_status@0 @40 - bncsutil_set_debug_status=_bncsutil_set_debug_status@4 @41 - bncsutil_internal_debug_messages=_bncsutil_internal_debug_messages@0 @42 + extractMPQNumber=_extractMPQNumber@4 @20 + + nls_account_create=_nls_account_create@12 @21 + nls_account_logon=_nls_account_logon@12 @22 + nls_free=_nls_free@4 @23 + nls_get_A=_nls_get_A@8 @24 + nls_get_K=_nls_get_K@12 @25 + nls_get_M1=_nls_get_M1@16 @26 + nls_get_S=_nls_get_S@16 @27 + nls_get_v=_nls_get_v@12 @28 + nls_init=_nls_init@8 @29 + nls_init_l=_nls_init_l@16 @30 + nls_reinit=_nls_reinit@12 @31 + nls_reinit_l=_nls_reinit_l@20 @32 + nls_check_M2=_nls_check_M2@16 @33 + nls_check_signature=_nls_check_signature@8 @34 + nls_account_change_proof=_nls_account_change_proof@20 @35 + \ No newline at end of file diff --git a/vc8_build/bncsutil.rc b/vc8_build/bncsutil.rc deleted file mode 100644 index 3406a30..0000000 --- a/vc8_build/bncsutil.rc +++ /dev/null @@ -1,101 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#include "afxres.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,1,0 - PRODUCTVERSION 1,3,1,0 - FILEFLAGSMASK 0x17L -#ifdef _DEBUG - FILEFLAGS 0x1L -#else - FILEFLAGS 0x0L -#endif - FILEOS 0x4L - FILETYPE 0x0L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "BNCSutil Logon Library" - VALUE "CompanyName", "ionws.com" - VALUE "FileDescription", "BNCSutil Logon Library" - VALUE "FileVersion", "1, 3, 1, 0" - VALUE "InternalName", "bncsutil" - VALUE "LegalCopyright", "Copyright © 2004-2006 Eric Naeseth." - VALUE "OriginalFilename", "BNCSutil.dll" - VALUE "ProductName", "BNCSutil Logon Library" - VALUE "ProductVersion", "1, 3, 1, 0" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" -END - -2 TEXTINCLUDE -BEGIN - "#include ""afxres.h""\r\n" -END - -#endif // APSTUDIO_INVOKED - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/vc8_build/gmp.lib b/vc8_build/gmp.lib new file mode 100644 index 0000000000000000000000000000000000000000..b5e2d63b077ec866153a8b4cdb5a72c92cf976b0 GIT binary patch literal 1659142 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

~ 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�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≺7^S%4~K@nl1(N!Y+v=Fl3~g+)B+E3 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

cCkZ2d#gSE2iWGNZ=9uEDB-)6SPu-&ho9A!qi{x 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 literal 0 HcmV?d00001 diff --git a/vc8_build/manual_link.bat b/vc8_build/manual_link.bat deleted file mode 100644 index 50d27d6..0000000 --- a/vc8_build/manual_link.bat +++ /dev/null @@ -1 +0,0 @@ -LINK /OUT:"Release/BNCSutil.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:".." /DLL /DEF:"bncsutil.def" /DEBUG /PDB:"Release/BNCSutil.pdb" /SUBSYSTEM:WINDOWS /OPT:REF /OPT:ICF /IMPLIB:"Release/BNCSutil.lib" /MACHINE:X86 kernel32.lib version.lib gmp.lib Release\BNCSutil1.res Release\*.obj ..\manual_build\nls.o user32.lib \ No newline at end of file diff --git a/vc8_build/resource.h b/vc8_build/resource.h deleted file mode 100644 index 8a67e0c..0000000 --- a/vc8_build/resource.h +++ /dev/null @@ -1,1210 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by bncsutil.rc -// -#define SW_HIDE 0 -#define HIDE_WINDOW 0 -#define WM_NULL 0x0000 -#define WA_INACTIVE 0 -#define HTNOWHERE 0 -#define SMTO_NORMAL 0x0000 -#define ICON_SMALL 0 -#define SIZE_RESTORED 0 -#define BN_CLICKED 0 -#define BST_UNCHECKED 0x0000 -#define HDS_HORZ 0x0000 -#define TBS_HORZ 0x0000 -#define TBS_BOTTOM 0x0000 -#define TBS_RIGHT 0x0000 -#define LVS_ICON 0x0000 -#define LVS_ALIGNTOP 0x0000 -#define TCS_TABS 0x0000 -#define TCS_SINGLELINE 0x0000 -#define TCS_RIGHTJUSTIFY 0x0000 -#define DTS_SHORTDATEFORMAT 0x0000 -#define PGS_VERT 0x00000000 -#define LANG_NEUTRAL 0x00 -#define SUBLANG_NEUTRAL 0x00 -#define SORT_DEFAULT 0x0 -#define SORT_JAPANESE_XJIS 0x0 -#define SORT_CHINESE_BIG5 0x0 -#define SORT_CHINESE_PRCP 0x0 -#define SORT_KOREAN_KSC 0x0 -#define SORT_HUNGARIAN_DEFAULT 0x0 -#define SORT_GEORGIAN_TRADITIONAL 0x0 -#define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 -#define MINIMUM_RESERVED_MANIFEST_RESOURCE_ID 1 -#define SW_SHOWNORMAL 1 -#define SW_NORMAL 1 -#define SHOW_OPENWINDOW 1 -#define SW_PARENTCLOSING 1 -#define VK_LBUTTON 0x01 -#define WM_CREATE 0x0001 -#define WA_ACTIVE 1 -#define PWR_OK 1 -#define PWR_SUSPENDREQUEST 1 -#define NFR_ANSI 1 -#define UIS_SET 1 -#define UISF_HIDEFOCUS 0x1 -#define XBUTTON1 0x0001 -#define WMSZ_LEFT 1 -#define HTCLIENT 1 -#define SMTO_BLOCK 0x0001 -#define MA_ACTIVATE 1 -#define ICON_BIG 1 -#define SIZE_MINIMIZED 1 -#define MK_LBUTTON 0x0001 -#define TME_HOVER 0x00000001 -#define CS_VREDRAW 0x0001 -#define CF_TEXT 1 -#define IDOK 1 -#define BN_PAINT 1 -#define BST_CHECKED 0x0001 -#define TTS_ALWAYSTIP 0x01 -#define TBS_AUTOTICKS 0x0001 -#define UDS_WRAP 0x0001 -#define PBS_SMOOTH 0x01 -#define LVS_REPORT 0x0001 -#define TVS_HASBUTTONS 0x0001 -#define TCS_SCROLLOPPOSITE 0x0001 -#define ACS_CENTER 0x0001 -#define MCS_DAYSTATE 0x0001 -#define DTS_UPDOWN 0x0001 -#define PGS_HORZ 0x00000001 -#define NFS_EDIT 0x0001 -#define LANG_ARABIC 0x01 -#define SUBLANG_DEFAULT 0x01 -#define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 -#define SUBLANG_AZERI_LATIN 0x01 -#define SUBLANG_CHINESE_TRADITIONAL 0x01 -#define SUBLANG_DUTCH 0x01 -#define SUBLANG_ENGLISH_US 0x01 -#define SUBLANG_FRENCH 0x01 -#define SUBLANG_GERMAN 0x01 -#define SUBLANG_ITALIAN 0x01 -#define SUBLANG_KOREAN 0x01 -#define SUBLANG_LITHUANIAN 0x01 -#define SUBLANG_MALAY_MALAYSIA 0x01 -#define SUBLANG_NORWEGIAN_BOKMAL 0x01 -#define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 -#define SUBLANG_SPANISH 0x01 -#define SUBLANG_SWEDISH 0x01 -#define SUBLANG_URDU_PAKISTAN 0x01 -#define SUBLANG_UZBEK_LATIN 0x01 -#define SORT_JAPANESE_UNICODE 0x1 -#define SORT_CHINESE_UNICODE 0x1 -#define SORT_KOREAN_UNICODE 0x1 -#define SORT_GERMAN_PHONE_BOOK 0x1 -#define SORT_HUNGARIAN_TECHNICAL 0x1 -#define SORT_GEORGIAN_MODERN 0x1 -#define VS_VERSION_INFO 1 -#define VFFF_ISSHAREDFILE 0x0001 -#define VFF_CURNEDEST 0x0001 -#define VIFF_FORCEINSTALL 0x0001 -#define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2 -#define SW_SHOWMINIMIZED 2 -#define SHOW_ICONWINDOW 2 -#define SW_OTHERZOOM 2 -#define VK_RBUTTON 0x02 -#define WM_DESTROY 0x0002 -#define WA_CLICKACTIVE 2 -#define PWR_SUSPENDRESUME 2 -#define NFR_UNICODE 2 -#define UIS_CLEAR 2 -#define UISF_HIDEACCEL 0x2 -#define XBUTTON2 0x0002 -#define WMSZ_RIGHT 2 -#define HTCAPTION 2 -#define SMTO_ABORTIFHUNG 0x0002 -#define MA_ACTIVATEANDEAT 2 -#define SIZE_MAXIMIZED 2 -#define MK_RBUTTON 0x0002 -#define TME_LEAVE 0x00000002 -#define CS_HREDRAW 0x0002 -#define CF_BITMAP 2 -#define IDCANCEL 2 -#define BN_HILITE 2 -#define BST_INDETERMINATE 0x0002 -#define HDS_BUTTONS 0x0002 -#define TTS_NOPREFIX 0x02 -#define TBS_VERT 0x0002 -#define UDS_SETBUDDYINT 0x0002 -#define LVS_SMALLICON 0x0002 -#define TVS_HASLINES 0x0002 -#define TCS_BOTTOM 0x0002 -#define TCS_RIGHT 0x0002 -#define ACS_TRANSPARENT 0x0002 -#define MCS_MULTISELECT 0x0002 -#define DTS_SHOWNONE 0x0002 -#define PGS_AUTOSCROLL 0x00000002 -#define NFS_STATIC 0x0002 -#define LANG_BULGARIAN 0x02 -#define SUBLANG_SYS_DEFAULT 0x02 -#define SUBLANG_ARABIC_IRAQ 0x02 -#define SUBLANG_AZERI_CYRILLIC 0x02 -#define SUBLANG_CHINESE_SIMPLIFIED 0x02 -#define SUBLANG_DUTCH_BELGIAN 0x02 -#define SUBLANG_ENGLISH_UK 0x02 -#define SUBLANG_FRENCH_BELGIAN 0x02 -#define SUBLANG_GERMAN_SWISS 0x02 -#define SUBLANG_ITALIAN_SWISS 0x02 -#define SUBLANG_KASHMIRI_INDIA 0x02 -#define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 -#define SUBLANG_NEPALI_INDIA 0x02 -#define SUBLANG_NORWEGIAN_NYNORSK 0x02 -#define SUBLANG_PORTUGUESE 0x02 -#define SUBLANG_SERBIAN_LATIN 0x02 -#define SUBLANG_SPANISH_MEXICAN 0x02 -#define SUBLANG_SWEDISH_FINLAND 0x02 -#define SUBLANG_URDU_INDIA 0x02 -#define SUBLANG_UZBEK_CYRILLIC 0x02 -#define SORT_CHINESE_PRC 0x2 -#define VFF_FILEINUSE 0x0002 -#define VIFF_DONTDELETEOLD 0x0002 -#define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3 -#define SW_SHOWMAXIMIZED 3 -#define SW_MAXIMIZE 3 -#define SHOW_FULLSCREEN 3 -#define SW_PARENTOPENING 3 -#define VK_CANCEL 0x03 -#define WM_MOVE 0x0003 -#define PWR_CRITICALRESUME 3 -#define NF_QUERY 3 -#define UIS_INITIALIZE 3 -#define WMSZ_TOP 3 -#define HTSYSMENU 3 -#define MA_NOACTIVATE 3 -#define SIZE_MAXSHOW 3 -#define CF_METAFILEPICT 3 -#define IDABORT 3 -#define BN_UNHILITE 3 -#define LVS_LIST 0x0003 -#define LVS_TYPEMASK 0x0003 -#define LANG_CATALAN 0x03 -#define SUBLANG_ARABIC_EGYPT 0x03 -#define SUBLANG_CHINESE_HONGKONG 0x03 -#define SUBLANG_ENGLISH_AUS 0x03 -#define SUBLANG_FRENCH_CANADIAN 0x03 -#define SUBLANG_GERMAN_AUSTRIAN 0x03 -#define SUBLANG_SERBIAN_CYRILLIC 0x03 -#define SUBLANG_SPANISH_MODERN 0x03 -#define SORT_CHINESE_BOPOMOFO 0x3 -#define SW_SHOWNOACTIVATE 4 -#define SHOW_OPENNOACTIVATE 4 -#define SW_OTHERUNZOOM 4 -#define VK_MBUTTON 0x04 -#define NF_REQUERY 4 -#define WMSZ_TOPLEFT 4 -#define HTGROWBOX 4 -#define MA_NOACTIVATEANDEAT 4 -#define SIZE_MAXHIDE 4 -#define MK_SHIFT 0x0004 -#define CF_SYLK 4 -#define IDRETRY 4 -#define BN_DISABLE 4 -#define BST_PUSHED 0x0004 -#define HDS_HOTTRACK 0x0004 -#define TBS_TOP 0x0004 -#define TBS_LEFT 0x0004 -#define UDS_ALIGNRIGHT 0x0004 -#define PBS_VERTICAL 0x04 -#define LVS_SINGLESEL 0x0004 -#define TVS_LINESATROOT 0x0004 -#define TCS_MULTISELECT 0x0004 -#define ACS_AUTOPLAY 0x0004 -#define MCS_WEEKNUMBERS 0x0004 -#define DTS_LONGDATEFORMAT 0x0004 -#define PGS_DRAGNDROP 0x00000004 -#define NFS_LISTCOMBO 0x0004 -#define LANG_CHINESE 0x04 -#define SUBLANG_ARABIC_LIBYA 0x04 -#define SUBLANG_CHINESE_SINGAPORE 0x04 -#define SUBLANG_ENGLISH_CAN 0x04 -#define SUBLANG_FRENCH_SWISS 0x04 -#define SUBLANG_GERMAN_LUXEMBOURG 0x04 -#define SUBLANG_SPANISH_GUATEMALA 0x04 -#define VFF_BUFFTOOSMALL 0x0004 -#define SW_SHOW 5 -#define VK_XBUTTON1 0x05 -#define WM_SIZE 0x0005 -#define WMSZ_TOPRIGHT 5 -#define HTMENU 5 -#define CF_DIF 5 -#define IDIGNORE 5 -#define BN_DOUBLECLICKED 5 -#define LANG_CZECH 0x05 -#define SUBLANG_ARABIC_ALGERIA 0x05 -#define SUBLANG_CHINESE_MACAU 0x05 -#define SUBLANG_ENGLISH_NZ 0x05 -#define SUBLANG_FRENCH_LUXEMBOURG 0x05 -#define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 -#define SUBLANG_SPANISH_COSTA_RICA 0x05 -#define SW_MINIMIZE 6 -#define VK_XBUTTON2 0x06 -#define WM_ACTIVATE 0x0006 -#define WMSZ_BOTTOM 6 -#define HTHSCROLL 6 -#define CF_TIFF 6 -#define IDYES 6 -#define BN_SETFOCUS 6 -#define LANG_DANISH 0x06 -#define SUBLANG_ARABIC_MOROCCO 0x06 -#define SUBLANG_ENGLISH_EIRE 0x06 -#define SUBLANG_FRENCH_MONACO 0x06 -#define SUBLANG_SPANISH_PANAMA 0x06 -#define SW_SHOWMINNOACTIVE 7 -#define WM_SETFOCUS 0x0007 -#define WMSZ_BOTTOMLEFT 7 -#define HTVSCROLL 7 -#define CF_OEMTEXT 7 -#define IDNO 7 -#define BN_KILLFOCUS 7 -#define LANG_GERMAN 0x07 -#define SUBLANG_ARABIC_TUNISIA 0x07 -#define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 -#define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 -#define SW_SHOWNA 8 -#define VK_BACK 0x08 -#define WM_KILLFOCUS 0x0008 -#define WMSZ_BOTTOMRIGHT 8 -#define HTMINBUTTON 8 -#define SMTO_NOTIMEOUTIFNOTHUNG 0x0008 -#define MK_CONTROL 0x0008 -#define CS_DBLCLKS 0x0008 -#define CF_DIB 8 -#define IDCLOSE 8 -#define BST_FOCUS 0x0008 -#define HDS_HIDDEN 0x0008 -#define TBS_BOTH 0x0008 -#define UDS_ALIGNLEFT 0x0008 -#define LVS_SHOWSELALWAYS 0x0008 -#define TVS_EDITLABELS 0x0008 -#define TCS_FLATBUTTONS 0x0008 -#define ACS_TIMER 0x0008 -#define MCS_NOTODAYCIRCLE 0x0008 -#define NFS_BUTTON 0x0008 -#define LANG_GREEK 0x08 -#define SUBLANG_ARABIC_OMAN 0x08 -#define SUBLANG_ENGLISH_JAMAICA 0x08 -#define SUBLANG_SPANISH_VENEZUELA 0x08 -#define SW_RESTORE 9 -#define VK_TAB 0x09 -#define HTMAXBUTTON 9 -#define CF_PALETTE 9 -#define IDHELP 9 -#define DTS_TIMEFORMAT 0x0009 -#define LANG_ENGLISH 0x09 -#define SUBLANG_ARABIC_YEMEN 0x09 -#define SUBLANG_ENGLISH_CARIBBEAN 0x09 -#define SUBLANG_SPANISH_COLOMBIA 0x09 -#define SW_SHOWDEFAULT 10 -#define WM_ENABLE 0x000A -#define HTLEFT 10 -#define CF_PENDATA 10 -#define IDTRYAGAIN 10 -#define HELP_CONTEXTMENU 0x000a -#define LANG_SPANISH 0x0a -#define SUBLANG_ARABIC_SYRIA 0x0a -#define SUBLANG_ENGLISH_BELIZE 0x0a -#define SUBLANG_SPANISH_PERU 0x0a -#define SW_FORCEMINIMIZE 11 -#define SW_MAX 11 -#define WM_SETREDRAW 0x000B -#define HTRIGHT 11 -#define CF_RIFF 11 -#define IDCONTINUE 11 -#define HELP_FINDER 0x000b -#define LANG_FINNISH 0x0b -#define SUBLANG_ARABIC_JORDAN 0x0b -#define SUBLANG_ENGLISH_TRINIDAD 0x0b -#define SUBLANG_SPANISH_ARGENTINA 0x0b -#define VK_CLEAR 0x0C -#define WM_SETTEXT 0x000C -#define HTTOP 12 -#define CF_WAVE 12 -#define HELP_WM_HELP 0x000c -#define DTS_SHORTDATECENTURYFORMAT 0x000C -#define LANG_FRENCH 0x0c -#define SUBLANG_ARABIC_LEBANON 0x0c -#define SUBLANG_ENGLISH_ZIMBABWE 0x0c -#define SUBLANG_SPANISH_ECUADOR 0x0c -#define VK_RETURN 0x0D -#define WM_GETTEXT 0x000D -#define HTTOPLEFT 13 -#define CF_UNICODETEXT 13 -#define HELP_SETPOPUP_POS 0x000d -#define LANG_HEBREW 0x0d -#define SUBLANG_ARABIC_KUWAIT 0x0d -#define SUBLANG_ENGLISH_PHILIPPINES 0x0d -#define SUBLANG_SPANISH_CHILE 0x0d -#define WM_GETTEXTLENGTH 0x000E -#define HTTOPRIGHT 14 -#define CF_ENHMETAFILE 14 -#define LANG_HUNGARIAN 0x0e -#define SUBLANG_ARABIC_UAE 0x0e -#define SUBLANG_SPANISH_URUGUAY 0x0e -#define WM_PAINT 0x000F -#define HTBOTTOM 15 -#define CF_HDROP 15 -#define LANG_ICELANDIC 0x0f -#define SUBLANG_ARABIC_BAHRAIN 0x0f -#define SUBLANG_SPANISH_PARAGUAY 0x0f -#define MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID 16 -#define VK_SHIFT 0x10 -#define WM_CLOSE 0x0010 -#define HTBOTTOMLEFT 16 -#define WVR_ALIGNTOP 0x0010 -#define MK_MBUTTON 0x0010 -#define TME_NONCLIENT 0x00000010 -#define CF_LOCALE 16 -#define HELP_TCARD_DATA 0x0010 -#define TTS_NOANIMATE 0x10 -#define TBS_NOTICKS 0x0010 -#define UDS_AUTOBUDDY 0x0010 -#define LVS_SORTASCENDING 0x0010 -#define TVS_DISABLEDRAGDROP 0x0010 -#define TCS_FORCEICONLEFT 0x0010 -#define MCS_NOTODAY 0x0010 -#define DTS_APPCANPARSE 0x0010 -#define NFS_ALL 0x0010 -#define LANG_ITALIAN 0x10 -#define SUBLANG_ARABIC_QATAR 0x10 -#define SUBLANG_SPANISH_BOLIVIA 0x10 -#define VK_CONTROL 0x11 -#define WM_QUERYENDSESSION 0x0011 -#define HTBOTTOMRIGHT 17 -#define CF_DIBV5 17 -#define HELP_TCARD_OTHER_CALLER 0x0011 -#define LANG_JAPANESE 0x11 -#define SUBLANG_SPANISH_EL_SALVADOR 0x11 -#define VK_MENU 0x12 -#define WM_QUIT 0x0012 -#define HTBORDER 18 -#define CF_MAX 18 -#define LANG_KOREAN 0x12 -#define SUBLANG_SPANISH_HONDURAS 0x12 -#define VK_PAUSE 0x13 -#define WM_QUERYOPEN 0x0013 -#define HTOBJECT 19 -#define LANG_DUTCH 0x13 -#define SUBLANG_SPANISH_NICARAGUA 0x13 -#define VK_CAPITAL 0x14 -#define WM_ERASEBKGND 0x0014 -#define HTCLOSE 20 -#define LANG_NORWEGIAN 0x14 -#define SUBLANG_SPANISH_PUERTO_RICO 0x14 -#define VK_KANA 0x15 -#define VK_HANGEUL 0x15 -#define VK_HANGUL 0x15 -#define WM_SYSCOLORCHANGE 0x0015 -#define HTHELP 21 -#define LANG_POLISH 0x15 -#define WM_ENDSESSION 0x0016 -#define LANG_PORTUGUESE 0x16 -#define VK_JUNJA 0x17 -#define RT_MANIFEST 24 -#define VK_FINAL 0x18 -#define WM_SHOWWINDOW 0x0018 -#define LANG_ROMANIAN 0x18 -#define VK_HANJA 0x19 -#define VK_KANJI 0x19 -#define LANG_RUSSIAN 0x19 -#define WM_WININICHANGE 0x001A -#define LANG_CROATIAN 0x1a -#define LANG_SERBIAN 0x1a -#define VK_ESCAPE 0x1B -#define WM_DEVMODECHANGE 0x001B -#define LANG_SLOVAK 0x1b -#define VK_CONVERT 0x1C -#define WM_ACTIVATEAPP 0x001C -#define LANG_ALBANIAN 0x1c -#define VK_NONCONVERT 0x1D -#define WM_FONTCHANGE 0x001D -#define LANG_SWEDISH 0x1d -#define VK_ACCEPT 0x1E -#define WM_TIMECHANGE 0x001E -#define LANG_THAI 0x1e -#define VK_MODECHANGE 0x1F -#define WM_CANCELMODE 0x001F -#define LANG_TURKISH 0x1f -#define VK_SPACE 0x20 -#define WM_SETCURSOR 0x0020 -#define WVR_ALIGNLEFT 0x0020 -#define MK_XBUTTON1 0x0020 -#define CS_OWNDC 0x0020 -#define TTS_NOFADE 0x20 -#define TBS_ENABLESELRANGE 0x0020 -#define UDS_ARROWKEYS 0x0020 -#define LVS_SORTDESCENDING 0x0020 -#define TVS_SHOWSELALWAYS 0x0020 -#define TCS_FORCELABELLEFT 0x0020 -#define DTS_RIGHTALIGN 0x0020 -#define NFS_USEFONTASSOC 0x0020 -#define LANG_URDU 0x20 -#define VK_PRIOR 0x21 -#define WM_MOUSEACTIVATE 0x0021 -#define LANG_INDONESIAN 0x21 -#define VK_NEXT 0x22 -#define WM_CHILDACTIVATE 0x0022 -#define LANG_UKRAINIAN 0x22 -#define VK_END 0x23 -#define WM_QUEUESYNC 0x0023 -#define LANG_BELARUSIAN 0x23 -#define VK_HOME 0x24 -#define WM_GETMINMAXINFO 0x0024 -#define LANG_SLOVENIAN 0x24 -#define VK_LEFT 0x25 -#define LANG_ESTONIAN 0x25 -#define VK_UP 0x26 -#define WM_PAINTICON 0x0026 -#define LANG_LATVIAN 0x26 -#define VK_RIGHT 0x27 -#define WM_ICONERASEBKGND 0x0027 -#define LANG_LITHUANIAN 0x27 -#define VK_DOWN 0x28 -#define WM_NEXTDLGCTL 0x0028 -#define VK_SELECT 0x29 -#define LANG_FARSI 0x29 -#define VK_PRINT 0x2A -#define WM_SPOOLERSTATUS 0x002A -#define LANG_VIETNAMESE 0x2a -#define VK_EXECUTE 0x2B -#define WM_DRAWITEM 0x002B -#define LANG_ARMENIAN 0x2b -#define VK_SNAPSHOT 0x2C -#define WM_MEASUREITEM 0x002C -#define LANG_AZERI 0x2c -#define VK_INSERT 0x2D -#define WM_DELETEITEM 0x002D -#define LANG_BASQUE 0x2d -#define VK_DELETE 0x2E -#define WM_VKEYTOITEM 0x002E -#define VK_HELP 0x2F -#define WM_CHARTOITEM 0x002F -#define LANG_MACEDONIAN 0x2f -#define WM_SETFONT 0x0030 -#define WM_GETFONT 0x0031 -#define WM_SETHOTKEY 0x0032 -#define WM_GETHOTKEY 0x0033 -#define LANG_AFRIKAANS 0x36 -#define WM_QUERYDRAGICON 0x0037 -#define LANG_GEORGIAN 0x37 -#define LANG_FAEROESE 0x38 -#define WM_COMPAREITEM 0x0039 -#define LANG_HINDI 0x39 -#define WM_GETOBJECT 0x003D -#define LANG_MALAY 0x3e -#define LANG_KAZAK 0x3f -#define WVR_ALIGNBOTTOM 0x0040 -#define MK_XBUTTON2 0x0040 -#define CS_CLASSDC 0x0040 -#define HDS_DRAGDROP 0x0040 -#define TTS_BALLOON 0x40 -#define TBS_FIXEDLENGTH 0x0040 -#define UDS_HORZ 0x0040 -#define LVS_SHAREIMAGELISTS 0x0040 -#define TVS_RTLREADING 0x0040 -#define TCS_HOTTRACK 0x0040 -#define LANG_KYRGYZ 0x40 -#define WM_COMPACTING 0x0041 -#define LANG_SWAHILI 0x41 -#define LANG_UZBEK 0x43 -#define WM_COMMNOTIFY 0x0044 -#define LANG_TATAR 0x44 -#define LANG_BENGALI 0x45 -#define WM_WINDOWPOSCHANGING 0x0046 -#define LANG_PUNJABI 0x46 -#define WM_WINDOWPOSCHANGED 0x0047 -#define LANG_GUJARATI 0x47 -#define WM_POWER 0x0048 -#define LANG_ORIYA 0x48 -#define LANG_TAMIL 0x49 -#define WM_COPYDATA 0x004A -#define LANG_TELUGU 0x4a -#define WM_CANCELJOURNAL 0x004B -#define LANG_KANNADA 0x4b -#define LANG_MALAYALAM 0x4c -#define LANG_ASSAMESE 0x4d -#define WM_NOTIFY 0x004E -#define LANG_MARATHI 0x4e -#define LANG_SANSKRIT 0x4f -#define WM_INPUTLANGCHANGEREQUEST 0x0050 -#define LANG_MONGOLIAN 0x50 -#define WM_INPUTLANGCHANGE 0x0051 -#define WM_TCARD 0x0052 -#define WM_HELP 0x0053 -#define WM_USERCHANGED 0x0054 -#define WM_NOTIFYFORMAT 0x0055 -#define LANG_GALICIAN 0x56 -#define LANG_KONKANI 0x57 -#define LANG_MANIPURI 0x58 -#define LANG_SINDHI 0x59 -#define LANG_SYRIAC 0x5a -#define VK_LWIN 0x5B -#define VK_RWIN 0x5C -#define VK_APPS 0x5D -#define VK_SLEEP 0x5F -#define VK_NUMPAD0 0x60 -#define LANG_KASHMIRI 0x60 -#define VK_NUMPAD1 0x61 -#define LANG_NEPALI 0x61 -#define VK_NUMPAD2 0x62 -#define VK_NUMPAD3 0x63 -#define VK_NUMPAD4 0x64 -#define VS_USER_DEFINED 100 -#define VK_NUMPAD5 0x65 -#define LANG_DIVEHI 0x65 -#define VK_NUMPAD6 0x66 -#define VK_NUMPAD7 0x67 -#define VK_NUMPAD8 0x68 -#define VK_NUMPAD9 0x69 -#define VK_MULTIPLY 0x6A -#define VK_ADD 0x6B -#define VK_SEPARATOR 0x6C -#define VK_SUBTRACT 0x6D -#define VK_DECIMAL 0x6E -#define VK_DIVIDE 0x6F -#define VK_F1 0x70 -#define VK_F2 0x71 -#define VK_F3 0x72 -#define VK_F4 0x73 -#define VK_F5 0x74 -#define VK_F6 0x75 -#define VK_F7 0x76 -#define VK_F8 0x77 -#define VK_F9 0x78 -#define WHEEL_DELTA 120 -#define VK_F10 0x79 -#define VK_F11 0x7A -#define VK_F12 0x7B -#define WM_CONTEXTMENU 0x007B -#define VK_F13 0x7C -#define WM_STYLECHANGING 0x007C -#define VK_F14 0x7D -#define WM_STYLECHANGED 0x007D -#define VK_F15 0x7E -#define WM_DISPLAYCHANGE 0x007E -#define VK_F16 0x7F -#define WM_GETICON 0x007F -#define LANG_INVARIANT 0x7f -#define VK_F17 0x80 -#define WM_SETICON 0x0080 -#define WVR_ALIGNRIGHT 0x0080 -#define CS_PARENTDC 0x0080 -#define CF_OWNERDISPLAY 0x0080 -#define HDS_FULLDRAG 0x0080 -#define TTS_CLOSE 0x80 -#define TBS_NOTHUMB 0x0080 -#define UDS_NOTHOUSANDS 0x0080 -#define LVS_NOLABELWRAP 0x0080 -#define TVS_NOTOOLTIPS 0x0080 -#define TCS_VERTICAL 0x0080 -#define VK_F18 0x81 -#define WM_NCCREATE 0x0081 -#define CF_DSPTEXT 0x0081 -#define VK_F19 0x82 -#define WM_NCDESTROY 0x0082 -#define CF_DSPBITMAP 0x0082 -#define VK_F20 0x83 -#define WM_NCCALCSIZE 0x0083 -#define CF_DSPMETAFILEPICT 0x0083 -#define VK_F21 0x84 -#define WM_NCHITTEST 0x0084 -#define VK_F22 0x85 -#define WM_NCPAINT 0x0085 -#define VK_F23 0x86 -#define WM_NCACTIVATE 0x0086 -#define VK_F24 0x87 -#define WM_GETDLGCODE 0x0087 -#define WM_SYNCPAINT 0x0088 -#define CF_DSPENHMETAFILE 0x008E -#define VK_NUMLOCK 0x90 -#define VK_SCROLL 0x91 -#define VK_OEM_NEC_EQUAL 0x92 -#define VK_OEM_FJ_JISHO 0x92 -#define VK_OEM_FJ_MASSHOU 0x93 -#define VK_OEM_FJ_TOUROKU 0x94 -#define VK_OEM_FJ_LOYA 0x95 -#define VK_OEM_FJ_ROYA 0x96 -#define VK_LSHIFT 0xA0 -#define WM_NCMOUSEMOVE 0x00A0 -#define VK_RSHIFT 0xA1 -#define WM_NCLBUTTONDOWN 0x00A1 -#define VK_LCONTROL 0xA2 -#define WM_NCLBUTTONUP 0x00A2 -#define VK_RCONTROL 0xA3 -#define WM_NCLBUTTONDBLCLK 0x00A3 -#define VK_LMENU 0xA4 -#define WM_NCRBUTTONDOWN 0x00A4 -#define VK_RMENU 0xA5 -#define WM_NCRBUTTONUP 0x00A5 -#define VK_BROWSER_BACK 0xA6 -#define WM_NCRBUTTONDBLCLK 0x00A6 -#define VK_BROWSER_FORWARD 0xA7 -#define WM_NCMBUTTONDOWN 0x00A7 -#define VK_BROWSER_REFRESH 0xA8 -#define WM_NCMBUTTONUP 0x00A8 -#define VK_BROWSER_STOP 0xA9 -#define WM_NCMBUTTONDBLCLK 0x00A9 -#define VK_BROWSER_SEARCH 0xAA -#define VK_BROWSER_FAVORITES 0xAB -#define WM_NCXBUTTONDOWN 0x00AB -#define VK_BROWSER_HOME 0xAC -#define WM_NCXBUTTONUP 0x00AC -#define VK_VOLUME_MUTE 0xAD -#define WM_NCXBUTTONDBLCLK 0x00AD -#define VK_VOLUME_DOWN 0xAE -#define VK_VOLUME_UP 0xAF -#define VK_MEDIA_NEXT_TRACK 0xB0 -#define EM_GETSEL 0x00B0 -#define VK_MEDIA_PREV_TRACK 0xB1 -#define EM_SETSEL 0x00B1 -#define VK_MEDIA_STOP 0xB2 -#define EM_GETRECT 0x00B2 -#define VK_MEDIA_PLAY_PAUSE 0xB3 -#define EM_SETRECT 0x00B3 -#define VK_LAUNCH_MAIL 0xB4 -#define EM_SETRECTNP 0x00B4 -#define VK_LAUNCH_MEDIA_SELECT 0xB5 -#define EM_SCROLL 0x00B5 -#define VK_LAUNCH_APP1 0xB6 -#define EM_LINESCROLL 0x00B6 -#define VK_LAUNCH_APP2 0xB7 -#define EM_SCROLLCARET 0x00B7 -#define EM_GETMODIFY 0x00B8 -#define EM_SETMODIFY 0x00B9 -#define VK_OEM_1 0xBA -#define EM_GETLINECOUNT 0x00BA -#define VK_OEM_PLUS 0xBB -#define EM_LINEINDEX 0x00BB -#define VK_OEM_COMMA 0xBC -#define EM_SETHANDLE 0x00BC -#define VK_OEM_MINUS 0xBD -#define EM_GETHANDLE 0x00BD -#define VK_OEM_PERIOD 0xBE -#define EM_GETTHUMB 0x00BE -#define VK_OEM_2 0xBF -#define VK_OEM_3 0xC0 -#define EM_LINELENGTH 0x00C1 -#define EM_REPLACESEL 0x00C2 -#define EM_GETLINE 0x00C4 -#define EM_LIMITTEXT 0x00C5 -#define EM_CANUNDO 0x00C6 -#define EM_UNDO 0x00C7 -#define EM_FMTLINES 0x00C8 -#define EM_LINEFROMCHAR 0x00C9 -#define EM_SETTABSTOPS 0x00CB -#define EM_SETPASSWORDCHAR 0x00CC -#define EM_EMPTYUNDOBUFFER 0x00CD -#define EM_GETFIRSTVISIBLELINE 0x00CE -#define EM_SETREADONLY 0x00CF -#define EM_SETWORDBREAKPROC 0x00D0 -#define EM_GETWORDBREAKPROC 0x00D1 -#define EM_GETPASSWORDCHAR 0x00D2 -#define EM_SETMARGINS 0x00D3 -#define EM_GETMARGINS 0x00D4 -#define EM_GETLIMITTEXT 0x00D5 -#define EM_POSFROMCHAR 0x00D6 -#define EM_CHARFROMPOS 0x00D7 -#define EM_SETIMESTATUS 0x00D8 -#define EM_GETIMESTATUS 0x00D9 -#define VK_OEM_4 0xDB -#define VK_OEM_5 0xDC -#define VK_OEM_6 0xDD -#define VK_OEM_7 0xDE -#define VK_OEM_8 0xDF -#define VK_OEM_AX 0xE1 -#define VK_OEM_102 0xE2 -#define VK_ICO_HELP 0xE3 -#define VK_ICO_00 0xE4 -#define VK_PROCESSKEY 0xE5 -#define VK_ICO_CLEAR 0xE6 -#define VK_PACKET 0xE7 -#define VK_OEM_RESET 0xE9 -#define VK_OEM_JUMP 0xEA -#define VK_OEM_PA1 0xEB -#define VK_OEM_PA2 0xEC -#define VK_OEM_PA3 0xED -#define VK_OEM_WSCTRL 0xEE -#define VK_OEM_CUSEL 0xEF -#define VK_OEM_ATTN 0xF0 -#define BM_GETCHECK 0x00F0 -#define VK_OEM_FINISH 0xF1 -#define BM_SETCHECK 0x00F1 -#define VK_OEM_COPY 0xF2 -#define BM_GETSTATE 0x00F2 -#define VK_OEM_AUTO 0xF3 -#define BM_SETSTATE 0x00F3 -#define VK_OEM_ENLW 0xF4 -#define BM_SETSTYLE 0x00F4 -#define VK_OEM_BACKTAB 0xF5 -#define BM_CLICK 0x00F5 -#define VK_ATTN 0xF6 -#define BM_GETIMAGE 0x00F6 -#define VK_CRSEL 0xF7 -#define BM_SETIMAGE 0x00F7 -#define VK_EXSEL 0xF8 -#define VK_EREOF 0xF9 -#define VK_PLAY 0xFA -#define VK_ZOOM 0xFB -#define VK_NONAME 0xFC -#define VK_PA1 0xFD -#define VK_OEM_CLEAR 0xFE -#define WM_KEYFIRST 0x0100 -#define WM_KEYDOWN 0x0100 -#define WVR_HREDRAW 0x0100 -#define HDS_FILTERBAR 0x0100 -#define RBS_TOOLTIPS 0x0100 -#define SBARS_SIZEGRIP 0x0100 -#define TBS_TOOLTIPS 0x0100 -#define UDS_HOTTRACK 0x0100 -#define LVS_AUTOARRANGE 0x0100 -#define TVS_CHECKBOXES 0x0100 -#define TCS_BUTTONS 0x0100 -#define WM_KEYUP 0x0101 -#define WM_CHAR 0x0102 -#define WM_DEADCHAR 0x0103 -#define WM_SYSKEYDOWN 0x0104 -#define WM_SYSKEYUP 0x0105 -#define WM_SYSCHAR 0x0106 -#define WM_SYSDEADCHAR 0x0107 -#define WM_KEYLAST 0x0108 -#define WM_IME_STARTCOMPOSITION 0x010D -#define WM_IME_ENDCOMPOSITION 0x010E -#define WM_IME_COMPOSITION 0x010F -#define WM_IME_KEYLAST 0x010F -#define WM_INITDIALOG 0x0110 -#define WM_COMMAND 0x0111 -#define WM_SYSCOMMAND 0x0112 -#define WM_TIMER 0x0113 -#define WM_HSCROLL 0x0114 -#define WM_VSCROLL 0x0115 -#define WM_INITMENU 0x0116 -#define WM_INITMENUPOPUP 0x0117 -#define WM_MENUSELECT 0x011F -#define WM_MENUCHAR 0x0120 -#define WM_ENTERIDLE 0x0121 -#define WM_MENURBUTTONUP 0x0122 -#define WM_MENUDRAG 0x0123 -#define WM_MENUGETOBJECT 0x0124 -#define WM_UNINITMENUPOPUP 0x0125 -#define WM_MENUCOMMAND 0x0126 -#define WM_CHANGEUISTATE 0x0127 -#define WM_UPDATEUISTATE 0x0128 -#define WM_QUERYUISTATE 0x0129 -#define WM_CTLCOLORMSGBOX 0x0132 -#define WM_CTLCOLOREDIT 0x0133 -#define WM_CTLCOLORLISTBOX 0x0134 -#define WM_CTLCOLORBTN 0x0135 -#define WM_CTLCOLORDLG 0x0136 -#define WM_CTLCOLORSCROLLBAR 0x0137 -#define WM_CTLCOLORSTATIC 0x0138 -#define MN_GETHMENU 0x01E1 -#define WM_MOUSEFIRST 0x0200 -#define WM_MOUSEMOVE 0x0200 -#define WVR_VREDRAW 0x0200 -#define CS_NOCLOSE 0x0200 -#define CF_PRIVATEFIRST 0x0200 -#define RBS_VARHEIGHT 0x0200 -#define TBS_REVERSED 0x0200 -#define LVS_EDITLABELS 0x0200 -#define TVS_TRACKSELECT 0x0200 -#define TCS_MULTILINE 0x0200 -#define WM_LBUTTONDOWN 0x0201 -#define WM_LBUTTONUP 0x0202 -#define WM_LBUTTONDBLCLK 0x0203 -#define WM_RBUTTONDOWN 0x0204 -#define WM_RBUTTONUP 0x0205 -#define WM_RBUTTONDBLCLK 0x0206 -#define WM_MBUTTONDOWN 0x0207 -#define WM_MBUTTONUP 0x0208 -#define WM_MBUTTONDBLCLK 0x0209 -#define WM_MOUSEWHEEL 0x020A -#define WM_XBUTTONDOWN 0x020B -#define WM_XBUTTONUP 0x020C -#define WM_XBUTTONDBLCLK 0x020D -#define WM_MOUSELAST 0x020D -#define WM_PARENTNOTIFY 0x0210 -#define WM_ENTERMENULOOP 0x0211 -#define WM_EXITMENULOOP 0x0212 -#define WM_NEXTMENU 0x0213 -#define WM_SIZING 0x0214 -#define WM_CAPTURECHANGED 0x0215 -#define WM_MOVING 0x0216 -#define WM_POWERBROADCAST 0x0218 -#define WM_DEVICECHANGE 0x0219 -#define WM_MDICREATE 0x0220 -#define WM_MDIDESTROY 0x0221 -#define WM_MDIACTIVATE 0x0222 -#define WM_MDIRESTORE 0x0223 -#define WM_MDINEXT 0x0224 -#define WM_MDIMAXIMIZE 0x0225 -#define WM_MDITILE 0x0226 -#define WM_MDICASCADE 0x0227 -#define WM_MDIICONARRANGE 0x0228 -#define WM_MDIGETACTIVE 0x0229 -#define WM_MDISETMENU 0x0230 -#define WM_ENTERSIZEMOVE 0x0231 -#define WM_EXITSIZEMOVE 0x0232 -#define WM_DROPFILES 0x0233 -#define WM_MDIREFRESHMENU 0x0234 -#define WM_IME_SETCONTEXT 0x0281 -#define WM_IME_NOTIFY 0x0282 -#define WM_IME_CONTROL 0x0283 -#define WM_IME_COMPOSITIONFULL 0x0284 -#define WM_IME_SELECT 0x0285 -#define WM_IME_CHAR 0x0286 -#define WM_IME_REQUEST 0x0288 -#define WM_IME_KEYDOWN 0x0290 -#define WM_IME_KEYUP 0x0291 -#define WM_NCMOUSEHOVER 0x02A0 -#define WM_MOUSEHOVER 0x02A1 -#define WM_NCMOUSELEAVE 0x02A2 -#define WM_MOUSELEAVE 0x02A3 -#define CF_PRIVATELAST 0x02FF -#define WM_CUT 0x0300 -#define CF_GDIOBJFIRST 0x0300 -#define WM_COPY 0x0301 -#define WM_PASTE 0x0302 -#define WM_CLEAR 0x0303 -#define WM_UNDO 0x0304 -#define WM_RENDERFORMAT 0x0305 -#define WM_RENDERALLFORMATS 0x0306 -#define WM_DESTROYCLIPBOARD 0x0307 -#define WM_DRAWCLIPBOARD 0x0308 -#define WM_PAINTCLIPBOARD 0x0309 -#define WM_VSCROLLCLIPBOARD 0x030A -#define WM_SIZECLIPBOARD 0x030B -#define WM_ASKCBFORMATNAME 0x030C -#define WM_CHANGECBCHAIN 0x030D -#define WM_HSCROLLCLIPBOARD 0x030E -#define WM_QUERYNEWPALETTE 0x030F -#define WM_PALETTEISCHANGING 0x0310 -#define WM_PALETTECHANGED 0x0311 -#define WM_HOTKEY 0x0312 -#define WM_PRINT 0x0317 -#define WM_PRINTCLIENT 0x0318 -#define WM_APPCOMMAND 0x0319 -#define WM_HANDHELDFIRST 0x0358 -#define WM_HANDHELDLAST 0x035F -#define WM_AFXFIRST 0x0360 -#define WM_AFXLAST 0x037F -#define WM_PENWINFIRST 0x0380 -#define WM_PENWINLAST 0x038F -#define WM_DDE_FIRST 0x03E0 -#define CF_GDIOBJLAST 0x03FF -#define WM_USER 0x0400 -#define WVR_VALIDRECTS 0x0400 -#define RBS_BANDBORDERS 0x0400 -#define TBS_DOWNISLEFT 0x0400 -#define LVS_OWNERDRAWFIXED 0x0400 -#define TVS_SINGLEEXPAND 0x0400 -#define TCS_FIXEDWIDTH 0x0400 -#define ctlFirst 0x0400 -#define psh1 0x0400 -#define psh2 0x0401 -#define psh3 0x0402 -#define psh4 0x0403 -#define psh5 0x0404 -#define psh6 0x0405 -#define psh7 0x0406 -#define psh8 0x0407 -#define psh9 0x0408 -#define psh10 0x0409 -#define psh11 0x040a -#define psh12 0x040b -#define psh13 0x040c -#define psh14 0x040d -#define psh15 0x040e -#define psh16 0x040f -#define _WIN32_WINDOWS 0x0410 -#define chx1 0x0410 -#define chx2 0x0411 -#define chx3 0x0412 -#define chx4 0x0413 -#define chx5 0x0414 -#define chx6 0x0415 -#define chx7 0x0416 -#define chx8 0x0417 -#define chx9 0x0418 -#define chx10 0x0419 -#define chx11 0x041a -#define chx12 0x041b -#define chx13 0x041c -#define chx14 0x041d -#define chx15 0x041e -#define chx16 0x041f -#define rad1 0x0420 -#define rad2 0x0421 -#define rad3 0x0422 -#define rad4 0x0423 -#define rad5 0x0424 -#define rad6 0x0425 -#define rad7 0x0426 -#define rad8 0x0427 -#define rad9 0x0428 -#define rad10 0x0429 -#define rad11 0x042a -#define rad12 0x042b -#define rad13 0x042c -#define rad14 0x042d -#define rad15 0x042e -#define rad16 0x042f -#define grp1 0x0430 -#define grp2 0x0431 -#define grp3 0x0432 -#define grp4 0x0433 -#define frm1 0x0434 -#define frm2 0x0435 -#define frm3 0x0436 -#define frm4 0x0437 -#define rct1 0x0438 -#define rct2 0x0439 -#define rct3 0x043a -#define rct4 0x043b -#define ico1 0x043c -#define ico2 0x043d -#define ico3 0x043e -#define ico4 0x043f -#define stc1 0x0440 -#define stc2 0x0441 -#define stc3 0x0442 -#define stc4 0x0443 -#define stc5 0x0444 -#define stc6 0x0445 -#define stc7 0x0446 -#define stc8 0x0447 -#define stc9 0x0448 -#define stc10 0x0449 -#define stc11 0x044a -#define stc12 0x044b -#define stc13 0x044c -#define stc14 0x044d -#define stc15 0x044e -#define stc16 0x044f -#define stc17 0x0450 -#define stc18 0x0451 -#define stc19 0x0452 -#define stc20 0x0453 -#define stc21 0x0454 -#define stc22 0x0455 -#define stc23 0x0456 -#define stc24 0x0457 -#define stc25 0x0458 -#define stc26 0x0459 -#define stc27 0x045a -#define stc28 0x045b -#define stc29 0x045c -#define stc30 0x045d -#define stc31 0x045e -#define stc32 0x045f -#define lst1 0x0460 -#define lst2 0x0461 -#define lst3 0x0462 -#define lst4 0x0463 -#define lst5 0x0464 -#define lst6 0x0465 -#define lst7 0x0466 -#define lst8 0x0467 -#define lst9 0x0468 -#define lst10 0x0469 -#define lst11 0x046a -#define lst12 0x046b -#define lst13 0x046c -#define lst14 0x046d -#define lst15 0x046e -#define lst16 0x046f -#define cmb1 0x0470 -#define cmb2 0x0471 -#define cmb3 0x0472 -#define cmb4 0x0473 -#define cmb5 0x0474 -#define cmb6 0x0475 -#define cmb7 0x0476 -#define cmb8 0x0477 -#define cmb9 0x0478 -#define cmb10 0x0479 -#define cmb11 0x047a -#define cmb12 0x047b -#define cmb13 0x047c -#define cmb14 0x047d -#define cmb15 0x047e -#define cmb16 0x047f -#define edt1 0x0480 -#define edt2 0x0481 -#define edt3 0x0482 -#define edt4 0x0483 -#define edt5 0x0484 -#define edt6 0x0485 -#define edt7 0x0486 -#define edt8 0x0487 -#define edt9 0x0488 -#define edt10 0x0489 -#define edt11 0x048a -#define edt12 0x048b -#define edt13 0x048c -#define edt14 0x048d -#define edt15 0x048e -#define edt16 0x048f -#define scr1 0x0490 -#define scr2 0x0491 -#define scr3 0x0492 -#define scr4 0x0493 -#define scr5 0x0494 -#define scr6 0x0495 -#define scr7 0x0496 -#define scr8 0x0497 -#define ctl1 0x04A0 -#define ctlLast 0x04ff -#define _WIN32_WINNT 0x0500 -#define WINVER 0x0501 -#define _WIN32_IE 0x0501 -#define FILEOPENORD 1536 -#define MULTIFILEOPENORD 1537 -#define PRINTDLGORD 1538 -#define PRNSETUPDLGORD 1539 -#define FINDDLGORD 1540 -#define REPLACEDLGORD 1541 -#define FONTDLGORD 1542 -#define FORMATDLGORD31 1543 -#define FORMATDLGORD30 1544 -#define RUNDLGORD 1545 -#define PAGESETUPDLGORD 1546 -#define NEWFILEOPENORD 1547 -#define PRINTDLGEXORD 1549 -#define PAGESETUPDLGORDMOTIF 1550 -#define COLORMGMTDLGORD 1551 -#define NEWFILEOPENV2ORD 1552 -#define CS_SAVEBITS 0x0800 -#define RBS_FIXEDORDER 0x0800 -#define SBARS_TOOLTIPS 0x0800 -#define SBT_TOOLTIPS 0x0800 -#define LVS_ALIGNLEFT 0x0800 -#define TVS_INFOTIP 0x0800 -#define TCS_RAGGEDRIGHT 0x0800 -#define LVS_ALIGNMASK 0x0c00 -#define CS_BYTEALIGNCLIENT 0x1000 -#define RBS_REGISTERDROP 0x1000 -#define LVS_OWNERDATA 0x1000 -#define TVS_FULLROWSELECT 0x1000 -#define TCS_FOCUSONBUTTONDOWN 0x1000 -#define CS_BYTEALIGNWINDOW 0x2000 -#define RBS_AUTOSIZE 0x2000 -#define LVS_NOSCROLL 0x2000 -#define TVS_NOSCROLL 0x2000 -#define TCS_OWNERDRAWFIXED 0x2000 -#define CS_GLOBALCLASS 0x4000 -#define RBS_VERTICALGRIPPER 0x4000 -#define LVS_NOCOLUMNHEADER 0x4000 -#define TVS_NONEVENHEIGHT 0x4000 -#define TCS_TOOLTIPS 0x4000 -#define IDH_NO_HELP 28440 -#define IDH_MISSING_CONTEXT 28441 -#define IDH_GENERIC_HELP_BUTTON 28442 -#define IDH_OK 28443 -#define IDH_CANCEL 28444 -#define IDH_HELP 28445 -#define IDTIMEOUT 32000 -#define OCR_NORMAL 32512 -#define OIC_SAMPLE 32512 -#define IDI_APPLICATION 32512 -#define OCR_IBEAM 32513 -#define OIC_HAND 32513 -#define IDI_HAND 32513 -#define OCR_WAIT 32514 -#define OIC_QUES 32514 -#define IDI_QUESTION 32514 -#define OCR_CROSS 32515 -#define OIC_BANG 32515 -#define IDI_EXCLAMATION 32515 -#define OCR_UP 32516 -#define OIC_NOTE 32516 -#define IDI_ASTERISK 32516 -#define OIC_WINLOGO 32517 -#define IDI_WINLOGO 32517 -#define OCR_SIZE 32640 -#define OCR_ICON 32641 -#define OCR_SIZENWSE 32642 -#define OCR_SIZENESW 32643 -#define OCR_SIZEWE 32644 -#define OCR_SIZENS 32645 -#define OCR_SIZEALL 32646 -#define OCR_ICOCUR 32647 -#define OCR_NO 32648 -#define OCR_HAND 32649 -#define OCR_APPSTARTING 32650 -#define OBM_LFARROWI 32734 -#define OBM_RGARROWI 32735 -#define OBM_DNARROWI 32736 -#define OBM_UPARROWI 32737 -#define OBM_COMBO 32738 -#define OBM_MNARROW 32739 -#define OBM_LFARROWD 32740 -#define OBM_RGARROWD 32741 -#define OBM_DNARROWD 32742 -#define OBM_UPARROWD 32743 -#define OBM_RESTORED 32744 -#define OBM_ZOOMD 32745 -#define OBM_REDUCED 32746 -#define OBM_RESTORE 32747 -#define OBM_ZOOM 32748 -#define OBM_REDUCE 32749 -#define OBM_LFARROW 32750 -#define OBM_RGARROW 32751 -#define OBM_DNARROW 32752 -#define OBM_UPARROW 32753 -#define OBM_CLOSE 32754 -#define OBM_OLD_RESTORE 32755 -#define OBM_OLD_ZOOM 32756 -#define OBM_OLD_REDUCE 32757 -#define OBM_BTNCORNERS 32758 -#define OBM_CHECKBOXES 32759 -#define OBM_CHECK 32760 -#define OBM_BTSIZE 32761 -#define OBM_OLD_LFARROW 32762 -#define OBM_OLD_RGARROW 32763 -#define OBM_OLD_DNARROW 32764 -#define OBM_OLD_UPARROW 32765 -#define OBM_SIZE 32766 -#define OBM_OLD_CLOSE 32767 -#define WM_APP 0x8000 -#define HELP_TCARD 0x8000 -#define RBS_DBLCLKTOGGLE 0x8000 -#define LVS_NOSORTHEADER 0x8000 -#define TVS_NOHSCROLL 0x8000 -#define TCS_FOCUSNEVER 0x8000 -#define SC_SIZE 0xF000 -#define SC_SEPARATOR 0xF00F -#define SC_MOVE 0xF010 -#define SC_MINIMIZE 0xF020 -#define SC_MAXIMIZE 0xF030 -#define SC_NEXTWINDOW 0xF040 -#define SC_PREVWINDOW 0xF050 -#define SC_CLOSE 0xF060 -#define SC_VSCROLL 0xF070 -#define SC_HSCROLL 0xF080 -#define SC_MOUSEMENU 0xF090 -#define SC_KEYMENU 0xF100 -#define SC_ARRANGE 0xF110 -#define SC_RESTORE 0xF120 -#define SC_TASKLIST 0xF130 -#define SC_SCREENSAVE 0xF140 -#define SC_HOTKEY 0xF150 -#define SC_DEFAULT 0xF160 -#define SC_MONITORPOWER 0xF170 -#define SC_CONTEXTHELP 0xF180 -#define LVS_TYPESTYLEMASK 0xfc00 -#define HTERROR -2 -#define PWR_FAIL -1 -#define HTTRANSPARENT -1 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/vc8_build/resource1.h b/vc8_build/resource1.h deleted file mode 100644 index c321beb..0000000 --- a/vc8_build/resource1.h +++ /dev/null @@ -1,14 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by BNCSutil1.rc - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 101 -#define _APS_NEXT_COMMAND_VALUE 40001 -#define _APS_NEXT_CONTROL_VALUE 1001 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/windows_dist.bat b/windows_dist.bat deleted file mode 100644 index 25c300a..0000000 --- a/windows_dist.bat +++ /dev/null @@ -1,19 +0,0 @@ -@REM GMP Library Path -@SET GMPPath=D:\gmp-4.2.1 - -@SET VSINSTALLDIR=C:\Program Files\Microsoft Visual Studio 8 -@SET VCINSTALLDIR=C:\Program Files\Microsoft Visual Studio 8\VC -@SET FrameworkDir=C:\WINDOWS\Microsoft.NET\Framework -@SET FrameworkVersion=v2.0.40607 -@SET FrameworkSDKDir=C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0 -@set PATH=C:\Program Files\Microsoft Visual Studio 8\Common7\IDE;C:\Program Files\Microsoft Visual Studio 8\VC\BIN;C:\Program Files\Microsoft Visual Studio 8\VC\VCPackages;C:\Program Files\Microsoft Visual Studio 8\Common7\Tools;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\bin;C:\WINDOWS\Microsoft.NET\Framework\v2.0.40607;%PATH% -@set INCLUDE=C:\Program Files\Microsoft Visual Studio 8\VC\INCLUDE;%GMPPath%;%INCLUDE% -@set LIB=C:\Program Files\Microsoft Visual Studio 8\VC\LIB;C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\lib;%LIB% -@set LIBPATH=C:\WINDOWS\Microsoft.NET\Framework\v2.0.40607 - -@Set MSSdk=C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK -@Set Lib=%MSSdk%\Lib;%Lib% -@Set Include=%MSSdk%\Include;%Include% -@Set Path=%MSSdk%\Bin;%MSSdk%\Bin\win95;%path% - -sh windows_dist.sh \ No newline at end of file diff --git a/windows_dist.sh b/windows_dist.sh deleted file mode 100644 index 66dd477..0000000 --- a/windows_dist.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -SCRIPT_PATH=`dirname $0`; -PKGDIR=bncsutil-`cat $SCRIPT_PATH/product_version` -FILES="" - -for config in Release Debug -do - vcbuild /u /r /nologo /htmllog:./$config/BuildLog.html $SCRIPT_PATH/vc8_build/BNCSutil.vcproj $config - rm -f $PKGDIR-$config.zip - mkdir $PKGDIR - - for f in BNCSutil.dll BNCSutil.lib BNCSutil.pdb BuildLog.html - do - cp $SCRIPT_PATH/vc8_build/$config/$f $PKGDIR/$f - done - - mkdir $PKGDIR/bncsutil - for f in $SCRIPT_PATH/src/bncsutil/*.h - do - cp $f $PKGDIR/bncsutil/`basename $f` - done - - cp vb6_example/BNCSutil.bas $PKGDIR - cp vb6_example/NLS.cls $PKGDIR - - zip -9q -r $PKGDIR-$config.zip $PKGDIR - rm -fr $PKGDIR - - FILES="$FILES $PKGDIR-$config.zip" -done - -zip -9q -r ${PKGDIR}_vb_example.zip vb6_example -FILES="$FILES ${PKGDIR}_vb_example.zip" - -pscp $FILES "ericn@ionws.com:/home/ericn/public_html/code/bncsutil/static/releases" \ No newline at end of file From 877f3ff45463811d448ad299f931816ba24a60d9 Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:42:15 +0000 Subject: [PATCH 08/10] Update gitignore for new build procedures --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index e69de29..89c3854 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +/src/bncsutil/libbncsutil.so From 85b80581c9bc6bfb50b82851b320480d9c29be73 Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 05:52:38 +0000 Subject: [PATCH 09/10] Whitespace refactoring --- src/bncsutil/Makefile | 73 +-- src/bncsutil/bsha1.cpp | 156 +++---- src/bncsutil/bsha1.h | 2 +- src/bncsutil/cdkeydecoder.cpp | 236 +++++----- src/bncsutil/cdkeydecoder.h | 24 +- src/bncsutil/checkrevision.cpp | 770 +++++++++++++++---------------- src/bncsutil/checkrevision.h | 14 +- src/bncsutil/debug.c | 378 ++++++++-------- src/bncsutil/debug.h | 14 +- src/bncsutil/decodekey.cpp | 498 ++++++++++---------- src/bncsutil/decodekey.h | 8 +- src/bncsutil/file.cpp | 418 ++++++++--------- src/bncsutil/file.h | 6 +- src/bncsutil/gmp.h | 248 +++++----- src/bncsutil/libinfo.cpp | 6 +- src/bncsutil/ms_stdint.h | 20 +- src/bncsutil/mutil.h | 24 +- src/bncsutil/mutil_types.h | 2 +- src/bncsutil/nls.c | 474 +++++++++---------- src/bncsutil/nls.h | 282 ++++++------ src/bncsutil/oldauth.cpp | 14 +- src/bncsutil/pe.c | 804 ++++++++++++++++----------------- src/bncsutil/pe.h | 206 ++++----- src/bncsutil/sha1.h | 2 +- src/bncsutil/stack.c | 112 ++--- src/bncsutil/stack.h | 10 +- 26 files changed, 2401 insertions(+), 2400 deletions(-) diff --git a/src/bncsutil/Makefile b/src/bncsutil/Makefile index 090fdbe..7cabdd7 100644 --- a/src/bncsutil/Makefile +++ b/src/bncsutil/Makefile @@ -1,36 +1,37 @@ -SHELL = /bin/sh -SYSTEM = $(shell uname) -CXX = g++ -CXXFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC -CXXOBJ = bsha1.o cdkeydecoder.o checkrevision.o decodekey.o file.o libinfo.o oldauth.o -CC = gcc -CCFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC -CCOBJ = nls.o pe.o sha1.o stack.o - -ifeq ($(SYSTEM),Darwin) -LDFLAGS = -dynamiclib -lgmp -L/opt/local/lib -TARGET = libbncsutil.dylib -else -LDFLAGS = -shared -lgmp -TARGET = libbncsutil.so -endif - -$(TARGET): $(CXXOBJ) $(CCOBJ) - $(CXX) $(CXXFLAGS) $(LDFLAGS) $(CXXOBJ) $(CCOBJ) -o $(TARGET) - -$(CXXOBJ): %.o: %.cpp - $(CXX) $(CXXFLAGS) -c $< -o $@ - -$(CCOBJ): %.o: %.c - $(CC) $(CCFLAGS) -c $< -o $@ - -clean: - rm -f $(CCOBJ) $(CXXOBJ) $(TARGET) *~ -all: - make $(TARGET) - -install: $(TARGET) - mkdir -p /usr/include/bncsutil - cp *.h /usr/include/bncsutil - cp $(TARGET) /usr/lib - ldconfig +SHELL = /bin/sh +SYSTEM = $(shell uname) +CXX = g++ +CXXFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC +CXXOBJ = bsha1.o cdkeydecoder.o checkrevision.o decodekey.o file.o libinfo.o oldauth.o +CC = gcc +CCFLAGS = -Wall -O3 -I ../ -Wno-multichar -fPIC +CCOBJ = nls.o pe.o sha1.o stack.o + +ifeq ($(SYSTEM),Darwin) +LDFLAGS = -dynamiclib -lgmp -L/opt/local/lib +TARGET = libbncsutil.dylib +else +LDFLAGS = -shared -lgmp +TARGET = libbncsutil.so +endif + +$(TARGET): $(CXXOBJ) $(CCOBJ) + $(CXX) $(CXXFLAGS) $(LDFLAGS) $(CXXOBJ) $(CCOBJ) -o $(TARGET) + +$(CXXOBJ): %.o: %.cpp + $(CXX) $(CXXFLAGS) -c $< -o $@ + +$(CCOBJ): %.o: %.c + $(CC) $(CCFLAGS) -c $< -o $@ + +clean: + rm -f $(CCOBJ) $(CXXOBJ) $(TARGET) *~ + +all: + make $(TARGET) + +install: $(TARGET) + mkdir -p /usr/include/bncsutil + cp *.h /usr/include/bncsutil + cp $(TARGET) /usr/lib + ldconfig diff --git a/src/bncsutil/bsha1.cpp b/src/bncsutil/bsha1.cpp index 4344f0f..3074255 100644 --- a/src/bncsutil/bsha1.cpp +++ b/src/bncsutil/bsha1.cpp @@ -27,7 +27,7 @@ #include #include -#define USE_NEW_BSHA1 0 +#define USE_NEW_BSHA1 0 #define BSHA_IC1 0x67452301lu #define BSHA_IC2 0xEFCDAB89lu @@ -41,10 +41,10 @@ #define BSHA_OC4 0x359D3E2Alu #if !USE_NEW_BSHA1 -# define BSHA_COP e = d; d = c; c = ROL(b, 30); b = a; a = g; +# define BSHA_COP e = d; d = c; c = ROL(b, 30); b = a; a = g; #else -# define BSHA_N_COP t[4] = t[3]; t[3] = t[2]; t[2] = ROL(t[1], 30); \ - t[1] = t[0]; t[0] = x +# define BSHA_N_COP t[4] = t[3]; t[3] = t[2]; t[2] = ROL(t[1], 30); \ + t[1] = t[0]; t[0] = x #endif #if !USE_NEW_BSHA1 @@ -60,81 +60,81 @@ #else #define BSHA_N_OP1() x = LSB4(*p++) + ROL(t[0], 5) + t[4] + \ - ((t[1] & t[2]) | (~t[1] & t[3])) + BSHA_OC1; BSHA_N_COP + ((t[1] & t[2]) | (~t[1] & t[3])) + BSHA_OC1; BSHA_N_COP #define BSHA_N_OP2() x = (t[3] ^ t[2] ^ t[1]) + t[4] + ROL(x, 5) + \ - LSB4(*p++) + BSHA_OC2; BSHA_N_COP + LSB4(*p++) + BSHA_OC2; BSHA_N_COP #define BSHA_N_OP3() x = LSB4(*p++) + ROL(x, 5) + t[4] + \ - ((t[2] & t[1]) | (t[3] & t[2]) | (t[3] & t[1])) - BSHA_OC3; BSHA_N_COP + ((t[2] & t[1]) | (t[3] & t[2]) | (t[3] & t[1])) - BSHA_OC3; BSHA_N_COP #define BSHA_N_OP4() x = (t[3] ^ t[2] ^ t[1]) + t[4] + ROL(x, 5) + \ - LSB4(*p++) - BSHA_OC4; BSHA_N_COP + LSB4(*p++) - BSHA_OC4; BSHA_N_COP #endif #if USE_NEW_BSHA1 MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) { - uint32_t vals[5]; - uint32_t t[5]; // a, b, c, d, e - uint32_t buf[0x50]; - uint32_t* p; - uint32_t x; - const char* in = input; - unsigned int i, j; - unsigned int sub_length; - - /* Initializer Values */ - p = vals; - *p++ = BSHA_IC1; - *p++ = BSHA_IC2; - *p++ = BSHA_IC3; - *p++ = BSHA_IC4; - *p++ = BSHA_IC5; - - memset(buf, 0, 320); // zero buf - - /* Process input in chunks. */ - for (i = 0; i < length; i += 0x40) { - sub_length = length - i; - - /* Maximum chunk size is 0x40 (64) bytes. */ - if (sub_length > 0x40) - sub_length = 0x40; - - memcpy(buf, in, sub_length); - in += sub_length; - - /* If necessary, pad with zeroes to 64 bytes. */ - if (sub_length < 0x40) - memset(buf + sub_length, 0, 0x40 - sub_length); - - for (j = 0; j < 64; j++) { - buf[j + 16] = - LSB4(ROL(1, LSB4(buf[j] ^ buf[j+8] ^ buf[j+2] ^ buf[j+13]) % 32)); - } - - memcpy(t, vals, 20); - p = buf; - - /* It's a kind of magic. */ - BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); - BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); - - BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); - BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); - - BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); - BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); - - BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); - BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); - - vals[0] += t[0]; - vals[1] += t[1]; - vals[2] += t[2]; - vals[3] += t[3]; - vals[4] += t[4]; - } - - /* Return result. */ - memcpy(result, vals, 20); + uint32_t vals[5]; + uint32_t t[5]; // a, b, c, d, e + uint32_t buf[0x50]; + uint32_t* p; + uint32_t x; + const char* in = input; + unsigned int i, j; + unsigned int sub_length; + + /* Initializer Values */ + p = vals; + *p++ = BSHA_IC1; + *p++ = BSHA_IC2; + *p++ = BSHA_IC3; + *p++ = BSHA_IC4; + *p++ = BSHA_IC5; + + memset(buf, 0, 320); // zero buf + + /* Process input in chunks. */ + for (i = 0; i < length; i += 0x40) { + sub_length = length - i; + + /* Maximum chunk size is 0x40 (64) bytes. */ + if (sub_length > 0x40) + sub_length = 0x40; + + memcpy(buf, in, sub_length); + in += sub_length; + + /* If necessary, pad with zeroes to 64 bytes. */ + if (sub_length < 0x40) + memset(buf + sub_length, 0, 0x40 - sub_length); + + for (j = 0; j < 64; j++) { + buf[j + 16] = + LSB4(ROL(1, LSB4(buf[j] ^ buf[j+8] ^ buf[j+2] ^ buf[j+13]) % 32)); + } + + memcpy(t, vals, 20); + p = buf; + + /* It's a kind of magic. */ + BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); + BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); BSHA_N_OP1(); + + BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); + BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); BSHA_N_OP2(); + + BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); + BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); BSHA_N_OP3(); + + BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); + BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); BSHA_N_OP4(); + + vals[0] += t[0]; + vals[1] += t[1]; + vals[2] += t[2]; + vals[3] += t[3]; + vals[4] += t[4]; + } + + /* Return result. */ + memcpy(result, vals, 20); } #else @@ -142,26 +142,26 @@ MEXP(void) calcHashBuf(const char* input, unsigned int length, char* result) { MEXP(void) calcHashBuf(const char* input, size_t length, char* result) { int i; uint32_t a, b, c, d, e, g; - uint32_t* ldata; + uint32_t* ldata; char data[1024]; memset(data, 0, 1024); memcpy(data, input, length); ldata = (uint32_t*) data; - + for (i = 0; i < 64; i++) { ldata[i + 16] = LSB4(ROL(1, LSB4(ldata[i] ^ ldata[i+8] ^ ldata[i+2] ^ ldata[i+13]) % 32)); } - - //dumpbuf(data, 1024); - + + //dumpbuf(data, 1024); + a = BSHA_IC1; b = BSHA_IC2; c = BSHA_IC3; d = BSHA_IC4; e = BSHA_IC5; g = 0; - + // Loops unrolled. BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) BSHA_OP1(a, b, c, d, e, *ldata++, g) diff --git a/src/bncsutil/bsha1.h b/src/bncsutil/bsha1.h index 6283c2e..71fb980 100644 --- a/src/bncsutil/bsha1.h +++ b/src/bncsutil/bsha1.h @@ -41,7 +41,7 @@ extern "C" { * hash: Buffer, at least 20 bytes in length, to receive the hash. */ MEXP(void) calcHashBuf(const char* data, size_t length, char* hash); - + /* * New implementation. Broken. No plans to fix. */ diff --git a/src/bncsutil/cdkeydecoder.cpp b/src/bncsutil/cdkeydecoder.cpp index 6c4ff3b..a606ba5 100644 --- a/src/bncsutil/cdkeydecoder.cpp +++ b/src/bncsutil/cdkeydecoder.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include #include #include // w2/d2 and w3 tables @@ -64,13 +64,13 @@ CDKeyDecoder::CDKeyDecoder() { initialized = 0; keyOK = 0; hashLen = 0; - cdkey = (char*) 0; - w3value2 = (char*) 0; - keyHash = (char*) 0; + cdkey = (char*) 0; + w3value2 = (char*) 0; + keyHash = (char*) 0; } CDKeyDecoder::CDKeyDecoder(const char* cd_key) { - CDKeyDecoder(cd_key, std::strlen(cd_key)); + CDKeyDecoder(cd_key, std::strlen(cd_key)); } /** @@ -81,19 +81,19 @@ CDKeyDecoder::CDKeyDecoder(const char* cd_key) { */ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { unsigned int i; - + initialized = 0; - product = 0; - value1 = 0; - value2 = 0; + product = 0; + value1 = 0; + value2 = 0; keyOK = 0; hashLen = 0; - cdkey = (char*) 0; - w3value2 = (char*) 0; - keyHash = (char*) 0; - + cdkey = (char*) 0; + w3value2 = (char*) 0; + keyHash = (char*) 0; + if (keyLength <= 0) return; - + // Initial sanity check if (keyLength == 13) { // StarCraft key @@ -102,9 +102,9 @@ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { } keyType = KEY_STARCRAFT; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with STAR key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with STAR key %s.", cdKey + ); #endif } else { // D2/W2/W3 key @@ -115,54 +115,54 @@ CDKeyDecoder::CDKeyDecoder(const char* cdKey, size_t keyLength) { case 16: keyType = KEY_WARCRAFT2; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with W2/D2 key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with W2/D2 key %s.", cdKey + ); #endif break; case 26: keyType = KEY_WARCRAFT3; #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with WAR3 key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with WAR3 key %s.", cdKey + ); #endif break; default: #if DEBUG - bncsutil_debug_message_a( - "Created CD key decoder with unrecognized key %s.", cdKey - ); + bncsutil_debug_message_a( + "Created CD key decoder with unrecognized key %s.", cdKey + ); #endif return; } } - + cdkey = new char[keyLength + 1]; initialized = 1; keyLen = keyLength; strcpy(cdkey, cdKey); - + switch (keyType) { case KEY_STARCRAFT: keyOK = processStarCraftKey(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " - "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " + "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); #endif break; case KEY_WARCRAFT2: keyOK = processWarCraft2Key(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " - "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; " + "private=%d", cdkey, keyOK, getProduct(), getVal1(), getVal2()); #endif break; case KEY_WARCRAFT3: keyOK = processWarCraft3Key(); #if DEBUG - bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ", - cdkey, keyOK, getProduct(), getVal1()); + bncsutil_debug_message_a("%s: ok=%d; product=%d; public=%d; ", + cdkey, keyOK, getProduct(), getVal1()); #endif break; default: @@ -175,8 +175,8 @@ CDKeyDecoder::~CDKeyDecoder() { delete [] cdkey; if (hashLen > 0 && keyHash != NULL) delete [] keyHash; - if (w3value2) - delete [] w3value2; + if (w3value2) + delete [] w3value2; } int CDKeyDecoder::isKeyValid() { @@ -188,27 +188,27 @@ int CDKeyDecoder::getVal2Length() { } uint32_t CDKeyDecoder::getProduct() { - switch (keyType) { - case KEY_STARCRAFT: - case KEY_WARCRAFT2: - return (uint32_t) LSB4(product); - case KEY_WARCRAFT3: - return (uint32_t) MSB4(product); - default: - return (uint32_t) -1; - } + switch (keyType) { + case KEY_STARCRAFT: + case KEY_WARCRAFT2: + return (uint32_t) LSB4(product); + case KEY_WARCRAFT3: + return (uint32_t) MSB4(product); + default: + return (uint32_t) -1; + } } uint32_t CDKeyDecoder::getVal1() { switch (keyType) { - case KEY_STARCRAFT: - case KEY_WARCRAFT2: - return (uint32_t) LSB4(value1); - case KEY_WARCRAFT3: - return (uint32_t) MSB4(value1); - default: - return (uint32_t) -1; - } + case KEY_STARCRAFT: + case KEY_WARCRAFT2: + return (uint32_t) LSB4(value1); + case KEY_WARCRAFT3: + return (uint32_t) MSB4(value1); + default: + return (uint32_t) -1; + } } uint32_t CDKeyDecoder::getVal2() { @@ -240,35 +240,35 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, { struct CDKEYHASH kh; SHA1Context sha; - + if (!initialized || !keyOK) return 0; hashLen = 0; - + kh.clientToken = clientToken; kh.serverToken = serverToken; - + switch (keyType) { case KEY_STARCRAFT: case KEY_WARCRAFT2: - kh.product = (uint32_t) LSB4(product); - kh.value1 = (uint32_t) LSB4(value1); + kh.product = (uint32_t) LSB4(product); + kh.value1 = (uint32_t) LSB4(value1); kh.value2.s.zero = 0; kh.value2.s.v = (uint32_t) LSB4(value2); - + keyHash = new char[20]; calcHashBuf((char*) &kh, 24, keyHash); hashLen = 20; #if DEBUG - bncsutil_debug_message_a("%s: Hash calculated.", cdkey); - bncsutil_debug_dump(keyHash, 20); + bncsutil_debug_message_a("%s: Hash calculated.", cdkey); + bncsutil_debug_dump(keyHash, 20); #endif return 20; case KEY_WARCRAFT3: - kh.product = (uint32_t) MSB4(product); - kh.value1 = (uint32_t) MSB4(value1); + kh.product = (uint32_t) MSB4(product); + kh.value1 = (uint32_t) MSB4(value1); memcpy(kh.value2.l.v, w3value2, 10); if (SHA1Reset(&sha)) @@ -282,10 +282,10 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, } SHA1Reset(&sha); hashLen = 20; - + #if DEBUG - bncsutil_debug_message_a("%s: Hash calculated.", cdkey); - bncsutil_debug_dump(keyHash, 20); + bncsutil_debug_message_a("%s: Hash calculated.", cdkey); + bncsutil_debug_dump(keyHash, 20); #endif return 20; @@ -301,7 +301,7 @@ size_t CDKeyDecoder::calculateHash(uint32_t clientToken, */ size_t CDKeyDecoder::getHash(char* outputBuffer) { if (hashLen == 0 || !keyHash || !outputBuffer) - return 0; + return 0; memcpy(outputBuffer, keyHash, hashLen); return hashLen; } @@ -319,21 +319,21 @@ int CDKeyDecoder::processStarCraftKey() { int accum, pos, i; char temp; int hashKey = 0x13AC9741; - char cdkey[14]; + char cdkey[14]; + + std::strcpy(cdkey, this->cdkey); - std::strcpy(cdkey, this->cdkey); - // Verification accum = 3; for (i = 0; i < (int) (keyLen - 1); i++) { accum += ((tolower(cdkey[i]) - '0') ^ (accum * 2)); } - - if ((accum % 10) != (cdkey[12] - '0')) { - // bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey); + + if ((accum % 10) != (cdkey[12] - '0')) { + // bncsutil_debug_message_a("error: %s is not a valid StarCraft key", cdkey); return 0; - } - + } + // Shuffling pos = 0x0B; for (i = 0xC2; i >= 7; i -= 0x11) { @@ -342,7 +342,7 @@ int CDKeyDecoder::processStarCraftKey() { cdkey[i % 0x0C] = temp; pos--; } - + // Final Value for (i = (int) (keyLen - 2); i >= 0; i--) { temp = toupper(cdkey[i]); @@ -354,10 +354,10 @@ int CDKeyDecoder::processStarCraftKey() { cdkey[i] ^= ((char) i & 1); } } - + // Final Calculations sscanf(cdkey, "%2ld%7ld%3ld", &product, &value1, &value2); - + return 1; } @@ -365,10 +365,10 @@ int CDKeyDecoder::processWarCraft2Key() { unsigned long r, n, n2, v, v2, checksum; int i; unsigned char c1, c2, c; - char cdkey[17]; + char cdkey[17]; + + std::strcpy(cdkey, this->cdkey); - std::strcpy(cdkey, this->cdkey); - r = 1; checksum = 0; for (i = 0; i < 16; i += 2) { @@ -376,7 +376,7 @@ int CDKeyDecoder::processWarCraft2Key() { n = c1 * 3; c2 = w2Map[(int) cdkey[i + 1]]; n = c2 + n * 8; - + if (n >= 0x100) { n -= 0x100; checksum |= r; @@ -388,7 +388,7 @@ int CDKeyDecoder::processWarCraft2Key() { cdkey[i + 1] = getHexValue(n); r <<= 1; } - + v = 3; for (i = 0; i < 16; i++) { c = cdkey[i]; @@ -398,11 +398,11 @@ int CDKeyDecoder::processWarCraft2Key() { v += n; } v &= 0xFF; - + if (v != checksum) { return 0; } - + n = 0; for (int j = 15; j >= 0; j--) { c = cdkey[j]; @@ -442,13 +442,13 @@ int CDKeyDecoder::processWarCraft3Key() { int a, b; int i; char decode; - + a = 0; b = 0x21; - + memset(table, 0, W3_BUFLEN); memset(values, 0, (sizeof(int) * 4)); - + for (i = 0; ((unsigned int) i) < keyLen; i++) { cdkey[i] = toupper(cdkey[i]); a = (b + 0x07B5) % W3_BUFLEN; @@ -457,40 +457,40 @@ int CDKeyDecoder::processWarCraft3Key() { table[a] = (decode / 5); table[b] = (decode % 5); } - + // Mult i = W3_BUFLEN; do { mult(4, 5, values + 3, table[i - 1]); } while (--i); - + decodeKeyTable(values); - - // 00 00 38 08 f0 64 18 6c 79 14 14 8E B9 49 1D BB - // -------- - // val1 - product = values[0] >> 0xA; - product = SWAP4(product); + // 00 00 38 08 f0 64 18 6c 79 14 14 8E B9 49 1D BB + // -------- + // val1 + + product = values[0] >> 0xA; + product = SWAP4(product); #if LITTLEENDIAN - for (i = 0; i < 4; i++) { - values[i] = MSB4(values[i]); - } + for (i = 0; i < 4; i++) { + values[i] = MSB4(values[i]); + } #endif - value1 = LSB4(*(uint32_t*) (((char*) values) + 2)) & 0xFFFFFF00; + value1 = LSB4(*(uint32_t*) (((char*) values) + 2)) & 0xFFFFFF00; - w3value2 = new char[10]; + w3value2 = new char[10]; #if LITTLEENDIAN - *((uint16_t*) w3value2) = MSB2(*(uint16_t*) (((char*) values) + 6)); - *((uint32_t*) ((char*) w3value2 + 2)) = MSB4(*(uint32_t*) (((char*) values) + 8)); - *((uint32_t*) ((char*) w3value2 + 6)) = MSB4(*(uint32_t*) (((char*) values) + 12)); + *((uint16_t*) w3value2) = MSB2(*(uint16_t*) (((char*) values) + 6)); + *((uint32_t*) ((char*) w3value2 + 2)) = MSB4(*(uint32_t*) (((char*) values) + 8)); + *((uint32_t*) ((char*) w3value2 + 6)) = MSB4(*(uint32_t*) (((char*) values) + 12)); #else - *((uint16_t*) w3value2) = LSB2(*(uint16_t*) (((char*) values) + 6)); - *((uint32_t*) ((char*) w3value2 + 2)) = LSB4(*(uint32_t*) (((char*) values) + 8)); - *((uint32_t*) ((char*) w3value2 + 6)) = LSB4(*(uint32_t*) (((char*) values) + 12)); + *((uint16_t*) w3value2) = LSB2(*(uint16_t*) (((char*) values) + 6)); + *((uint32_t*) ((char*) w3value2 + 2)) = LSB4(*(uint32_t*) (((char*) values) + 8)); + *((uint32_t*) ((char*) w3value2 + 6)) = LSB4(*(uint32_t*) (((char*) values) + 12)); #endif - return 1; + return 1; } inline void CDKeyDecoder::mult(int r, const int x, int* a, int dcByte) { @@ -511,7 +511,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { int ckt_temp; var8 = 29; int i = 464; - + // pass 1 do { int j; @@ -521,7 +521,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = keyTable[3 - var4]; varC &= (0xF << esi); varC = varC >> esi; - + if (i < 464) { for (j = 29; (unsigned int) j > var8; j--) { /* @@ -537,7 +537,7 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = w3TranslateMap[ebp ^ w3TranslateMap[varC + i] + i]; } } - + j = --var8; while (j >= 0) { ecx = (j & 7) << 2; @@ -548,12 +548,12 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { varC = w3TranslateMap[ebp ^ w3TranslateMap[varC + i] + i]; j--; } - + j = 3 - var4; ebx = (w3TranslateMap[varC + i] & 0xF) << esi; keyTable[j] = (ebx | ~(0xF << esi) & ((int) keyTable[j])); } while ((i -= 16) >= 0); - + // pass 2 eax = 0; edx = 0; @@ -561,26 +561,26 @@ void CDKeyDecoder::decodeKeyTable(int* keyTable) { edi = 0; esi = 0; ebp = 0; - + for (i = 0; i < 4; i++) { copy[i] = LSB4(keyTable[i]); } scopy = (unsigned char*) copy; - + for (edi = 0; edi < 120; edi++) { unsigned int location = 12; eax = edi & 0x1F; ecx = esi & 0x1F; edx = 3 - (edi >> 5); - + location -= ((esi >> 5) << 2); ebp = *(int*) (scopy + location); ebp = LSB4(ebp); - + //ebp = (ebp & (1 << ecx)) >> ecx; ebp &= (1 << ecx); ebp = ebp >> ecx; - + //keyTable[edx] = ((ebp & 1) << eax) | (~(1 << eax) & keyTable[edx]); ckt = (keyTable + edx); ckt_temp = *ckt; diff --git a/src/bncsutil/cdkeydecoder.h b/src/bncsutil/cdkeydecoder.h index cdf46bb..0f845f1 100644 --- a/src/bncsutil/cdkeydecoder.h +++ b/src/bncsutil/cdkeydecoder.h @@ -27,7 +27,7 @@ #define BNCSUTIL_CDKEYDECODER_H #include - + /** * Internal key type constants. */ @@ -49,18 +49,18 @@ MCEXP(CDKeyDecoder) { unsigned long value2; unsigned long product; char* w3value2; - + int processStarCraftKey(); int processWarCraft2Key(); int processWarCraft3Key(); - + void decodeKeyTable(int* keyTable); - + inline char getHexValue(int v); inline int getNumValue(char v); - + inline void mult(const int r, const int x, int* a, int dcByte); - + public: /** * Creates a new CD-key decoder object. @@ -68,8 +68,8 @@ MCEXP(CDKeyDecoder) { */ CDKeyDecoder(); - CDKeyDecoder(const char* cd_key); - + CDKeyDecoder(const char* cd_key); + /** * Creates a new CD-key decoder object, using the specified key. * keyLength should be the length of the key, NOT INCLUDING the @@ -77,16 +77,16 @@ MCEXP(CDKeyDecoder) { * this constructor to check the validity of the provided key. */ CDKeyDecoder(const char* cdKey, size_t keyLength); - + virtual ~CDKeyDecoder(); - + int isKeyValid(); int getVal2Length(); uint32_t getProduct(); uint32_t getVal1(); uint32_t getVal2(); int getLongVal2(char* out); - + /** * Calculates the CD-Key hash for use in SID_AUTH_CHECK (0x51) * Returns the length of the generated hash; call getHash and pass @@ -99,7 +99,7 @@ MCEXP(CDKeyDecoder) { * endianness is not a factor. */ size_t calculateHash(uint32_t clientToken, uint32_t serverToken); - + /** * Places the calculated CD-key hash in outputBuffer. You must call * calculateHash before getHash. Returns the length of the hash diff --git a/src/bncsutil/checkrevision.cpp b/src/bncsutil/checkrevision.cpp index 99819a6..1bd4610 100644 --- a/src/bncsutil/checkrevision.cpp +++ b/src/bncsutil/checkrevision.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include #include #include @@ -67,442 +67,442 @@ extern "C" { std::vector checkrevision_seeds; void initialize_checkrevision_seeds() { - static bool run = false; - - if (run) - return; - - run = true; - - checkrevision_seeds.reserve(8); - - checkrevision_seeds.push_back(0xE7F4CB62); - checkrevision_seeds.push_back(0xF6A14FFC); - checkrevision_seeds.push_back(0xAA5504AF); - checkrevision_seeds.push_back(0x871FCDC2); - checkrevision_seeds.push_back(0x11BF6A18); - checkrevision_seeds.push_back(0xC57292E6); - checkrevision_seeds.push_back(0x7927D27E); - checkrevision_seeds.push_back(0x2FEC8733); + static bool run = false; + + if (run) + return; + + run = true; + + checkrevision_seeds.reserve(8); + + checkrevision_seeds.push_back(0xE7F4CB62); + checkrevision_seeds.push_back(0xF6A14FFC); + checkrevision_seeds.push_back(0xAA5504AF); + checkrevision_seeds.push_back(0x871FCDC2); + checkrevision_seeds.push_back(0x11BF6A18); + checkrevision_seeds.push_back(0xC57292E6); + checkrevision_seeds.push_back(0x7927D27E); + checkrevision_seeds.push_back(0x2FEC8733); } MEXP(long) get_mpq_seed(int mpq_number) { - if (((size_t) mpq_number) >= checkrevision_seeds.size()) { - //bncsutil_debug_message_a("error: no known revision check seed for " - // "MPQ#%u", mpq_number); - return 0; - } - - return checkrevision_seeds[mpq_number]; + if (((size_t) mpq_number) >= checkrevision_seeds.size()) { + //bncsutil_debug_message_a("error: no known revision check seed for " + // "MPQ#%u", mpq_number); + return 0; + } + + return checkrevision_seeds[mpq_number]; } MEXP(long) set_mpq_seed(int mpq_number, long new_seed) { - long ret; - - if (((size_t) mpq_number) >= checkrevision_seeds.size()) { - ret = 0; - checkrevision_seeds.reserve((size_t) mpq_number); - } else { - ret = checkrevision_seeds[mpq_number]; - } - - checkrevision_seeds[mpq_number] = new_seed; - return ret; + long ret; + + if (((size_t) mpq_number) >= checkrevision_seeds.size()) { + ret = 0; + checkrevision_seeds.reserve((size_t) mpq_number); + } else { + ret = checkrevision_seeds[mpq_number]; + } + + checkrevision_seeds[mpq_number] = new_seed; + return ret; } MEXP(int) extractMPQNumber(const char* mpqName) { - const char* n; - int mpqNum; - if (mpqName == NULL) - return -1; - if ((n = (const char*) std::strchr(mpqName, '.')) == NULL) - return -1; - // extract int value of version number - mpqNum = atoi(n - 1); - return mpqNum; + const char* n; + int mpqNum; + if (mpqName == NULL) + return -1; + if ((n = (const char*) std::strchr(mpqName, '.')) == NULL) + return -1; + // extract int value of version number + mpqNum = atoi(n - 1); + return mpqNum; } const char* get_basename(const char* file_name) { - const char* base; - - for (base = (file_name + strlen(file_name)); base >= file_name; base--) { - if (*base == '\\' || *base == '/') - break; - } - - return ++base; + const char* base; + + for (base = (file_name + strlen(file_name)); base >= file_name; base--) { + if (*base == '\\' || *base == '/') + break; + } + + return ++base; } MEXP(int) checkRevision(const char* formula, const char* files[], int numFiles, - int mpqNumber, unsigned long* checksum) + int mpqNumber, unsigned long* checksum) { - uint64_t values[4]; - long ovd[4], ovs1[4], ovs2[4]; - char ops[4]; - const char* token; - int curFormula = 0; - file_t f; - uint8_t* file_buffer; - uint32_t* dwBuf; - uint32_t* current; - size_t seed_count; - + uint64_t values[4]; + long ovd[4], ovs1[4], ovs2[4]; + char ops[4]; + const char* token; + int curFormula = 0; + file_t f; + uint8_t* file_buffer; + uint32_t* dwBuf; + uint32_t* current; + size_t seed_count; + #if DEBUG - int i; - bncsutil_debug_message_a("checkRevision(\"%s\", {", formula); - for (i = 0; i < numFiles; i++) { - bncsutil_debug_message_a("\t\"%s\",", files[i]); - } - bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum); + int i; + bncsutil_debug_message_a("checkRevision(\"%s\", {", formula); + for (i = 0; i < numFiles; i++) { + bncsutil_debug_message_a("\t\"%s\",", files[i]); + } + bncsutil_debug_message_a("}, %d, %d, %p);", numFiles, mpqNumber, checksum); #endif - - if (!formula || !files || numFiles == 0 || mpqNumber < 0 || !checksum) { - //bncsutil_debug_message("error: checkRevision() parameter sanity check " - // "failed"); - return 0; - } - - seed_count = checkrevision_seeds.size(); - if (seed_count == 0) { - initialize_checkrevision_seeds(); - seed_count = checkrevision_seeds.size(); - } - - if (seed_count <= (size_t) mpqNumber) { - //bncsutil_debug_message_a("error: no revision check seed value defined " - // "for MPQ number %d", mpqNumber); - return 0; - } - - token = formula; - while (token && *token) { - if (*(token + 1) == '=') { - int variable = BUCR_GETNUM(*token); - if (variable < 0 || variable > 3) { - //bncsutil_debug_message_a("error: Unknown revision check formula" - // " variable %c", *token); - return 0; - } - - token += 2; // skip over equals sign - if (BUCR_ISNUM(*token)) { - values[variable] = ATOL64(token); - } else { - if (curFormula > 3) { - // more than 4 operations? bloody hell. - //bncsutil_debug_message("error: Revision check formula" - // " contains more than 4 operations; unsupported."); - return 0; - } - ovd[curFormula] = variable; - ovs1[curFormula] = BUCR_GETNUM(*token); - ops[curFormula] = *(token + 1); - ovs2[curFormula] = BUCR_GETNUM(*(token + 2)); - curFormula++; - } - } - - for (; *token != 0; token++) { - if (*token == ' ') { - token++; - break; - } - } - } - - // Actual hashing (yay!) - // "hash A by the hashcode" - values[0] ^= checkrevision_seeds[mpqNumber]; - - for (int i = 0; i < numFiles; i++) { - size_t file_len, remainder, rounded_size, buffer_size; - - f = file_open(files[i], FILE_READ); - if (!f) { - //bncsutil_debug_message_a("error: Failed to open file %s", - // files[i]); - return 0; - } - - file_len = file_size(f); - remainder = file_len % 1024; - rounded_size = file_len - remainder; - - file_buffer = (uint8_t*) file_map(f, file_len, 0); - if (!file_buffer) { - file_close(f); - //bncsutil_debug_message_a("error: Failed to map file %s into memory", - // files[i]); - return 0; - } - - if (remainder == 0) { - // Mapped buffer may be used directly, without padding. - dwBuf = (uint32_t*) file_buffer; - buffer_size = file_len; - } else { - // Must be padded to nearest KB. - size_t extra = 1024 - remainder; - uint8_t pad = (uint8_t) 0xFF; - uint8_t* pad_dest; - - buffer_size = file_len + extra; - dwBuf = (uint32_t*) malloc(buffer_size); - if (!dwBuf) { - //bncsutil_debug_message_a("error: Failed to allocate %d bytes " - // "of memory as a temporary buffer", buffer_size); - file_unmap(f, file_buffer); - file_close(f); - return 0; - } - - memcpy(dwBuf, file_buffer, file_len); - file_unmap(f, file_buffer); - file_buffer = (uint8_t*) 0; - - pad_dest = ((uint8_t*) dwBuf) + file_len; - for (size_t j = file_len; j < buffer_size; j++) { - *pad_dest++ = pad--; - } - - } - - current = dwBuf; - for (size_t j = 0; j < buffer_size; j += 4) { - values[3] = LSB4(*(current++)); - for (int k = 0; k < curFormula; k++) { - switch (ops[k]) { - case '+': - values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]]; - break; - case '-': - values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]]; - break; - case '^': - values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]]; - break; - case '*': - // well, you never know - values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]]; - break; - case '/': - // well, you never know - values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]]; - break; - default: - // unrecognized operation - // shit - file_unmap(f, dwBuf); - file_close(f); - return 0; - } - } - } - - if (file_buffer) - file_unmap(f, file_buffer); - else if (dwBuf && file_buffer == 0) - free(dwBuf); // padded buffer - file_close(f); - } - - *checksum = (unsigned long) LSB4(values[2]); + + if (!formula || !files || numFiles == 0 || mpqNumber < 0 || !checksum) { + //bncsutil_debug_message("error: checkRevision() parameter sanity check " + // "failed"); + return 0; + } + + seed_count = checkrevision_seeds.size(); + if (seed_count == 0) { + initialize_checkrevision_seeds(); + seed_count = checkrevision_seeds.size(); + } + + if (seed_count <= (size_t) mpqNumber) { + //bncsutil_debug_message_a("error: no revision check seed value defined " + // "for MPQ number %d", mpqNumber); + return 0; + } + + token = formula; + while (token && *token) { + if (*(token + 1) == '=') { + int variable = BUCR_GETNUM(*token); + if (variable < 0 || variable > 3) { + //bncsutil_debug_message_a("error: Unknown revision check formula" + // " variable %c", *token); + return 0; + } + + token += 2; // skip over equals sign + if (BUCR_ISNUM(*token)) { + values[variable] = ATOL64(token); + } else { + if (curFormula > 3) { + // more than 4 operations? bloody hell. + //bncsutil_debug_message("error: Revision check formula" + // " contains more than 4 operations; unsupported."); + return 0; + } + ovd[curFormula] = variable; + ovs1[curFormula] = BUCR_GETNUM(*token); + ops[curFormula] = *(token + 1); + ovs2[curFormula] = BUCR_GETNUM(*(token + 2)); + curFormula++; + } + } + + for (; *token != 0; token++) { + if (*token == ' ') { + token++; + break; + } + } + } + + // Actual hashing (yay!) + // "hash A by the hashcode" + values[0] ^= checkrevision_seeds[mpqNumber]; + + for (int i = 0; i < numFiles; i++) { + size_t file_len, remainder, rounded_size, buffer_size; + + f = file_open(files[i], FILE_READ); + if (!f) { + //bncsutil_debug_message_a("error: Failed to open file %s", + // files[i]); + return 0; + } + + file_len = file_size(f); + remainder = file_len % 1024; + rounded_size = file_len - remainder; + + file_buffer = (uint8_t*) file_map(f, file_len, 0); + if (!file_buffer) { + file_close(f); + //bncsutil_debug_message_a("error: Failed to map file %s into memory", + // files[i]); + return 0; + } + + if (remainder == 0) { + // Mapped buffer may be used directly, without padding. + dwBuf = (uint32_t*) file_buffer; + buffer_size = file_len; + } else { + // Must be padded to nearest KB. + size_t extra = 1024 - remainder; + uint8_t pad = (uint8_t) 0xFF; + uint8_t* pad_dest; + + buffer_size = file_len + extra; + dwBuf = (uint32_t*) malloc(buffer_size); + if (!dwBuf) { + //bncsutil_debug_message_a("error: Failed to allocate %d bytes " + // "of memory as a temporary buffer", buffer_size); + file_unmap(f, file_buffer); + file_close(f); + return 0; + } + + memcpy(dwBuf, file_buffer, file_len); + file_unmap(f, file_buffer); + file_buffer = (uint8_t*) 0; + + pad_dest = ((uint8_t*) dwBuf) + file_len; + for (size_t j = file_len; j < buffer_size; j++) { + *pad_dest++ = pad--; + } + + } + + current = dwBuf; + for (size_t j = 0; j < buffer_size; j += 4) { + values[3] = LSB4(*(current++)); + for (int k = 0; k < curFormula; k++) { + switch (ops[k]) { + case '+': + values[ovd[k]] = values[ovs1[k]] + values[ovs2[k]]; + break; + case '-': + values[ovd[k]] = values[ovs1[k]] - values[ovs2[k]]; + break; + case '^': + values[ovd[k]] = values[ovs1[k]] ^ values[ovs2[k]]; + break; + case '*': + // well, you never know + values[ovd[k]] = values[ovs1[k]] * values[ovs2[k]]; + break; + case '/': + // well, you never know + values[ovd[k]] = values[ovs1[k]] / values[ovs2[k]]; + break; + default: + // unrecognized operation + // shit + file_unmap(f, dwBuf); + file_close(f); + return 0; + } + } + } + + if (file_buffer) + file_unmap(f, file_buffer); + else if (dwBuf && file_buffer == 0) + free(dwBuf); // padded buffer + file_close(f); + } + + *checksum = (unsigned long) LSB4(values[2]); #if DEBUG - bncsutil_debug_message_a("\tChecksum = %lu", *checksum); + bncsutil_debug_message_a("\tChecksum = %lu", *checksum); #endif - return 1; + return 1; } MEXP(int) checkRevisionFlat(const char* valueString, const char* file1, const char* file2, const char* file3, int mpqNumber, unsigned long* checksum) { - const char* files[] = - {file1, file2, file3}; - return checkRevision(valueString, files, 3, mpqNumber, - checksum); + const char* files[] = + {file1, file2, file3}; + return checkRevision(valueString, files, 3, mpqNumber, + checksum); } MEXP(int) getExeInfo(const char* file_name, char* exe_info, - size_t exe_info_size, uint32_t* version, int platform) + size_t exe_info_size, uint32_t* version, int platform) { - const char* base = (char*) 0; - unsigned long file_size; - FILE* f = (FILE*) 0; - int ret; + const char* base = (char*) 0; + unsigned long file_size; + FILE* f = (FILE*) 0; + int ret; #ifdef MOS_WINDOWS - HANDLE hFile; - FILETIME ft; - SYSTEMTIME st; - LPBYTE buf; - VS_FIXEDFILEINFO* ffi; - DWORD infoSize, bytesRead; + HANDLE hFile; + FILETIME ft; + SYSTEMTIME st; + LPBYTE buf; + VS_FIXEDFILEINFO* ffi; + DWORD infoSize, bytesRead; #else - cm_pe_t pe; - cm_pe_resdir_t* root; - cm_pe_resdir_t* dir; - cm_pe_version_t ffi; - size_t i; - struct stat st; - struct tm* time; + cm_pe_t pe; + cm_pe_resdir_t* root; + cm_pe_resdir_t* dir; + cm_pe_version_t ffi; + size_t i; + struct stat st; + struct tm* time; #endif - - if (!file_name || !exe_info || !exe_info_size || !version) - return 0; - - base = get_basename(file_name); - - switch (platform) { - case BNCSUTIL_PLATFORM_X86: -#ifdef MOS_WINDOWS - infoSize = GetFileVersionInfoSize(file_name, &bytesRead); - if (infoSize == 0) - return 0; - buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, - PAGE_READWRITE); - if (buf == NULL) - return 0; - if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) - return 0; - if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) - return 0; - - *version = - ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | - ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | - ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | - (LOWORD(ffi->dwProductVersionLS) & 0xFF); + + if (!file_name || !exe_info || !exe_info_size || !version) + return 0; + + base = get_basename(file_name); + + switch (platform) { + case BNCSUTIL_PLATFORM_X86: +#ifdef MOS_WINDOWS + infoSize = GetFileVersionInfoSize(file_name, &bytesRead); + if (infoSize == 0) + return 0; + buf = (LPBYTE) VirtualAlloc(NULL, infoSize, MEM_COMMIT, + PAGE_READWRITE); + if (buf == NULL) + return 0; + if (GetFileVersionInfo(file_name, NULL, infoSize, buf) == FALSE) + return 0; + if (!VerQueryValue(buf, "\\", (LPVOID*) &ffi, (PUINT) &infoSize)) + return 0; + + *version = + ((HIWORD(ffi->dwProductVersionMS) & 0xFF) << 24) | + ((LOWORD(ffi->dwProductVersionMS) & 0xFF) << 16) | + ((HIWORD(ffi->dwProductVersionLS) & 0xFF) << 8) | + (LOWORD(ffi->dwProductVersionLS) & 0xFF); #if DEBUG - bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", - base, (HIWORD(ffi->dwProductVersionMS) & 0xFF), - (LOWORD(ffi->dwProductVersionMS) & 0xFF), - (HIWORD(ffi->dwProductVersionLS) & 0xFF), - (LOWORD(ffi->dwProductVersionLS) & 0xFF), - *version); + bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", + base, (HIWORD(ffi->dwProductVersionMS) & 0xFF), + (LOWORD(ffi->dwProductVersionMS) & 0xFF), + (HIWORD(ffi->dwProductVersionLS) & 0xFF), + (LOWORD(ffi->dwProductVersionLS) & 0xFF), + *version); #endif - VirtualFree(buf, 0lu, MEM_RELEASE); + VirtualFree(buf, 0lu, MEM_RELEASE); #else - pe = cm_pe_load(file_name); - if (!pe) - return 0; - root = cm_pe_load_resources(pe); - if (!root) { - cm_pe_unload(pe); - return 0; - } - - for (i = 0; i < root->subdir_count; i++) { - dir = (root->subdirs + i); - if (dir->name == 16) { - if (!cm_pe_fixed_version(pe, dir->subdirs->resources, - &ffi)) - { - cm_pe_unload_resources(root); - cm_pe_unload(pe); - return 0; - } - break; - } - } - *version = - ((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) | - ((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) | - ((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | - (LOWORD(ffi.dwProductVersionLS) & 0xFF); + pe = cm_pe_load(file_name); + if (!pe) + return 0; + root = cm_pe_load_resources(pe); + if (!root) { + cm_pe_unload(pe); + return 0; + } + + for (i = 0; i < root->subdir_count; i++) { + dir = (root->subdirs + i); + if (dir->name == 16) { + if (!cm_pe_fixed_version(pe, dir->subdirs->resources, + &ffi)) + { + cm_pe_unload_resources(root); + cm_pe_unload(pe); + return 0; + } + break; + } + } + *version = + ((HIWORD(ffi.dwProductVersionMS) & 0xFF) << 24) | + ((LOWORD(ffi.dwProductVersionMS) & 0xFF) << 16) | + ((HIWORD(ffi.dwProductVersionLS) & 0xFF) << 8) | + (LOWORD(ffi.dwProductVersionLS) & 0xFF); #if DEBUG - bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", - base, (HIWORD(ffi.dwProductVersionMS) & 0xFF), - (LOWORD(ffi.dwProductVersionMS) & 0xFF), - (HIWORD(ffi.dwProductVersionLS) & 0xFF), - (LOWORD(ffi.dwProductVersionLS) & 0xFF), - *version); + bncsutil_debug_message_a("%s version = %d.%d.%d.%d (0x%08X)", + base, (HIWORD(ffi.dwProductVersionMS) & 0xFF), + (LOWORD(ffi.dwProductVersionMS) & 0xFF), + (HIWORD(ffi.dwProductVersionLS) & 0xFF), + (LOWORD(ffi.dwProductVersionLS) & 0xFF), + *version); #endif - - cm_pe_unload_resources(root); - cm_pe_unload(pe); + + cm_pe_unload_resources(root); + cm_pe_unload(pe); #endif - break; - case BNCSUTIL_PLATFORM_MAC: - case BNCSUTIL_PLATFORM_OSX: - f = fopen(file_name, "r"); - if (!f) - return 0; - if (fseek(f, -4, SEEK_END) != 0) { - fclose(f); - return 0; - } - if (fread(version, 4, 1, f) != 1) { - fclose(f); - return 0; - } + break; + case BNCSUTIL_PLATFORM_MAC: + case BNCSUTIL_PLATFORM_OSX: + f = fopen(file_name, "r"); + if (!f) + return 0; + if (fseek(f, -4, SEEK_END) != 0) { + fclose(f); + return 0; + } + if (fread(version, 4, 1, f) != 1) { + fclose(f); + return 0; + } #ifdef MOS_WINDOWS - fclose(f); + fclose(f); #endif - } - + } + #ifdef MOS_WINDOWS - hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - return 0; - file_size = GetFileSize(hFile, NULL); - if (!GetFileTime(hFile, &ft, NULL, NULL)) { - CloseHandle(hFile); - return 0; - } - - if (!FileTimeToSystemTime(&ft, &st)) { - CloseHandle(hFile); - return 0; - } - CloseHandle(hFile); - - ret = snprintf(exe_info, exe_info_size, - "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth, - st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond, - file_size); + hFile = CreateFile(file_name, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + return 0; + file_size = GetFileSize(hFile, NULL); + if (!GetFileTime(hFile, &ft, NULL, NULL)) { + CloseHandle(hFile); + return 0; + } + + if (!FileTimeToSystemTime(&ft, &st)) { + CloseHandle(hFile); + return 0; + } + CloseHandle(hFile); + + ret = snprintf(exe_info, exe_info_size, + "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, st.wMonth, + st.wDay, (st.wYear % 100), st.wHour, st.wMinute, st.wSecond, + file_size); #else - if (!f) - f = fopen(file_name, "r"); - if (!f) - return 0; - if (fseek(f, 0, SEEK_END) == -1) { - fclose(f); - return 0; - } - file_size = ftell(f); - fclose(f); - - if (stat(file_name, &st) != 0) - return 0; - - time = gmtime(&st.st_mtime); - if (!time) - return 0; - - switch (platform) { - case BNCSUTIL_PLATFORM_MAC: - case BNCSUTIL_PLATFORM_OSX: - if (time->tm_year >= 100) // y2k - time->tm_year -= 100; - break; - } - - ret = (int) snprintf(exe_info, exe_info_size, - "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, - (time->tm_mon+1), time->tm_mday, time->tm_year, - time->tm_hour, time->tm_min, time->tm_sec, file_size); + if (!f) + f = fopen(file_name, "r"); + if (!f) + return 0; + if (fseek(f, 0, SEEK_END) == -1) { + fclose(f); + return 0; + } + file_size = ftell(f); + fclose(f); + + if (stat(file_name, &st) != 0) + return 0; + + time = gmtime(&st.st_mtime); + if (!time) + return 0; + + switch (platform) { + case BNCSUTIL_PLATFORM_MAC: + case BNCSUTIL_PLATFORM_OSX: + if (time->tm_year >= 100) // y2k + time->tm_year -= 100; + break; + } + + ret = (int) snprintf(exe_info, exe_info_size, + "%s %02u/%02u/%02u %02u:%02u:%02u %lu", base, + (time->tm_mon+1), time->tm_mday, time->tm_year, + time->tm_hour, time->tm_min, time->tm_sec, file_size); #endif #if DEBUG - bncsutil_debug_message(exe_info); + bncsutil_debug_message(exe_info); #endif - return ret; + return ret; } #ifdef __cplusplus diff --git a/src/bncsutil/checkrevision.h b/src/bncsutil/checkrevision.h index 1e42fe7..c31aa9f 100644 --- a/src/bncsutil/checkrevision.h +++ b/src/bncsutil/checkrevision.h @@ -71,8 +71,8 @@ MEXP(int) checkRevision( MEXP(int) checkRevisionFlat( const char* valueString, const char* file1, - const char* file2, - const char* file3, + const char* file2, + const char* file3, int mpqNumber, unsigned long* checksum ); @@ -87,11 +87,11 @@ MEXP(int) checkRevisionFlat( * necessary. */ MEXP(int) getExeInfo(const char* file_name, - char* exe_info, - size_t exe_info_size, - uint32_t* version, - int platform); - + char* exe_info, + size_t exe_info_size, + uint32_t* version, + int platform); + /** * Gets the seed value for the given MPQ file. If no seed value for the given * MPQ is registered with BNCSutil, returns 0. diff --git a/src/bncsutil/debug.c b/src/bncsutil/debug.c index 5d07b62..587edeb 100644 --- a/src/bncsutil/debug.c +++ b/src/bncsutil/debug.c @@ -20,14 +20,14 @@ typedef struct _bncsutil_debug_env { - int enabled; + int enabled; #ifdef MOS_WINDOWS - HANDLE output; - BOOL console_was_created; - WORD orig_attributes; - WORD sans_foreground; + HANDLE output; + BOOL console_was_created; + WORD orig_attributes; + WORD sans_foreground; #else - FILE* output; + FILE* output; #endif } debug_env_t; @@ -36,109 +36,109 @@ const char default_err_msg[] = "[unknown error]"; #ifdef MOS_WINDOWS BOOL debug_set_color(debug_env_t env, WORD color) { - return SetConsoleTextAttribute(env.output, color | env.sans_foreground); + return SetConsoleTextAttribute(env.output, color | env.sans_foreground); } BOOL debug_restore_color(debug_env_t env) { - return SetConsoleTextAttribute(env.output, env.orig_attributes); + return SetConsoleTextAttribute(env.output, env.orig_attributes); } BOOL debug_intense_color(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env.output, &info)) - return FALSE; - return SetConsoleTextAttribute(env.output, info.wAttributes | - FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env.output, &info)) + return FALSE; + return SetConsoleTextAttribute(env.output, info.wAttributes | + FOREGROUND_INTENSITY); } BOOL debug_mellow_color(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env.output, &info)) - return FALSE; - return SetConsoleTextAttribute(env.output, info.wAttributes | - ~FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env.output, &info)) + return FALSE; + return SetConsoleTextAttribute(env.output, info.wAttributes | + ~FOREGROUND_INTENSITY); } void debug_setup_console(debug_env_t env) { - CONSOLE_SCREEN_BUFFER_INFO info; - - if (AllocConsole()) { - // only set title if new console was created - SetConsoleTitle("BNCSutil Debug Console"); - env.console_was_created = TRUE; - } else { - env.console_was_created = FALSE; - } - env.output = GetStdHandle(STD_OUTPUT_HANDLE); - GetConsoleScreenBufferInfo(env.output, &info); - env.orig_attributes = info.wAttributes; - env.sans_foreground = info.wAttributes & - ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); + CONSOLE_SCREEN_BUFFER_INFO info; + + if (AllocConsole()) { + // only set title if new console was created + SetConsoleTitle("BNCSutil Debug Console"); + env.console_was_created = TRUE; + } else { + env.console_was_created = FALSE; + } + env.output = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(env.output, &info); + env.orig_attributes = info.wAttributes; + env.sans_foreground = info.wAttributes & + ~(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | + FOREGROUND_INTENSITY); } #endif size_t debug_write(debug_env_t env, const char* message) { #ifdef MOS_WINDOWS - DWORD chars_written; - BOOL res; - if (!env.output) - debug_setup_console(env); - res = WriteConsole(env.output, message, (DWORD) strlen(message), - &chars_written, (LPVOID) 0); - return (res) ? (size_t) chars_written : (size_t) -1; + DWORD chars_written; + BOOL res; + if (!env.output) + debug_setup_console(env); + res = WriteConsole(env.output, message, (DWORD) strlen(message), + &chars_written, (LPVOID) 0); + return (res) ? (size_t) chars_written : (size_t) -1; #else - return fwrite(message, 1, strlen(message), env->output); + return fwrite(message, 1, strlen(message), env->output); #endif } size_t get_console_width(debug_env_t env) { #ifdef MOS_WINDOWS - CONSOLE_SCREEN_BUFFER_INFO info; - if (!GetConsoleScreenBufferInfo(env.output, &info)) - return (size_t) 0; - return (size_t) info.dwSize.X; + CONSOLE_SCREEN_BUFFER_INFO info; + if (!GetConsoleScreenBufferInfo(env.output, &info)) + return (size_t) 0; + return (size_t) info.dwSize.X; #else - char* columns = getenv("COLUMNS"); - if (!columns) - return (size_t) 0; - return (size_t) strtol(columns, (char**) 0, 0); + char* columns = getenv("COLUMNS"); + if (!columns) + return (size_t) 0; + return (size_t) strtol(columns, (char**) 0, 0); #endif } char* produce_dump(const char* data, size_t length) { - return (char*) 0; + return (char*) 0; } debug_env_t get_debug_environment() { - static debug_env_t env = (debug_env_t) 0; - - if (!env) { - env = (debug_env_t) malloc(sizeof(struct _bncsutil_debug_env)); + static debug_env_t env = (debug_env_t) 0; + + if (!env) { + env = (debug_env_t) malloc(sizeof(struct _bncsutil_debug_env)); /*#if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES - env->enabled = 1; + env->enabled = 1; #else - env->enabled = 0; + env->enabled = 0; #endif*/ - env->enabled = 0; + env->enabled = 0; #ifdef MOS_WINDOWS - env->output = (HANDLE) NULL; - //debug_setup_console(env); + env->output = (HANDLE) NULL; + //debug_setup_console(env); #else - env->output = stderr; + env->output = stderr; #endif - } - - return env; + } + + return env; } /** @@ -146,8 +146,8 @@ debug_env_t get_debug_environment() */ MEXP(int) bncsutil_debug_status(void) { - debug_env_t env = get_debug_environment(); - return env->enabled; + debug_env_t env = get_debug_environment(); + return env->enabled; } /** * Set new_status to zero to turn debugging messages off or nonzero to turn @@ -155,197 +155,197 @@ MEXP(int) bncsutil_debug_status(void) */ MEXP(int) bncsutil_set_debug_status(int new_status) { - debug_env_t env = get_debug_environment(); - if (!env) { - return 0; - } + debug_env_t env = get_debug_environment(); + if (!env) { + return 0; + } #ifdef MOS_WINDOWS - if (env->enabled && !new_status && env->console_was_created) { - FreeConsole(); - } else if (!env->enabled && new_status) { - debug_setup_console(env); - } + if (env->enabled && !new_status && env->console_was_created) { + FreeConsole(); + } else if (!env->enabled && new_status) { + debug_setup_console(env); + } #endif - env->enabled = (new_status != 0) ? 1 : 0; - return 1; + env->enabled = (new_status != 0) ? 1 : 0; + return 1; } MEXP(int) bncsutil_internal_debug_messages() { #if DEBUG - return 1; + return 1; #else - return 0; + return 0; #endif } MEXP(void) bncsutil_debug_message(const char* message) { - debug_env_t env = get_debug_environment(); - char timestamp[12]; - /*size_t length;*/ + debug_env_t env = get_debug_environment(); + char timestamp[12]; + /*size_t length;*/ #ifdef MOS_WINDOWS - SYSTEMTIME local_time; + SYSTEMTIME local_time; #else - time_t unix_time; - struct tm* local_time; + time_t unix_time; + struct tm* local_time; #endif - if (!env->enabled) { - return; - } + if (!env->enabled) { + return; + } #ifdef MOS_WINDOWS - GetLocalTime(&local_time); - sprintf(timestamp, "[%02d:%02d:%02d] ", local_time.wHour, - local_time.wMinute, local_time.wSecond); - debug_set_color(env, FOREGROUND_RED | FOREGROUND_GREEN | - FOREGROUND_INTENSITY); -#else - time(&unix_time); - local_time = localtime(&unix_time); - sprintf(timestamp, "[%02d:%02d:%02d] ", local_time->tm_hour, - local_time->tm_min, local_time->tm_sec); + GetLocalTime(&local_time); + sprintf(timestamp, "[%02d:%02d:%02d] ", local_time.wHour, + local_time.wMinute, local_time.wSecond); + debug_set_color(env, FOREGROUND_RED | FOREGROUND_GREEN | + FOREGROUND_INTENSITY); +#else + time(&unix_time); + local_time = localtime(&unix_time); + sprintf(timestamp, "[%02d:%02d:%02d] ", local_time->tm_hour, + local_time->tm_min, local_time->tm_sec); #endif - debug_write(env, timestamp); + debug_write(env, timestamp); #ifdef MOS_WINDOWS - debug_restore_color(env); + debug_restore_color(env); #endif - - debug_write(env, message); - debug_write(env, "\r\n"); + + debug_write(env, message); + debug_write(env, "\r\n"); } MEXP(void) bncsutil_debug_message_a(const char* message, ...) { - char buf[4092]; - va_list args; - va_start(args, message); - - vsprintf(buf, message, args); - va_end(args); - - bncsutil_debug_message(buf); + char buf[4092]; + va_list args; + va_start(args, message); + + vsprintf(buf, message, args); + va_end(args); + + bncsutil_debug_message(buf); } MEXP(void) bncsutil_debug_dump(const void* data, size_t data_length) { - char ascii[] = " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; - char hex[4]; - char pos_indicator[] = "0000 "; - debug_env_t env = get_debug_environment(); - size_t i; - size_t j = 2; /* printing to ASCII buffer skips over 2 spaces */ - size_t k; - char cur; - int on_boundary; - size_t current_string_length; - - if (!env->enabled) { - return; - } - - debug_intense_color(env); - for (i = 0; i < data_length; i++) { - on_boundary = ((i + 1) % 16 == 0); - - if ((i + 1) % 16 == 1) { + char ascii[] = " \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + char hex[4]; + char pos_indicator[] = "0000 "; + debug_env_t env = get_debug_environment(); + size_t i; + size_t j = 2; /* printing to ASCII buffer skips over 2 spaces */ + size_t k; + char cur; + int on_boundary; + size_t current_string_length; + + if (!env->enabled) { + return; + } + + debug_intense_color(env); + for (i = 0; i < data_length; i++) { + on_boundary = ((i + 1) % 16 == 0); + + if ((i + 1) % 16 == 1) { #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_RED | FOREGROUND_BLUE | - FOREGROUND_INTENSITY); + debug_set_color(env, FOREGROUND_RED | FOREGROUND_BLUE | + FOREGROUND_INTENSITY); #endif - debug_write(env, pos_indicator); + debug_write(env, pos_indicator); #ifdef MOS_WINDOWS - debug_restore_color(env); + debug_restore_color(env); #endif - } - - cur = *(((char*) data) + i); - /* The cast to unsigned char and then int is required to properly - * handle 8 bit characters. */ - ascii[j++] = (isprint((int) (unsigned char) cur)) ? cur : '.'; - sprintf(hex, "%02X ", (cur & 0xFF)); - debug_write(env, hex); - - if ((i + 1) % 8 == 0) { - debug_write(env, " "); - } - - if (on_boundary || (i + 1) == data_length) { - if (!on_boundary) { - current_string_length = 3 * (i % 16); - if ((i % 16) > 8) - current_string_length++; - - for (k = 0; k < (47 - current_string_length); k++) { - debug_write(env, " "); - } - } + } + + cur = *(((char*) data) + i); + /* The cast to unsigned char and then int is required to properly + * handle 8 bit characters. */ + ascii[j++] = (isprint((int) (unsigned char) cur)) ? cur : '.'; + sprintf(hex, "%02X ", (cur & 0xFF)); + debug_write(env, hex); + + if ((i + 1) % 8 == 0) { + debug_write(env, " "); + } + + if (on_boundary || (i + 1) == data_length) { + if (!on_boundary) { + current_string_length = 3 * (i % 16); + if ((i % 16) > 8) + current_string_length++; + + for (k = 0; k < (47 - current_string_length); k++) { + debug_write(env, " "); + } + } #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_GREEN | - FOREGROUND_INTENSITY); -#endif - ascii[j] = 0; - debug_write(env, ascii); - debug_write(env, "\r\n"); - j = 2; /* reset position in ASCII buffer */ + debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_INTENSITY); +#endif + ascii[j] = 0; + debug_write(env, ascii); + debug_write(env, "\r\n"); + j = 2; /* reset position in ASCII buffer */ #ifdef MOS_WINDOWS - debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_INTENSITY); + debug_set_color(env, FOREGROUND_BLUE | FOREGROUND_INTENSITY); #endif - sprintf(pos_indicator, "%04X ", i + 1); + sprintf(pos_indicator, "%04X ", i + 1); #ifdef MOS_WINDOWS - debug_restore_color(env); -#endif - } - } + debug_restore_color(env); +#endif + } + } } #ifdef MOS_WINDOWS const char* sys_error_msg() { - const char* buffer; - DWORD res; - - res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - (const void*) 0, (DWORD) 0, (DWORD) 0, (LPTSTR) &buffer, (DWORD) 0, - (va_list*) 0); - if (!res) { - bncsutil_debug_message("error: Failed to get Windows error message."); - return default_err_msg; - } - - return buffer; + const char* buffer; + DWORD res; + + res = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + (const void*) 0, (DWORD) 0, (DWORD) 0, (LPTSTR) &buffer, (DWORD) 0, + (va_list*) 0); + if (!res) { + bncsutil_debug_message("error: Failed to get Windows error message."); + return default_err_msg; + } + + return buffer; } void free_sys_err_msg(const char* message_pointer) { - if (message_pointer) - LocalFree(message_pointer); + if (message_pointer) + LocalFree(message_pointer); } #else const char* sys_error_msg() { - return (const char*) strerror(errno); + return (const char*) strerror(errno); } void free_sys_err_msg() { - /* Do nothing. */ + /* Do nothing. */ } #endif MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length) { - + } #ifdef MOS_WINDOWS MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, - size_t length) + size_t length) { - + } #endif diff --git a/src/bncsutil/debug.h b/src/bncsutil/debug.h index 21c66f9..b799a17 100644 --- a/src/bncsutil/debug.h +++ b/src/bncsutil/debug.h @@ -11,13 +11,13 @@ /* #undef DEBUG */ /* #if defined(BNCSUTIL_DEBUG_MESSAGES) && BNCSUTIL_DEBUG_MESSAGES */ -/* # define INTERNAL_DEBUG(msg) bncsutil_debug_message(msg) */ -/* # define INTERNAL_DUMP(data, length) bncsutil_debug_dump((data), (length)) */ -/* # define DEBUG 1 */ +/* # define INTERNAL_DEBUG(msg) bncsutil_debug_message(msg) */ +/* # define INTERNAL_DUMP(data, length) bncsutil_debug_dump((data), (length)) */ +/* # define DEBUG 1 */ /* #else */ -/* # define INTERNAL_DEBUG(msg) */ -/* # define INTERNAL_DUMP(data, length) */ -/* # define DEBUG 0 */ +/* # define INTERNAL_DEBUG(msg) */ +/* # define INTERNAL_DUMP(data, length) */ +/* # define DEBUG 0 */ /* #endif */ /* #undef DEBUG */ @@ -82,7 +82,7 @@ /* MEXP(void) bncsutil_print_dump(FILE* stream, const void* data, size_t length); */ /* #ifdef MOS_WINDOWS */ /* //MEXP(void) bncsutil_print_dump_win(HANDLE stream, const void* data, */ -/* // size_t length); */ +/* // size_t length); */ /* #endif */ /* #ifdef __cplusplus */ diff --git a/src/bncsutil/decodekey.cpp b/src/bncsutil/decodekey.cpp index 6caf08d..c38276e 100644 --- a/src/bncsutil/decodekey.cpp +++ b/src/bncsutil/decodekey.cpp @@ -32,11 +32,11 @@ #include #ifdef MOS_WINDOWS - #include + #include #else - #include - #include - #include + #include + #include + #include #endif #include #include @@ -61,37 +61,37 @@ unsigned int numDecoders = 0; unsigned int sizeDecoders = 0; #ifdef MOS_WINDOWS -// HANDLE mutex; - CRITICAL_SECTION kd_control; +// HANDLE mutex; + CRITICAL_SECTION kd_control; #else - pthread_mutex_t mutex; + pthread_mutex_t mutex; #endif int kd_lock_decoders() { #ifdef MOS_WINDOWS -/* DWORD dwWaitResult; - dwWaitResult = WaitForSingleObject(mutex, MUTEX_TIMEOUT_MS); - switch (dwWaitResult) { - case WAIT_OBJECT_0: - // success - break; - case WAIT_TIMEOUT: - return 0; - break; - case WAIT_ABANDONED: - // weird, but should be OK - break; - default: - return 0; - break; - }*/ - EnterCriticalSection(&kd_control); +/* DWORD dwWaitResult; + dwWaitResult = WaitForSingleObject(mutex, MUTEX_TIMEOUT_MS); + switch (dwWaitResult) { + case WAIT_OBJECT_0: + // success + break; + case WAIT_TIMEOUT: + return 0; + break; + case WAIT_ABANDONED: + // weird, but should be OK + break; + default: + return 0; + break; + }*/ + EnterCriticalSection(&kd_control); #else - int err = 0; - pthread_cond_t cond = PTHREAD_COND_INITIALIZER; - struct timespec wait_time = {0, MUTEX_TIMEOUT_MS * 1000}; - - err = pthread_cond_timedwait(&cond, &mutex, &wait_time); + int err = 0; + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; + struct timespec wait_time = {0, MUTEX_TIMEOUT_MS * 1000}; + + err = pthread_cond_timedwait(&cond, &mutex, &wait_time); switch (err) { case 0: // success @@ -99,7 +99,7 @@ int kd_lock_decoders() { default: // error return 0; - } + } #endif return 1; } @@ -111,312 +111,312 @@ int kd_lock_decoders() { #endif MEXP(int) kd_quick(const char* cd_key, uint32_t client_token, - uint32_t server_token, uint32_t* public_value, - uint32_t* product, char* hash_buffer, size_t buffer_len) + uint32_t server_token, uint32_t* public_value, + uint32_t* product, char* hash_buffer, size_t buffer_len) { - CDKeyDecoder kd(cd_key, strlen(cd_key)); - size_t hash_len; - - if (!kd.isKeyValid()) - return 0; - - *public_value = kd.getVal1(); - *product = kd.getProduct(); - - hash_len = kd.calculateHash(client_token, server_token); - if (!hash_len || hash_len > buffer_len) - return 0; - - kd.getHash(hash_buffer); - return 1; + CDKeyDecoder kd(cd_key, strlen(cd_key)); + size_t hash_len; + + if (!kd.isKeyValid()) + return 0; + + *public_value = kd.getVal1(); + *product = kd.getProduct(); + + hash_len = kd.calculateHash(client_token, server_token); + if (!hash_len || hash_len > buffer_len) + return 0; + + kd.getHash(hash_buffer); + return 1; } MEXP(int) kd_init() { - static int has_run = 0; + static int has_run = 0; + + if (has_run) + return 1; - if (has_run) - return 1; - #ifdef MOS_WINDOWS - /*mutex = CreateMutex(NULL, FALSE, NULL); - if (mutex == NULL) - return 0;*/ - InitializeCriticalSection(&kd_control); + /*mutex = CreateMutex(NULL, FALSE, NULL); + if (mutex == NULL) + return 0;*/ + InitializeCriticalSection(&kd_control); #else - if (pthread_mutex_init(&mutex, NULL)) - return 0; + if (pthread_mutex_init(&mutex, NULL)) + return 0; #endif - numDecoders = 0; - sizeDecoders = 0; - decoders = (CDKeyDecoder**) 0; - has_run = 1; + numDecoders = 0; + sizeDecoders = 0; + decoders = (CDKeyDecoder**) 0; + has_run = 1; #if DEBUG - bncsutil_debug_message("Initialized key decoding C API."); + bncsutil_debug_message("Initialized key decoding C API."); #endif - return 1; + return 1; } unsigned int kd_findAvailable() { - unsigned int i; - CDKeyDecoder** d; - - d = decoders; - for (i = 0; i < sizeDecoders; i++) { - if (*d == (CDKeyDecoder*) 0) - return i; - d++; - } - - // no room available, must expand - decoders = (CDKeyDecoder**) realloc(decoders, sizeof(CDKeyDecoder*) * - (sizeDecoders + DEFAULT_DECODERS_SIZE)); - if (!decoders) - return (unsigned int) -1; - - memset(decoders + sizeDecoders, 0, - sizeof(CDKeyDecoder*) * DEFAULT_DECODERS_SIZE); // zero new memory - - i = sizeDecoders; - sizeDecoders += DEFAULT_DECODERS_SIZE; - return i; + unsigned int i; + CDKeyDecoder** d; + + d = decoders; + for (i = 0; i < sizeDecoders; i++) { + if (*d == (CDKeyDecoder*) 0) + return i; + d++; + } + + // no room available, must expand + decoders = (CDKeyDecoder**) realloc(decoders, sizeof(CDKeyDecoder*) * + (sizeDecoders + DEFAULT_DECODERS_SIZE)); + if (!decoders) + return (unsigned int) -1; + + memset(decoders + sizeDecoders, 0, + sizeof(CDKeyDecoder*) * DEFAULT_DECODERS_SIZE); // zero new memory + + i = sizeDecoders; + sizeDecoders += DEFAULT_DECODERS_SIZE; + return i; } MEXP(int) kd_create(const char* cdkey, int keyLength) { - unsigned int i; - CDKeyDecoder** d; - static int dcs_initialized = 0; - - if (!dcs_initialized) { - if (!kd_init()) - return -1; - dcs_initialized = 1; - } - - if (!kd_lock_decoders()) return -1; - - i = kd_findAvailable(); - if (i == (unsigned int) -1) - return -1; - - d = (decoders + i); - *d = new CDKeyDecoder(cdkey, keyLength); - if (!(**d).isKeyValid()) { - delete *d; - *d = (CDKeyDecoder*) 0; - return -1; - } - - numDecoders++; - - kd_unlock_decoders(); - return (int) i; + unsigned int i; + CDKeyDecoder** d; + static int dcs_initialized = 0; + + if (!dcs_initialized) { + if (!kd_init()) + return -1; + dcs_initialized = 1; + } + + if (!kd_lock_decoders()) return -1; + + i = kd_findAvailable(); + if (i == (unsigned int) -1) + return -1; + + d = (decoders + i); + *d = new CDKeyDecoder(cdkey, keyLength); + if (!(**d).isKeyValid()) { + delete *d; + *d = (CDKeyDecoder*) 0; + return -1; + } + + numDecoders++; + + kd_unlock_decoders(); + return (int) i; } /* MEXP(int) kd_create(char* cdkey, int keyLength) { if (!kd_lock_decoders()) return -1; - CDKeyDecoder* d; - unsigned int i; - if (numDecoders >= sizeDecoders) { - CDKeyDecoder** temp = new CDKeyDecoder*[sizeDecoders]; - for (unsigned int j = 0; j < sizeDecoders; j++) { - temp[j] = decoders[j]; - } - delete [] decoders; - decoders = new CDKeyDecoder*[sizeDecoders + DEFAULT_DECODERS_SIZE]; - - for (unsigned int j = 0; j < sizeDecoders; j++) { - decoders[j] = temp[j]; - } - delete [] temp; - sizeDecoders += DEFAULT_DECODERS_SIZE; - } - i = numDecoders++; - decoders[i] = new CDKeyDecoder(cdkey, keyLength); - d = decoders[i]; - if (!d->isKeyValid()) { - delete decoders[i]; - return -1; - } - kd_unlock_decoders(); - - d = NULL; - return (int) i; + CDKeyDecoder* d; + unsigned int i; + if (numDecoders >= sizeDecoders) { + CDKeyDecoder** temp = new CDKeyDecoder*[sizeDecoders]; + for (unsigned int j = 0; j < sizeDecoders; j++) { + temp[j] = decoders[j]; + } + delete [] decoders; + decoders = new CDKeyDecoder*[sizeDecoders + DEFAULT_DECODERS_SIZE]; + + for (unsigned int j = 0; j < sizeDecoders; j++) { + decoders[j] = temp[j]; + } + delete [] temp; + sizeDecoders += DEFAULT_DECODERS_SIZE; + } + i = numDecoders++; + decoders[i] = new CDKeyDecoder(cdkey, keyLength); + d = decoders[i]; + if (!d->isKeyValid()) { + delete decoders[i]; + return -1; + } + kd_unlock_decoders(); + + d = NULL; + return (int) i; }*/ MEXP(int) kd_free(int decoder) { - CDKeyDecoder* d; + CDKeyDecoder* d; + + if (!kd_lock_decoders()) return 0; - if (!kd_lock_decoders()) return 0; + if ((unsigned int) decoder >= sizeDecoders) + return 0; - if ((unsigned int) decoder >= sizeDecoders) - return 0; + d = *(decoders + decoder); + if (!d) + return 0; - d = *(decoders + decoder); - if (!d) - return 0; + delete d; + *(decoders + decoder) = (CDKeyDecoder*) 0; - delete d; - *(decoders + decoder) = (CDKeyDecoder*) 0; - - kd_unlock_decoders(); - return 1; + kd_unlock_decoders(); + return 1; } MEXP(int) kd_val2Length(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getVal2Length(); - value = d->getVal2Length(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_product(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getProduct(); - value = d->getProduct(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_val1(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getVal1(); - value = d->getVal1(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_val2(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; - if (!kd_lock_decoders()) return -1; + if (!kd_lock_decoders()) return -1; + + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->getVal2(); - value = d->getVal2(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_longVal2(int decoder, char* out) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; - if (!kd_lock_decoders()) return -1; + if (!kd_lock_decoders()) return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - value = d->getLongVal2(out); - - kd_unlock_decoders(); - return value; + value = d->getLongVal2(out); + + kd_unlock_decoders(); + return value; } MEXP(int) kd_calculateHash(int decoder, uint32_t clientToken, - uint32_t serverToken) + uint32_t serverToken) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = (int) d->calculateHash(clientToken, serverToken); - value = (int) d->calculateHash(clientToken, serverToken); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_getHash(int decoder, char* out) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = (int) d->getHash(out); - value = (int) d->getHash(out); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } MEXP(int) kd_isValid(int decoder) { - CDKeyDecoder* d; - int value; + CDKeyDecoder* d; + int value; + + if (!kd_lock_decoders()) return -1; - if (!kd_lock_decoders()) return -1; + if ((unsigned int) decoder >= sizeDecoders) + return -1; - if ((unsigned int) decoder >= sizeDecoders) - return -1; + d = *(decoders + decoder); + if (!d) + return -1; - d = *(decoders + decoder); - if (!d) - return -1; + value = d->isKeyValid(); - value = d->isKeyValid(); - - kd_unlock_decoders(); - return value; + kd_unlock_decoders(); + return value; } #ifdef __cplusplus diff --git a/src/bncsutil/decodekey.h b/src/bncsutil/decodekey.h index dbade12..5dc8033 100644 --- a/src/bncsutil/decodekey.h +++ b/src/bncsutil/decodekey.h @@ -30,7 +30,7 @@ #ifdef __cplusplus extern "C" { #endif - + /** * Decodes a CD-key, retrieves its relevant values, and calculates a hash * suitable for SID_AUTH_CHECK (0x51) in one function call. Returns 1 on @@ -38,8 +38,8 @@ extern "C" { * calling this function. Available since BNCSutil 1.1.0. */ MEXP(int) kd_quick(const char* cd_key, uint32_t client_token, - uint32_t server_token, uint32_t* public_value, - uint32_t* product, char* hash_buffer, size_t buffer_len); + uint32_t server_token, uint32_t* public_value, + uint32_t* product, char* hash_buffer, size_t buffer_len); /** * Initializes the CD-key decoding C wrappers. @@ -96,7 +96,7 @@ MEXP(int) kd_longVal2(int decoder, char* out); * Returns the hash length or 0 on failure. */ MEXP(int) kd_calculateHash(int decoder, uint32_t clientToken, - uint32_t serverToken); + uint32_t serverToken); /** * Places the key hash in "out". The "out" buffer must be diff --git a/src/bncsutil/file.cpp b/src/bncsutil/file.cpp index 2e4e783..bced9af 100644 --- a/src/bncsutil/file.cpp +++ b/src/bncsutil/file.cpp @@ -21,12 +21,12 @@ typedef std::map mapping_map; struct _file { #if BWIN - HANDLE f; + HANDLE f; #else - FILE* f; + FILE* f; #endif - const char* filename; - mapping_map mappings; + const char* filename; + mapping_map mappings; }; #include @@ -39,265 +39,265 @@ extern "C" { file_t file_open(const char* filename, unsigned int mode) { - file_t data; - HANDLE file; - DWORD access; - DWORD share_mode; - DWORD open_mode; - //const char* sys_err; - size_t filename_buf_len; - - if (mode & FILE_READ) { - access = GENERIC_READ; - share_mode = FILE_SHARE_READ; - open_mode = OPEN_EXISTING; - } else if (mode & FILE_WRITE) { - access = GENERIC_WRITE; - share_mode = 0; - open_mode = CREATE_ALWAYS; - } - - file = CreateFile(filename, access, share_mode, NULL, open_mode, - FILE_ATTRIBUTE_NORMAL, NULL); - - if (file == INVALID_HANDLE_VALUE) { - //sys_err = sys_error_msg(); - //bncsutil_debug_message_a("Cannot open file \"%s\"; %s", filename, sys_err); - //free_sys_err_msg(sys_err); - return ((file_t) 0); - } - - try { - data = new _file; - } catch (std::bad_alloc) { - //bncsutil_debug_message_a("Failed to allocate %u bytes to hold file structure.", sizeof(struct _file)); - CloseHandle(file); - return (file_t) 0; - } - - filename_buf_len = strlen(filename) + 1; - data->filename = (const char*) malloc(filename_buf_len); - if (!data->filename) { - //bncsutil_debug_message_a("Failed to allocate %u bytes to hold filename.", filename_buf_len); - CloseHandle(file); - delete data; - return (file_t) 0; - } - strcpy_s((char*) data->filename, filename_buf_len, filename); - - data->f = file; - - return data; + file_t data; + HANDLE file; + DWORD access; + DWORD share_mode; + DWORD open_mode; + //const char* sys_err; + size_t filename_buf_len; + + if (mode & FILE_READ) { + access = GENERIC_READ; + share_mode = FILE_SHARE_READ; + open_mode = OPEN_EXISTING; + } else if (mode & FILE_WRITE) { + access = GENERIC_WRITE; + share_mode = 0; + open_mode = CREATE_ALWAYS; + } + + file = CreateFile(filename, access, share_mode, NULL, open_mode, + FILE_ATTRIBUTE_NORMAL, NULL); + + if (file == INVALID_HANDLE_VALUE) { + //sys_err = sys_error_msg(); + //bncsutil_debug_message_a("Cannot open file \"%s\"; %s", filename, sys_err); + //free_sys_err_msg(sys_err); + return ((file_t) 0); + } + + try { + data = new _file; + } catch (std::bad_alloc) { + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold file structure.", sizeof(struct _file)); + CloseHandle(file); + return (file_t) 0; + } + + filename_buf_len = strlen(filename) + 1; + data->filename = (const char*) malloc(filename_buf_len); + if (!data->filename) { + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold filename.", filename_buf_len); + CloseHandle(file); + delete data; + return (file_t) 0; + } + strcpy_s((char*) data->filename, filename_buf_len, filename); + + data->f = file; + + return data; } void file_close(file_t file) { - mapping_map::iterator it; - - if (!file) { - //bncsutil_debug_message_a("error: null pointer given to file_close"); - return; - } - - for (it = file->mappings.begin(); it != file->mappings.end(); it++) { - UnmapViewOfFile((*it).first); - CloseHandle((*it).second); - } - - CloseHandle((HANDLE) file->f); - free((void*) file->filename); - delete file; + mapping_map::iterator it; + + if (!file) { + //bncsutil_debug_message_a("error: null pointer given to file_close"); + return; + } + + for (it = file->mappings.begin(); it != file->mappings.end(); it++) { + UnmapViewOfFile((*it).first); + CloseHandle((*it).second); + } + + CloseHandle((HANDLE) file->f); + free((void*) file->filename); + delete file; } size_t file_read(file_t file, void* ptr, size_t size, size_t count) { - DWORD bytes_read; - - if (!ReadFile(file->f, ptr, (DWORD) (size * count), &bytes_read, NULL)) { - return (size_t) 0; - } - - return (size_t) bytes_read; + DWORD bytes_read; + + if (!ReadFile(file->f, ptr, (DWORD) (size * count), &bytes_read, NULL)) { + return (size_t) 0; + } + + return (size_t) bytes_read; } size_t file_write(file_t file, const void* ptr, size_t size, - size_t count) + size_t count) { - DWORD bytes_written; - - if (!WriteFile(file->f, ptr, (DWORD) (size * count), &bytes_written, NULL)) - return (size_t) 0; - - return (size_t) bytes_written; + DWORD bytes_written; + + if (!WriteFile(file->f, ptr, (DWORD) (size * count), &bytes_written, NULL)) + return (size_t) 0; + + return (size_t) bytes_written; } size_t file_size(file_t file) { - return (size_t) GetFileSize(file->f, (LPDWORD) 0); + return (size_t) GetFileSize(file->f, (LPDWORD) 0); } void* file_map(file_t file, size_t len, off_t offset) { - HANDLE mapping = - CreateFileMapping((HANDLE) file->f, NULL, PAGE_READONLY, 0, 0, NULL); - void* base; - //const char* err; - - if (!mapping) { - //err = sys_error_msg(); - //bncsutil_debug_message_a("Failed to create file mapping for \"%s\": %s", file->filename, err); - //free_sys_err_msg(err); - return (void*) 0; - } - - base = MapViewOfFile(mapping, FILE_MAP_READ, 0, (DWORD) offset, len); - if (!base) { - CloseHandle(mapping); - //err = sys_error_msg(); - //bncsutil_debug_message_a("Failed to map %u bytes of \"%s\" starting at %u: %s", len, file->filename, offset, err); - //free_sys_err_msg(err); - return (void*) 0; - } - - file->mappings[base] = mapping; - - return base; + HANDLE mapping = + CreateFileMapping((HANDLE) file->f, NULL, PAGE_READONLY, 0, 0, NULL); + void* base; + //const char* err; + + if (!mapping) { + //err = sys_error_msg(); + //bncsutil_debug_message_a("Failed to create file mapping for \"%s\": %s", file->filename, err); + //free_sys_err_msg(err); + return (void*) 0; + } + + base = MapViewOfFile(mapping, FILE_MAP_READ, 0, (DWORD) offset, len); + if (!base) { + CloseHandle(mapping); + //err = sys_error_msg(); + //bncsutil_debug_message_a("Failed to map %u bytes of \"%s\" starting at %u: %s", len, file->filename, offset, err); + //free_sys_err_msg(err); + return (void*) 0; + } + + file->mappings[base] = mapping; + + return base; } void file_unmap(file_t file, const void* base) { - mapping_map::iterator item = file->mappings.find(base); - HANDLE mapping; - - if (item == file->mappings.end()) { - //bncsutil_debug_message_a("warning: failed to unmap the block starting at %p from %s; unknown block.", base, file->filename); - return; - } - - mapping = (*item).second; - - UnmapViewOfFile(base); - CloseHandle(mapping); - - file->mappings.erase(item); + mapping_map::iterator item = file->mappings.find(base); + HANDLE mapping; + + if (item == file->mappings.end()) { + //bncsutil_debug_message_a("warning: failed to unmap the block starting at %p from %s; unknown block.", base, file->filename); + return; + } + + mapping = (*item).second; + + UnmapViewOfFile(base); + CloseHandle(mapping); + + file->mappings.erase(item); } #else file_t file_open(const char* filename, unsigned int mode_flags) { - char mode[] = "rb"; - file_t data; - FILE* f; - size_t filename_buf_len; - //const char* err; - - if (mode_flags & FILE_WRITE) - mode[0] = 'w'; - - f = fopen(filename, mode); - if (!f) { - return (file_t) 0; - } - - try { - data = new _file; - } catch (std::bad_alloc) { - //bncsutil_debug_message_a("Failed to allocate %u bytes to hold file structure.", sizeof(struct _file)); - fclose(f); - return (file_t) 0; - } - - filename_buf_len = strlen(filename) + 1; - data->filename = (const char*) malloc(filename_buf_len); - if (!data->filename) { - //err = sys_error_msg(); - //bncsutil_debug_message_a("Failed to allocate %u bytes to hold filename; %s", filename_buf_len); - //free_sys_err_msg(err); - fclose(f); - delete data; - return (file_t) 0; - } - strcpy((char*) data->filename, filename); - - data->f = f; - - return data; + char mode[] = "rb"; + file_t data; + FILE* f; + size_t filename_buf_len; + //const char* err; + + if (mode_flags & FILE_WRITE) + mode[0] = 'w'; + + f = fopen(filename, mode); + if (!f) { + return (file_t) 0; + } + + try { + data = new _file; + } catch (std::bad_alloc) { + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold file structure.", sizeof(struct _file)); + fclose(f); + return (file_t) 0; + } + + filename_buf_len = strlen(filename) + 1; + data->filename = (const char*) malloc(filename_buf_len); + if (!data->filename) { + //err = sys_error_msg(); + //bncsutil_debug_message_a("Failed to allocate %u bytes to hold filename; %s", filename_buf_len); + //free_sys_err_msg(err); + fclose(f); + delete data; + return (file_t) 0; + } + strcpy((char*) data->filename, filename); + + data->f = f; + + return data; } void file_close(file_t file) { - mapping_map::iterator it; - - if (!file) { - //bncsutil_debug_message("error: null pointer given to file_close"); - return; - } - - for (it = file->mappings.begin(); it != file->mappings.end(); it++) { - munmap((void*) (*it).first, (*it).second); - } - - fclose(file->f); - delete file; + mapping_map::iterator it; + + if (!file) { + //bncsutil_debug_message("error: null pointer given to file_close"); + return; + } + + for (it = file->mappings.begin(); it != file->mappings.end(); it++) { + munmap((void*) (*it).first, (*it).second); + } + + fclose(file->f); + delete file; } size_t file_read(file_t file, void* ptr, size_t size, size_t count) { - return fread(ptr, size, count, file->f); + return fread(ptr, size, count, file->f); } size_t file_write(file_t file, const void* ptr, size_t size, - size_t count) + size_t count) { - return fwrite(ptr, size, count, file->f); + return fwrite(ptr, size, count, file->f); } size_t file_size(file_t file) { - long cur_pos = ftell(file->f); - size_t size_of_file; - - fseek(file->f, 0, SEEK_END); - size_of_file = (size_t) ftell(file->f); - fseek(file->f, cur_pos, SEEK_SET); - - return size_of_file; + long cur_pos = ftell(file->f); + size_t size_of_file; + + fseek(file->f, 0, SEEK_END); + size_of_file = (size_t) ftell(file->f); + fseek(file->f, cur_pos, SEEK_SET); + + return size_of_file; } void* file_map(file_t file, size_t len, off_t offset) { - int fd = fileno(file->f); - void* base = mmap((void*) 0, len, PROT_READ, MAP_SHARED, fd, offset); - //const char* err; - - if (!base) { - //err = sys_error_msg(); - //bncsutil_debug_message_a("error: failed to map %u bytes of %s starting at %u into memory; %s", len, file->filename, offset, err); - //free_sys_err_msg(err); - return (void*) 0; - } - - file->mappings[base] = len; - - return base; + int fd = fileno(file->f); + void* base = mmap((void*) 0, len, PROT_READ, MAP_SHARED, fd, offset); + //const char* err; + + if (!base) { + //err = sys_error_msg(); + //bncsutil_debug_message_a("error: failed to map %u bytes of %s starting at %u into memory; %s", len, file->filename, offset, err); + //free_sys_err_msg(err); + return (void*) 0; + } + + file->mappings[base] = len; + + return base; } void file_unmap(file_t file, const void* base) { - mapping_map::iterator item = file->mappings.find(base); - size_t len; - - if (item == file->mappings.end()) { - //bncsutil_debug_message_a("warning: failed to unmap the block starting at %p from %s; unknown block.", base, file->filename); - return; - } - - len = (*item).second; - - munmap((void*) base, len); - - file->mappings.erase(item); + mapping_map::iterator item = file->mappings.find(base); + size_t len; + + if (item == file->mappings.end()) { + //bncsutil_debug_message_a("warning: failed to unmap the block starting at %p from %s; unknown block.", base, file->filename); + return; + } + + len = (*item).second; + + munmap((void*) base, len); + + file->mappings.erase(item); } #endif diff --git a/src/bncsutil/file.h b/src/bncsutil/file.h index 4721e28..3ff4bbd 100644 --- a/src/bncsutil/file.h +++ b/src/bncsutil/file.h @@ -41,15 +41,15 @@ extern "C" { typedef struct _file* file_t; -#define FILE_READ (0x01) -#define FILE_WRITE (0x02) +#define FILE_READ (0x01) +#define FILE_WRITE (0x02) file_t file_open(const char* filename, unsigned int mode); void file_close(file_t file); size_t file_read(file_t file, void* ptr, size_t size, size_t count); size_t file_write(file_t file, const void* ptr, size_t size, - size_t count); + size_t count); size_t file_size(file_t file); void* file_map(file_t file, size_t len, off_t offset); diff --git a/src/bncsutil/gmp.h b/src/bncsutil/gmp.h index 0a8c32c..2a036bf 100644 --- a/src/bncsutil/gmp.h +++ b/src/bncsutil/gmp.h @@ -192,15 +192,15 @@ along with the GNU MP Library. If not, see http://www.gnu.org/licenses/. */ #ifdef __GMP_SHORT_LIMB -typedef unsigned int mp_limb_t; -typedef int mp_limb_signed_t; +typedef unsigned int mp_limb_t; +typedef int mp_limb_signed_t; #else #ifdef _LONG_LONG_LIMB -typedef unsigned long long int mp_limb_t; -typedef long long int mp_limb_signed_t; +typedef unsigned long long int mp_limb_t; +typedef long long int mp_limb_signed_t; #else -typedef unsigned long int mp_limb_t; -typedef long int mp_limb_signed_t; +typedef unsigned long int mp_limb_t; +typedef long int mp_limb_signed_t; #endif #endif @@ -209,12 +209,12 @@ typedef long int mp_limb_signed_t; must leave this name for binary compatibility. */ typedef struct { - int _mp_alloc; /* Number of *limbs* allocated and pointed - to by the _mp_d field. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ + int _mp_alloc; /* Number of *limbs* allocated and pointed + to by the _mp_d field. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ } __mpz_struct; #endif /* __GNU_MP__ */ @@ -223,17 +223,17 @@ typedef struct typedef __mpz_struct MP_INT; /* gmp 1 source compatibility */ typedef __mpz_struct mpz_t[1]; -typedef mp_limb_t * mp_ptr; -typedef __gmp_const mp_limb_t * mp_srcptr; +typedef mp_limb_t * mp_ptr; +typedef __gmp_const mp_limb_t * mp_srcptr; #if defined (_CRAY) && ! defined (_CRAYMPP) /* plain `int' is much faster (48 bits) */ #define __GMP_MP_SIZE_T_INT 1 -typedef int mp_size_t; -typedef int mp_exp_t; +typedef int mp_size_t; +typedef int mp_exp_t; #else #define __GMP_MP_SIZE_T_INT 0 -typedef long int mp_size_t; -typedef long int mp_exp_t; +typedef long int mp_size_t; +typedef long int mp_exp_t; #endif typedef struct @@ -247,15 +247,15 @@ typedef __mpq_struct mpq_t[1]; typedef struct { - int _mp_prec; /* Max precision, in number of `mp_limb_t's. - Set by mpf_init and modified by - mpf_set_prec. The area pointed to by the - _mp_d field contains `prec' + 1 limbs. */ - int _mp_size; /* abs(_mp_size) is the number of limbs the - last field points to. If _mp_size is - negative this is a negative number. */ - mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ - mp_limb_t *_mp_d; /* Pointer to the limbs. */ + int _mp_prec; /* Max precision, in number of `mp_limb_t's. + Set by mpf_init and modified by + mpf_set_prec. The area pointed to by the + _mp_d field contains `prec' + 1 limbs. */ + int _mp_size; /* abs(_mp_size) is the number of limbs the + last field points to. If _mp_size is + negative this is a negative number. */ + mp_exp_t _mp_exp; /* Exponent, in the base of `mp_limb_t'. */ + mp_limb_t *_mp_d; /* Pointer to the limbs. */ } __mpf_struct; /* typedef __mpf_struct MP_FLOAT; */ @@ -271,7 +271,7 @@ typedef enum /* Random state struct. */ typedef struct { - mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ + mpz_t _mp_seed; /* _mp_d member points to state of the generator. */ gmp_randalg_t _mp_alg; /* Currently unused. */ union { void *_mp_lc; /* Pointer to function pointers structure. */ @@ -333,7 +333,7 @@ typedef __mpq_struct *mpq_ptr; || defined (_FILE_DEFINED) /* Microsoft */ \ || defined (__STDIO__) /* Apple MPW MrC */ \ || defined (_MSL_STDIO_H) /* Metrowerks */ \ - || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ + || defined (_STDIO_H_INCLUDED) /* QNX4 */ \ || defined (_ISO_STDIO_ISO_H) /* Sun C++ */ #define _GMP_H_HAVE_FILE 1 #endif @@ -532,8 +532,8 @@ using std::FILE; #define mp_set_memory_functions __gmp_set_memory_functions __GMP_DECLSPEC void mp_set_memory_functions __GMP_PROTO ((void *(*) (size_t), - void *(*) (void *, size_t, size_t), - void (*) (void *, size_t))) __GMP_NOTHROW; + void *(*) (void *, size_t, size_t), + void (*) (void *, size_t))) __GMP_NOTHROW; #define mp_get_memory_functions __gmp_get_memory_functions __GMP_DECLSPEC void mp_get_memory_functions __GMP_PROTO ((void *(**) (size_t), @@ -562,7 +562,7 @@ __GMP_DECLSPEC void gmp_randinit_default __GMP_PROTO ((gmp_randstate_t)); #define gmp_randinit_lc_2exp __gmp_randinit_lc_2exp __GMP_DECLSPEC void gmp_randinit_lc_2exp __GMP_PROTO ((gmp_randstate_t, mpz_srcptr, unsigned long int, - unsigned long int)); + unsigned long int)); #define gmp_randinit_lc_2exp_size __gmp_randinit_lc_2exp_size __GMP_DECLSPEC int gmp_randinit_lc_2exp_size __GMP_PROTO ((gmp_randstate_t, unsigned long)); @@ -1620,16 +1620,16 @@ mpz_abs (mpz_ptr __gmp_w, mpz_srcptr __gmp_u) #endif #if GMP_NAIL_BITS == 0 -#define __GMPZ_FITS_UTYPE_P(z,maxval) \ - mp_size_t __gmp_n = z->_mp_size; \ - mp_ptr __gmp_p = z->_mp_d; \ +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval)); #else -#define __GMPZ_FITS_UTYPE_P(z,maxval) \ - mp_size_t __gmp_n = z->_mp_size; \ - mp_ptr __gmp_p = z->_mp_d; \ - return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ - || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); +#define __GMPZ_FITS_UTYPE_P(z,maxval) \ + mp_size_t __gmp_n = z->_mp_size; \ + mp_ptr __gmp_p = z->_mp_d; \ + return (__gmp_n == 0 || (__gmp_n == 1 && __gmp_p[0] <= maxval) \ + || (__gmp_n == 2 && __gmp_p[1] <= ((mp_limb_t) maxval >> GMP_NUMB_BITS))); #endif #if defined (__GMP_EXTERN_INLINE) || defined (__GMP_FORCE_mpz_fits_uint_p) @@ -1883,89 +1883,89 @@ mpq_neg (mpq_ptr __gmp_w, mpq_srcptr __gmp_u) juggling setting up for the asm. */ #if GMP_NAIL_BITS == 0 -#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ - do { \ - mp_size_t __gmp_i; \ +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ mp_limb_t __gmp_x, __gmp_r; \ - \ - /* ASSERT ((n) >= 1); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ - \ - __gmp_x = (src)[0]; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ __gmp_r = __gmp_x OP (v); \ - (dst)[0] = __gmp_r; \ + (dst)[0] = __gmp_r; \ if (CB (__gmp_r, __gmp_x, (v))) \ - { \ - (cout) = 1; \ - for (__gmp_i = 1; __gmp_i < (n);) \ - { \ - __gmp_x = (src)[__gmp_i]; \ - __gmp_r = __gmp_x OP 1; \ - (dst)[__gmp_i] = __gmp_r; \ - ++__gmp_i; \ - if (!CB (__gmp_r, __gmp_x, 1)) \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, __gmp_i); \ - (cout) = 0; \ - break; \ - } \ - } \ - } \ - else \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, 1); \ - (cout) = 0; \ - } \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r; \ + ++__gmp_i; \ + if (!CB (__gmp_r, __gmp_x, 1)) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ } while (0) #endif #if GMP_NAIL_BITS >= 1 -#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ - do { \ - mp_size_t __gmp_i; \ - mp_limb_t __gmp_x, __gmp_r; \ - \ - /* ASSERT ((n) >= 1); */ \ - /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ - \ - __gmp_x = (src)[0]; \ - __gmp_r = __gmp_x OP (v); \ - (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ - if (__gmp_r >> GMP_NUMB_BITS != 0) \ - { \ - (cout) = 1; \ - for (__gmp_i = 1; __gmp_i < (n);) \ - { \ - __gmp_x = (src)[__gmp_i]; \ - __gmp_r = __gmp_x OP 1; \ - (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ - ++__gmp_i; \ - if (__gmp_r >> GMP_NUMB_BITS == 0) \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, __gmp_i); \ - (cout) = 0; \ - break; \ - } \ - } \ - } \ - else \ - { \ - if ((src) != (dst)) \ - __GMPN_COPY_REST (dst, src, n, 1); \ - (cout) = 0; \ - } \ +#define __GMPN_AORS_1(cout, dst, src, n, v, OP, CB) \ + do { \ + mp_size_t __gmp_i; \ + mp_limb_t __gmp_x, __gmp_r; \ + \ + /* ASSERT ((n) >= 1); */ \ + /* ASSERT (MPN_SAME_OR_SEPARATE_P (dst, src, n)); */ \ + \ + __gmp_x = (src)[0]; \ + __gmp_r = __gmp_x OP (v); \ + (dst)[0] = __gmp_r & GMP_NUMB_MASK; \ + if (__gmp_r >> GMP_NUMB_BITS != 0) \ + { \ + (cout) = 1; \ + for (__gmp_i = 1; __gmp_i < (n);) \ + { \ + __gmp_x = (src)[__gmp_i]; \ + __gmp_r = __gmp_x OP 1; \ + (dst)[__gmp_i] = __gmp_r & GMP_NUMB_MASK; \ + ++__gmp_i; \ + if (__gmp_r >> GMP_NUMB_BITS == 0) \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, __gmp_i); \ + (cout) = 0; \ + break; \ + } \ + } \ + } \ + else \ + { \ + if ((src) != (dst)) \ + __GMPN_COPY_REST (dst, src, n, 1); \ + (cout) = 0; \ + } \ } while (0) #endif #define __GMPN_ADDCB(r,x,y) ((r) < (y)) #define __GMPN_SUBCB(r,x,y) ((x) < (y)) -#define __GMPN_ADD_1(cout, dst, src, n, v) \ +#define __GMPN_ADD_1(cout, dst, src, n, v) \ __GMPN_AORS_1(cout, dst, src, n, v, +, __GMPN_ADDCB) -#define __GMPN_SUB_1(cout, dst, src, n, v) \ +#define __GMPN_SUB_1(cout, dst, src, n, v) \ __GMPN_AORS_1(cout, dst, src, n, v, -, __GMPN_SUBCB) @@ -2108,15 +2108,15 @@ mpn_sub_1 (mp_ptr __gmp_dst, mp_srcptr __gmp_src, mp_size_t __gmp_size, mp_limb_ /* When using GCC, optimize certain common comparisons. */ #if defined (__GNUC__) #define mpz_cmp_ui(Z,UI) \ - (__builtin_constant_p (UI) && (UI) == 0 \ + (__builtin_constant_p (UI) && (UI) == 0 \ ? mpz_sgn (Z) : _mpz_cmp_ui (Z,UI)) #define mpz_cmp_si(Z,SI) \ - (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ - : __builtin_constant_p (SI) && (SI) > 0 \ - ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ + (__builtin_constant_p (SI) && (SI) == 0 ? mpz_sgn (Z) \ + : __builtin_constant_p (SI) && (SI) > 0 \ + ? _mpz_cmp_ui (Z, __GMP_CAST (unsigned long int, SI)) \ : _mpz_cmp_si (Z,SI)) #define mpq_cmp_ui(Q,NUI,DUI) \ - (__builtin_constant_p (NUI) && (NUI) == 0 \ + (__builtin_constant_p (NUI) && (NUI) == 0 \ ? mpq_sgn (Q) : _mpq_cmp_ui (Q,NUI,DUI)) #define mpq_cmp_si(q,n,d) \ (__builtin_constant_p ((n) >= 0) && (n) >= 0 \ @@ -2154,22 +2154,22 @@ __GMP_DECLSPEC_XX std::istream& operator>> (std::istream &, mpf_ptr); mpn_divrem (qp, __GMP_CAST (mp_size_t, 0), np, nsize, dp, dsize) /* Source-level compatibility with GMP 1. */ -#define mpz_mdiv mpz_fdiv_q -#define mpz_mdivmod mpz_fdiv_qr -#define mpz_mmod mpz_fdiv_r -#define mpz_mdiv_ui mpz_fdiv_q_ui +#define mpz_mdiv mpz_fdiv_q +#define mpz_mdivmod mpz_fdiv_qr +#define mpz_mmod mpz_fdiv_r +#define mpz_mdiv_ui mpz_fdiv_q_ui #define mpz_mdivmod_ui(q,r,n,d) \ (((r) == 0) ? mpz_fdiv_q_ui (q,n,d) : mpz_fdiv_qr_ui (q,r,n,d)) #define mpz_mmod_ui(r,n,d) \ (((r) == 0) ? mpz_fdiv_ui (n,d) : mpz_fdiv_r_ui (r,n,d)) /* Useful synonyms, but not quite compatible with GMP 1. */ -#define mpz_div mpz_fdiv_q -#define mpz_divmod mpz_fdiv_qr -#define mpz_div_ui mpz_fdiv_q_ui -#define mpz_divmod_ui mpz_fdiv_qr_ui -#define mpz_div_2exp mpz_fdiv_q_2exp -#define mpz_mod_2exp mpz_fdiv_r_2exp +#define mpz_div mpz_fdiv_q +#define mpz_divmod mpz_fdiv_qr +#define mpz_div_ui mpz_fdiv_q_ui +#define mpz_divmod_ui mpz_fdiv_qr_ui +#define mpz_div_2exp mpz_fdiv_q_2exp +#define mpz_mod_2exp mpz_fdiv_r_2exp enum { diff --git a/src/bncsutil/libinfo.cpp b/src/bncsutil/libinfo.cpp index 4fc032e..956ba2c 100644 --- a/src/bncsutil/libinfo.cpp +++ b/src/bncsutil/libinfo.cpp @@ -38,17 +38,17 @@ MEXP(int) bncsutil_getVersionString(char* outBuf) { // major major = (unsigned long) (BNCSUTIL_VERSION / 10000); if (major > 99 || major < 0) return 0; - + // minor ver -= (major * 10000); minor = (unsigned long) (ver / 100); if (minor > 99 || minor < 0) return 0; - + // revision ver -= (minor * 100); rev = ver; if (rev > 99 || rev < 0) return 0; - + printed = std::sprintf(outBuf, "%lu.%lu.%lu", major, minor, rev); if (printed < 0) return 0; outBuf[8] = '\0'; diff --git a/src/bncsutil/ms_stdint.h b/src/bncsutil/ms_stdint.h index e032ff1..17dcad4 100644 --- a/src/bncsutil/ms_stdint.h +++ b/src/bncsutil/ms_stdint.h @@ -1,32 +1,32 @@ // ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// // Copyright (c) 2006-2008 Alexander Chemeris -// +// // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: -// +// // 1. Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. -// +// // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. -// +// // 3. The name of the author may be used to endorse or promote products // derived from this software without specific prior written permission. -// +// // THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO // EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF // ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// +// /////////////////////////////////////////////////////////////////////////////// #ifndef _MSC_VER // [ @@ -47,7 +47,7 @@ // error C2733: second C linkage of overloaded function 'wmemchr' not allowed #if (_MSC_VER < 1300) && defined(__cplusplus) extern "C++" { -#endif +#endif # include #if (_MSC_VER < 1300) && defined(__cplusplus) } diff --git a/src/bncsutil/mutil.h b/src/bncsutil/mutil.h index e6316b7..a5f5c05 100644 --- a/src/bncsutil/mutil.h +++ b/src/bncsutil/mutil.h @@ -36,7 +36,7 @@ /* Specific-Sized Integers */ #include "mutil_types.h" -#include +#include // functions for converting a string to a 64-bit number. #if defined(_MSC_VER) @@ -46,9 +46,9 @@ #endif #ifdef _MSC_VER -#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */ -#define ROL(x,n) _lrotl((x),(n)) -#define ROR(x,n) _lrotr((x),(n)) +#pragma intrinsic(_lrotl,_lrotr) /* use intrinsic compiler rotations */ +#define ROL(x,n) _lrotl((x),(n)) +#define ROR(x,n) _lrotr((x),(n)) #else #ifndef ROL #define ROL(a,b) (((a) << (b)) | ((a) >> 32 - (b))) @@ -102,8 +102,8 @@ #define SWAP2(num) ((((num) >> 8) & 0x00FF) | (((num) << 8) & 0xFF00)) #define SWAP4(num) ((((num) >> 24) & 0x000000FF) | (((num) >> 8) & 0x0000FF00) | (((num) << 8) & 0x00FF0000) | (((num) << 24) & 0xFF000000)) -#define SWAP8(x) \ - (uint64_t)((((uint64_t)(x) & 0xff) << 56) | \ +#define SWAP8(x) \ + (uint64_t)((((uint64_t)(x) & 0xff) << 56) | \ ((uint64_t)(x) & 0xff00ULL) << 40 | \ ((uint64_t)(x) & 0xff0000ULL) << 24 | \ ((uint64_t)(x) & 0xff000000ULL) << 8 | \ @@ -129,17 +129,17 @@ #define MSB4(num) SWAP4(num) #endif /* (endianness) */ -#ifndef MOS_WINDOWS +#ifndef MOS_WINDOWS /* attempt automatic Windows detection */ - #ifdef _MSC_VER + #ifdef _MSC_VER /* Microsoft C++ compiler, has to be windows */ - #define MOS_WINDOWS - #else + #define MOS_WINDOWS + #else #if defined(_WIN) || defined(_WINDOWS) || defined(WINDOWS) || \ defined(_WIN32) || defined(_WIN64) || defined(WIN32) || defined(WIN64) #define MOS_WINDOWS - #endif - #endif + #endif + #endif #endif #if !(defined(MUTIL_LIB_BUILD)) && defined(BNCSUTIL_EXPORTS) diff --git a/src/bncsutil/mutil_types.h b/src/bncsutil/mutil_types.h index aec9a3d..31b7320 100644 --- a/src/bncsutil/mutil_types.h +++ b/src/bncsutil/mutil_types.h @@ -122,7 +122,7 @@ typedef unsigned long long uintmax_t; #define INTPTR_MIN INT32_MIN #define INTPTR_MAX INT32_MAX - + #define UINTPTR_MAX UINT32_MAX #define INTMAX_MIN INT64_MIN diff --git a/src/bncsutil/nls.c b/src/bncsutil/nls.c index 8d19cd0..3def492 100644 --- a/src/bncsutil/nls.c +++ b/src/bncsutil/nls.c @@ -36,17 +36,17 @@ struct _nls { const char* password; unsigned long username_len; unsigned long password_len; - + mpz_t n; mpz_t a; - + gmp_randstate_t rand; - char* A; - char* S; - char* K; - char* M1; - char* M2; + char* A; + char* S; + char* K; + char* M1; + char* M2; }; #ifdef MOS_WINDOWS @@ -95,7 +95,7 @@ uint32_t nls_get_u(const char* B); MEXP(nls_t*) nls_init(const char* username, const char* password) { return nls_init_l(username, (unsigned long) strlen(username), - password, (unsigned long) strlen(password)); + password, (unsigned long) strlen(password)); } MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, @@ -105,21 +105,21 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, char* d; /* destination */ const char* o; /* original */ nls_t* nls; - + nls = (nls_t*) malloc(sizeof(nls_t)); if (!nls) return (nls_t*) 0; - + nls->username_len = username_length; nls->password_len = password_length; - + nls->username = (char*) malloc(nls->username_len + 1); nls->password = (char*) malloc(nls->password_len + 1); if (!nls->username || !nls->password) { free(nls); return (nls_t*) 0; } - + d = (char*) nls->username; o = username; for (i = 0; i < nls->username_len; i++) { @@ -127,10 +127,10 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, d++; o++; } - + *((char*) nls->username + username_length) = 0; *((char*) nls->password + password_length) = 0; - + d = (char*) nls->password; o = password; for (i = 0; i < nls->password_len; i++) { @@ -138,9 +138,9 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, d++; o++; } - + mpz_init_set_str(nls->n, NLS_VAR_N_STR, 16); - + gmp_randinit_default(nls->rand); gmp_randseed_ui(nls->rand, nls_pre_seed()); mpz_init2(nls->a, 256); @@ -149,12 +149,12 @@ MEXP(nls_t*) nls_init_l(const char* username, unsigned long username_length, /* The following line replaces preceding 2 lines during testing. */ /*mpz_init_set_str(nls->a, "1234", 10);*/ - nls->A = (char*) 0; - nls->S = (char*) 0; - nls->K = (char*) 0; - nls->M1 = (char*) 0; - nls->M2 = (char*) 0; - + nls->A = (char*) 0; + nls->S = (char*) 0; + nls->K = (char*) 0; + nls->M1 = (char*) 0; + nls->M2 = (char*) 0; + return nls; } @@ -167,63 +167,63 @@ MEXP(void) nls_free(nls_t* nls) { free((void*) nls->username); free((void*) nls->password); - if (nls->A) - free(nls->A); - if (nls->S) - free(nls->S); - if (nls->K) - free(nls->K); - if (nls->M1) - free(nls->M1); - if (nls->M2) - free(nls->M2); + if (nls->A) + free(nls->A); + if (nls->S) + free(nls->S); + if (nls->K) + free(nls->K); + if (nls->M1) + free(nls->M1); + if (nls->M2) + free(nls->M2); free(nls); } MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, - const char* password) + const char* password) { - return nls_reinit_l(nls, username, (unsigned long) strlen(username), - password, (unsigned long) strlen(password)); + return nls_reinit_l(nls, username, (unsigned long) strlen(username), + password, (unsigned long) strlen(password)); } MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, - unsigned long username_length, const char* password, - unsigned long password_length) + unsigned long username_length, const char* password, + unsigned long password_length) { - unsigned int i; + unsigned int i; char* d; /* destination */ const char* o; /* original */ - if (nls->A) - free(nls->A); - if (nls->S) - free(nls->S); - if (nls->K) - free(nls->K); - if (nls->M1) - free(nls->M1); - if (nls->M2) - free(nls->M2); - - nls->username_len = username_length; + if (nls->A) + free(nls->A); + if (nls->S) + free(nls->S); + if (nls->K) + free(nls->K); + if (nls->M1) + free(nls->M1); + if (nls->M2) + free(nls->M2); + + nls->username_len = username_length; nls->password_len = password_length; - - nls->username = (const char*) realloc((void*) nls->username, - nls->username_len + 1); - if (!nls->username) { + + nls->username = (const char*) realloc((void*) nls->username, + nls->username_len + 1); + if (!nls->username) { free(nls); return (nls_t*) 0; } nls->password = (const char*) realloc((void*) nls->password, - nls->password_len + 1); + nls->password_len + 1); if (!nls->password) { - free((void*) nls->username); + free((void*) nls->username); free(nls); return (nls_t*) 0; } - + d = (char*) nls->username; o = username; for (i = 0; i < nls->username_len; i++) { @@ -232,30 +232,30 @@ MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, o++; } - d = (char*) nls->password; + d = (char*) nls->password; o = password; for (i = 0; i < nls->password_len; i++) { *d = (char) toupper(*o); d++; o++; } - + *((char*) nls->username + username_length) = 0; *((char*) nls->password + password_length) = 0; - mpz_urandomm(nls->a, nls->rand, nls->n); /* generates the private key */ + mpz_urandomm(nls->a, nls->rand, nls->n); /* generates the private key */ - nls->A = (char*) 0; - nls->S = (char*) 0; - nls->K = (char*) 0; - nls->M1 = (char*) 0; - nls->M2 = (char*) 0; + nls->A = (char*) 0; + nls->S = (char*) 0; + nls->K = (char*) 0; + nls->M1 = (char*) 0; + nls->M2 = (char*) 0; - return nls; + return nls; } MEXP(unsigned long) nls_account_create(nls_t* nls, char* buf, unsigned long bufSize) { - mpz_t s; /* salt */ + mpz_t s; /* salt */ mpz_t v; mpz_t x; @@ -263,20 +263,20 @@ MEXP(unsigned long) nls_account_create(nls_t* nls, char* buf, unsigned long bufS return 0; if (bufSize < nls->username_len + 65) return 0; - + mpz_init2(s, 256); mpz_urandomb(s, nls->rand, 256); mpz_export(buf, (size_t*) 0, -1, 1, 0, 0, s); - /*memset(buf, 0, 32);*/ - + /*memset(buf, 0, 32);*/ + nls_get_x(nls, x, buf); nls_get_v_mpz(nls, v, x); mpz_export(buf + 32, (size_t*) 0, -1, 1, 0, 0, v); - - mpz_clear(x); + + mpz_clear(x); mpz_clear(v); mpz_clear(s); - + strcpy(buf + 64, nls->username); return nls->username_len + 65; } @@ -286,7 +286,7 @@ MEXP(unsigned long) nls_account_logon(nls_t* nls, char* buf, unsigned long bufSi return 0; if (bufSize < nls->username_len + 33) return 0; - + nls_get_A(nls, buf); strcpy(buf + 32, nls->username); return nls->username_len + 33; @@ -297,27 +297,27 @@ MEXP(nls_t*) nls_account_change_proof(nls_t* nls, char* buf, { nls_t* nouveau; mpz_t s; /* salt */ - + if (!nls) return (nls_t*) 0; - + /* create new nls_t */ nouveau = nls_init_l(nls->username, nls->username_len, new_password, (unsigned long) strlen(new_password)); if (!nouveau) return (nls_t*) 0; - + /* fill buf */ nls_get_M1(nls, buf, B, salt); - + mpz_init2(s, 256); mpz_urandomb(s, nouveau->rand, 256); mpz_export(buf + 20, (size_t*) 0, -1, 1, 0, 0, s); - - nls_get_v(nouveau, buf + 52, buf + 20); + + nls_get_v(nouveau, buf + 52, buf + 20); mpz_clear(s); - + return nouveau; } @@ -326,34 +326,34 @@ MEXP(void) nls_get_S(nls_t* nls, char* out, const char* B, const char* salt) { mpz_t S_base, S_exp; mpz_t x; mpz_t v; - + if (!nls) return; - if (nls->S) { - memcpy(out, nls->S, 32); - return; - } - + if (nls->S) { + memcpy(out, nls->S, 32); + return; + } + mpz_init2(temp, 256); mpz_import(temp, 32, -1, 1, 0, 0, B); - + nls_get_x(nls, x, salt); nls_get_v_mpz(nls, v, x); - + mpz_init_set(S_base, nls->n); mpz_add(S_base, S_base, temp); mpz_sub(S_base, S_base, v); mpz_mod(S_base, S_base, nls->n); - + mpz_init_set(S_exp, x); mpz_mul_ui(S_exp, S_exp, nls_get_u(B)); mpz_add(S_exp, S_exp, nls->a); - + mpz_clear(x); mpz_clear(v); mpz_clear(temp); - + mpz_init(temp); mpz_powm(temp, S_base, S_exp, nls->n); mpz_clear(S_base); @@ -361,25 +361,25 @@ MEXP(void) nls_get_S(nls_t* nls, char* out, const char* B, const char* salt) { mpz_export(out, (size_t*) 0, -1, 1, 0, 0, temp); mpz_clear(temp); - nls->S = (char*) malloc(32); - if (nls->S) - memcpy(nls->S, out, 32); + nls->S = (char*) malloc(32); + if (nls->S) + memcpy(nls->S, out, 32); } MEXP(void) nls_get_v(nls_t* nls, char* out, const char* salt) { mpz_t g; mpz_t v; mpz_t x; - + if (!nls) return; - + mpz_init_set_ui(g, NLS_VAR_g); mpz_init(v); nls_get_x(nls, x, salt); - + mpz_powm(v, g, x, nls->n); - + mpz_export(out, (size_t*) 0, -1, 1, 0, 0, v); mpz_clear(v); mpz_clear(g); @@ -391,62 +391,62 @@ MEXP(void) nls_get_A(nls_t* nls, char* out) { mpz_t g; mpz_t A; size_t o; - + if (!nls) return; - if (nls->A) { - memcpy(out, nls->A, 32); - return; - } - + if (nls->A) { + memcpy(out, nls->A, 32); + return; + } + mpz_init_set_ui(g, NLS_VAR_g); mpz_init2(A, 256); - + mpz_powm(A, g, nls->a, nls->n); mpz_export(out, &o, -1, 1, 0, 0, A); - + mpz_clear(A); mpz_clear(g); - nls->A = (char*) malloc(32); - if (nls->A) - memcpy(nls->A, out, 32); + nls->A = (char*) malloc(32); + if (nls->A) + memcpy(nls->A, out, 32); } MEXP(void) nls_get_K(nls_t* nls, char* out, const char* S) { char odd[16], even[16]; uint8_t odd_hash[20], even_hash[20]; - + char* Sp = (char*) S; char* op = odd; char* ep = even; unsigned int i; - + SHA1Context ctx; - if (!nls) - return; + if (!nls) + return; + + if (nls->K) { + memcpy(out, nls->K, 40); + return; + } - if (nls->K) { - memcpy(out, nls->K, 40); - return; - } - for (i = 0; i < 16; i++) { *(op++) = *(Sp++); *(ep++) = *(Sp++); } - + SHA1Reset(&ctx); SHA1Input(&ctx, (uint8_t*) odd, 16); SHA1Result(&ctx, odd_hash); - + SHA1Reset(&ctx); SHA1Input(&ctx, (uint8_t*) even, 16); SHA1Result(&ctx, even_hash); - + Sp = out; op = (char*) odd_hash; ep = (char*) even_hash; @@ -455,9 +455,9 @@ MEXP(void) nls_get_K(nls_t* nls, char* out, const char* S) { *(Sp++) = *(ep++); } - nls->K = (char*) malloc(40); - if (nls->K) - memcpy(nls->K, out, 40); + nls->K = (char*) malloc(40); + if (nls->K) + memcpy(nls->K, out, 40); } MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { @@ -467,21 +467,21 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { char S[32]; char K[40]; - if (!nls) - return; + if (!nls) + return; - if (nls->M1) { - nls_dbg("nls_get_M1(): Using cached M[1] value."); - memcpy(out, nls->M1, 20); - return; - } + if (nls->M1) { + nls_dbg("nls_get_M1(): Using cached M[1] value."); + memcpy(out, nls->M1, 20); + return; + } /* calculate SHA-1 hash of username */ SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); SHA1Result(&sha, username_hash); - + nls_get_A(nls, A); nls_get_S(nls, S, B, salt); nls_get_K(nls, K, S); @@ -496,9 +496,9 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt) { SHA1Input(&sha, (uint8_t*) K, 40); SHA1Result(&sha, (uint8_t*) out); - nls->M1 = (char*) malloc(20); - if (nls->M1) - memcpy(nls->M1, out, 20); + nls->M1 = (char*) malloc(20); + if (nls->M1) + memcpy(nls->M1, out, 20); } MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, @@ -506,66 +506,66 @@ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, { SHA1Context sha; char local_M2[20]; - char* A; - char S[32]; - char* K; - char* M1; + char* A; + char S[32]; + char* K; + char* M1; uint8_t username_hash[20]; - int res; - int mustFree = 0; - - if (!nls) - return 0; - - if (nls->M2) - return (memcmp(nls->M2, var_M2, 20) == 0); - - if (nls->A && nls->K && nls->M1) { - A = nls->A; - K = nls->K; - M1 = nls->M1; - } else { - if (!B || !salt) - return 0; - - A = (char*) malloc(32); - if (!A) - return 0; - K = (char*) malloc(40); - if (!K) { - free(A); - return 0; - } - M1 = (char*) malloc(20); - if (!M1) { - free(K); - free(A); - return 0; - } - - mustFree = 1; - - /* get the other values needed for the hash */ - nls_get_A(nls, A); - nls_get_S(nls, S, (char*) B, (char*) salt); - nls_get_K(nls, K, S); - - /* calculate SHA-1 hash of username */ - SHA1Reset(&sha); - SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); - SHA1Result(&sha, username_hash); - - /* calculate M[1] */ - SHA1Reset(&sha); - SHA1Input(&sha, (uint8_t*) bncsutil_NLS_I, 20); - SHA1Input(&sha, username_hash, 20); - SHA1Input(&sha, (uint8_t*) salt, 32); - SHA1Input(&sha, (uint8_t*) A, 32); - SHA1Input(&sha, (uint8_t*) B, 32); - SHA1Input(&sha, (uint8_t*) K, 40); - SHA1Result(&sha, (uint8_t*) M1); - } - + int res; + int mustFree = 0; + + if (!nls) + return 0; + + if (nls->M2) + return (memcmp(nls->M2, var_M2, 20) == 0); + + if (nls->A && nls->K && nls->M1) { + A = nls->A; + K = nls->K; + M1 = nls->M1; + } else { + if (!B || !salt) + return 0; + + A = (char*) malloc(32); + if (!A) + return 0; + K = (char*) malloc(40); + if (!K) { + free(A); + return 0; + } + M1 = (char*) malloc(20); + if (!M1) { + free(K); + free(A); + return 0; + } + + mustFree = 1; + + /* get the other values needed for the hash */ + nls_get_A(nls, A); + nls_get_S(nls, S, (char*) B, (char*) salt); + nls_get_K(nls, K, S); + + /* calculate SHA-1 hash of username */ + SHA1Reset(&sha); + SHA1Input(&sha, (uint8_t*) nls->username, nls->username_len); + SHA1Result(&sha, username_hash); + + /* calculate M[1] */ + SHA1Reset(&sha); + SHA1Input(&sha, (uint8_t*) bncsutil_NLS_I, 20); + SHA1Input(&sha, username_hash, 20); + SHA1Input(&sha, (uint8_t*) salt, 32); + SHA1Input(&sha, (uint8_t*) A, 32); + SHA1Input(&sha, (uint8_t*) B, 32); + SHA1Input(&sha, (uint8_t*) K, 40); + SHA1Result(&sha, (uint8_t*) M1); + } + /* calculate M[2] */ SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) A, 32); @@ -573,19 +573,19 @@ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, SHA1Input(&sha, (uint8_t*) K, 40); SHA1Result(&sha, (uint8_t*) local_M2); - res = (memcmp(local_M2, var_M2, 20) == 0); + res = (memcmp(local_M2, var_M2, 20) == 0); + + if (mustFree) { + free(A); + free(K); + free(M1); + } - if (mustFree) { - free(A); - free(K); - free(M1); - } + /* cache result */ + nls->M2 = (char*) malloc(20); + if (nls->M2) + memcpy(nls->M2, local_M2, 20); - /* cache result */ - nls->M2 = (char*) malloc(20); - if (nls->M2) - memcpy(nls->M2, local_M2, 20); - return res; } @@ -595,55 +595,55 @@ MEXP(int) nls_check_signature(uint32_t address, const char* signature_raw) { mpz_t result; mpz_t modulus; mpz_t signature; - size_t size, alloc_size; - int cmp_result; - + size_t size, alloc_size; + int cmp_result; + /* build the "check" array */ - memcpy(check, &address, 4); - memset(check + 4, 0xBB, 28); - + memcpy(check, &address, 4); + memset(check + 4, 0xBB, 28); + /* initialize the modulus */ mpz_init2(modulus, 1024); mpz_import(modulus, 128, -1, 1, 0, 0, bncsutil_NLS_sig_n); - + /* initialize the server signature */ mpz_init2(signature, 1024); mpz_import(signature, 128, -1, 1, 0, 0, signature_raw); - + /* initialize the result */ mpz_init2(result, 1024); - + /* calculate the result */ mpz_powm_ui(result, signature, NLS_SIGNATURE_KEY, modulus); - + /* clear (free) the intermediates */ mpz_clear(signature); mpz_clear(modulus); - /* allocate space for raw signature */ - alloc_size = mpz_size(result) * sizeof(mp_limb_t); - result_raw = (char*) malloc(alloc_size); - if (!result_raw) { - mpz_clear(result); - return 0; - } - + /* allocate space for raw signature */ + alloc_size = mpz_size(result) * sizeof(mp_limb_t); + result_raw = (char*) malloc(alloc_size); + if (!result_raw) { + mpz_clear(result); + return 0; + } + /* get a byte array of the signature */ mpz_export(result_raw, &size, -1, 1, 0, 0, result); - + /* clear (free) the result */ mpz_clear(result); - + /* check the result */ cmp_result = (memcmp(result_raw, check, 32) == 0); - /* free the result_raw buffer */ - free(result_raw); + /* free the result_raw buffer */ + free(result_raw); - /* return */ - return cmp_result; + /* return */ + return cmp_result; } - + unsigned long nls_pre_seed() { #ifdef MOS_WINDOWS return (unsigned long) GetTickCount(); @@ -673,28 +673,28 @@ void nls_get_x(nls_t* nls, mpz_t x_c, const char* raw_salt) { char* userpass; uint8_t hash[20], final_hash[20]; SHA1Context shac; - + // build the string Username:Password userpass = (char*) malloc(nls->username_len + nls->password_len + 2); memcpy(userpass, nls->username, nls->username_len); userpass[nls->username_len] = ':'; memcpy(userpass + nls->username_len + 1, nls->password, nls->password_len); userpass[nls->username_len + nls->password_len + 1] = 0; // null-terminator - + // get the SHA-1 hash of the string SHA1Reset(&shac); SHA1Input(&shac, (uint8_t*) userpass, (nls->username_len + nls->password_len + 1)); SHA1Result(&shac, hash); free(userpass); - + // get the SHA-1 hash of the salt and user:pass hash SHA1Reset(&shac); SHA1Input(&shac, (uint8_t*) raw_salt, 32); SHA1Input(&shac, hash, 20); SHA1Result(&shac, final_hash); SHA1Reset(&shac); - + // create an arbitrary-length integer from the hash and return it mpz_init2(x_c, 160); mpz_import(x_c, 20, -1, 1, 0, 0, (char*) final_hash); @@ -712,12 +712,12 @@ uint32_t nls_get_u(const char* B) { SHA1Context sha; uint8_t hash[20]; uint32_t u; - + SHA1Reset(&sha); SHA1Input(&sha, (uint8_t*) B, 32); SHA1Result(&sha, hash); SHA1Reset(&sha); - + u = *(uint32_t*) hash; u = MSB4(u); // needed? yes return u; diff --git a/src/bncsutil/nls.h b/src/bncsutil/nls.h index 3e94df1..545a447 100644 --- a/src/bncsutil/nls.h +++ b/src/bncsutil/nls.h @@ -72,7 +72,7 @@ MEXP(void) nls_free(nls_t* nls); * pointer on failure. */ MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, - const char* password); + const char* password); /** * Re-initializes an nls_t structure with a new username and @@ -80,8 +80,8 @@ MEXP(nls_t*) nls_reinit(nls_t* nls, const char* username, * on success or a NULL pointer on failure. */ MEXP(nls_t*) nls_reinit_l(nls_t* nls, const char* username, - unsigned long username_length, const char* password, - unsigned long password_length); + unsigned long username_length, const char* password, + unsigned long password_length); /* Packet Generation Functions */ @@ -123,7 +123,7 @@ MEXP(unsigned long) nls_account_logon(nls_t* nls, char* buf, unsigned long bufSi */ MEXP(nls_t*) nls_account_change_proof(nls_t* nls, char* buf, const char* new_password, const char* B, const char* salt); - + /* Calculation Functions */ /** @@ -161,8 +161,8 @@ MEXP(void) nls_get_M1(nls_t* nls, char* out, const char* B, const char* salt); * safely set to NULL. */ MEXP(int) nls_check_M2(nls_t* nls, const char* var_M2, const char* B, - const char* salt); - + const char* salt); + /** * Checks the server signature received in SID_AUTH_INFO (0x50). * Pass the IPv4 address of the server you're connecting to in the address @@ -188,142 +188,142 @@ MEXP(int) nls_check_signature(uint32_t address, const char* signature_raw); class NLS { public: - NLS(const char* username, const char* password) : n((nls_t*) 0) - { - n = nls_init(username, password); - } - - NLS(const char* username, size_t username_length, const char* password, - size_t password_length) - { - n = nls_init_l(username, username_length, password, password_length); - } - - NLS(const std::string& username, const std::string& password) - { - n = nls_init_l(username.c_str(), username.length(), - password.c_str(), password.length()); - } - - virtual ~NLS() - { - std::vector::iterator i; - - if (n) - nls_free(n); - - for (i = blocks.begin(); i != blocks.end(); i++) { - delete [] *i; - } - } - - void getSecret(char* out, const char* salt, const char* B) - { - nls_get_S(n, out, B, salt); - } - - const char* getSecret(const char* salt, const char* B) - { - char* buf = allocateBuffer(32); - getSecret(buf, salt, B); - return buf; - } - - void getVerifier(char* out, const char* salt) - { - nls_get_v(n, out, salt); - } - - const char* getVerifier(const char* salt) - { - char* buf = allocateBuffer(32); - getVerifier(buf, salt); - return buf; - } - - void getPublicKey(char* out) - { - nls_get_A(n, out); - } - - const char* getPublicKey(void) - { - char* buf = allocateBuffer(32); - getPublicKey(buf); - return buf; - } - - void getHashedSecret(char* out, const char* secret) - { - nls_get_K(n, out, secret); - } - - const char* getHashedSecret(const char* secret) - { - char* buf = allocateBuffer(40); - getHashedSecret(buf, secret); - return buf; - } - - void getClientSessionKey(char* out, const char* salt, const char* B) - { - nls_get_M1(n, out, B, salt); - } - - const char* getClientSessionKey(const char* salt, const char* B) - { - char* buf = allocateBuffer(20); - getClientSessionKey(buf, salt, B); - return buf; - } - - bool checkServerSessionKey(const char* key, const char* salt, - const char* B) - { - return (nls_check_M2(n, key, B, salt) != 0); - } - - NLS makeChangeProof(char* buf, const char* new_password, const char* salt, - const char* B) - { - return NLS(nls_account_change_proof(n, buf, new_password, B, salt)); - } - - NLS makeChangeProof(char* buf, const std::string& new_password, - const char* salt, const char* B) - { - return NLS(nls_account_change_proof(n, buf, new_password.c_str(), B, - salt)); - } - - std::pair makeChangeProof(const char* new_password, - const char* salt, const char* B) - { - char* buf = allocateBuffer(84); - NLS nls = NLS(nls_account_change_proof(n, buf, new_password, B, salt)); - return std::pair(nls, buf); - } - - std::pair makeChangeProof(const std::string& new_password, - const char* salt, const char* B) - { - return makeChangeProof(new_password.c_str(), salt, B); - } + NLS(const char* username, const char* password) : n((nls_t*) 0) + { + n = nls_init(username, password); + } + + NLS(const char* username, size_t username_length, const char* password, + size_t password_length) + { + n = nls_init_l(username, username_length, password, password_length); + } + + NLS(const std::string& username, const std::string& password) + { + n = nls_init_l(username.c_str(), username.length(), + password.c_str(), password.length()); + } + + virtual ~NLS() + { + std::vector::iterator i; + + if (n) + nls_free(n); + + for (i = blocks.begin(); i != blocks.end(); i++) { + delete [] *i; + } + } + + void getSecret(char* out, const char* salt, const char* B) + { + nls_get_S(n, out, B, salt); + } + + const char* getSecret(const char* salt, const char* B) + { + char* buf = allocateBuffer(32); + getSecret(buf, salt, B); + return buf; + } + + void getVerifier(char* out, const char* salt) + { + nls_get_v(n, out, salt); + } + + const char* getVerifier(const char* salt) + { + char* buf = allocateBuffer(32); + getVerifier(buf, salt); + return buf; + } + + void getPublicKey(char* out) + { + nls_get_A(n, out); + } + + const char* getPublicKey(void) + { + char* buf = allocateBuffer(32); + getPublicKey(buf); + return buf; + } + + void getHashedSecret(char* out, const char* secret) + { + nls_get_K(n, out, secret); + } + + const char* getHashedSecret(const char* secret) + { + char* buf = allocateBuffer(40); + getHashedSecret(buf, secret); + return buf; + } + + void getClientSessionKey(char* out, const char* salt, const char* B) + { + nls_get_M1(n, out, B, salt); + } + + const char* getClientSessionKey(const char* salt, const char* B) + { + char* buf = allocateBuffer(20); + getClientSessionKey(buf, salt, B); + return buf; + } + + bool checkServerSessionKey(const char* key, const char* salt, + const char* B) + { + return (nls_check_M2(n, key, B, salt) != 0); + } + + NLS makeChangeProof(char* buf, const char* new_password, const char* salt, + const char* B) + { + return NLS(nls_account_change_proof(n, buf, new_password, B, salt)); + } + + NLS makeChangeProof(char* buf, const std::string& new_password, + const char* salt, const char* B) + { + return NLS(nls_account_change_proof(n, buf, new_password.c_str(), B, + salt)); + } + + std::pair makeChangeProof(const char* new_password, + const char* salt, const char* B) + { + char* buf = allocateBuffer(84); + NLS nls = NLS(nls_account_change_proof(n, buf, new_password, B, salt)); + return std::pair(nls, buf); + } + + std::pair makeChangeProof(const std::string& new_password, + const char* salt, const char* B) + { + return makeChangeProof(new_password.c_str(), salt, B); + } private: - std::vector blocks; - nls_t* n; - - NLS(nls_t* nls) - { - n = nls; - } - - char* allocateBuffer(size_t length) - { - char* buf = new char[length]; - blocks.push_back(buf); - return buf; - } + std::vector blocks; + nls_t* n; + + NLS(nls_t* nls) + { + n = nls; + } + + char* allocateBuffer(size_t length) + { + char* buf = new char[length]; + blocks.push_back(buf); + return buf; + } }; #endif diff --git a/src/bncsutil/oldauth.cpp b/src/bncsutil/oldauth.cpp index 308d823..bde739d 100644 --- a/src/bncsutil/oldauth.cpp +++ b/src/bncsutil/oldauth.cpp @@ -22,7 +22,7 @@ * write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA */ - + #include // for MEXP() #include #include @@ -44,11 +44,11 @@ uint32_t serverToken, char* outBuffer) { lp[0] = clientToken; lp[1] = serverToken; calcHashBuf(intermediate, 28, outBuffer); - + #if DEBUG - bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =", - password, clientToken, serverToken); - bncsutil_debug_dump(outBuffer, 20); + bncsutil_debug_message_a("doubleHashPassword(\"%s\", 0x%08X, 0x%08X) =", + password, clientToken, serverToken); + bncsutil_debug_dump(outBuffer, 20); #endif } @@ -61,7 +61,7 @@ MEXP(void) hashPassword(const char* password, char* outBuffer) { calcHashBuf(password, std::strlen(password), outBuffer); #if DEBUG - bncsutil_debug_message_a("hashPassword(\"%s\") =", password); - bncsutil_debug_dump(outBuffer, 20); + bncsutil_debug_message_a("hashPassword(\"%s\") =", password); + bncsutil_debug_dump(outBuffer, 20); #endif } diff --git a/src/bncsutil/pe.c b/src/bncsutil/pe.c index 0c35ada..24de769 100644 --- a/src/bncsutil/pe.c +++ b/src/bncsutil/pe.c @@ -32,453 +32,453 @@ int cm_pe_load_resdir(FILE* f, uint32_t offset, cm_pe_resdir_t* dir); MEXP(cm_pe_t) cm_pe_load(const char* filename) { - cm_pe_t pe; - cm_pe_header_t* header; - cm_pe_optional_header_t* opt_header; - cm_pe_windows_header_t* win_header; - long pe_offset = 0; - //size_t i; - size_t count; - - pe = (cm_pe_t) malloc(sizeof(struct cm_pe)); - if (!pe) - return (cm_pe_t) 0; - - memset(pe, 0, sizeof(struct cm_pe)); - - pe->f = fopen(filename, "r"); - if (!pe->f) { - free(pe); - return (cm_pe_t) 0; - } - - if (fseek(pe->f, 0x3CL, SEEK_SET) == -1) - goto err_trap; - - if (fread(&pe_offset, 4, 1, pe->f) != 1) - goto err_trap; - + cm_pe_t pe; + cm_pe_header_t* header; + cm_pe_optional_header_t* opt_header; + cm_pe_windows_header_t* win_header; + long pe_offset = 0; + //size_t i; + size_t count; + + pe = (cm_pe_t) malloc(sizeof(struct cm_pe)); + if (!pe) + return (cm_pe_t) 0; + + memset(pe, 0, sizeof(struct cm_pe)); + + pe->f = fopen(filename, "r"); + if (!pe->f) { + free(pe); + return (cm_pe_t) 0; + } + + if (fseek(pe->f, 0x3CL, SEEK_SET) == -1) + goto err_trap; + + if (fread(&pe_offset, 4, 1, pe->f) != 1) + goto err_trap; + #if BIG_ENDIAN - pe_offset = LSB4(pe_offset); + pe_offset = LSB4(pe_offset); #endif - - if (fseek(pe->f, pe_offset, SEEK_SET) == -1) - goto err_trap; - - if (fread(&pe->header, sizeof(cm_pe_header_t), 1, pe->f) != 1) - goto err_trap; - - header = &pe->header; + + if (fseek(pe->f, pe_offset, SEEK_SET) == -1) + goto err_trap; + + if (fread(&pe->header, sizeof(cm_pe_header_t), 1, pe->f) != 1) + goto err_trap; + + header = &pe->header; #if BIGENDIAN - /* Without regular expressions, this would've sucked. */ - header->signature = SWAP32(header->signature); - header->machine = SWAP16(header->machine); - header->section_count = SWAP16(header->section_count); - header->timestamp = SWAP32(header->timestamp); - header->symbol_table_offset = SWAP32(header->symbol_table_offset); - header->symbol_count = SWAP32(header->symbol_count); - header->optional_header_size = SWAP16(header->optional_header_size); - header->characteristics = SWAP16(header->characteristics); + /* Without regular expressions, this would've sucked. */ + header->signature = SWAP32(header->signature); + header->machine = SWAP16(header->machine); + header->section_count = SWAP16(header->section_count); + header->timestamp = SWAP32(header->timestamp); + header->symbol_table_offset = SWAP32(header->symbol_table_offset); + header->symbol_count = SWAP32(header->symbol_count); + header->optional_header_size = SWAP16(header->optional_header_size); + header->characteristics = SWAP16(header->characteristics); #endif - - if (header->optional_header_size > 0) { - if (fread(&pe->optional_header, PE_OPTIONAL_HEADER_MIN_SIZE, 1, pe->f) - != 1) - { - goto err_trap; - } - - opt_header = &pe->optional_header; - win_header = &pe->windows_header; - + + if (header->optional_header_size > 0) { + if (fread(&pe->optional_header, PE_OPTIONAL_HEADER_MIN_SIZE, 1, pe->f) + != 1) + { + goto err_trap; + } + + opt_header = &pe->optional_header; + win_header = &pe->windows_header; + #if BIGENDIAN - opt_header->magic = SWAP16(opt_header->magic); + opt_header->magic = SWAP16(opt_header->magic); #endif - - if (opt_header->magic == IMAGE_FORMAT_PE32) { - if (fread(&opt_header->data_base, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->image_base, 4, 1, pe->f) != 1) - goto err_trap; - // The 40 is not a typo. - if (fread(&win_header->section_alignment, 40, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->stack_reserve_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->stack_commit_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->heap_reserve_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->heap_commit_size, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->loader_flags, 4, 1, pe->f) != 1) - goto err_trap; - if (fread(&win_header->data_directory_count, 4, 1, pe->f) != 1) - goto err_trap; - } else if (opt_header->magic == IMAGE_FORMAT_PE32_PLUS) { - if (fread(win_header, sizeof(cm_pe_windows_header_t), 1, pe->f)!= 1) - goto err_trap; - } else { - goto err_trap; - } - + + if (opt_header->magic == IMAGE_FORMAT_PE32) { + if (fread(&opt_header->data_base, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->image_base, 4, 1, pe->f) != 1) + goto err_trap; + // The 40 is not a typo. + if (fread(&win_header->section_alignment, 40, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->stack_reserve_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->stack_commit_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->heap_reserve_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->heap_commit_size, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->loader_flags, 4, 1, pe->f) != 1) + goto err_trap; + if (fread(&win_header->data_directory_count, 4, 1, pe->f) != 1) + goto err_trap; + } else if (opt_header->magic == IMAGE_FORMAT_PE32_PLUS) { + if (fread(win_header, sizeof(cm_pe_windows_header_t), 1, pe->f)!= 1) + goto err_trap; + } else { + goto err_trap; + } + #if BIGENDIAN - opt_header->code_section_size = SWAP32(opt_header->code_section_size); - opt_header->initialized_data_size = - SWAP32(opt_header->initialized_data_size); - opt_header->uninitialized_data_size = - SWAP32(opt_header->uninitialized_data_size); - opt_header->entry_point = SWAP32(opt_header->entry_point); - opt_header->code_base = SWAP32(opt_header->code_base); - opt_header->data_base = SWAP32(opt_header->data_base); - - win_header->image_base = SWAP64(win_header->image_base); - win_header->section_alignment = SWAP32(win_header->section_alignment); - win_header->file_alignment = SWAP32(win_header->file_alignment); - win_header->major_os_version = SWAP16(win_header->major_os_version); - win_header->minor_os_version = SWAP16(win_header->minor_os_version); - win_header->major_image_version = - SWAP16(win_header->major_image_version); - win_header->minor_image_version = - SWAP16(win_header->minor_image_version); - win_header->major_subsystem_version = - SWAP16(win_header->major_subsystem_version); - win_header->minor_subsystem_version = - SWAP16(win_header->minor_subsystem_version); - win_header->reserved = SWAP32(win_header->reserved); - win_header->image_size = SWAP32(win_header->image_size); - win_header->headers_size = SWAP32(win_header->headers_size); - win_header->checksum = SWAP32(win_header->checksum); - win_header->subsystem = SWAP16(win_header->subsystem); - win_header->dll_characteristics = - SWAP16(win_header->dll_characteristics); - win_header->stack_reserve_size = SWAP64(win_header->stack_reserve_size); - win_header->stack_commit_size = SWAP64(win_header->stack_commit_size); - win_header->heap_reserve_size = SWAP64(win_header->heap_reserve_size); - win_header->heap_commit_size = SWAP64(win_header->heap_commit_size); - win_header->loader_flags = SWAP32(win_header->loader_flags); - win_header->data_directory_count = - SWAP32(win_header->data_directory_count); + opt_header->code_section_size = SWAP32(opt_header->code_section_size); + opt_header->initialized_data_size = + SWAP32(opt_header->initialized_data_size); + opt_header->uninitialized_data_size = + SWAP32(opt_header->uninitialized_data_size); + opt_header->entry_point = SWAP32(opt_header->entry_point); + opt_header->code_base = SWAP32(opt_header->code_base); + opt_header->data_base = SWAP32(opt_header->data_base); + + win_header->image_base = SWAP64(win_header->image_base); + win_header->section_alignment = SWAP32(win_header->section_alignment); + win_header->file_alignment = SWAP32(win_header->file_alignment); + win_header->major_os_version = SWAP16(win_header->major_os_version); + win_header->minor_os_version = SWAP16(win_header->minor_os_version); + win_header->major_image_version = + SWAP16(win_header->major_image_version); + win_header->minor_image_version = + SWAP16(win_header->minor_image_version); + win_header->major_subsystem_version = + SWAP16(win_header->major_subsystem_version); + win_header->minor_subsystem_version = + SWAP16(win_header->minor_subsystem_version); + win_header->reserved = SWAP32(win_header->reserved); + win_header->image_size = SWAP32(win_header->image_size); + win_header->headers_size = SWAP32(win_header->headers_size); + win_header->checksum = SWAP32(win_header->checksum); + win_header->subsystem = SWAP16(win_header->subsystem); + win_header->dll_characteristics = + SWAP16(win_header->dll_characteristics); + win_header->stack_reserve_size = SWAP64(win_header->stack_reserve_size); + win_header->stack_commit_size = SWAP64(win_header->stack_commit_size); + win_header->heap_reserve_size = SWAP64(win_header->heap_reserve_size); + win_header->heap_commit_size = SWAP64(win_header->heap_commit_size); + win_header->loader_flags = SWAP32(win_header->loader_flags); + win_header->data_directory_count = + SWAP32(win_header->data_directory_count); #endif - - if (win_header->data_directory_count > 0) { - count = win_header->data_directory_count; - pe->data_directories = (cm_pe_data_directory_t*) - calloc(sizeof(cm_pe_data_directory_t), count); - - if (!pe->data_directories) - goto err_trap; - - if (fread(pe->data_directories, sizeof(cm_pe_data_directory_t), - count, pe->f) != count) - { - goto dir_err_trap; - } - + + if (win_header->data_directory_count > 0) { + count = win_header->data_directory_count; + pe->data_directories = (cm_pe_data_directory_t*) + calloc(sizeof(cm_pe_data_directory_t), count); + + if (!pe->data_directories) + goto err_trap; + + if (fread(pe->data_directories, sizeof(cm_pe_data_directory_t), + count, pe->f) != count) + { + goto dir_err_trap; + } + #if BIGENDIAN - for (i = 0; i < count; i++) { - pe->data_directories[i].rva = - SWAP32(pe->data_directories[i].rva); - pe->data_directories[i].size = - SWAP32(pe->data_directories[i].size); - } + for (i = 0; i < count; i++) { + pe->data_directories[i].rva = + SWAP32(pe->data_directories[i].rva); + pe->data_directories[i].size = + SWAP32(pe->data_directories[i].size); + } #endif - } - - count = (size_t) header->section_count; - if (count) { - pe->sections = (cm_pe_section_t*) calloc(sizeof(cm_pe_section_t), - count); - - if (!pe->sections) - goto dir_err_trap; - - if (fread(pe->sections, sizeof(cm_pe_section_t), count, pe->f) - != count) - { - goto sect_err_trap; - } - } - + } + + count = (size_t) header->section_count; + if (count) { + pe->sections = (cm_pe_section_t*) calloc(sizeof(cm_pe_section_t), + count); + + if (!pe->sections) + goto dir_err_trap; + + if (fread(pe->sections, sizeof(cm_pe_section_t), count, pe->f) + != count) + { + goto sect_err_trap; + } + } + #if BIGENDIAN - for (i = 0; i < count; i++) { - pe->sections[i].virtual_size = SWAP32(pe->sections[i].virtual_size); - pe->sections[i].virtual_address = - SWAP32(pe->sections[i].virtual_address); - pe->sections[i].raw_data_size = - SWAP32(pe->sections[i].raw_data_size); - pe->sections[i].raw_data_offset = - SWAP32(pe->sections[i].raw_data_offset); - pe->sections[i].relocations_offset = - SWAP32(pe->sections[i].relocations_offset); - pe->sections[i].line_numbers_offset = - SWAP32(pe->sections[i].line_numbers_offset); - pe->sections[i].relocation_count = - SWAP16(pe->sections[i].relocation_count); - pe->sections[i].line_number_count = - SWAP16(pe->sections[i].line_number_count); - pe->sections[i].characteristics = - SWAP32(pe->sections[i].characteristics); - } + for (i = 0; i < count; i++) { + pe->sections[i].virtual_size = SWAP32(pe->sections[i].virtual_size); + pe->sections[i].virtual_address = + SWAP32(pe->sections[i].virtual_address); + pe->sections[i].raw_data_size = + SWAP32(pe->sections[i].raw_data_size); + pe->sections[i].raw_data_offset = + SWAP32(pe->sections[i].raw_data_offset); + pe->sections[i].relocations_offset = + SWAP32(pe->sections[i].relocations_offset); + pe->sections[i].line_numbers_offset = + SWAP32(pe->sections[i].line_numbers_offset); + pe->sections[i].relocation_count = + SWAP16(pe->sections[i].relocation_count); + pe->sections[i].line_number_count = + SWAP16(pe->sections[i].line_number_count); + pe->sections[i].characteristics = + SWAP32(pe->sections[i].characteristics); + } #endif - } - - return pe; + } + + return pe; sect_err_trap: - free(pe->sections); + free(pe->sections); dir_err_trap: - free(pe->data_directories); + free(pe->data_directories); err_trap: - fclose(pe->f); - free(pe); - return (cm_pe_t) 0; + fclose(pe->f); + free(pe); + return (cm_pe_t) 0; } MEXP(void) cm_pe_unload(cm_pe_t pe) { - if (pe->data_directories) - free(pe->data_directories); - if (pe->sections) - free(pe->sections); - if (pe->f) - fclose(pe->f); - free(pe); + if (pe->data_directories) + free(pe->data_directories); + if (pe->sections) + free(pe->sections); + if (pe->f) + fclose(pe->f); + free(pe); } MEXP(cm_pe_section_t*) cm_pe_get_section(cm_pe_t pe, const char* name) { - unsigned int i; - cm_pe_section_t* s; - uint32_t section_count = pe->header.section_count; - - if (!pe || !pe->sections) - return (cm_pe_section_t*) 0; - - for (i = 0, s = pe->sections; i < section_count; i++, s++) { - if (strcmp(s->name, name) == 0) - return s; - } - - return (cm_pe_section_t*) 0; + unsigned int i; + cm_pe_section_t* s; + uint32_t section_count = pe->header.section_count; + + if (!pe || !pe->sections) + return (cm_pe_section_t*) 0; + + for (i = 0, s = pe->sections; i < section_count; i++, s++) { + if (strcmp(s->name, name) == 0) + return s; + } + + return (cm_pe_section_t*) 0; } MEXP(cm_pe_resdir_t*) cm_pe_load_resources(cm_pe_t pe) { - cm_pe_section_t* sect; - cm_pe_resdir_t* root = (cm_pe_resdir_t*) 0; - cm_pe_resdir_t* dir; - cm_pe_resdir_t* subdirs; - cm_pe_res_t res; - cm_pe_res_t* resources; - cm_stack_t stack; - size_t i; - uint32_t base; - - // no need to check validity of pe pointer; cm_pe_get_section does this - sect = cm_pe_get_section(pe, ".rsrc"); - if (!sect) - return (cm_pe_resdir_t*) 0; - - root = (cm_pe_resdir_t*) malloc(sizeof(cm_pe_resdir_t)); - if (!root) - return (cm_pe_resdir_t*) 0; - - base = sect->raw_data_offset; - if (!cm_pe_load_resdir(pe->f, base, root)) { - free(root); - return (cm_pe_resdir_t*) 0; - } - - stack = cm_stack_create(); - if (!stack) { - free(root); - return (cm_pe_resdir_t*) 0; - } - - cm_stack_push(stack, root); - - while ( (dir = (cm_pe_resdir_t*) cm_stack_pop(stack)) ) { - while (dir->subdir_count + dir->resource_count < - dir->named_entry_count + dir->id_entry_count) - { - if (fseek(pe->f, dir->offset, SEEK_SET) == -1) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - - if (fread(&res, CM_RES_REAL_SIZE, 1, pe->f) != 1) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - - #if BIGENDIAN - res.name = SWAP4(res.name); - res.offset = SWAP4(res.offset); - #endif - if (res.offset & 0x80000000) { - // subdirectory - i = dir->subdir_count++; - subdirs = (cm_pe_resdir_t*) realloc(dir->subdirs, - sizeof(cm_pe_resdir_t) * dir->subdir_count); - if (!subdirs) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->subdirs = subdirs; - - cm_stack_push(stack, dir); - dir->offset += CM_RES_REAL_SIZE; - dir = (subdirs + i); - - res.offset &= 0x7FFFFFFF; - res.file_offset = base + res.offset; - - if (!cm_pe_load_resdir(pe->f, res.file_offset, dir)) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->name = res.name; - - cm_stack_push(stack, dir); - break; - } - // real resource - res.file_offset = base + res.offset; - i = dir->resource_count++; - resources = (cm_pe_res_t*) realloc(dir->resources, - sizeof(cm_pe_res_t) * dir->resource_count); - if (!resources) { - cm_pe_unload_resources(root); - cm_stack_destroy(stack); - return (cm_pe_resdir_t*) 0; - } - dir->resources = resources; - memcpy(dir->resources + i, &res, sizeof(cm_pe_res_t)); - dir->offset += CM_RES_REAL_SIZE; - } - } - - cm_stack_destroy(stack); - return root; + cm_pe_section_t* sect; + cm_pe_resdir_t* root = (cm_pe_resdir_t*) 0; + cm_pe_resdir_t* dir; + cm_pe_resdir_t* subdirs; + cm_pe_res_t res; + cm_pe_res_t* resources; + cm_stack_t stack; + size_t i; + uint32_t base; + + // no need to check validity of pe pointer; cm_pe_get_section does this + sect = cm_pe_get_section(pe, ".rsrc"); + if (!sect) + return (cm_pe_resdir_t*) 0; + + root = (cm_pe_resdir_t*) malloc(sizeof(cm_pe_resdir_t)); + if (!root) + return (cm_pe_resdir_t*) 0; + + base = sect->raw_data_offset; + if (!cm_pe_load_resdir(pe->f, base, root)) { + free(root); + return (cm_pe_resdir_t*) 0; + } + + stack = cm_stack_create(); + if (!stack) { + free(root); + return (cm_pe_resdir_t*) 0; + } + + cm_stack_push(stack, root); + + while ( (dir = (cm_pe_resdir_t*) cm_stack_pop(stack)) ) { + while (dir->subdir_count + dir->resource_count < + dir->named_entry_count + dir->id_entry_count) + { + if (fseek(pe->f, dir->offset, SEEK_SET) == -1) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + + if (fread(&res, CM_RES_REAL_SIZE, 1, pe->f) != 1) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + + #if BIGENDIAN + res.name = SWAP4(res.name); + res.offset = SWAP4(res.offset); + #endif + if (res.offset & 0x80000000) { + // subdirectory + i = dir->subdir_count++; + subdirs = (cm_pe_resdir_t*) realloc(dir->subdirs, + sizeof(cm_pe_resdir_t) * dir->subdir_count); + if (!subdirs) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->subdirs = subdirs; + + cm_stack_push(stack, dir); + dir->offset += CM_RES_REAL_SIZE; + dir = (subdirs + i); + + res.offset &= 0x7FFFFFFF; + res.file_offset = base + res.offset; + + if (!cm_pe_load_resdir(pe->f, res.file_offset, dir)) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->name = res.name; + + cm_stack_push(stack, dir); + break; + } + // real resource + res.file_offset = base + res.offset; + i = dir->resource_count++; + resources = (cm_pe_res_t*) realloc(dir->resources, + sizeof(cm_pe_res_t) * dir->resource_count); + if (!resources) { + cm_pe_unload_resources(root); + cm_stack_destroy(stack); + return (cm_pe_resdir_t*) 0; + } + dir->resources = resources; + memcpy(dir->resources + i, &res, sizeof(cm_pe_res_t)); + dir->offset += CM_RES_REAL_SIZE; + } + } + + cm_stack_destroy(stack); + return root; } MEXP(int) cm_pe_unload_resources(cm_pe_resdir_t* root) { - cm_pe_resdir_t* dir; - cm_stack_t stack; - - stack = cm_stack_create(); - if (!stack) - return 0; - - cm_stack_push(stack, root); - - while ( (dir = cm_stack_pop(stack)) ) { - if (dir->subdir_count) { - dir->subdir_count--; - cm_stack_push(stack, dir); - cm_stack_push(stack, (dir->subdirs + dir->subdir_count)); - continue; - } - - if (dir->subdirs) { - free(dir->subdirs); - dir->subdirs = (cm_pe_resdir_t*) 0; - } - - if (dir->resources) { - free(dir->resources); - dir->resource_count = 0; - } - } - - cm_stack_destroy(stack); - free(root); - return 1; + cm_pe_resdir_t* dir; + cm_stack_t stack; + + stack = cm_stack_create(); + if (!stack) + return 0; + + cm_stack_push(stack, root); + + while ( (dir = cm_stack_pop(stack)) ) { + if (dir->subdir_count) { + dir->subdir_count--; + cm_stack_push(stack, dir); + cm_stack_push(stack, (dir->subdirs + dir->subdir_count)); + continue; + } + + if (dir->subdirs) { + free(dir->subdirs); + dir->subdirs = (cm_pe_resdir_t*) 0; + } + + if (dir->resources) { + free(dir->resources); + dir->resource_count = 0; + } + } + + cm_stack_destroy(stack); + free(root); + return 1; } MEXP(int) cm_pe_fixed_version(cm_pe_t pe, cm_pe_res_t* res, - cm_pe_version_t* ver) + cm_pe_version_t* ver) { - cm_pe_section_t* sect = (pe->sections + 3); + cm_pe_section_t* sect = (pe->sections + 3); #if BIGENDIAN - uint32_t check = 0xBD04EFFE; + uint32_t check = 0xBD04EFFE; #else - uint32_t check = 0xFEEF04BD; + uint32_t check = 0xFEEF04BD; #endif - uint32_t rva; - uint32_t size; - uint32_t offset; - uint32_t align; - - if (!pe || !res || !ver) - return 0; - - if (fseek(pe->f, res->file_offset, SEEK_SET) == -1) - return 0; - if (fread(&rva, 4, 1, pe->f) != 1) - return 0; - if (fread(&size, 4, 1, pe->f) != 1) - return 0; + uint32_t rva; + uint32_t size; + uint32_t offset; + uint32_t align; + + if (!pe || !res || !ver) + return 0; + + if (fseek(pe->f, res->file_offset, SEEK_SET) == -1) + return 0; + if (fread(&rva, 4, 1, pe->f) != 1) + return 0; + if (fread(&size, 4, 1, pe->f) != 1) + return 0; #if BIGENDIAN - rva = SWAP4(rva); - size = SWAP4(size); + rva = SWAP4(rva); + size = SWAP4(size); #endif - - offset = sect->raw_data_offset + (rva - sect->virtual_address) + 0x26; - align = 4 -(offset & 0xF % 4); - if (align < 4) - offset += align; - if (fseek(pe->f, offset, SEEK_SET) == -1) - return 0; - if (fread(ver, sizeof(cm_pe_version_t), 1, pe->f) != 1) - return 0; - - if (ver->dwSignature != check) - return 0; - + + offset = sect->raw_data_offset + (rva - sect->virtual_address) + 0x26; + align = 4 -(offset & 0xF % 4); + if (align < 4) + offset += align; + if (fseek(pe->f, offset, SEEK_SET) == -1) + return 0; + if (fread(ver, sizeof(cm_pe_version_t), 1, pe->f) != 1) + return 0; + + if (ver->dwSignature != check) + return 0; + #if BIGENDIAN - ver->dwSignature = SWAP32(ver->dwSignature); - ver->dwStrucVersion = SWAP32(ver->dwStrucVersion); - ver->dwFileVersionMS = SWAP32(ver->dwFileVersionMS); - ver->dwFileVersionLS = SWAP32(ver->dwFileVersionLS); - ver->dwProductVersionMS = SWAP32(ver->dwProductVersionMS); - ver->dwProductVersionLS = SWAP32(ver->dwProductVersionLS); - ver->dwFileFlagsMask = SWAP32(ver->dwFileFlagsMask); - ver->dwFileFlags = SWAP32(ver->dwFileFlags); - ver->dwFileOS = SWAP32(ver->dwFileOS); - ver->dwFileType = SWAP32(ver->dwFileType); - ver->dwFileSubtype = SWAP32(ver->dwFileSubtype); - ver->dwFileDateMS = SWAP32(ver->dwFileDateMS); - ver->dwFileDateLS = SWAP32(ver->dwFileDateLS); + ver->dwSignature = SWAP32(ver->dwSignature); + ver->dwStrucVersion = SWAP32(ver->dwStrucVersion); + ver->dwFileVersionMS = SWAP32(ver->dwFileVersionMS); + ver->dwFileVersionLS = SWAP32(ver->dwFileVersionLS); + ver->dwProductVersionMS = SWAP32(ver->dwProductVersionMS); + ver->dwProductVersionLS = SWAP32(ver->dwProductVersionLS); + ver->dwFileFlagsMask = SWAP32(ver->dwFileFlagsMask); + ver->dwFileFlags = SWAP32(ver->dwFileFlags); + ver->dwFileOS = SWAP32(ver->dwFileOS); + ver->dwFileType = SWAP32(ver->dwFileType); + ver->dwFileSubtype = SWAP32(ver->dwFileSubtype); + ver->dwFileDateMS = SWAP32(ver->dwFileDateMS); + ver->dwFileDateLS = SWAP32(ver->dwFileDateLS); #endif - - return 1; + + return 1; } int cm_pe_load_resdir(FILE* f, uint32_t offset, cm_pe_resdir_t* dir) { - memset(dir, 0, sizeof(cm_pe_resdir_t)); - - if (fseek(f, offset, SEEK_SET) == -1) - return 0; - - if (fread(dir, 16, 1, f) != 1) - return 0; - + memset(dir, 0, sizeof(cm_pe_resdir_t)); + + if (fseek(f, offset, SEEK_SET) == -1) + return 0; + + if (fread(dir, 16, 1, f) != 1) + return 0; + #if BIGENDIAN - dir->characteristics = SWAP32(dir->characteristics); - dir->timestamp = SWAP32(dir->timestamp); - dir->major_version = SWAP16(dir->major_version); - dir->minor_version = SWAP16(dir->minor_version); - dir->named_entry_count = SWAP16(dir->named_entry_count); - dir->id_entry_count = SWAP16(dir->id_entry_count); + dir->characteristics = SWAP32(dir->characteristics); + dir->timestamp = SWAP32(dir->timestamp); + dir->major_version = SWAP16(dir->major_version); + dir->minor_version = SWAP16(dir->minor_version); + dir->named_entry_count = SWAP16(dir->named_entry_count); + dir->id_entry_count = SWAP16(dir->id_entry_count); #endif - - dir->offset = (uint32_t) ftell(f); - - return 1; + + dir->offset = (uint32_t) ftell(f); + + return 1; } diff --git a/src/bncsutil/pe.h b/src/bncsutil/pe.h index 9ff28d6..1795a10 100644 --- a/src/bncsutil/pe.h +++ b/src/bncsutil/pe.h @@ -34,135 +34,135 @@ extern "C" { #endif typedef struct cm_pe_header { - uint32_t signature; - uint16_t machine; // IMAGE_FILE_MACHINE_* - uint16_t section_count; - uint32_t timestamp; - uint32_t symbol_table_offset; - uint32_t symbol_count; - uint16_t optional_header_size; - uint16_t characteristics; + uint32_t signature; + uint16_t machine; // IMAGE_FILE_MACHINE_* + uint16_t section_count; + uint32_t timestamp; + uint32_t symbol_table_offset; + uint32_t symbol_count; + uint16_t optional_header_size; + uint16_t characteristics; } cm_pe_header_t; -#define IMAGE_FORMAT_PE32 0x10B -#define IMAGE_FORMAT_PE32_PLUS 0x20B +#define IMAGE_FORMAT_PE32 0x10B +#define IMAGE_FORMAT_PE32_PLUS 0x20B typedef struct cm_pe_optional_header { - uint16_t magic; // image format (PE32/PE32+) - uint8_t major_linker_version; - uint8_t minor_linker_version; - uint32_t code_section_size; - uint32_t initialized_data_size; - uint32_t uninitialized_data_size; - uint32_t entry_point; - uint32_t code_base; - uint32_t data_base; // not present in PE32+! + uint16_t magic; // image format (PE32/PE32+) + uint8_t major_linker_version; + uint8_t minor_linker_version; + uint32_t code_section_size; + uint32_t initialized_data_size; + uint32_t uninitialized_data_size; + uint32_t entry_point; + uint32_t code_base; + uint32_t data_base; // not present in PE32+! } cm_pe_optional_header_t; #define PE_OPTIONAL_HEADER_MIN_SIZE (sizeof(cm_pe_optional_header_t) - 4) typedef struct cm_pe_windows_header { - uint64_t image_base; - uint32_t section_alignment; - uint32_t file_alignment; - uint16_t major_os_version; - uint16_t minor_os_version; - uint16_t major_image_version; - uint16_t minor_image_version; - uint16_t major_subsystem_version; - uint16_t minor_subsystem_version; - uint32_t reserved; - uint32_t image_size; - uint32_t headers_size; - uint32_t checksum; - uint16_t subsystem; - uint16_t dll_characteristics; - uint64_t stack_reserve_size; - uint64_t stack_commit_size; - uint64_t heap_reserve_size; - uint64_t heap_commit_size; - uint32_t loader_flags; - uint32_t data_directory_count; + uint64_t image_base; + uint32_t section_alignment; + uint32_t file_alignment; + uint16_t major_os_version; + uint16_t minor_os_version; + uint16_t major_image_version; + uint16_t minor_image_version; + uint16_t major_subsystem_version; + uint16_t minor_subsystem_version; + uint32_t reserved; + uint32_t image_size; + uint32_t headers_size; + uint32_t checksum; + uint16_t subsystem; + uint16_t dll_characteristics; + uint64_t stack_reserve_size; + uint64_t stack_commit_size; + uint64_t heap_reserve_size; + uint64_t heap_commit_size; + uint32_t loader_flags; + uint32_t data_directory_count; } cm_pe_windows_header_t; typedef struct cm_pe_data_directory { - uint32_t rva; - uint32_t size; + uint32_t rva; + uint32_t size; } cm_pe_data_directory_t; typedef struct cm_pe_section { - char name[8]; - uint32_t virtual_size; - uint32_t virtual_address; - uint32_t raw_data_size; - uint32_t raw_data_offset; - uint32_t relocations_offset; - uint32_t line_numbers_offset; - uint16_t relocation_count; - uint16_t line_number_count; - uint32_t characteristics; + char name[8]; + uint32_t virtual_size; + uint32_t virtual_address; + uint32_t raw_data_size; + uint32_t raw_data_offset; + uint32_t relocations_offset; + uint32_t line_numbers_offset; + uint16_t relocation_count; + uint16_t line_number_count; + uint32_t characteristics; } cm_pe_section_t; -typedef struct VS_FIXEDFILEINFO { - uint32_t dwSignature; - uint32_t dwStrucVersion; - uint32_t dwFileVersionMS; - uint32_t dwFileVersionLS; - union { - struct { - uint32_t dwProductVersionMS; - uint32_t dwProductVersionLS; - }; - uint64_t qwProductVersion; - }; - uint32_t dwFileFlagsMask; - uint32_t dwFileFlags; - uint32_t dwFileOS; - uint32_t dwFileType; - uint32_t dwFileSubtype; - union { - struct { - uint32_t dwFileDateMS; - uint32_t dwFileDateLS; - }; - uint64_t qwFileDate; - }; +typedef struct VS_FIXEDFILEINFO { + uint32_t dwSignature; + uint32_t dwStrucVersion; + uint32_t dwFileVersionMS; + uint32_t dwFileVersionLS; + union { + struct { + uint32_t dwProductVersionMS; + uint32_t dwProductVersionLS; + }; + uint64_t qwProductVersion; + }; + uint32_t dwFileFlagsMask; + uint32_t dwFileFlags; + uint32_t dwFileOS; + uint32_t dwFileType; + uint32_t dwFileSubtype; + union { + struct { + uint32_t dwFileDateMS; + uint32_t dwFileDateLS; + }; + uint64_t qwFileDate; + }; } cm_pe_version_t; typedef struct cm_pe_resource { - uint32_t name; - uint32_t offset; - uint32_t file_offset; + uint32_t name; + uint32_t offset; + uint32_t file_offset; } cm_pe_res_t; -#define CM_RES_REAL_SIZE 8 +#define CM_RES_REAL_SIZE 8 typedef struct cm_pe_resdir { - uint32_t characteristics; - uint32_t timestamp; - uint16_t major_version; - uint16_t minor_version; - uint16_t named_entry_count; - uint16_t id_entry_count; - - size_t subdir_count; - struct cm_pe_resdir* subdirs; - size_t resource_count; - cm_pe_res_t* resources; - - uint32_t offset; - uint32_t name; + uint32_t characteristics; + uint32_t timestamp; + uint16_t major_version; + uint16_t minor_version; + uint16_t named_entry_count; + uint16_t id_entry_count; + + size_t subdir_count; + struct cm_pe_resdir* subdirs; + size_t resource_count; + cm_pe_res_t* resources; + + uint32_t offset; + uint32_t name; } cm_pe_resdir_t; typedef struct cm_pe { - FILE* f; - cm_pe_header_t header; - cm_pe_optional_header_t optional_header; - cm_pe_windows_header_t windows_header; - cm_pe_data_directory_t* data_directories; - cm_pe_section_t* sections; + FILE* f; + cm_pe_header_t header; + cm_pe_optional_header_t optional_header; + cm_pe_windows_header_t windows_header; + cm_pe_data_directory_t* data_directories; + cm_pe_section_t* sections; } *cm_pe_t; -#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 +#define IMAGE_FILE_MACHINE_UNKNOWN 0x0 #define IMAGE_FILE_MACHINE_ALPHA 0x184 #define IMAGE_FILE_MACHINE_ARM 0x1c0 #define IMAGE_FILE_MACHINE_ALPHA64 0x284 @@ -171,7 +171,7 @@ typedef struct cm_pe { #define IMAGE_FILE_MACHINE_M68K 0x268 #define IMAGE_FILE_MACHINE_MIPS16 0x266 #define IMAGE_FILE_MACHINE_MIPSFPU 0x366 -#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 +#define IMAGE_FILE_MACHINE_MIPSFPU16 0x466 #define IMAGE_FILE_MACHINE_POWERPC 0x1f0 #define IMAGE_FILE_MACHINE_R3000 0x162 #define IMAGE_FILE_MACHINE_R4000 0x166 @@ -185,7 +185,7 @@ MEXP(void) cm_pe_unload(cm_pe_t pe); MEXP(cm_pe_resdir_t*) cm_pe_load_resources(cm_pe_t pe); MEXP(int) cm_pe_unload_resources(cm_pe_resdir_t* dir); MEXP(int) cm_pe_fixed_version(cm_pe_t pe, cm_pe_res_t* res, - cm_pe_version_t* ver); + cm_pe_version_t* ver); #ifdef __cplusplus } diff --git a/src/bncsutil/sha1.h b/src/bncsutil/sha1.h index e7753d4..23a3452 100644 --- a/src/bncsutil/sha1.h +++ b/src/bncsutil/sha1.h @@ -74,7 +74,7 @@ int SHA1Input( SHA1Context *, unsigned int); int SHA1Result( SHA1Context *, uint8_t Message_Digest[SHA1HashSize]); - + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/bncsutil/stack.c b/src/bncsutil/stack.c index 0525209..1b37f6d 100644 --- a/src/bncsutil/stack.c +++ b/src/bncsutil/stack.c @@ -23,7 +23,7 @@ * Boston, MA 02111-1307 USA */ -/* +/** * Mule Server * Copyright (c) 2004-2006 Eric Naeseth. * @@ -33,81 +33,81 @@ #include #include - + cm_stack_t cm_stack_create() { - cm_stack_t stack = (cm_stack_t) calloc(1, sizeof(struct cm_stack)); - if (!stack) - return (cm_stack_t) 0; - return stack; + cm_stack_t stack = (cm_stack_t) calloc(1, sizeof(struct cm_stack)); + if (!stack) + return (cm_stack_t) 0; + return stack; } void cm_stack_destroy(cm_stack_t stack) { - cm_stack_node_t* node; - cm_stack_node_t* next; - - if (!stack) - return; - - node = stack->top; - - while (node) { - next = node->next; - free(node); - node = next; - } - - free(stack); + cm_stack_node_t* node; + cm_stack_node_t* next; + + if (!stack) + return; + + node = stack->top; + + while (node) { + next = node->next; + free(node); + node = next; + } + + free(stack); } void cm_stack_push(cm_stack_t stack, void* item) { - cm_stack_node_t* new_node; - - if (!stack || !item) - return; - - new_node = (cm_stack_node_t*) malloc(sizeof(cm_stack_node_t)); - if (!new_node) - return; - new_node->next = stack->top; - new_node->value = item; - - stack->size++; - - stack->top = new_node; + cm_stack_node_t* new_node; + + if (!stack || !item) + return; + + new_node = (cm_stack_node_t*) malloc(sizeof(cm_stack_node_t)); + if (!new_node) + return; + new_node->next = stack->top; + new_node->value = item; + + stack->size++; + + stack->top = new_node; } void* cm_stack_pop(cm_stack_t stack) { - cm_stack_node_t* next; - void* value; - - if (!stack || !stack->top) - return (void*) 0; - - next = stack->top->next; - value = stack->top->value; - free(stack->top); - - stack->top = next; - stack->size--; - return value; + cm_stack_node_t* next; + void* value; + + if (!stack || !stack->top) + return (void*) 0; + + next = stack->top->next; + value = stack->top->value; + free(stack->top); + + stack->top = next; + stack->size--; + return value; } void* cm_stack_peek(cm_stack_t stack) { - if (!stack || !stack->top) - return (void*) 0; - - return stack->top->value; + if (!stack || !stack->top) + return (void*) 0; + + return stack->top->value; } unsigned int cm_stack_size(cm_stack_t stack) { - if (!stack) - return 0; - - return stack->size; + if (!stack) + return 0; + + return stack->size; } diff --git a/src/bncsutil/stack.h b/src/bncsutil/stack.h index 82a0ba5..882b075 100644 --- a/src/bncsutil/stack.h +++ b/src/bncsutil/stack.h @@ -23,7 +23,7 @@ * Boston, MA 02111-1307 USA */ -/* +/** * Mule Server * Copyright (c) 2004-2006 Eric Naeseth. * @@ -35,13 +35,13 @@ #define CM_STACK_H_INCLUDED 1 typedef struct cm_stack_node { - void* value; - struct cm_stack_node* next; + void* value; + struct cm_stack_node* next; } cm_stack_node_t; typedef struct cm_stack { - unsigned int size; - cm_stack_node_t* top; + unsigned int size; + cm_stack_node_t* top; } *cm_stack_t; cm_stack_t cm_stack_create(); From 8bfd89cc4d48dfda3869c33971318b74d6e2b03a Mon Sep 17 00:00:00 2001 From: Carl Bennett Date: Fri, 1 Jul 2016 06:04:58 +0000 Subject: [PATCH 10/10] Update the README with updated information --- README.md | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 882bcbe..ff6f1ce 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,58 @@ # BNCSUtil ## Preface **BNCSUtil** is the **B**attle.**N**et **C**hat **S**ervice **Util**ity which -aids applications trying to logon to Battle.net™ v1 using the binary +aids applications trying to logon to Classic Battle.net™ using the binary protocol. Specifically, BNCSUtil has functions that help with the cryptography of game versions, keys, and passwords. ## Installing -Simply place the .so or .dll file in the same directory as the application that -wishes to use it. If this does not work, install the file into the system +Simply place the `.so` or `.dll` file in the same directory as the application +that wishes to use it. If this does not work, install the file into the system library directory. -On Windows, this directory is: +### Windows +Copy the file to: + ``` C:\Windows\System32 ``` -On Linux, this directory is: +### Linux +If you just have the `.so` file, copy it to: + ``` /usr/lib/ ``` +And run: + +``` +sudo ldconfig +``` + +If you have just compiled from source, run this instead: + +``` +sudo make install +``` + ## Building ### Windows The official build of BNCSUtil for Windows is produced using Visual Studio 2005 -using the solution file in the `vc8_build` folder. The `vc7_build` is no longer -officially used or supported. +using the solution file in the `vc8_build` folder. BNCSUtil requires GMP. ### Linux To build: ``` -./configure +cd src/bncsutil +make clean make -make install ``` -If you have a fresh checkout or are having build-related issues, run the -following to (re)generate the configure script: -``` -autoreconf -if -``` +If you are having build related issues, ensure that: -Note that to use `autoreconf` you will need to have GNU `autotools` installed. +- You have the `gcc` package installed. +- You have the `glibc` development package installed. +- You have the `gmp` development package installed.