Converting a PIDL to file path with SHGetPathFromIDList - c++

My application receives a PIDL as a string:
QString pidl = "::{20D04FE1-3AEA-1069-A2D8-08002B30309B}";
In this case it corresponds to My Computer. I need to convert it to My Computer.
Theres a WINAPI function SHGetPathFromIDList which requires the LPCITEMIDLIST as the first parameter and converts it to a string.
How can I build that LPCITEMIDLIST?
UPDATE
This is what I got so far:
LPCWSTR csPath = (LPCWSTR)"::{20D04FE1-3AEA-1069-A2D8-08002B30309B}";
LPITEMIDLIST stId = 0;
SFGAOF stSFGAOFIn = 0;
SFGAOF stSFGAOFOut = 0;
if(!FAILED(SHParseDisplayName(csPath, 0, stId, stSFGAOFIn, &stSFGAOFOut)))
msgBox("not failed")
Unfortunately this code crashes.

Your code crashes because you are not setting up the 1st and 3rd parameters of SHParseDisplayName() correctly. Try this instead:
LPCWSTR csPath = L"::{20D04FE1-3AEA-1069-A2D8-08002B30309B}";
PIDLIST_ABSOLUTE stId = NULL;
SFGAOF stSFGAOFIn = 0;
SFGAOF stSFGAOFOut = 0;
if (!FAILED(SHParseDisplayName(csPath, NULL, &stId, stSFGAOFIn, &stSFGAOFOut)))
msgBox("not failed")

The function you need is not SHGetPathFromIDList, because there is no path for "My Computer".
To convert your QString pidl to an PIDLIST_ABSOLUTE you need to use SHParseDisplayName.
To convert the PIDLIST_ABSOLUTE to a localised string like "My Computer" you need SHGetNameFromIDList.

I think may be:
SHParseDisplayName(csPath, 0, &stId, stSFGAOFIn, &stSFGAOFOut)
Declaration of SHParseDisplayName from MSDN:
HRESULT SHParseDisplayName(
__in LPCWSTR pszName,
__in_opt IBindCtx *pbc,
__out PIDLIST_ABSOLUTE *ppidl,
__in SFGAOF sfgaoIn,
__out_opt SFGAOF *psfgaoOut
);

Related

InvalidArgs When trying to use UrlCreateFromPath in c++

I am trying to convert filepath to fileUrl using UrlCreateFromPath() function in c++.
Following code tries to convert filepath to fileUrl
PCTSTR lpszUnicode = L"C:\\Users\\TBD\\Downloads\\index.html";
PTSTR output =L"C:\\Users\\TBD\\Downloads\\index.html";
DWORD dwDisp = 0;
DWORD dw2 = 0;
LPDWORD lpdwDisp = &dwDisp;
HRESULT res2 = UrlCreateFromPath(lpszUnicode, output, lpdwDisp, dw2);
std::wstring newOutput(output);
but res2 always shows InvalidArgs.Am i doing something wrong in above code snap ?
You actualy write to constant buffer (wich is wrong)
PCTSTR lpszUnicode = L"C:\\Users\\TBD\\Downloads\\index.html";
//PTSTR output =L"C:\\Users\\TBD\\Downloads\\index.html"; cannot do that way
TCHAR output[MAX_PATH]; // allocate buffer in memory (stack)
DWORD dwDisp = MAX_PATH; // max posible buffer size
LPDWORD lpdwDisp = &dwDisp;
HRESULT res2 = UrlCreateFromPath(lpszUnicode, output, lpdwDisp, NULL);
std::wstring newOutput(output);
And why did you do that
LPDWORD lpdwDisp = &dwDisp;
you can simply do so
HRESULT res2 = UrlCreateFromPath(lpszUnicode, output, &dwDisp, dw2);

Reading and Writing registry keys. C++ MFC MBCS.

I would like to detect, and if possible read to a CString, a registry key starting with "HKEY_LOCAL_MACHINE\SOFTWARE\blah\SetupPath".
I see the MSDN on RegOpenKeyEx function
LONG WINAPI RegOpenKeyEx(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpSubKey,
_Reserved_ DWORD ulOptions,
_In_ REGSAM samDesired,
_Out_ PHKEY phkResult
);
So for this it looks like I need to setup a few things.
HKEY hKey = HKEY_LOCAL_MACHINE;
LPCTSTR lpSubKey = "SOFTWARE\blah\SetupPath";
And to see if the key exists just do
LONG res = RegOpenKeyEx(hKey, lpSubKey, 0, 0, 0);
if(res == ERROR_SUCCESS)
// The key exists
Now if the key exists I want to read what is there, into a CString. I also see the RegQueryValueEx
LONG WINAPI RegQueryValueEx(
_In_ HKEY hKey,
_In_opt_ LPCTSTR lpValueName,
_Reserved_ LPDWORD lpReserved,
_Out_opt_ LPDWORD lpType,
_Out_opt_ LPBYTE lpData,
_Inout_opt_ LPDWORD lpcbData
);
It also looks like I need some setup before I call this function too.
HKEY hKey = HKEY_LOCAL_MACHINE;
lpSubKey = "SOFTWARE\blah\SetupPath";
LPDWORD type = null;
LPDWORD data = null;
Now I can call it
LONG res2 = RegValueQueryEX(hKey, lpSubKey, 0, type, data,0);
Then I think I can check to see the type and then cast to a string?
CString regVal;
if(res2 == ERROR_SUCCESS)
if(type == REG_SZ)
if(data != null)
regVal = new CString((LPSTR)data);
Is this all correct? What might I be missing or need to do?
No that's not correct. Your main misunderstanding is how pointers work in C++. It's not enough to supply NULL for a pointer argument, you must supply a pointer to a variable so that the RegOpenKeyEx or RegValueQueryEx routine can return a value to that variable. You also seem to be misunderstanding how to assign to a CString (no need for new). Finally although it's not an error you don't need to do 'setup' you just pass the values directly to the function.
First open the key
HKEY key;
RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\blah", 0, 0, &key);
then get the value
DWORD type, size;
char data[99];
size = sizeof(data);
RegQueryValueEx(key, "SetupPath", 0, &type, (BYTE*)data, &size);
then assign the value to your CString
CString regval(data);
finally close the key
RegCloseKey(key);
No error checking in that code, you should add it. Also I'm assuming that any value you could get will fit in 99 bytes, that might not be true.
Note how I pass a pointer to the key variable, so that RegOpenKeyEx can return the key. I then use that key in the call to RegValueQueryEx and RegCloseKey. Same for the type and size variables. Also note that I've split the path between the calls to RegOpenKeyEx and RegValueQueryEx. I think that is correct.
Not 100% sure that is correct, I haven't tested it but should be quite a bit closer.
Is this all correct? What might I be missing or need to do?
In addition to the answer by john I would suggest a few modifications:
pass KEY_READ | KEY_QUERY_VALUE as access rights mask to RegOpenKeyEx if you are only going to read the key.
RegQueryValueEx may return ERROR_MORE_DATA if the buffer size is too small. Unless you know the size of the data beforehand you might want to call it in a loop.
simple way to enabled javascript execution in internet explorer using the registry:
HKEY hKey;
RegCreateKeyEx(HKEY_CURRENT_USER, _T("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Zones\\3"),
NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
NULL, &hKey, NULL);
DWORD byte = 0x0;
RegSetValueEx(hKey, L"1400", NULL, REG_DWORD, (BYTE*)&byte, sizeof(byte));
RegCloseKey(hKey);

How does one convert LPTSTR to LPCTSTR?

I need to convert:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646839(v=vs.85).aspx
lpstrFileTitle
Type: LPTSTR
The file name and extension (without path information) of the selected file. This member can be NULL.
Even though in MSVC++ 2012 Express it says its LPSTR.
To
http://msdn.microsoft.com/en-us/library/windows/desktop/bb172802(v=vs.85).aspx
pSrcFile [in]
Type: LPCTSTR
Pointer to a string that specifies the filename. If the compiler settings require Unicode, the data type LPCTSTR resolves to LPCWSTR. Otherwise, the string data type resolves to LPCSTR. See Remarks.
I would very much appreciate this. :)
char szFileName[MAX_PATH] = {0};
char szFileTitleName[MAX_PATH] = {0};
HRESULT hr = S_OK;
RtlZeroMemory(&gc.ofn, sizeof(gc.ofn));
gc.ofn.lStructSize = sizeof(gc.ofn);
gc.ofn.hwndOwner = hWnd;
gc.ofn.lpstrFilter = "All Image Files\0" "*.bmp;*.dib;*.wdp;*.mdp;*.hdp;*.gif;*.png;*.jpg;*.jpeg;*.tif;*.ico\0"
"Windows Bitmap\0" "*.bmp;*.dib\0"
"High Definition Photo\0" "*.wdp;*.mdp;*.hdp\0"
"Graphics Interchange Format\0" "*.gif\0"
"Portable Network Graphics\0" "*.png\0"
"JPEG File Interchange Format\0" "*.jpg;*.jpeg\0"
"Tiff File\0" "*.tif\0"
"Icon\0" "*.ico\0"
"All Files\0" "*.*\0"
"\0";
gc.ofn.nMaxFileTitle = MAX_PATH;
gc.ofn.lpstrFileTitle = gc.szFileTitleName; // its a char
gc.ofn.lpstrFile = szFileName;
gc.ofn.nMaxFile = MAX_PATH;
gc.ofn.lpstrTitle = "Open Image";
gc.ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if(GetOpenFileName(&gc.ofn)) {
gc.render_on = true;
}
.
D3DXCreateTextureFromFileEx (d3dDevice, gc.szFileTitleName , D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0,
D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT,
colorkey, &init_map->image_info, NULL, &init_map->texture_buffer)
This will have a blank image. I have tested this with a messagebox right after GetOpenFile, and it returns great.
MessageBoxA ( NULL , gc.ofn.lpstrFileTitle , "" , 0 );
But before the D3DXCreateTextureFromFileEx, its messed up.
Just storing the the char into gc.szFileTitleName. No idea why the other way was going out of scope ...
LPCTSTR is just a const version of LPTSTR. That type of conversion is a standard conversion, so you shouldn't need to do anything explicitly to get what you want. Your error must be somewhere else.
Unless you are somehow compiling a piece of your code with UNICODE set and some without it...
GetOpenFileName(), D3DXCreateTextureFromFileEx(), and MessageBox() all deal with TCHAR-based strings, but you are not actually utilizing TCHAR in your code. Try this instead:
TCHAR szFileName[MAX_PATH] = {0};
TCHAR szFileTitleName[MAX_PATH] = {0};
HRESULT hr = S_OK;
RtlZeroMemory(&gc.ofn, sizeof(gc.ofn));
gc.ofn.lStructSize = sizeof(gc.ofn);
gc.ofn.hwndOwner = hWnd;
gc.ofn.lpstrFilter = TEXT("All Image Files\0") TEXT("*.bmp;*.dib;*.wdp;*.mdp;*.hdp;*.gif;*.png;*.jpg;*.jpeg;*.tif;*.ico\0")
TEXT("Windows Bitmap\0") TEXT("*.bmp;*.dib\0")
TEXT("High Definition Photo\0") TEXT("*.wdp;*.mdp;*.hdp\0")
TEXT("Graphics Interchange Format\0") TEXT("*.gif\0")
TEXT("Portable Network Graphics\0") TEXT("*.png\0")
TEXT("JPEG File Interchange Format\0") TEXT("*.jpg;*.jpeg\0")
TEXT("Tiff File\0") TEXT("*.tif\0")
TEXT("Icon\0") TEXT("*.ico\0")
TEXT("All Files\0") TEXT("*.*\0")
TEXT("\0");
gc.ofn.nMaxFileTitle = MAX_PATH;
gc.ofn.lpstrFileTitle = gc.szFileTitleName;
gc.ofn.lpstrFile = szFileName;
gc.ofn.nMaxFile = MAX_PATH;
gc.ofn.lpstrTitle = TEXT("Open Image");
gc.ofn.Flags = OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
if(GetOpenFileName(&gc.ofn)) {
gc.render_on = true;
}
.
D3DXCreateTextureFromFileEx (d3dDevice, gc.szFileTitleName , D3DX_DEFAULT_NONPOW2, D3DX_DEFAULT_NONPOW2, 0, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, colorkey, &init_map->image_info, NULL, &init_map->texture_buffer)
.
MessageBox(NULL, gc.ofn.lpstrFileTitle, TEXT(""), 0);

Extract file from resource in Windows module

The below code executes, but it only extracts an empty bitmap file. Any ideas as to what is wrong with it?
void Extract(WORD wResId , LPSTR lpszOutputPath)
{ //example: Extract(IDB_BITMAP1, "Redrose.bmp");
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId) , RT_BITMAP);
HGLOBAL hLoaded = LoadResource( NULL,hrsrc);
LPVOID lpLock = LockResource( hLoaded);
DWORD dwSize = SizeofResource(NULL, hrsrc);
HANDLE hFile = CreateFile (lpszOutputPath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwByteWritten;
WriteFile(hFile, lpLock , dwSize , &dwByteWritten , NULL);
CloseHandle(hFile);
FreeResource(hLoaded);
}
You are asking for RT_RCDATA but I bet you didn't add your bitmap via a RCDATA statement. You probably added it via a BITMAP statement, which makes it RT_BITMAP.
In the future, please state which step failed rather than making people guess.
Insert your raw file as a custom data.
Give this custom data a text name, example "MyType", then:
HRSRC hrsrc = FindResource(NULL, MAKEINTRESOURCE(wResId) , _T("MyType"));
The problem is in passing NULL as your HINSTANCE parameter to FindResource, LoadResource, and SizeOfResource.
If you have not already saved your HINSTANCE during startup (from WinMain or DllMain) you can get it using:
MFC:
HINSTANCE hInstance = AfxGetInstanceHandle();
Else:
HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(NULL);

Installing a driver programmatically using INF file c++

Could someone here please let me know how to install 3rd party device drivers
programmatically if all the required files i.e. inf file, .sys etc are provided. The
minimum operating system this solution SHOULD work on is Windows2000.
I tried copying the .inf file into the Win Folder\INF folder and the sys file
into the Win folder\system32\drivers but each time plug in the device, windows
pops up Found New Hardware user interface which is what i am trying to avoid.
Below is something i tried but the function returns error 87 (The parameter is incorrect).
HINF HInf;
UINT ErrorLine;
BOOL bRes = FALSE;
PBOOL FileWasInUse = FALSE;
LPCSTR szSourceFileName = _T("C:\\Drivers_HypercomP1320\\hypvcpusb.inf");
LPCSTR szInfFileName = _T("hypvcpusb.inf");
PVOID Context = NULL;
HInf = SetupOpenInfFile ( szSourceFileName, NULL, INF_STYLE_WIN4, &ErrorLine);
LPCSTR SourceFile = ("hypvcp.sys");
LPCSTR SourcePathRoot = _T("C:\\Drivers_HypercomP1320");
LPCSTR DestinationName = _T("C:\\WINDOWS\\system32\\drivers\\hypvcp.sys");
bRes = SetupInstallFileEx ( HInf, NULL, SourceFile, SourcePathRoot, DestinationName, SP_COPY_FORCE_IN_USE,
(PSP_FILE_CALLBACK)CopyMsgHandler, Context, FileWasInUse);
DWORD dwVal = GetLastError();
SetupCloseInfFile(HInf);
// Callback function
UINT CopyMsgHandler (UINT Context, UINT Notification,UINT_PTR Param1, UINT_PTR Param2)
{
UINT rtnValue = NO_ERROR;
return rtnValue;
}
Thanks.
Yes. You start by calling
SC_HANDLE manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (manager)
{
wprintf(L"Opened SC Manager\n");
}
else
{
wprintf(L"Open SC Manager failed\n");
return;
}
Then having the .inf file stored in szInfFileName you call:
HInf = SetupOpenInfFile(szInfFileName.c_str(), NULL, INF_STYLE_WIN4, &ErrorLine);
Then you call
if (SetupInstallFileEx(HInf, NULL, SourceFile, SourcePathRoot, DestinationName, SP_COPY_NEWER_OR_SAME, NULL, Context, &FileWasInUse) == NULL)
SourceFile = the driver file name (ending with .sys)
SourcePathRoot = the location of the driver file (would be the path where your program runs from)
DestinationName = full path of the driver to be installed (for example:
c:\windows\system32\drivers\yourdriver.sys
Then there is the Registry. You need to add an entry for your driver under
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\
this entry (key) should have:
Driver name, display name, description, ErrorControl and Group.
Next step, you start the driver using:
SC_HANDLE service = CreateService(manager,
DRIVER_NAME,
DRIVER_NAME,
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
KeyName,
NULL, NULL, NULL, NULL, NULL);
When KeyName is the driver's path under System32 as appeared in the Registry entry. For example:
system32\drivers\yourdriver.sys
Last step:
BOOL result = StartService(service, 0, NULL);
and cleaning up
CloseServiceHandle(manager)
You can use InstallHinfSection.
It might be your use of
PBOOL FileWasInUse = FALSE;
. You should change it in
BOOL FileWasInUse = FALSE;
and use it in the function-call with &FileWasInUse (note the &-character).