Why function GetLastError returns 2? - winapi

Today, I decided to practice by creating a simple program that creates a new file. But I got a problem that the file is not being created. How to solve this?
Firstly, I'm importing the required crate, then creating the err() function for printing errors after creating the file, if they will.
Secondly, I'm creating a function to_u16(), because LPCWSTR type needs *const u16.
Thirdly, I'm calling the CreateFileW() function for creating file.rs, and passing all necessary arguments (according to this and this).
createfile.rs
use winapi::shared::minwindef::DWORD;
use winapi::um::winnt;
use std::ffi::CString;
use winapi::um::errhandlingapi;
use winapi::ctypes::*;
use winapi::um::minwinbase::*;
use winapi::um::fileapi;
use std::io;
fn err(){//print the last error
unsafe{
let xui =errhandlingapi::GetLastError();
print!("{:?}",xui) ;// 2
}
}
fn to_u16(s: &str) ->*const u16 {
let c_str = CString::new(s).unwrap();
c_str.as_ptr() as *const u16
}
fn main() {
unsafe{
let name:winnt::LPCWSTR =to_u16("file.rs") ; //lpFileName
let acces:DWORD = winnt::GENERIC_WRITE; //dwDesiredAccess
let share = winnt::FILE_SHARE_DELETE|winnt::FILE_SHARE_READ|winnt::FILE_SHARE_WRITE;//dwShareMode
let security = 0 as *mut SECURITY_ATTRIBUTES ;//lpSecurityAttributes
let disposition = fileapi::OPEN_EXISTING; //dwCreationDisposition
let atr = winnt::FILE_ATTRIBUTE_NORMAL;//dwFlagsAndAttributes
let handle = 0 as *mut c_void;//hTemplateFile
fileapi::CreateFileW(name,acces,share,security,disposition,atr,handle);
err();
}
}
cargo.toml
[package]
name = "createfile"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
kernel32-sys = "0.2.2"
winapi = "0.3.9"
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["winuser", "fileapi", "errhandlingapi"] }

Error 2 is ERROR_FILE_NOT_FOUND.
You say you want to create a new file, but you are setting the disposition argument to OPEN_EXISTING, so if file.rs does not already exist then CreateFileW() will fail with this error.
Try using CREATE_ALWAYS, CREATE_NEW, or OPEN_ALWAYS, per the documentation:
[in] dwCreationDisposition
An action to take on a file or device that exists or does not exist.
For devices other than files, this parameter is usually set to OPEN_EXISTING.
For more information, see the Remarks section.
This parameter must be one of the following values, which cannot be combined:
Value
Meaning
CREATE_ALWAYS2
Creates a new file, always.If the specified file exists and is writable, the function overwrites the file, the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS (183).If the specified file does not exist and is a valid path, a new file is created, the function succeeds, and the last-error code is set to zero.For more information, see the Remarks section of this topic.
CREATE_NEW1
Creates a new file, only if it does not already exist.If the specified file exists, the function fails and the last-error code is set to ERROR_FILE_EXISTS (80).If the specified file does not exist and is a valid path to a writable location, a new file is created.
OPEN_ALWAYS4
Opens a file, always.If the specified file exists, the function succeeds and the last-error code is set to ERROR_ALREADY_EXISTS (183).If the specified file does not exist and is a valid path to a writable location, the function creates a file and the last-error code is set to zero.
OPEN_EXISTING3
Opens a file or device, only if it exists.If the specified file or device does not exist, the function fails and the last-error code is set to ERROR_FILE_NOT_FOUND (2).For more information about devices, see the Remarks section.
TRUNCATE_EXISTING5
Opens a file and truncates it so that its size is zero bytes, only if it exists.If the specified file does not exist, the function fails and the last-error code is set to ERROR_FILE_NOT_FOUND (2).The calling process must open the file with the GENERIC_WRITE bit set as part of the dwDesiredAccess parameter.

Related

EnumProcessModules returns 998

I am trying to run this code in Rust (2021 version):
let module_list_size: PDWORD = ptr::null_mut();
res = winapi::um::psapi::EnumProcessModules(remote_handle, ptr::null_mut(), 0, module_list_size);
Res is well defined and the handle is valid (I checked it before) yet I'm still getting windows error 998 which is invalid access (I'm running this code as admin).
(The function exists and I imported it correctly).
Thank you in advance!
The last parameter is a pointer that indicates where to write how many bytes are needed to store all the module handles. But you're pointing at null, so it'll fail with an invalid access error when it tries to give you the result.
Instead, make a DWORD variable and pass a pointer to it:
let module_list_size: DWORD = 0;
res = winapi::um::psapi::EnumProcessModules(remote_handle, ptr::null_mut(), 0, &mut module_list_size);

Creating a shortcut on Win10 fails accessdenied

I have implemented the creation of a shortcut as defined in this article on Shell Links by MSDN
MSDN Shell Links
Here is what I implemented
CreateLink - Uses the Shell's IShellLink and IPersistFile interfaces
to create and store a shortcut to the specified object.
Returns the result of calling the member functions of the interfaces.
Parameters:
lpszPathObj - Address of a buffer that contains the path of the object,
including the file name.
lpszPathLink - Address of a buffer that contains the path where the
Shell link is to be stored, including the file name.
lpszDesc - Address of a buffer that contains a description of the
Shell link, stored in the Comment field of the link
properties.
HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc)
{
HRESULT hres;
IShellLink* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(lpszPathObj);
psl->SetDescription(lpszDesc);
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH);
// Add code here to check return value from MultiByteWideChar
// for success.
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
return hres;
I call it as:
r = CreateLink("c:\\TT\\TT.exe", "C:\\Users\\Public\\Desktop\\TT.lnk", "TT Program");
This works great on a WIN7 machine but fails on a WIN10
This is the code line that is failing:
hres = ppf->Save(wsz, TRUE);
hres == AccessDenied;
I have found other system calls that work on a Win7 but fails on Win10 and it usually comes down to some undocumented change.
Has Win10 tightened privileges on the DeskTop?
Any suggestions on addressing this on a Win10 machine?
Thanks.

SHBrowseForFolder not returning Selected folder string by reference

Hello there I'm working on a windows application using the Windows API with MS VC++ 2010 and I have the following code for selecting folders:
BOOL BrowseFolder(TCHAR *result)
{
BROWSEINFO brwinfo = { 0 };
brwinfo.lpszTitle = _T("Select Your Source Directory");
brwinfo.hwndOwner = hWnd;
LPITEMIDLIST pitemidl = SHBrowseForFolder (&brwinfo);
if (pitemidl == 0) return FALSE;
// get the full path of the folder
TCHAR path[MAX_PATH];
if (SHGetPathFromIDList (pitemidl, path)) result = path;
IMalloc *pMalloc = 0;
if (SUCCEEDED(SHGetMalloc(&pMalloc)))
{
pMalloc->Free(pitemidl);
pMalloc->Release();
}
::MessageBox(hWnd, result, "input", MB_OK);
::MessageBox(hWnd, inputFolder, "input", MB_OK); // Reference Test
return TRUE;
}
So, it opens up a browse folder dialog, saves the selected folder string in the reference parameter "result" and returns true if everything is ok.
Later I call:
BrowseFolder(inputFolder);
And when i try to print out the content of "inputFolder", it shows blank (inputFolder is a global variable TCHAR* inputFolder)
As you can see in the BrowseFolder definition I send two Message Boxes one for "result" and the other for "inputFolder" (this last one shows blank)
So my question is.. If I call: BrowseFolder(inputFolder); Shouldn't "inputFolder" be modified by reference? Why does it show empty?
Thanks in advance.
if (SHGetPathFromIDList (pitemidl, path)) result = path;
This line is your problem. result isn't a class like std::string, it's simply a pointer to a buffer of one or more TCHAR. Assigning it like that simply changes the pointer to point to path, it doesn't copy path into the buffer that result points to.
If you don't want to change to use a string class then you need to call a function to copy the string into the supplied buffer. For example:
StringCchCopy(result, MAX_PATH, path);
(this assumes the buffer is MAX_PATH characters in size).

Deleting currently loaded files using Qt on Windows

I am trying to delete all the temporary files created by my application during uninstall. I use the following code:
bool DeleteFileNow( QString filenameStr )
{
wchar_t* filename;
filenameStr.toWCharArray(filename);
QFileInfo info(filenameStr);
// don't do anything if the file doesn't exist!
if (!info.exists())
return false;
// determine the path in which to store the temp filename
wchar_t* path;
info.absolutePath().toWCharArray(path);
TRACE( "Generating temporary name" );
// generate a guaranteed to be unique temporary filename to house the pending delete
wchar_t tempname[MAX_PATH];
if (!GetTempFileNameW(path, L".xX", 0, tempname))
return false;
TRACE( "Moving real file name to dummy" );
// move the real file to the dummy filename
if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
{
// clean up the temp file
DeleteFileW(tempname);
return false;
}
TRACE( "Queueing the OS" );
// queue the deletion (the OS will delete it when all handles (ours or other processes) close)
return DeleteFileW(tempname) != FALSE;
}
My application is crashing. I think its due to some missing windows dll for the operations performed. Is there any other way to perform the same operation using Qt alone?
Roku have already told your problem in manipulating with QString and wchar_t*.
See the documentation: QString Class Reference, method toWCharArray:
int QString::toWCharArray ( wchar_t * array ) const
Fills the array with the data contained in this QString object. The array is encoded in utf16 on platforms where wchar_t is 2 bytes wide (e.g. windows) and in ucs4 on platforms where wchar_t is 4 bytes wide (most Unix systems).
array has to be allocated by the caller and contain enough space to hold the complete string (allocating the array with the same length as the string is always sufficient).
returns the actual length of the string in array.
If you are simply looking for a way to remove a file using Qt, use QFile::remove:
QFile file(fileNameStr);
file.remove(); // Returns a bool; true if successful
If you want Qt to manage the entire life cycle of a temporary file for you, take a look at QTemporaryFile:
QTemporaryFile tempFile(fileName);
if (tempFile.open())
{
// Do stuff with file here
}
// When tempFile falls out of scope, it is automatically deleted.

What is the Win32 API function to use to delete a folder?

What are the Win32 APIs to use to programically delete files and folders?
Edit
DeleteFile and RemoveDirectory are what I was looking for.
However, for this project I ended up using SHFileOperation.
I found the sample code at CodeGuru helpful.
There are two ways to approach this. One is through the File Services (using commands such as DeleteFile and RemoveDirectory) and the other is through the Windows Shell (using SHFileOperation). The latter is recommended if you want to delete non-empty directories or if you want explorer style feedback (progress dialogs with flying files, for example). The quickest way of doing this is to create a SHFILEOPSTRUCT, initialise it and call SHFileOperation, thus:
void silently_remove_directory(LPCTSTR dir) // Fully qualified name of the directory being deleted, without trailing backslash
{
SHFILEOPSTRUCT file_op = {
NULL,
FO_DELETE,
dir,
"",
FOF_NOCONFIRMATION |
FOF_NOERRORUI |
FOF_SILENT,
false,
0,
"" };
SHFileOperation(&file_op);
}
This silently deletes the entire directory. You can add feedback and prompts by varying the SHFILEOPSTRUCT initialisation - do read up on it.
I think you want DeleteFile and RemoveDirectory
See uvgroovy's comment above. You need 2 nulls at the end of the 'dir' field.
int silently_remove_directory(LPCTSTR dir) // Fully qualified name of the directory being deleted, without trailing backslash
{
int len = strlen(dir) + 2; // required to set 2 nulls at end of argument to SHFileOperation.
char* tempdir = (char*) malloc(len);
memset(tempdir,0,len);
strcpy(tempdir,dir);
SHFILEOPSTRUCT file_op = {
NULL,
FO_DELETE,
tempdir,
NULL,
FOF_NOCONFIRMATION |
FOF_NOERRORUI |
FOF_SILENT,
false,
0,
"" };
int ret = SHFileOperation(&file_op);
free(tempdir);
return ret; // returns 0 on success, non zero on failure.
}
I believe DeleteFile does not send the file to the Recycle Bin. Also, RemoveDirectory removes only empty dirs. SHFileOperation would give you the most control over what and how to delete and would show the standard Windows UI dialog boxes (e.g. "Preparing to delete etc.) if needed.
/* function used to send files and folder to recycle bin in win32 */
int fn_Send_Item_To_RecycleBin(TCHAR newpath[])
{
_tcscat_s(newpath, MAX_PATH,_T("|"));
TCHAR* Lastptr = _tcsrchr(newpath, _T('|'));
*Lastptr = _T('\0'); // Replace last pointer with Null for double null termination
SHFILEOPSTRUCT shFileStruct;
ZeroMemory(&shFileStruct,sizeof(shFileStruct));
shFileStruct.hwnd=NULL;
shFileStruct.wFunc= FO_DELETE;
shFileStruct.pFrom= newpath;
shFileStruct.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
return SHFileOperation(&shFileStruct);
}
For C++ programming, if you're willing to work with third-party libraries,
boost::filesystem::remove_all(yourPath)
is much simpler than SHFileOperation.

Resources