How to convert wcstombs to wcstombs_s - c++

How can I convert the following code to use wcstombs_s instead of wcstombs?
char dbcs[1024];
char *pbstr = (char *)pPropVar->bstrVal;
int i = wcstombs(dbcs, pPropVar->bstrVal, *((DWORD *)(pbstr - 4)));

char dbcs[1024];
char *pbstr = (char *)pPropVar->bstrVal;
size_t i;
int err = wcstombs_s(&i, dbcs, 1024, pPropVar->bstrVal, *((DWORD *)(pbstr - 4)));
Note
By the way, you can tell the compiler not to warn about non secure calls:
#define _CRT_SECURE_NO_DEPRECATE

Related

How to use typedef and define

I write this code to print on the output the current line and the file name:
#ifdef _DEBUG
char buffer[10000];
std::string const full_path = __FILE__;
auto const basename = full_path.substr(full_path.rfind('\\'));
sprintf(buffer, "Line:%d %s \n\n", __LINE__, basename.c_str());
OutputDebugStringA(buffer);
#endif
I don't know much about typedef and define, is possible to convert this part of the code below, into a typedef or define?
I mean a way to call it in just a single line.
std::string const full_path = __FILE__;
auto const basename = full_path.substr(full_path.rfind('\\'));
I mean a way to call it in just a single line.
std::string const full_path = __FILE__;
auto const basename = full_path.substr(full_path.rfind('\\'));
Generally, that's what functions are for. The only problem is the use of the macro that depends on what file it's in (__FILE__). Luckily, C++20 allows us to not need a macro:
#include <source_location>
std::string
current_source_file_base(const std::source_location& location
= std::source_location::current())
{
return std::filesystem::path(location.file_name()).filename();
}
Now, you can call that in a reusable fashion:
std::string source_file = current_source_file_base();
Alternative that doesn't require std::string and thus won't allocate dynamic memory... but may give partial filenames if they contain escaped directory separators. This is a problem with your original code as well. The limitation could be fixed by more complex logic, or by using std::filesystem::path_view which is proposed but not part of the standard. (Please don't use escaped directory separators in source file names).
constexpr std::string_view
current_source_file_base(const std::source_location& location
= std::source_location::current())
{
char separators[] = {
std::filesystem::path::preferred_separator,
'/',
'\0',
};
std::string_view path = location.file_name();
std::size_t pos = path.find_last_of(separators);
return pos == std::string_view::npos
? path
: path.substr(pos + 1);
}
All that said, I recommend to not remove the directories from the path because that will make it impossible to distinguish dir1/file.cpp from dir2/file.cpp.
Prior to C++20, you would need to use a function-like macro.
You can remove the std::string construction this way:
char buffer[1000];
snprintf(buffer, sizeof buffer, "Line:%d %s\n\n", __LINE__,
strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__);
OutputDebugStringA(buffer);
If must make it a one liner:
char buffer[1000]; snprintf(buffer, sizeof buffer, "Line:%d %s\n\n", __LINE__, strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__); OutputDebugStringA(buffer);
Here is a more general approach:
#ifdef _DEBUG
#define DEBUG_TRACE(s) do { \
char buffer[1000]; \
snprintf(buffer, sizeof buffer, "Line:%d %s %s\n\n", __LINE__, \
strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__, s); \
OutputDebugStringA(buffer); \
} while (0)
#else
#define DEBUG_TRACE()
#endif
Put the above definitions is a header file and add traces in your code:
int test(int a) {
int res = 0;
DEBUG_TRACE("entering test");
if (a % 3 == a % 5)
res = 1;
DEBUG_TRACE("leaving test");
return res;
}
A platform agnostic way to get the basename of a file would be:
#include <filesystem>
auto basename = std::filesystem::path(__FILE__).filename();
or, if you prefer it as a std::string object instead of a std::filesystem::path object:
auto basename = std::filesystem::path(__FILE__).filename().string();

SHFileOperation error 87

I am trying to copy the contents of the A drive into folder C:\test\disk1. Folder disk1 already exists. The program compiles but when it runs I get error 87. I know error 87 has something to do with an invalid parameter but Im not sure where the problem lies. Has anyone any ideas?
#include <Windows.h>
#include <stdio.h>
int main(int argc, char ** argv)
{
const wchar_t *const sourceFile = L"A:\\";
const wchar_t *const outputFile = L"C:\\test\\disk1";
SHFILEOPSTRUCTW fileOperation;
memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));
fileOperation.wFunc = FO_COPY;
fileOperation.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR |
FOF_NOERRORUI | FOF_FILESONLY;
fileOperation.pFrom = sourceFile;
fileOperation.pTo = outputFile;
int result = SHFileOperationW(&fileOperation);
if (result != 0)
{
printf("SHFileOperation Failure: Error%u\n", result);
return 1;
}
memset(&fileOperation, 0, sizeof(SHFILEOPSTRUCTW));
printf("OK\n");
return 0;
}
Note the documentation of SHFILEOPSTRUCT and in particular that of pFrom and pTo:
PCZZTSTR pFrom;
PCZZTSTR pTo;
What does PCZZTSTR mean?
pFrom
Type: PCZZTSTR
Note This string must be double-null terminated.
So your fix is to supply an additional trailing zero.
const wchar_t *const sourceFile = L"A:\\\0";
const wchar_t *const outputFile = L"C:\\test\\disk1\0";
Note that Windows API functions accept / as a directory separator, so that can be written as the slightly easier to read:
const wchar_t *const sourceFile = L"A:/\0";
const wchar_t *const outputFile = L"C:/test/disk1\0";
(PCZZSTR is actually a pointer to a list of zero terminated strings which is terminated by an empty string.)

String not decrypted properly using <openssl/aes>

I want to write one simple a program that will encrypt one test using <openssl/aes.h> and at the same time decrypt it. I wrote below program
Adding my whole code here:
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>
#include <string.h>
int main(void)
{
//encryption testing
unsigned char inputb[2048] = {'\0'};
unsigned char encpb[2048]= {'\0'};
unsigned char opb[2048]= {'\0'};
#define MAX_SIZE 100
unsigned char oneKey[] = "6BC1BEE22E409F96E93D7E117393172A";
AES_KEY key;
AES_KEY key1;
char testchat[] = "!!!test doctors file!!! #Hospitan name(norman) SICKAPP_NAME=9873471093 #Duration (Duration\
of doctor visitdfwhedf in months)higibujiji TESTATION=-5 #Expiry date MADICINE_NAME=678041783478\n";
char NULL_byte[16] = {0};
memcpy((char*)inputb, (testchat), strlen(testchat)+1);
printf("\n\ninputb= %s strlen(testchat)=%d \n\n",inputb, strlen(testchat));
AES_set_encrypt_key(oneKey, 128, &key);
unsigned char tmp_char[50] = {'\0'};
char* pChar = (char*)inputb;
unsigned char tmp_char_encpb[MAX_SIZE];
while(*pChar != '\0') {
memset(tmp_char, '\0', 50);
memset(tmp_char_encpb, '\0', MAX_SIZE);
if(strlen(pChar) < 16) {
strncpy((char*)tmp_char, (char*)pChar, strlen(pChar)+1);
strncat((char*)tmp_char, NULL_byte, 16 - strlen(pChar)+1);
}
else
strncpy((char*)tmp_char, (char*)pChar, 16);
printf("Line:%d tmp_char = %s pChar=%d\n", __LINE__, tmp_char, strlen(pChar));
AES_encrypt(tmp_char, tmp_char_encpb, &key);
strcat((char*)encpb, (char*)tmp_char_encpb);
pChar += 16;
}
printf("len encpb=%d\n", strlen((char*)encpb));
//now test with decrypting and check if all okk....
unsigned char oneKey1[] = "6BC1BEE22E409F96E93D7E117393172A";
AES_set_decrypt_key(oneKey1,128,&key1);
unsigned char tmp_char_dencpb[MAX_SIZE];
pChar = (char*)encpb;
while(*pChar != '\0') {
memset(tmp_char, '\0', 50);
if(strlen(pChar) < 16) {
strncpy((char*)tmp_char, (char*)pChar, strlen(pChar)+1);
strncat((char*)tmp_char, NULL_byte, 16 - strlen(pChar)+1);
}
else
strncpy((char*)tmp_char, (char*)pChar, 16);
AES_decrypt(tmp_char, tmp_char_dencpb, &key1);
strncat((char*)opb, (char*)tmp_char_dencpb,16);
memset(tmp_char_dencpb, '\0', MAX_SIZE);
pChar += 16;
}
printf("\n\nopb = %s\n\n",opb);
return 0;
}
I am building via:
g++ mytest.cpp -lssl -lcrypto
running through GDB:
Program received signal SIGSEGV, Segmentation fault.
0x0000003e48437122 in ____strtoll_l_internal () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.47.el6_2.12.x86_64 keyutils-libs-1.4-3.el6.x86_64 krb5-libs-1.9-22.el6_2.1.x86_64 libcom_err-1.41.12-11.el6.x86_64 libgcc-4.4.6-3.el6.x86_64 libselinux-2.0.94-5.2.el6.x86_64 libstdc++-4.4.6-3.el6.x86_64 openssl-1.0.0-20.el6_2.4.x86_64 zlib-1.2.3-27.el6.x86_64
(gdb) backtrace
#0 0x0000003e48437122 in ____strtoll_l_internal () from /lib64/libc.so.6
#1 0x0000000000400e9b in GetExpiryDate (exp_date=0x7fffffffd970) at LicReader.cpp:66
#2 0x0000000000400eeb in IsLicenseExpired () at LicReader.cpp:74
#3 0x0000000000400f3b in main (argc=1, argv=0x7fffffffda88) at LicReader.cpp:86
(gdb)
OP: in out put some time I got current decrypted string and some time getting with junk character.(when i/p string changed)
Am I missed something anywhere? Can anyone tell why AES_decrypt not workin gsometimes?
Zero-terminated string manipulation is not how to manage encrypted data... for example you're using strcat to add encrypted data to encpb... but what happens if there's a zero in the encrypted data? What happens is you don't get all the data. Deal instead with the actual block-size which is 16 bytes. What happens if the data you encrypt is not a multiple of 16 bytes? You have to pad it out to a multiple of 16. How? Lots of different ways, like PKCS7. Plus you should look into cipher-block-chaining and salting... lots to learn!

cudaMemcpyToSymbol using or not using string

I was trying to copy a structure to constant memory in this way:
struct Foo {
int a, b, c;
};
__constant__ Foo cData;
int main() {
Foo hData = {1, 2, 3};
cudaMemcpyToSymbol(cData, &hData, sizeof(Foo));
// ...
}
And this worked fine, in my kernel I could access the constant data directly:
__global__ void kernel() {
printf("Data is: %d %d %d\n", cData.a, cData.b, cData.c); // 1 2 3
}
But then I tried to use a const char * as symbol name, and things stopped working:
cudaMemcpyToSymbol("cData", &hData, sizeof(Foo)); // prints 0 0 0
I thought both versions were similar, but it seems I was wrong.
What is happening?
EDIT:
I'd like to report this same behavior with cudaGetSymbolAddress, which works for me if no const char * is used:
__constant__ int someData[10];
__constant__ int *ptrToData;
int *dataPosition;
cudaGetSymbolAddress((void **)&dataPosition, someData); // Works
// cudaGetSymbolAddress((void **)&dataPosition, "someData"); // Do not work
cudaMemcpyToSymbol(ptrToData, &dataPosition, sizeof(int *));
As of CUDA 5, using a string for symbol names is no longer supported. This is covered in the CUDA 5 release notes here
•The use of a character string to indicate a device symbol, which was possible with certain API functions, is no longer supported. Instead, the symbol should be used directly.
One of the reasons for this has to do with enabling of a true device linker, which is new functionality in CUDA 5.
Because of getting the same error again and again, I want to share this sample code that shows nearly all of the example cases for this problem (so I may refer here later when I make same mistakes again).
//file: main.cu
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
__constant__ float constData[256];
__device__ float devData;
__device__ float* devPointer;
int main(int argc, char **argv)
{
cudaFree(0);
float data[256];
cudaError_t err = cudaMemcpyToSymbol(constData, data, sizeof(data));
printf("Err id: %d, str: %s\n", err, cudaGetErrorString(err));
float value = 3.14f;
err = cudaMemcpyToSymbol(devData, &value, sizeof(float));
printf("Err id: %d, str: %s\n", err, cudaGetErrorString(err));
float* ptr;
cudaMalloc(&ptr, 256 * sizeof(float));
err = cudaMemcpyToSymbol(devPointer, &ptr, sizeof(ptr));
printf("Err id: %d, str: %s\n", err, cudaGetErrorString(err));
cudaFree(ptr);
return EXIT_SUCCESS;
}
I was getting "invalid device symbol" and many others which are related to _constant_ _device_ memory usage. This code gives no such errors at runtime.

invalid conversion from ‘const void*’ to ‘const char*’ in tokoyo cabinate table database

i am new to tokyo cabin ate and i compile the example program and i am getting an error can any one tell me why i get this error invalid conversion from ‘const void*’ to ‘const char*’
#include <tcutil.h>
#include <tctdb.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
int main(int argc, char **argv){
TCTDB *tdb;
int ecode, pksiz, i, rsiz;
char pkbuf[256];
const char *rbuf, *name;
TCMAP *cols;
TDBQRY *qry;
TCLIST *res;
/* create the object */
tdb = tctdbnew();
/* open the database */
if(!tctdbopen(tdb, "casket.tct", TDBOWRITER | TDBOCREAT)){
ecode = tctdbecode(tdb);
fprintf(stderr, "open error: %s\n", tctdberrmsg(ecode));
}
/* store a record */
pksiz = sprintf(pkbuf, "%ld", (long)tctdbgenuid(tdb));
cols = tcmapnew3("name", "mikio", "age", "30", "lang", "ja,en,c", NULL);
if(!tctdbput(tdb, pkbuf, pksiz, cols)){
ecode = tctdbecode(tdb);
fprintf(stderr, "put error: %s\n", tctdberrmsg(ecode));
}
tcmapdel(cols);
/* store a record in a naive way */
pksiz = sprintf(pkbuf, "12345");
cols = tcmapnew();
tcmapput2(cols, "name", "falcon");
tcmapput2(cols, "age", "31");
tcmapput2(cols, "lang", "ja");
if(!tctdbput(tdb, pkbuf, pksiz, cols)){
ecode = tctdbecode(tdb);
fprintf(stderr, "put error: %s\n", tctdberrmsg(ecode));
}
tcmapdel(cols);
/* store a record with a TSV string */
if(!tctdbput3(tdb, "abcde", "name\tjoker\tage\t19\tlang\ten,es")){
ecode = tctdbecode(tdb);
fprintf(stderr, "put error: %s\n", tctdberrmsg(ecode));
}
/* search for records */
qry = tctdbqrynew(tdb);
tctdbqryaddcond(qry, "age", TDBQCNUMGE, "20");
tctdbqryaddcond(qry, "lang", TDBQCSTROR, "ja,en");
tctdbqrysetorder(qry, "name", TDBQOSTRASC);
tctdbqrysetlimit(qry, 10, 0);
res = tctdbqrysearch(qry);
for(i = 0; i < tclistnum(res); i++){
rbuf = tclistval(res, i, &rsiz);
cols = tctdbget(tdb, rbuf, rsiz);
if(cols){
printf("%s", rbuf);
tcmapiterinit(cols);
while((name = tcmapiternext2(cols)) != NULL){
printf("\t%s\t%s", name, tcmapget2(cols, name));
}
printf("\n");
tcmapdel(cols);
}
}
tclistdel(res);
tctdbqrydel(qry);
/* close the database */
if(!tctdbclose(tdb)){
ecode = tctdbecode(tdb);
fprintf(stderr, "close error: %s\n", tctdberrmsg(ecode));
}
/* delete the object */
tctdbdel(tdb);
return 0;
}
The example file is obviously intended to be compiled as C, not as C++. The cast rbuf = tclistval(res, i, &rsiz); (rbuf is of type const char*) is valid in C, but in C++, you need to be explicit. It seems like you set up Eclipse to compile the source file as C++ - if the cast is the only error you get, you can solve it like so:
rbuf = (const char*)tclistval(res, i, &rsiz); // explicit cast to const char*
Or change your settings to compile as C.
It might be possible that you need to surround the Tokyo Cabinet header files with extern C { ... } if they don't support inclusion in C++ themselves.
you are trying to fill in one of the columns(char*) in your functions which is of type void* , if you see line at which this error is coming, you will get to know where you are doing.
This is generic c++ error, nothing to do with tokyocabinet, this is what I believe.
--
Cheers
Tokyocabinet looks like a c library. In c, you can cast pointer of any type to (void *) and (void *) to any type. Like this:
int *array = malloc(10*sizeof(int));
In c++, this is forbidden, you have to cast manually:
int *array = (int *)malloc(10*sizeof(int));