I'm writing a small program with QT creator under windows 7 (32 bit). My goal is to create a windows key.
I'm using
QSettings settings("HKEY_CURRENT_USER\\Software\\Company", QSettings::NativeFormat);
settings.setValue("C:\\path\\prog.exe", "Value");
but in the windows registry the generated key has the value C:/path/prog.exe
I've tryed to convert it with
qDebug() << QDir::toNativeSeparators("C:\\path\\prog.exe");
the output of qDebug() is right c:\path\prog.exe
but doing
settings.setValue(QDir::toNativeSeparators("C:\\path\\prog.exe"), "Value");
results again in a path with a wrong slash.
do there is a way to write correctly the path in the windows registry without using the windows API?
Thanks
Francesco
You can't do it even with WinAPI. Because you are specifying an invalid key. You should understand that QSettings class use platform-specific backend, so it is useful to read documentation, if something does not work as expected. Start here.
QSettings class performs custom transformation to keys and values, so you may store any QVariant values there. Even arrays. Invalid values for each platform will be escaped. You may look at exact transformation rules in Qt sources.
Note: values transformation depends on type of settings storage. For example^ for .ini files.
ok, I managed to achieve my goal by using
RegSetValueEx(hkey, TEXT("C:\\path\\prog.exe"), 0, REG_SZ, (LPBYTE)TEXT("WIN98"), 6 * sizeof(WCHAR));
for a constant string.
in case the program path is strored in a char * (like in my case), it works with
char* exe_name = /*something*/
wchar_t* wString=new wchar_t[4096];
MultiByteToWideChar(CP_ACP, 0, exe_name, -1, wString, 4096);
RegCreateKeyEx( .......... )
RegSetValueEx(hkey, (LPCWSTR) wString, 0, REG_SZ, (LPBYTE)TEXT("WIN98"), 6 * sizeof(WCHAR));
Francesco
Related
I am struggling to understand what may be causing the issue in my case.
I am using
ShellExecuteW('open', 'explorer.exe', '/select,[file_name]', None, win32con.SW_SHOW)
What I am trying to do is open the file in the OS, highlight it, and bring the File Explorer to the foreground. This works fine for most cases, but when I try to open a file that exceeds the MAX_PATH limit (260 characters), the file doesn't open, and instead it takes me to the "My Files" page.
I have tried prepending "\\?\" to the beginning of my file name, because that is what other Stack Overflow posts said to do with regards to overriding the MAX_PATH limit, but it has not changed the situation.
Does the ShellExecuteW function not allow for files that exceed MAX_PATH? And, if so, is there any workaround I could use?
I read some cases, about this issue. Find this article:Long Paths in .NET, Part 1 of 3 [Kim Hamilton]
If you prefix the file name with "\?\" and call the Unicode versions of the Windows APIs, then you can use file names up to 32K characters in length. In other words, the \?\ prefix is a way to enable long paths while working with the Windows file APIs.
and:
Long paths with the \?\ prefix can be used in most of the file-related Windows APIs, but not all Windows APIs.
I also test ShellExcuteW with \\?\,it failed.
Working well with SHOpenFolderAndSelectItems
CoInitialize(NULL);
LPCWSTR file_name ;//Change the path according to your needs
PIDLIST_ABSOLUTE pidl;
if (SUCCEEDED(SHParseDisplayName(file_name, 0, &pidl, 0, 0)))
{
ITEMIDLIST idNull = { 0 };
LPCITEMIDLIST pidlNull[1] = { &idNull };
SHOpenFolderAndSelectItems(pidl, 1, pidlNull, 0);
ILFree(pidl);
}
Note:CoInitialize or CoInitializeEx must be called before using SHOpenFolderAndSelectItems. Not doing so causes SHOpenFolderAndSelectItems to fail.
I'm reading a book called "Introduction to 3D Game Programming with DirectX 9.0c: A Shader Approach" and I was following the codes there but the application used Multi-Byte Character Set and I read from somewhere that it's not a good practice to use that and im having error when creating a window. here is the code that im having error.
mhMainWnd = CreateWindow(L"D3DWndClassName", mMainWndCaption.c_str(), WS_OVERLAPPEDWINDOW,
GetSystemMetrics(SM_CXSCREEN)/2 - width/2,
GetSystemMetrics(SM_CYSCREEN)/2 - height/2,
R.right, R.bottom, 0, 0, mhAppInst, 0);
then the eror is:
error C2664: 'CreateWindowExW' : cannot convert parameter 2 from 'const char [16]' to 'LPCWSTR'
hope someone can help me
What you heard about the preferability of Unicode over the ANSI/MBCS is entirely correct. All new Windows code should be written to work with Unicode. In order to make this happen, you have to ensure two things:
Both the UNICODE and _UNICODE symbols need to be defined globally to ensure that the Unicode versions of the API functions are called, even if you forget the W suffix.
You can either do this at the top of your precompiled header
#define UNICODE
#define _UNICODE
or in your project's Properties window within Visual Studio. Simply add both of the values to the list.
All of your strings (both literals and otherwise) need to be Unicode strings.
With literals, you accomplish this by prefixing them with L, just as you've done in the example: L"D3DWndClassName"
With strings that are allocated at runtime, you need to use the wchar_t type. Since you're using C++, you should obviously be using a string class rather than raw character arrays like you would in C. So you need to use a string class that treats the characters in the string as wchar_t. This would either be std::wstring or MFC/ATL/WTL's CStringW class.
It looks like you've got most of this down already. The culprit is mMainWndCaption.c_str(). You are using std::string (which returns a nul-terminated array of chars) instead of std::wstring (which returns a nul-terminated array of wchar_ts).
Either change your project to ANSI or MBCS rather than UNICODE, then change
L"D3DWndClassName"
to
"D3DWndClassName"
or, leave your project properties as UNICODE but use a UNICODE string of your window caption - so
CString szCaption(mMainWndCaption.c_str()); // CString is actually CStringW in UNICODE build
mhMainWnd = CreateWindow(L"D3DWndClassName", szCaption, WS_OVERLAPPEDWINDOW,
GetSystemMetrics(SM_CXSCREEN)/2 - width/2,
GetSystemMetrics(SM_CYSCREEN)/2 - height/2,
R.right, R.bottom, 0, 0, mhAppInst, 0);
I'm trying to hide some values in the registry (such as serial numbers) with C++/windows
so I've been looking at this article http://www.codeproject.com/KB/system/NtRegistry.aspx
which says:
How is this possible? The answer is
that a name which is a counted as a
Unicode string can explicitly include
NULL characters (0) as part of the
name. For example, "Key\0". To include
the NULL at the end, the length of the
Unicode string is specified as 4.
There is absolutely no way to specify
this name using the Win32 API since if
"Key\0" is passed as a name, the API
will determine that the name is "Key"
(3 characters in length) because the
"\0" indicates the end of the name.
When a key (or any other object with a
name such as a named Event, Semaphore,
or Mutex) is created with such a name,
any application using the Win32 API
will be unable to open the name, even
though they might seem to see it.
so I tried doing something similar:
HKEY keyHandle;
PHKEY key;
unsigned long status = 0;
wchar_t *wKeyName = new wchar_t[m_keyLength];
MultiByteToWideChar(CP_ACP, 0, m_keyName, m_keyLength, wKeyName, m_keyLength);
wKeyName[18] = '\0';
long result = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
wKeyName,
0,
NULL,
0,
KEY_ALL_ACCESS,
NULL,
&keyHandle,
&status);
where m_keyName is the ASCII text and wKeyName is the wide char text, but in regedit I see that it is treated the same and the key is just cut where I put the '\0'.
what is wrong with it?
The problem is that you are using the Win32 API and not the NT Native API. There is a table about 1/2 way through the article that you referenced that contains the list of Native APIs. For example, you would use NtCreateKey or ZwCreateKey instead of RegCreateKeyExW. The Win32 API assumes that alls strings are terminated by a NUL character whereas the Native API counterparts use a UNICODE_STRING structure for the name.
I'll take a stab in the dark, as I have never tried to do this.
It appears that you are using the wrong function to create your registry key. You should be using the NtCreateKey method because RegCreateKeyEx[AW] will notice your '\0' and chop off past it.
Why not use the class provided in the example? It provides a method called CreateHiddenKey. To use it, simply call SetKey before it. It would be much cleaner.
There is a function that copies a value to registry using
RegSetValueEx(hKey, theName, 0, REG_DWORD, (unsigned char *)&value, sizeof(value));
theName passed by the caller is a char *
I get a compile error:
Argument of type char * is incompatible with LPCWSTR
Why do I get this error?
I have copied some code that uses it (and I know it builds succesfully) and built it myself.
Has the function changed or my project settings is messed up? I do not know which version of VS the code was created.
It is because Windows has been a Unicode operating system for the past 18 years. Its default string type is utf-16 encoded, wchar_t* in your code. Or std::wstring. Or LPCWSTR, the typedef used in the Windows headers. Note the prevalence of 'w', it means Wide.
It still supports char* strings, you have to use RegSetValueExA(). Note the added "A". It is also a project setting to make your program use the old multi-byte API. Project + Properties, General, Character Set. Avoid marketing to the other 5 billion customers when you do.
I have to convert the encoding of a string output of a VB6 application to a specific encoding.
The problem is, I don't know the encoding of the string, because of that:
According to the VB6 documentation when accessing certain API functions the internal Unicode strings are converted to ANSI strings using the default codepage of Windows.
Because of that, the encoding of the string output can be different on different systems, but I have to know it to perform the conversion.
How can I read the default codepage using the Win32 API or - if there's no other way - by reading the registry?
It could be even more succinct by using GetACP - the Win32 API call for returning the default code page! (Default code page is often called "ANSI")
int nCodePage = GetACP();
Also many API calls (such as MultiByteToWideChar) accept the constant value CP_ACP (zero) which always means "use the system code page". So you may not actually need to know the current code page, depending on what you want to do with it.
GetSystemDefaultLCID() gives you the system locale.
If the LCID is not enough and you truly need the codepage, use this code:
TCHAR szCodePage[10];
int cch= GetLocaleInfo(
GetSystemDefaultLCID(), // or any LCID you may be interested in
LOCALE_IDEFAULTANSICODEPAGE,
szCodePage,
countof(szCodePage));
nCodePage= cch>0 ? _ttoi(szCodePage) : 0;
That worked for me, thanks, but can be written more succinctly as:
UINT nCodePage = CP_ACP;
const int cch = ::GetLocaleInfo(LOCALE_SYSTEM_DEFAULT,
LOCALE_RETURN_NUMBER|LOCALE_IDEFAULTANSICODEPAGE,
(LPTSTR)&nCodePage, sizeof(nCodePage) / sizeof(_TCHAR) );