WideCharToMultiByte 随机失败并出现错误 122/ERROR_INSUFFICIENT_BUFFER
WideCharToMultiByte fails randomly with error 122/ERROR_INSUFFICIENT_BUFFER
我用 C 语言创建了一个小应用程序,它使用凯撒密码对字符串进行加密和解密。字符串 (unicode) 解密后,使用 WideCharToMultiByte 将其转换为 UTF8。它在大约 90% 的时间内工作,但有时 WideCharToMultiByte 似乎失败并且 GetLastError 函数打印 122,这意味着 ERROR_INSUFFICIENT_BUFFER.
我将 unicode 字符串转换为 UTF8 的函数如下所示:
LPSTR convert(LPWSTR wideStringToDecryptAndConvertUTF) {
LPWSTR res = shift(wideStringToDecryptAndConvertUTF, -6); //Decrypting the string by shifting -6 letters.
MessageBoxW(NULL, res, L"Decrypted output", MB_OK); //Check if the string was successfully decrypted - judging by the output of the messagebox this is always the case, the decrypted string looks as expected.
LPSTR retVal = 0;
ULONG cb = 0, cch = (ULONG)strl(res);
cb = WideCharToMultiByte(CP_UTF8, 0, res, cch * sizeof(WCHAR), retVal, cb, 0, 0);
retVal = GlobalAlloc(GMEM_FIXED, cb);
WideCharToMultiByte(CP_UTF8, 0, res, cch * sizeof(WCHAR), retVal, cb, 0, 0);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { //Check for debugging purposes. At random times (even with the same string) this specific error occurs.
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
}
GlobalFree(res);
return retVal;
}
我对 decrypt/encrypt 字符串的转换函数如下所示(在本例中它被解密):
LPWSTR shift(LPWSTR shift, int param) {
LPWSTR allc = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]<>()[]";
LPWSTR encrypted = (LPWSTR)GlobalAlloc(GMEM_FIXED, strl(shift) * sizeof(WCHAR) + 1);
int r = 0;
if (encrypted != NULL) {
for (size_t i = 0; i < strl(shift); i++) {
r++;
if (strchr42a((LPWSTR)allc, shift[i]) != NULL) {
LPWSTR e = strchr42a((LPWSTR)allc, shift[i]);
int index = (int)(e - allc);
encrypted[i] = allc[index + param];
}
else {
encrypted[i] = shift[i];
}
}
}
if (encrypted != NULL) {
encrypted[r] = 0;
}
return encrypted;
}
虽然这很简单,但这里是上面两个函数中使用的strl函数:
size_t strl(LPWSTR s) {
size_t i = 0;
while (s && *s != '[=13=]') {
s++;
i++;
}
return i;
}
我尝试加密的所有字符串都使用相同的程序加密,并且只包含字母。
我知道加密本身有局限性(例如加密时不能移动超过 8 个字母),但这不是我的问题。
我不明白为什么 WideCharToMultiByte 函数在我的情况下似乎工作不稳定。任何建议表示赞赏!
你打错了WideCharToMultiByte
。第 4 个参数是 字符数 ,而不是 字节数 。您也没有以 null 终止 retVal
缓冲区,并且根本没有进行任何错误处理。
此外,shift()
正在为其 encrypted
缓冲区计算错误的字节大小。更糟糕的是,如果输入 shift
字符串包含任何字符 A..F
,找到的索引被 -6
偏移将超出 allc
.
的范围
试试像这样的东西:
LPCWSTR strchr42a(LPCWSTR str, int ch)
{
do {
if (*str == ch) return str;
} while (*str++);
return NULL;
}
LPWSTR shift(LPCWSTR shift, int param) {
LPCWSTR allc = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]<>()[]";
ULONG shift_len = strl(shift);
LPWSTR encrypted = (LPWSTR) GlobalAlloc(GMEM_FIXED, (shift_len + 1) * sizeof(WCHAR));
if (!encrypted) return NULL;
int r = 0;
for (size_t i = 0; i < shift_len; ++i) {
++r;
LPCWSTR e = strchr42a(allc, shift[i]);
if (e != NULL) {
int index = (int)(e - allc) + param;
if (index < 0) {
// OUT OF BOUNDS! Need to wrap the index, or fail the function...
}
encrypted[i] = allc[index];
}
else {
encrypted[i] = shift[i];
}
}
encrypted[r] = 0;
return encrypted;
}
LPSTR convert(LPWSTR wideStringToDecryptAndConvertUTF) {
LPWSTR res = shift(wideStringToDecryptAndConvertUTF, -6); //Decrypting the string by shifting -6 letters.
if (!res) {
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
return NULL;
}
MessageBoxW(NULL, res, L"Decrypted output", MB_OK); //Check if the string was successfully decrypted - judging by the output of the messagebox this is always the case, the decrypted string looks as expected.
ULONG cch = (ULONG) strl(res);
ULONG cb = WideCharToMultiByte(CP_UTF8, 0, res, cch, retVal, 0, NULL, NULL);
if (cb == 0) {
DWORD errCode = GetLastError();
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
return NULL;
}
LPSTR retVal = GlobalAlloc(GMEM_FIXED, cb + 1);
if (!retVal) {
DWORD errCode = GetLastError();
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
return NULL;
}
WideCharToMultiByte(CP_UTF8, 0, res, cch, retVal, cb, NULL, NULL);
retVal[cb] = 0;
GlobalFree(res);
return retVal;
}
我用 C 语言创建了一个小应用程序,它使用凯撒密码对字符串进行加密和解密。字符串 (unicode) 解密后,使用 WideCharToMultiByte 将其转换为 UTF8。它在大约 90% 的时间内工作,但有时 WideCharToMultiByte 似乎失败并且 GetLastError 函数打印 122,这意味着 ERROR_INSUFFICIENT_BUFFER.
我将 unicode 字符串转换为 UTF8 的函数如下所示:
LPSTR convert(LPWSTR wideStringToDecryptAndConvertUTF) {
LPWSTR res = shift(wideStringToDecryptAndConvertUTF, -6); //Decrypting the string by shifting -6 letters.
MessageBoxW(NULL, res, L"Decrypted output", MB_OK); //Check if the string was successfully decrypted - judging by the output of the messagebox this is always the case, the decrypted string looks as expected.
LPSTR retVal = 0;
ULONG cb = 0, cch = (ULONG)strl(res);
cb = WideCharToMultiByte(CP_UTF8, 0, res, cch * sizeof(WCHAR), retVal, cb, 0, 0);
retVal = GlobalAlloc(GMEM_FIXED, cb);
WideCharToMultiByte(CP_UTF8, 0, res, cch * sizeof(WCHAR), retVal, cb, 0, 0);
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { //Check for debugging purposes. At random times (even with the same string) this specific error occurs.
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
}
GlobalFree(res);
return retVal;
}
我对 decrypt/encrypt 字符串的转换函数如下所示(在本例中它被解密):
LPWSTR shift(LPWSTR shift, int param) {
LPWSTR allc = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]<>()[]";
LPWSTR encrypted = (LPWSTR)GlobalAlloc(GMEM_FIXED, strl(shift) * sizeof(WCHAR) + 1);
int r = 0;
if (encrypted != NULL) {
for (size_t i = 0; i < strl(shift); i++) {
r++;
if (strchr42a((LPWSTR)allc, shift[i]) != NULL) {
LPWSTR e = strchr42a((LPWSTR)allc, shift[i]);
int index = (int)(e - allc);
encrypted[i] = allc[index + param];
}
else {
encrypted[i] = shift[i];
}
}
}
if (encrypted != NULL) {
encrypted[r] = 0;
}
return encrypted;
}
虽然这很简单,但这里是上面两个函数中使用的strl函数:
size_t strl(LPWSTR s) {
size_t i = 0;
while (s && *s != '[=13=]') {
s++;
i++;
}
return i;
}
我尝试加密的所有字符串都使用相同的程序加密,并且只包含字母。 我知道加密本身有局限性(例如加密时不能移动超过 8 个字母),但这不是我的问题。 我不明白为什么 WideCharToMultiByte 函数在我的情况下似乎工作不稳定。任何建议表示赞赏!
你打错了WideCharToMultiByte
。第 4 个参数是 字符数 ,而不是 字节数 。您也没有以 null 终止 retVal
缓冲区,并且根本没有进行任何错误处理。
此外,shift()
正在为其 encrypted
缓冲区计算错误的字节大小。更糟糕的是,如果输入 shift
字符串包含任何字符 A..F
,找到的索引被 -6
偏移将超出 allc
.
试试像这样的东西:
LPCWSTR strchr42a(LPCWSTR str, int ch)
{
do {
if (*str == ch) return str;
} while (*str++);
return NULL;
}
LPWSTR shift(LPCWSTR shift, int param) {
LPCWSTR allc = L"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz[]<>()[]";
ULONG shift_len = strl(shift);
LPWSTR encrypted = (LPWSTR) GlobalAlloc(GMEM_FIXED, (shift_len + 1) * sizeof(WCHAR));
if (!encrypted) return NULL;
int r = 0;
for (size_t i = 0; i < shift_len; ++i) {
++r;
LPCWSTR e = strchr42a(allc, shift[i]);
if (e != NULL) {
int index = (int)(e - allc) + param;
if (index < 0) {
// OUT OF BOUNDS! Need to wrap the index, or fail the function...
}
encrypted[i] = allc[index];
}
else {
encrypted[i] = shift[i];
}
}
encrypted[r] = 0;
return encrypted;
}
LPSTR convert(LPWSTR wideStringToDecryptAndConvertUTF) {
LPWSTR res = shift(wideStringToDecryptAndConvertUTF, -6); //Decrypting the string by shifting -6 letters.
if (!res) {
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
return NULL;
}
MessageBoxW(NULL, res, L"Decrypted output", MB_OK); //Check if the string was successfully decrypted - judging by the output of the messagebox this is always the case, the decrypted string looks as expected.
ULONG cch = (ULONG) strl(res);
ULONG cb = WideCharToMultiByte(CP_UTF8, 0, res, cch, retVal, 0, NULL, NULL);
if (cb == 0) {
DWORD errCode = GetLastError();
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
return NULL;
}
LPSTR retVal = GlobalAlloc(GMEM_FIXED, cb + 1);
if (!retVal) {
DWORD errCode = GetLastError();
MessageBoxW(NULL, L"Error", L"Debug", MB_OK);
return NULL;
}
WideCharToMultiByte(CP_UTF8, 0, res, cch, retVal, cb, NULL, NULL);
retVal[cb] = 0;
GlobalFree(res);
return retVal;
}