Using CHttpFile with HTTPS sites - https

I have this code that I use to read a data file from my website:
CInternetSession iSession;
CHttpFile *pWebFile = nullptr;
DWORD dwStatusCode;
CString strError, strTargetZIP, strDownloadURL;
strTargetZIP = theApp.GetWorkingPath() + _T("AutoUpdate\\MWBDataUpdate.zip");
strDownloadURL = _T("http://www.publictalksoftware.co.uk/mwbdata/MWBDataUpdate.zip");
// ask user to go online
if (InternetGoOnline((LPTSTR)(LPCTSTR)strDownloadURL, hWnd, 0))
{
TRY
{
// our session should already be open
// try to open up internet session to my URL
// Use flag INTERNET_FLAG_RELOAD
pWebFile = (CHttpFile*)iSession.OpenURL(strDownloadURL, 1,
INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_RELOAD);
if (pWebFile != nullptr)
{
if (pWebFile->QueryInfoStatusCode(dwStatusCode))
{
// 20x codes mean success
if ((dwStatusCode / 100) == 2)
{
}
else
{
// There was a problem!
strError.Format(IDS_TPL_INVALID_URL, dwStatusCode);
AfxMessageBox(strError, MB_OK | MB_ICONERROR);
}
}
}
else
{
// Note, there is no error log. Use new error message?
AfxMessageBox(IDS_STR_UPDATE_CHECK_ERR, MB_OK | MB_ICONERROR);
}
}
CATCH(CException, e)
{
e->GetErrorMessage(szError, _MAX_PATH);
AfxMessageBox(szError, MB_OK | MB_ICONERROR);
}
END_CATCH
// Tidy up
if (pWebFile != nullptr)
{
pWebFile->Close();
delete pWebFile;
}
iSession.Close();
}
I have recently changed my site to use HTTPS and I am trying to find if all I need to do is just change the URL here in my code. I have looked up the latest documentation for CHttpFile and it only mentions HTTP.
Thanks for the clarification.

CInternetSession::OpenURL calls InternetOpenUrl API. InternetOpenUrl needs INTERNET_FLAG_SECURE for secure websites.
Change the url from http:// to https://
Add INTERNET_FLAG_SECURE to OpenURL's option.
Example:
CInternetSession isession;
CString url = _T("https://www.google.com");
CString filename = _T("c:\\test\\test.html");
CHttpFile *httpfile = (CHttpFile*)isession.OpenURL(url, 1, INTERNET_FLAG_SECURE |
INTERNET_FLAG_TRANSFER_BINARY | INTERNET_FLAG_RELOAD);
if (httpfile)
{
DWORD dwStatusCode;
httpfile->QueryInfoStatusCode(dwStatusCode);
if(dwStatusCode == 200)
{
char buf[0x1000] = { 0 };
DWORD read = 0;
CFile file;
if (file.Open(filename, CFile::modeCreate | CFile::modeWrite))
while(InternetReadFile(*httpfile, buf, sizeof(buf), &read) && read)
file.Write(buf, read);
}
httpfile->Close();
delete httpfile;
}

Related

win32: improve performance of disk write

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.

Structure of the certificate pointed to by NCRYPT_KEY_HANDLE

I've written a credential provider and a key storage provider to logon to windows via certificate. As the documentation in this points is quite vague I used different samples from Microsoft to get things working.
I think I'm nearly there, but the logon behaves unpredictably. Sometimes I get through to the kerberos server (which complains about the certificate), sometimes the process fails with 0x80090029 without any information and sometimes windows crashes. As these crashes all have to do with access violations or null pointers and happen to occur in various places (kerberos.dll, Windows.UI.Logon.dll, ...) I think it has something to do with my key structure that i point the given NCRYT_KEY_HANDLE to in my OpenKey-implementation.
The KeyStorageProviderSample in the CNG-Kit has an example, but relies on a RSA-key stored in %AppData%. I don't have the private key available as it is stored in secure hardware, I just have the public part (i.e. the public certificate), that I read from another device and import via the following code:
SECURITY_STATUS WINAPI KeyHandler::ReadPemCert(__inout KSP_KEY *keyHandle)
{
LOG_FUNCTION;
CERT_CONTEXT certContext = {};
DWORD readLength = 0;
LOG("Fetch certificate");
const int maxSizeInBytes = 4096;
char pemCertificateAsBytes[maxSizeInBytes];
BluetoothClient bluetoothClient = BluetoothClient();
bluetoothClient.getCertificate((PBYTE)pemCertificateAsBytes, readLength);
DWORD certAsDerLen = readLength;
BYTE* certAsDer = new BYTE[certAsDerLen];
LOG("convert PEM to DER");
if (!CryptStringToBinaryA(pemCertificateAsBytes, 0, CRYPT_STRING_BASE64, certAsDer, &certAsDerLen, NULL, NULL))
{
LOG_LAST_ERROR("CryptStringToBinary failed. Err:");
}
LOG_BYTES_AS_HEX("DER-Zertifikat", certAsDer, certAsDerLen);
PCCERT_CONTEXT pcCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, certAsDer, certAsDerLen);
certContext->pCertInfo = pcCertContext->pCertInfo;
certContext->cbCertEncoded = pcCertContext->cbCertEncoded;
certContext->pbCertEncoded = pcCertContext->pbCertEncoded;
certContext->dwCertEncodingType = pcCertContext->dwCertEncodingType;
CERT_INFO *certInfo;
certInfo = certContext.pCertInfo;
CERT_PUBLIC_KEY_INFO pubKeyInfo = certInfo->SubjectPublicKeyInfo;
LOG("Aquire cryptocontext");
HCRYPTPROV hProv = 0;
if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
{
{
LOG_LAST_ERROR("CryptAcquireContext failed. Err:");
return -1;
}
}
LOG("Importing public key");
NCRYPT_KEY_HANDLE publicKeyHandle = NULL;
if (!CryptImportPublicKeyInfo(hProv, X509_ASN_ENCODING, &pubKeyInfo, &publicKeyHandle))
{
LOG_LAST_ERROR("CryptImportPublicKeyInfo failed. Err:");
return -1;
}
keyHandle->fFinished = TRUE;
keyHandle->hPublicKey = (BCRYPT_KEY_HANDLE)publicKeyHandle;
keyHandle->pszKeyBlobType = BCRYPT_RSAPUBLIC_BLOB;
LocalFree(certInfo);
return ERROR_SUCCESS;
}
The key structure is initialized this way:
SECURITY_STATUS
WINAPI
KeyHandler::CreateNewKeyObject(
__in_opt LPCWSTR pszKeyName,
__deref_out KSP_KEY **ppKey)
{
LOG_FUNCTION;
KSP_KEY *pKey = NULL;
DWORD cbKeyName = 0;
SECURITY_STATUS Status = NTE_INTERNAL_ERROR;
NTSTATUS ntStatus = STATUS_INTERNAL_ERROR;
pKey = (KSP_KEY *)HeapAlloc(GetProcessHeap(), 0, sizeof(KSP_KEY));
if (pKey == NULL)
{
return NTE_NO_MEMORY;
}
pKey->cbLength = sizeof(KSP_KEY);
pKey->dwMagic = KSP_KEY_MAGIC;
pKey->dwAlgID = KSP_RSA_ALGID;
pKey->pszKeyFilePath = NULL;
pKey->pszKeyBlobType = NULL;
pKey->dwKeyBitLength = 0;
pKey->fFinished = FALSE;
//Copy the keyname into the key struct.
if (pszKeyName != NULL)
{
cbKeyName = (DWORD)(wcslen(pszKeyName) + 1) * sizeof(WCHAR);
pKey->pszKeyName = (LPWSTR)HeapAlloc(
GetProcessHeap(),
0,
cbKeyName + sizeof(WCHAR));
if (pKey->pszKeyName == NULL)
{
return NTE_NO_MEMORY;
}
CopyMemory(pKey->pszKeyName, pszKeyName, cbKeyName);
pKey->pszKeyName[cbKeyName / sizeof(WCHAR)] = L'\0';
}
else
{
pKey->pszKeyName = NULL;
}
if (globalRSAProviderHandle == NULL)
{
ntStatus = BCryptOpenAlgorithmProvider(
&globalRSAProviderHandle,
BCRYPT_RSA_ALGORITHM,
NULL,
0);
if (!NT_SUCCESS(ntStatus))
{
return NormalizeNteStatus(ntStatus);
}
}
pKey->hProvider = globalRSAProviderHandle;
pKey->pbKeyFile = NULL;
pKey->cbKeyFile = 0;
pKey->pbPrivateKey = NULL;
pKey->cbPrivateKey = 0;
pKey->hPublicKey = NULL;
pKey->hPrivateKey = NULL;
pKey->dwExportPolicy = NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG;
pKey->dwKeyUsagePolicy = NCRYPT_ALLOW_DECRYPT_FLAG | NCRYPT_ALLOW_SIGNING_FLAG;
pKey->pbSecurityDescr = NULL;
pKey->cbSecurityDescr = 0;
InitializeListHead(&pKey->PropertyList);
*ppKey = pKey;
pKey = NULL;
return ERROR_SUCCESS;
}
Somewhere in there must be the mistake leading to the various memory errors. But as I'm quite new to windows programming and c/c++ I just can't spot the point and can't find any documentation about the datastructure that windows expects for the NCRYTP_KEY_HANDLE.
Does anybody know more about this structure?
NCRYPT_KEY_HANDLE is just a pointer to a structure that you defined.
Windows itself doesn't care about this structure and expect that your provider knows how to work with it.
In KeyHandler::ReadPemCert you mixed legacy CryptoAPI and CNG API. Since you are implementing KSP you should use only CNG API (CryptImportPublicKeyInfoEx2).
DWORD error = NTE_FAIL;
BCRYPT_KEY_HANDLE hKey = NULL;
...
PCCERT_CONTEXT pcCertContext = CertCreateCertificateContext(X509_ASN_ENCODING, certAsDer, certAsDerLen);
if(!pcCertContext)
{
goto Exit;
}
if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &pcCertContext->pCertInfo->SubjectPublicKeyInfo, 0, nullptr, &hKey))
{
goto Exit;
}
/* Also you can export key and print out the result to make sure everything works
DWORD temp = 0;
status = BCryptExportKey(hKey, 0, BCRYPT_RSAPUBLIC_BLOB, nullptr, 0, &temp, 0);
if (status != ERROR_SUCCESS)
{
goto Exit;
}
std::vector<BYTE> key(temp);
status = BCryptExportKey(hKey, 0, BCRYPT_RSAPUBLIC_BLOB, key.data(), key.size(), &temp, 0);
if (status != ERROR_SUCCESS)
{
goto Exit;
}
for (auto const& i : key)
{
std::cout << std::hex << (int)i;
}
}
*/
keyHandle->fFinished = TRUE;
keyHandle->hPublicKey = hKey;
keyHandle->pszKeyBlobType = BCRYPT_RSAPUBLIC_BLOB;
erro = ERROR_SUCCESS;
Exit:
if(pcCertContext)
{
CertFreeCertificateContext(pcCertContext);
}
return error;

Asynchronous ReadDirectoryChangesW fails with ERROR_INVALID_PARAMETER

I've managed to use ReadDirectoryChangesW synchronously, but when I attempt to use completion ports, ReadDirectoryChangesW always returns ERROR_INVALID_PARAMETER. I guess there should be some obvious error in my code, but I cannot figure it.
My code is based on How to use ReadDirectoryChangesW() method with completion routine?
const wchar_t *directory = L"X:\\X";
HANDLE h = CreateFile(
directory,
FILE_LIST_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, NULL);
if (h==INVALID_HANDLE_VALUE) return;
HANDLE p = CreateIoCompletionPort(h,0,0,1);
if (p==NULL) {CloseHandle(h); return;}
DWORD *buffer =new DWORD[4096];
DWORD bytesReturned;
DWORD notifyFilter = FILE_NOTIFY_CHANGE_FILE_NAME
| FILE_NOTIFY_CHANGE_DIR_NAME
| FILE_NOTIFY_CHANGE_SIZE
| FILE_NOTIFY_CHANGE_LAST_WRITE;
while (true) {
OVERLAPPED overlapped;
memset(&overlapped,0,sizeof(overlapped));
BOOL success = ReadDirectoryChangesW(h,
&buffer[0],
4096*sizeof(DWORD),
FALSE, notifyFilter,
NULL, //&bytesReturned,
&overlapped,myFileIOCompletionRoutine);
if (!success) {
//always ERROR_INVALID_PARAMETER
CloseHandle(h);
CloseHandle(p);
return;
}
}
As Hans Passant kindly reminds, the documentation already says that a completion routine must not be used if the directory is associated to a completion port. In this case I solved the problem by waiting on the completion port, i.e. ReadDirectoryChangesW(...,&overlapped,0);
Complete code is below.
while (true) {
OVERLAPPED overlapped;
memset(&overlapped,0,sizeof(overlapped));
BOOL success = ReadDirectoryChangesW(h,
&buffer[0],
4096*sizeof(DWORD),
FALSE, notifyFilter, 0, &overlapped,0);
if (!success) {
if (GetLastError()==ERROR_INVALID_HANDLE) {
//asynchronously closed by cancel
CloseHandle(p); //close completion port
return 0;
} else {
CloseHandle(h); //close directory handle
CloseHandle(p); //close completion port
return 1;
}
}
DWORD di;
LPOVERLAPPED lpOverlapped;
if (!GetQueuedCompletionStatus(p,&bytesReturned,&di,&lpOverlapped,1000)) {
int ret;
if (GetLastError()==WAIT_TIMEOUT) {
if (GetFileAttributes(directory)!=INVALID_FILE_ATTRIBUTES) {
continue; //timeout
} else {
//directory has been deleted or renamed
ret=0;
}
} else {
//other failure
ret=1;
}
CloseHandle(h); //close directory handle
CloseHandle(p); //close completion port
return ret;
}
char* ptr = (char*)&buffer[0];
char* end = ptr+bytesReturned;
while (ptr<end) {
FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION*) ptr;
//process FILE_NOTIFY_INFORMATION
ptr+=info->NextEntryOffset;
if (!info->NextEntryOffset) break;
}
}

How to refresh only one time in ReadDirectoryChange in WIN32 API?

I use ReadDirectoryChange in WIN32 API. After I copy 10 folder, my program is running refresh 10 times. However I only want it refresh once.
Can you help me? Here is my code:
bool FolderWatcher::Loop ()
{
// declare a variable and using it to return
int i = 0;
// convert from WCHAR to LPWSTR
LPWSTR ptr = _folder;
char buf[256 * (sizeof(FILE_NOTIFY_INFORMATION) + MAX_PATH * sizeof(WCHAR))] = {0};
DWORD bytesReturned = 0;
BOOL result = FALSE;
FILE_NOTIFY_INFORMATION *fni = NULL;
// using CreateFile to choose folder need to watch
HANDLE hDir = CreateFileW(
ptr,
FILE_LIST_DIRECTORY |
STANDARD_RIGHTS_READ,
//Enables subsequent open operations on a file or device to request read access.
FILE_SHARE_READ |
//Enables subsequent open operations on a file or device to request write access.
FILE_SHARE_WRITE |
//Enables subsequent open operations on a file or device to request delete access.
FILE_SHARE_DELETE,
NULL,
//Opens a file or device, only if it exists.
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
// check if directory is not exists
if (!hDir || hDir == INVALID_HANDLE_VALUE)
{
i = 0;
}
else
{
for (;;)
{
// call ReadDirectoryChangeW to watch folder
result = ReadDirectoryChangesW(hDir,
buf,
sizeof(buf) / sizeof(*buf),
FALSE, /* monitor the entire subtree */
FILE_NOTIFY_CHANGE_FILE_NAME |
FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_ATTRIBUTES |
FILE_NOTIFY_CHANGE_SIZE |
/*FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_LAST_ACCESS |*/
FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_SECURITY,
&bytesReturned,
NULL,
NULL);
if (result && bytesReturned)
{
wchar_t filename[MAX_PATH];
wchar_t action[256];
for (fni = (FILE_NOTIFY_INFORMATION*)buf; fni; )
{
switch (fni->Action)
{
// excute if a folder/ text docu is added
case FILE_ACTION_ADDED:
{
i = 1;
PostMessage (_hwndNotifySink, WM_FOLDER_CHANGE, 0, (LPARAM) _folder);
}
break;
// excute if a folder/ text docu is removed
case FILE_ACTION_REMOVED:
{
i = 1;
PostMessage (_hwndNotifySink, WM_FOLDER_CHANGE, 0, (LPARAM) _folder);
}
break;
case FILE_ACTION_MODIFIED:
{
i = 1;
if(lstrcmp(fni->FileName, L"service.log") != 0)
PostMessage (_hwndNotifySink, WM_FOLDER_CHANGE, 0, (LPARAM) _folder);
break;
}
// excute if a folder/ text docu is renamed
case FILE_ACTION_RENAMED_OLD_NAME:
{
i = 1;
PostMessage (_hwndNotifySink, WM_FOLDER_CHANGE, 0, (LPARAM) _folder);
break;
}
// excute if a folder/ text docu is renamed new name
case FILE_ACTION_RENAMED_NEW_NAME:
{
i = 1;
PostMessage (_hwndNotifySink, WM_FOLDER_CHANGE, 0, (LPARAM) _folder);
}
break;
}
if (fni->NextEntryOffset)
{
char *p = (char*)fni;
fni = (FILE_NOTIFY_INFORMATION*)(p + fni->NextEntryOffset);
}
else
{
fni = NULL;
}
}
}
else
{
i = 0;
}
}
CloseHandle(hDir); // close handle
}
return i; // return value of i
}
In case WM_FOLDER_CHANGE, I call refresh function.

renaming multiple file

int rename_file()
{
WIN32_FIND_DATA FindFileData;
HANDLE hFind;
hFind = FindFirstFile(L"\\Hard Disk\\*.*", &FindFileData);
LPTSTR oldfilename;
LPTSTR newfilename;
if (hFind == INVALID_HANDLE_VALUE)
{
printf ("FindFirstFile failed (%d)\n", GetLastError());
return 0;
}
else
{
int i=1000;
while (FindNextFile(hFind, &FindFileData) != 0)
{
_tprintf (TEXT("The first file found is %s\n"),FindFileData.cFileName);
oldfilename =FindFileData.cFileName;
StringCchPrintf(newfilename, 30, TEXT("%s\\newfile_%d.txt"),dirname, i);
BOOL rs = MoveFile(oldfilename,newfilename);
i++;
}
FindClose(hFind);
return 1;
}
}
i am unable to rename file ,i am working on wince 6 ,while debugging at StringCchPrintf iam getting exception in coredll.dll can any one help me ....
You have not allocated any buffer for newFileName, so when you use it in the StringCchPrintf it's just an uninitialized pointer.
Try this:
TCHAR newFile[260]; // or whatever length you wish
LPTSTR newfilename = &newFile[0];
Also you should check the return code from MoveFile, and output something sensible on error. Make a habit of doing this for all your function calls that can return an error.

Resources