I have one win32 prog where i want to call GetOpenFileName() but every time it got crash and CommDlgExtendedError() return error code as 1008. Please help me out.
char Filestring[MAX_PATH] = "\0";
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.lpstrFile = (LPWSTR)Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileName(&ofn) == TRUE)
{
}
else
{
int err = CommDlgExtendedError();
}
You are using the TCHAR version of the GetOpenFileName() API, which maps to either the ANSI (GetOpenFileNameA()) or Unicode (GetOpenFileNameW()) API depending on whether UNICODE is defined.
Since ofn.lpstrFile is accepting a LPWSTR (wchar_t*) pointer, expecting it to point at a wchar[] buffer, your project clearly has UNICODE defined. But you are giving it a type-casted pointer to a char[] buffer instead, which has 1/2 the storage space than you are telling the API is available for it to write to.
Your type-cast on the ofn.lpstrFile field is lying to the API. The code is calling the Unicode API, so it will write Unicode data to your char[] buffer, giving you mojibake output, and risking a buffer overflow.
You should use a TCHAR[] buffer instead to match what the API is expecting, eg:
TCHAR Filestring[MAX_PATH] = TEXT("\0");
OPENFILENAME ofn = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileName(&ofn))
{
...
}
else
{
int err = CommDlgExtendedError();
...
}
Otherwise, use the ANSI or Unicode API explicitly, depending on your desired character encoding, eg:
CHAR Filestring[MAX_PATH] = "\0";
OPENFILENAMEA ofn = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileNameA(&ofn))
{
...
}
else
{
int err = CommDlgExtendedError();
...
}
WCHAR Filestring[MAX_PATH] = L"\0";
OPENFILENAMEW ofn = { 0 };
ofn.lStructSize = sizeof(ofn);
ofn.lpstrFile = Filestring;
ofn.nMaxFile = MAX_PATH;
if (GetOpenFileNameW(&ofn))
{
...
}
else
{
int err = CommDlgExtendedError();
...
}
Related
In order to write to HD at max. performance I'm using overlapped I/O.
It works.
Upon acquiring 4MB of data (from sensor) I'm writing it to disk.
Then, upon getting the next 4MB I first ask if the previous writing completed.
How can I know what is the optimal block size (4MB ?) that is best for my disk ?
// AsyncFile.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "AsyncFile.h"
/****************************************************************************/
CAsyncFile::CAsyncFile()
{
}
/****************************************************************************/
CAsyncFile::~CAsyncFile()
{
}
/****************************************************************************/
int CAsyncFile::OpenFile(char *pcFileName,
bool bAsync, // Whether async read/write is required
bool bWrite) // True is file is used for writing to
{
DWORD dwAsyncMask = bAsync ? (FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING) : 0;
DWORD dwCreation = bWrite ? CREATE_ALWAYS : OPEN_EXISTING;
DWORD dwAccess = bWrite ? GENERIC_WRITE : GENERIC_READ;
DWORD dwShareMode = bWrite ? FILE_SHARE_READ : FILE_SHARE_WRITE;
if (strlen(pcFileName) < sizeof(m_cFileName))
strcpy_s(m_cFileName, 256, pcFileName);
else
m_cFileName[0] = 0; // NULL (error - file name is too long)
// Calling openFile() sets a valid value to the file handle
m_hFileHandle = INVALID_HANDLE_VALUE;
// Auto reset (manual reset=false), init state = false, no name
m_hIoCompleted = CreateEvent(NULL, FALSE, FALSE, NULL);
// Init OVERLAPPED structure, for async read
m_tOverlapped.Offset = 0;
m_tOverlapped.OffsetHigh = 0;
m_tOverlapped.hEvent = m_hIoCompleted;
m_Event = m_tOverlapped.hEvent;
if (m_hFileHandle != INVALID_HANDLE_VALUE)
{
// File is already openned; check open mode
if ((bAsync == m_bAsync) && (bWrite == m_bWrite))
return (ASYNCFILE_OK);
// File is already openned, but in other mode; Should close file
// before using it again
return ASYNCFILE_FILE_IS_NOT_IN_WRITE_MODE;
}
m_hFileHandle =
CreateFile((LPCTSTR)m_cFileName,
dwAccess, // Open for read or write
dwShareMode, //
NULL, // No SECURITY_ATTRBUTES
dwCreation, // Open exisiting file (if read) \ create new (if write)
dwAsyncMask, // For asynchronous operations, for maximum asynchronous performence
0);
if (m_hFileHandle == INVALID_HANDLE_VALUE)
{
DWORD dwError = GetLastError();
return ASYNCFILE_FAILED_TO_OPEN_FILE;
}
//In case file opened for reading, get its size
if (bWrite == false)
{
GetFileSizeEx(m_hFileHandle, &m_FileSize);
}
// Save open mode
m_bAsync = bAsync;
m_bWrite = bWrite;
return ASYNCFILE_OK;
}
/****************************************************************************/
int CAsyncFile::CloseFile()
{
//BOOL Status;
if (!CloseHandle(m_hFileHandle))
return ASYNCFILE_FAILED_TO_CLOSE_FILE;
if (!CloseHandle(m_hIoCompleted))
return ASYNCFILE_FAILED_TO_CLOSE_FILE;
return ASYNCFILE_OK;
}
/****************************************************************************/
int CAsyncFile::StartAsyncRead(void* pBuffer,
DWORD dwReadSize,
bool* pbEof)
{
*pbEof = false; // By default, EOF is false
int iError;
if (m_hFileHandle == INVALID_HANDLE_VALUE)
return (false);
if (!ReadFile(m_hFileHandle,
pBuffer,
dwReadSize,
NULL, // actual bytes read is not valid now
&m_tOverlapped))
{
if ((iError = GetLastError()) == ERROR_HANDLE_EOF)
{
*pbEof = true;
return ASYNCFILE_OK;
}
else if (!(m_bAsync && (iError == ERROR_IO_PENDING)))
{
return ASYNCFILE_START_READ_FAILED;
}
}
return ASYNCFILE_OK;
}
/****************************************************************************/
int CAsyncFile::WaitAsyncOperationEnd(DWORD* pdwActualBytesTransferred)
{
if (m_hFileHandle == INVALID_HANDLE_VALUE)
return ASYNCFILE_WAIT_FOR_COMPLETION_FAILED;
// Wait for read operation to complete
if (!GetOverlappedResult(m_hFileHandle,
&m_tOverlapped,
pdwActualBytesTransferred,
true))
return ASYNCFILE_WAIT_FOR_COMPLETION_FAILED;
return ASYNCFILE_OK;
}
/****************************************************************************/
int CAsyncFile::StartAsyncWrite(void* pSrcBuf,
DWORD dwSize) // In bytes
{
int iError;
if (!WriteFile(m_hFileHandle,
pSrcBuf,
dwSize,
NULL, // actual bytes written is not valid now
&m_tOverlapped))
{
iError = GetLastError();
if (iError != ERROR_IO_PENDING)
return ASYNCFILE_START_WRITE_FAILED;
}
return ASYNCFILE_OK;
}
/****************************************************************************/
void CAsyncFile::SetFilePosition(UINT64 Position)
{
m_tOverlapped.Offset = Position & 0xFFFFFFFF;
m_tOverlapped.OffsetHigh = Position >> 32;
}
/****************************************************************************/
UINT64 CAsyncFile::GetFilePosition()
{
UINT64 Position;
Position = (m_tOverlapped.Offset) | ((UINT64)m_tOverlapped.OffsetHigh << 32);
return (Position);
}
/****************************************************************************/
UINT64 CAsyncFile::GetFileSize()
{
return (m_FileSize.QuadPart);
}
Well it depends on the average size of your files as well. If your file sizes are constantly ranging near 7 to 8 MB, then there would be some benefit in increasing the buffer size to 8192KB. How old is the drive? How often have you used it, many other factors come into play. We are able to learn more about this topic from an excellent piece of software called FastCopy. Hope this helps.
I want to develop an encrypt-virtual-disk based on the FileDisk-17 opensource project.
Here is my solution:
In IPR_MJ_READ, when the ZwReadFile returns, I use function 'DecryptData' to decrypt the data read by ZwReadFile.
In IPR_MJ_WRITE, before call ZwWriteFile, I use function 'EncryptData' to encrypt the data which will be written to the disk.
I put EncryptData & DecryptData functions in a single C source file.
The question is; when I loaded my driver, I get the ERROR_PROC_NOT_FOUND(127) error code
every time, even there are only one line in the EncryptData or DecryptData function.
Who can tell me what caused this and how to fix it?
filedisk.c
switch (io_stack->MajorFunction)
{
case IRP_MJ_READ:
system_buffer = (PUCHAR) MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority);
if (system_buffer == NULL)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
buffer = (PUCHAR) ExAllocatePool(PagedPool, io_stack->Parameters.Read.Length);
if (buffer == NULL)
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
ZwReadFile(
device_extension->file_handle,
NULL,
NULL,
NULL,
&irp->IoStatus,
buffer,
io_stack->Parameters.Read.Length,
&io_stack->Parameters.Read.ByteOffset,
NULL
);
*if(bEncrypt)
{
cipher = (PUCHAR)ExAllocatePoolWithTag(NonPagedPool, irp->IoStatus.Information, 'TAG');
if(cipher)
{
**DecryptData**(buffer, cipher, irp->IoStatus.Information);
RtlCopyMemory(system_buffer, cipher, irp->IoStatus.Information);
ExFreePool(cipher);
}
else
{
irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
irp->IoStatus.Information = 0;
break;
}
}*
else
{
RtlCopyMemory(system_buffer, buffer, io_stack->Parameters.Read.Length);
ExFreePool(buffer);
}
crypto.c
VOID EncryptData(PUCHAR src, PUCHAR dst, ULONG length)
{
BF_LONG data[2];
BF_KEY key;
BF_set_key(&key, pCryptoInformation->CryptoKey, sizeof(pCryptoInformation->CryptoKey));
}
VOID DecryptData(PUCHAR src, PUCHAR dst, ULONG length)
{
BF_LONG data[2];
BF_KEY key;
BF_set_key(&key, pCryptoInformation->CryptoKey, sizeof(pCryptoInformation->CryptoKey));
}
I searching function something like OpenFileDialog on .NET but on win32, i can't find this function on this name on msdn and i remember this function exists.
Can anyone give me name?
Greetings,
I believe you are looking for the GetOpenFileName.
//make sure this is commented out in all code (usually stdafx.h)
// #define WIN32_LEAN_AND_MEAN
#include <windows.h>
OPENFILENAME ofn; // common dialog box structure
TCHAR szFile[260] = { 0 }; // if using TCHAR macros
// Initialize OPENFILENAME
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hWnd;
ofn.lpstrFile = szFile;
ofn.nMaxFile = sizeof(szFile);
ofn.lpstrFilter = _T("All\0*.*\0Text\0*.TXT\0");
ofn.nFilterIndex = 1;
ofn.lpstrFileTitle = NULL;
ofn.nMaxFileTitle = 0;
ofn.lpstrInitialDir = NULL;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
if (GetOpenFileName(&ofn) == TRUE)
{
// use ofn.lpstrFile
}
Taken from Displaying Open File Dialog using WinApi
how to convert char to LPCTSTR in vc++
I am using MVC.
QByteArray qBary;
qBary.append(temp);
char toChar[512];
for(int ii = 0; ii < 512; ii++)
{
toChar[ii] = qBary[ii];
if(qBary[ii] == '\0')
{
break;
}
}
SHFILEOPSTRUCT sf;
memset(&sf, 0, sizeof(sf));
sf.hwnd = 0;
sf.wFunc = FO_COPY;
sf.pFrom = toChar; // error occurring here
if you are using MFC (is your label supposed to be MFC instead of MVC?):
char name[] = "your name";
CString sName(name);
LPCTSTR lpszName = sName;
if you are using Qt, take a look at QString and QByteArray
// (1)
QString filename;
LPCWSTR lpszFilename = filename.utf16(); // alternatively, .unicode()
// alternatively, (2)
QByteArray qBA("abcdef.txt");
QString qString(qBA);
LPCWSTR lpszFileName = qString.utf16(); // or, .unicode() , .utf8()
...
sf.pFrom = lpszFileName;
How do you resolve an NT style device path, e.g. \Device\CdRom0, to its logical drive letter, e.g. G:\ ?
Edit: A Volume Name isn't the same as a Device Path so unfortunately GetVolumePathNamesForVolumeName() won't work.
Hopefully the following piece of code will give you enough to solve this - after you've initialised it, you just need to iterate through the collection to find your match. You may want to convert everything to upper/lower case before you insert into the collection to help with lookup performance.
typedef basic_string<TCHAR> tstring;
typedef map<tstring, tstring> HardDiskCollection;
void Initialise( HardDiskCollection &_hardDiskCollection )
{
TCHAR tszLinkName[MAX_PATH] = { 0 };
TCHAR tszDevName[MAX_PATH] = { 0 };
TCHAR tcDrive = 0;
_tcscpy_s( tszLinkName, MAX_PATH, _T("a:") );
for ( tcDrive = _T('a'); tcDrive < _T('z'); ++tcDrive )
{
tszLinkName[0] = tcDrive;
if ( QueryDosDevice( tszLinkName, tszDevName, MAX_PATH ) )
{
_hardDiskCollection.insert( pair<tstring, tstring>( tszLinkName, tszDevName ) );
}
}
}
Maybe you could use GetVolumeNameForMountPoint and iterate through all mount points A:\ through Z:\, breaking when you find a match?
http://msdn.microsoft.com/en-us/library/aa364994(VS.85).aspx
(I haven't tried this)
Following function does the job using C only
BOOL GetWin32FileName(const TCHAR* pszNativeFileName, TCHAR *pszWin32FileName)
{
BOOL bFound = FALSE;
// Translate path with device name to drive letters.
TCHAR szTemp[MAX_PATH];
szTemp[0] = '\0';
if (GetLogicalDriveStrings(MAX_PATH - 1, szTemp))
{
TCHAR szName[MAX_PATH];
TCHAR szDrive[3] = TEXT(" :");
TCHAR* p = szTemp;
do
{
// Copy the drive letter to the template string
*szDrive = *p;
// Look up each device name
if (QueryDosDevice(szDrive, szName, MAX_PATH))
{
size_t uNameLen = _tcslen(szName);
if (uNameLen < MAX_PATH)
{
bFound = _tcsnicmp(pszNativeFileName, szName, uNameLen) == 0
&& *(pszNativeFileName + uNameLen) == _T('\\');
if (bFound)
{
// Replace device path with DOS path
StringCchPrintf(pszWin32FileName,
MAX_PATH,
TEXT("%s%s"),
szDrive,
pszNativeFileName + uNameLen);
}
}
}
// Go to the next NULL character.
while (*p++);
} while (!bFound && *p);
}
return(bFound);
}
You can lookup all volumes' name to match a device name and get drive letter.Here is a sample:
int DeviceNameToVolumePathName(WCHAR *filepath) {
WCHAR fileDevName[MAX_PATH];
WCHAR devName[MAX_PATH];
WCHAR fileName[MAX_PATH];
HANDLE FindHandle = INVALID_HANDLE_VALUE;
WCHAR VolumeName[MAX_PATH];
DWORD Error = ERROR_SUCCESS;
size_t Index = 0;
DWORD CharCount = MAX_PATH + 1;
int index = 0;
// \Device\HarddiskVolume1\windows,locate \windows.
for (int i = 0; i < lstrlenW(filepath); i++) {
if (!memcmp(&filepath[i], L"\\", 2)) {
index++;
if (index == 3) {
index = i;
break;
}
}
}
filepath[index] = L'\0';
memcpy(fileDevName, filepath, (index + 1) * sizeof(WCHAR));
FindHandle = FindFirstVolumeW(VolumeName, ARRAYSIZE(VolumeName));
if (FindHandle == INVALID_HANDLE_VALUE)
{
Error = GetLastError();
wprintf(L"FindFirstVolumeW failed with error code %d\n", Error);
return FALSE;
}
for (;;)
{
// Skip the \\?\ prefix and remove the trailing backslash.
Index = wcslen(VolumeName) - 1;
if (VolumeName[0] != L'\\' ||
VolumeName[1] != L'\\' ||
VolumeName[2] != L'?' ||
VolumeName[3] != L'\\' ||
VolumeName[Index] != L'\\')
{
Error = ERROR_BAD_PATHNAME;
wprintf(L"FindFirstVolumeW/FindNextVolumeW returned a bad path: %s\n", VolumeName);
break;
}
VolumeName[Index] = L'\0';
CharCount = QueryDosDeviceW(&VolumeName[4], devName, 100);
if (CharCount == 0)
{
Error = GetLastError();
wprintf(L"QueryDosDeviceW failed with error code %d\n", Error);
break;
}
if (!lstrcmpW(devName, filepath)) {
VolumeName[Index] = L'\\';
Error = GetVolumePathNamesForVolumeNameW(VolumeName, fileName, CharCount, &CharCount);
if (!Error) {
Error = GetLastError();
wprintf(L"GetVolumePathNamesForVolumeNameW failed with error code %d\n", Error);
break;
}
// concat drive letter to path
lstrcatW(fileName, &filepath[index + 1]);
lstrcpyW(filepath, fileName);
Error = ERROR_SUCCESS;
break;
}
Error = FindNextVolumeW(FindHandle, VolumeName, ARRAYSIZE(VolumeName));
if (!Error)
{
Error = GetLastError();
if (Error != ERROR_NO_MORE_FILES)
{
wprintf(L"FindNextVolumeW failed with error code %d\n", Error);
break;
}
//
// Finished iterating
// through all the volumes.
Error = ERROR_BAD_PATHNAME;
break;
}
}
FindVolumeClose(FindHandle);
if (Error != ERROR_SUCCESS)
return FALSE;
return TRUE;
}
If you want to resolve it in driver,you can check this link for reference.
Here is refactored version of the solution.
I replaced TChAR with wchar_t because afaik it's not a good idea to use it in most projects.
std::map<std::wstring, std::wstring> GetDosPathDevicePathMap()
{
// It's not really related to MAX_PATH, but I guess it should be enough.
// Though the docs say "The first null-terminated string stored into the buffer is the current mapping for the device.
// The other null-terminated strings represent undeleted prior mappings for the device."
wchar_t devicePath[MAX_PATH] = { 0 };
std::map<std::wstring, std::wstring> result;
std::wstring dosPath = L"A:";
for (wchar_t letter = L'A'; letter <= L'Z'; ++letter)
{
dosPath[0] = letter;
if (QueryDosDeviceW(dosPath.c_str(), devicePath, MAX_PATH)) // may want to properly handle errors instead ... e.g. check ERROR_INSUFFICIENT_BUFFER
{
result[dosPath] = devicePath;
}
}
return result;
}