I know that the main problem comes from recursively calling FindFile(). With recursively calling this function, my i becomes 0. But I don't understand how I can fix this problem.
If possible, give advice on how to fix this bug without completely reworking all the functions below. Or provide a link where you can read about the correct initialization of icons in CListViewCtrl.
void Finder::FindFile(CString szPath)
{
HIMAGELIST hSmall{};
CFindFile F;
CString S = szPath + TEXT("\\*.*");
int i = 0;
BOOL bFlag = F.FindFile(S);
if (!bFlag)
{
MessageBox(TEXT("Error"), TEXT("File not found"), 0);
}
else
{
do
{
if (F.IsDots() == TRUE)
{
continue;
}
else
{
if (F.IsDirectory() == TRUE)
{
View_List(F.GetFileName(), i, F.GetFilePath());
i++;
FindFile(F.GetFilePath());
}
else
{
View_List(F.GetFileName(), i, F.GetFilePath());
i++;
}
}
} while (F.FindNextFileW());
F.Close();
InitListViewImage(i, S);
}
}
void Finder::View_List(CString name, int i, CString path)
{
CString nameWithoutEx=std::get<0>(Split(name));
CString extention= std::get<1>(Split(name));
lvItem.mask = LVIF_IMAGE | LVIF_TEXT;
lvItem.state = 0;
lvItem.stateMask = 0;
lvItem.iItem = i;
lvItem.iImage = i;
lvItem.iSubItem = 0;
lvItem.pszText = (LPWSTR)nameWithoutEx.GetString();
lvItem.cchTextMax = nameWithoutEx.GetLength();
myListView.InsertItem(&lvItem);
myListView.SetItemText(i, 1, extention.GetString());
myListView.SetItemText(i, 2, path.GetString());
}
std::tuple<CString, CString> Finder::Split(CString buf)
{
CString tmp = buf;
if (buf.Find(TEXT(".")) == -1)
{
return { buf.GetString(),TEXT("Directory") };
}
else
{
int index = buf.Find(TEXT("."))+1;
if (buf.Find(TEXT("."),index) != -1)
{
while (buf.Find(TEXT("."), index) != -1)
{
index = buf.Find(TEXT("."), index)+1;
}
}
buf.Delete(index-1, buf.GetLength());
tmp.Delete(0, index-1);
return{ buf.GetString(),tmp.GetString() };
}
}
BOOL Finder::InitListViewImage(int size, CString path)
{
CFindFile F;
HIMAGELIST hSmall;
SHFILEINFO lp{};
hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR32, size, 1);
bool hFind = F.FindFile(path);
if (!hFind)
{
MessageBox(TEXT("Error"), TEXT("File not found"), MB_OK | MB_ICONWARNING);
}
else
{
do
{
if (F.IsDots() == TRUE)
{
continue;
}
DWORD num = GetFileAttributesW(F.GetFilePath());
SHGetFileInfoW(F.GetFilePath(), num, &lp, sizeof(lp), SHGFI_SYSICONINDEX | SHGFI_ICON | SHGFI_USEFILEATTRIBUTES);
ImageList_AddIcon(hSmall, lp.hIcon);
DestroyIcon(lp.hIcon);
} while (F.FindNextFileW());
F.Close();
}
myListView.SetImageList(hSmall, 1);
return TRUE;
}
You need to pass the value of i as a reference to FindFile so that when you call it recursively the value continues to increment.
void Finder::FindFile(CString szPath, int& i)
{
HIMAGELIST hSmall{};
CFindFile F;
CString S = szPath + TEXT("\\*.*");
// int i = 0; <-- not declared here, as it is now an argument
BOOL bFlag = F.FindFile(S);
if (!bFlag)
{
MessageBox(TEXT("Error"), TEXT("File not found"), 0);
}
else
{
do
{
if (F.IsDots() == TRUE)
{
continue;
}
else
{
if (F.IsDirectory() == TRUE)
{
View_List(F.GetFileName(), i, F.GetFilePath());
i++;
FindFile(F.GetFilePath(), i); // <-- pass i to the recursive function
}
else
{
View_List(F.GetFileName(), i, F.GetFilePath());
i++;
}
}
} while (F.FindNextFileW());
F.Close();
InitListViewImage(i, S);
}
}
When you call FindFile from your main function or wherever, you need to give it a variable to use as the starting point, e.g.
main()
{
int i = 0;
FindFile("C:\", i);
}
Related
This is the main code where error happened:
void VRInputRemapping::DigitalInputConfig() {
bool orginput = this->curVRConfig->GetorgDigitalInput();
uint32_t deviceId = this->curVRConfig->GetcurDeviceId();
uint32_t buttonId = this->curVRConfig->GetcurButtonId();
printf("Digital orginput: %d device:%d butonid:%d\n", orginput, deviceId, buttonId);
vrinputemulator::DigitalInputRemapping* m_currentRemapping =new vrinputemulator::DigitalInputRemapping(true);
vrinputemulator::DigitalBinding* m_currentBinding = new vrinputemulator::DigitalBinding;
if (orginput == false) {
m_currentBinding->type = vrinputemulator::DigitalBindingType::Disabled;
memset(&m_currentBinding->data, 0, sizeof(m_currentBinding->data));
m_currentBinding->data.openvr.buttonId = buttonId;
m_currentBinding->toggleEnabled = false;
m_currentBinding->toggleDelay = 0;
m_currentBinding->autoTriggerEnabled = false;
m_currentBinding->autoTriggerFrequency = 1;
m_currentRemapping->binding = *m_currentBinding;
}
else if (orginput == true) {
m_currentBinding->type = vrinputemulator::DigitalBindingType::NoRemapping;
memset(&m_currentBinding->data, 0, sizeof(m_currentBinding->data));
m_currentBinding->data.openvr.buttonId = buttonId;
m_currentBinding->toggleEnabled = false;
m_currentBinding->toggleDelay = 0;
m_currentBinding->autoTriggerEnabled = false;
m_currentBinding->autoTriggerFrequency = 1;
m_currentRemapping->binding = *m_currentBinding;
}
printf(" void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:%d device:%d buttonId:%d remapping.data.openvr.buttonId%d\n", m_currentRemapping->binding.type, deviceId, buttonId, m_currentRemapping->binding.data.openvr.buttonId);
//<--------------------Here is the function call-------------------------------------->
this->inputEmulator->setDigitalInputRemapping(deviceId, buttonId, m_currentRemapping);
//<--------------------Here is the function call-------------------------------------->
printf(" void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:%d device:%d buttonId:%d remapping.data.openvr.buttonId%d\n", m_currentRemapping->binding.type, deviceId, buttonId, m_currentRemapping->binding.data.openvr.buttonId);
delete m_currentBinding;
delete m_currentRemapping;
Sleep(1);
}
This is the Function:
void VRInputEmulator::setDigitalInputRemapping(uint32_t deviceId, uint32_t buttonId, DigitalInputRemapping* remapping, bool modal) {
printf("VRInputEmulator::setDigitalInputRemapping Digital orginput: %d device:%d butonid:%d remapping->binding.data.openvr.buttonId%d\n", remapping->binding.type, deviceId, buttonId, remapping->binding.data.openvr.buttonId);
if (_ipcServerQueue) {
ipc::Request message(ipc::RequestType::InputRemapping_SetDigitalRemapping);
memset(&message.msg, 0, sizeof(message.msg));
message.msg.ir_SetDigitalRemapping.clientId = m_clientId;
message.msg.ir_SetDigitalRemapping.messageId = 0;
message.msg.ir_SetDigitalRemapping.controllerId = deviceId;
message.msg.ir_SetDigitalRemapping.buttonId = buttonId;
message.msg.ir_SetDigitalRemapping.remapData = *remapping;
if (modal) {
uint32_t messageId = _ipcRandomDist(_ipcRandomDevice);
message.msg.ir_SetDigitalRemapping.messageId = messageId;
std::promise<ipc::Reply> respPromise;
auto respFuture = respPromise.get_future();
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
_ipcPromiseMap.insert({ messageId, std::move(respPromise) });
}
_ipcServerQueue->send(&message, sizeof(ipc::Request), 0);
auto resp = respFuture.get();
{
std::lock_guard<std::recursive_mutex> lock(_mutex);
_ipcPromiseMap.erase(messageId);
}
std::stringstream ss;
ss << "Error while setting digital input remapping: ";
if (resp.status == ipc::ReplyStatus::InvalidId) {
ss << "Invalid device id";
throw vrinputemulator_invalidid(ss.str(), (int)resp.status);
} else if (resp.status == ipc::ReplyStatus::NotFound) {
ss << "Device not found";
throw vrinputemulator_notfound(ss.str(), (int)resp.status);
} else if (resp.status != ipc::ReplyStatus::Ok) {
ss << "Error code " << (int)resp.status;
throw vrinputemulator_exception(ss.str(), (int)resp.status);
}
} else {
_ipcServerQueue->send(&message, sizeof(ipc::Request), 0);
}
} else {
throw vrinputemulator_connectionerror("No active connection.");
}
}
You can See the Printf I had use before and after the function call, also used in the head of the dunction,This is the output:
void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type:0 device:1 buttonId:32 remapping.data.openvr.buttonId: 32
VRInputEmulator::setDigitalInputRemapping Digital orginput: 0 device:1 butonid:32 remapping->binding.data.openvr.buttonId: 0
void VRInputRemapping::DigitalInputConfig() m_currentRemapping->binding.type 0 device:1 buttonId:32 remapping.data.openvr.buttonId: 32
The output in the consloe
I'm trying to add Nvidia API into kodi for HDR switching.
I don't have much knowledge of code, I'm trying to adapt a project HDR Switcher into kodi functions.
When compiling the HDR Switcher into an exe with visual studio it works and triggers HDR.
Now I need to make it work with kodi for seamless HDR pasthrough playback.
This uses the NVidia private APIs.
Please help this will be valuable for many users if it gets implemented.
The error:
error C2664: 'NvAPI_St
atus NvAPI_GPU_GetConnectedDisplayIds(NvPhysicalGpuHandle,NV_GPU_DISPLAYIDS *,NvU32 *,NvU32)': cannot convert argument
1 from 'NvPhysicalGpuHandle [64]' to 'NvPhysicalGpuHandle'
#include "WinRenderer.h"
#include "RenderCapture.h"
#include "RenderFactory.h"
#include "RenderFlags.h"
#include "rendering/dx/RenderContext.h"
#include "settings/Settings.h"
#include "settings/SettingsComponent.h"
#include "utils/log.h"
#include "windows/RendererDXVA.h"
#include "windows/RendererSoftware.h"
#include "windows/RendererShaders.h"
#include "windowing/GraphicContext.h"
#include "windowing/WinSystem.h"
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "DeviceManager.h"
#include "nvapi.h"
#include "uhdDisplay.h"
struct render_details
{
using map = std::map<RenderMethod, int>;
using weights_fn = std::function<void(map&, const VideoPicture&)>;
using create_fn = std::function<CRendererBase*(CVideoSettings&)>;
RenderMethod method;
std::string name;
create_fn create;
weights_fn weights;
template<class T>
constexpr static render_details get(RenderMethod method, const std::string& name)
{
return { method, name, T::Create, T::GetWeight };
}
};
static std::vector<render_details> RenderMethodDetails =
{
render_details::get<CRendererSoftware>(RENDER_SW, "Software"),
render_details::get<CRendererShaders>(RENDER_PS, "Pixel Shaders"),
render_details::get<CRendererDXVA>(RENDER_DXVA, "DXVA"),
};
CBaseRenderer* CWinRenderer::Create(CVideoBuffer*)
{
return new CWinRenderer();
}
bool CWinRenderer::Register()
{
VIDEOPLAYER::CRendererFactory::RegisterRenderer("default", Create);
return true;
}
CWinRenderer::CWinRenderer()
{
m_format = AV_PIX_FMT_NONE;
PreInit();
}
CWinRenderer::~CWinRenderer()
{
CWinRenderer::UnInit();
}
CRendererBase* CWinRenderer::SelectRenderer(const VideoPicture& picture)
{
int iRequestedMethod = CServiceBroker::GetSettingsComponent()->GetSettings()->GetInt(CSettings::SETTING_VIDEOPLAYER_RENDERMETHOD);
CLog::LogF(LOGDEBUG, "requested render method: %d", iRequestedMethod);
std::map<RenderMethod, int> weights;
for (auto& details : RenderMethodDetails)
details.weights(weights, picture);
RenderMethod method;
switch (iRequestedMethod)
{
case RENDER_METHOD_SOFTWARE:
if (weights[RENDER_SW])
{
method = RENDER_SW;
break;
}
// fallback to PS
case RENDER_METHOD_D3D_PS:
if (weights[RENDER_PS])
{
method = RENDER_PS;
break;
}
//fallback to DXVA
case RENDER_METHOD_DXVA:
if (weights[RENDER_DXVA])
{
method = RENDER_DXVA;
break;
}
// fallback to AUTO
case RENDER_METHOD_AUTO:
default:
{
const auto it = std::max_element(weights.begin(), weights.end(),
[](auto& w1, auto& w2) { return w1.second < w2.second; });
if (it != weights.end())
{
method = it->first;
break;
}
// there is no elements in weights, so no renderer which supports incoming video buffer
CLog::LogF(LOGERROR, "unable to select render method for video buffer");
return nullptr;
}
}
const auto it = std::find_if(RenderMethodDetails.begin(), RenderMethodDetails.end(),
[method](render_details& d) { return d.method == method; });
if (it != RenderMethodDetails.end())
{
CLog::LogF(LOGDEBUG, "selected render method: {}", it->name);
return it->create(m_videoSettings);
}
// something goes really wrong
return nullptr;
}
CRect CWinRenderer::GetScreenRect() const
{
CRect screenRect(0.f, 0.f,
static_cast<float>(CServiceBroker::GetWinSystem()->GetGfxContext().GetWidth()),
static_cast<float>(CServiceBroker::GetWinSystem()->GetGfxContext().GetHeight()));
switch (CServiceBroker::GetWinSystem()->GetGfxContext().GetStereoMode())
{
case RENDER_STEREO_MODE_SPLIT_HORIZONTAL:
screenRect.y2 *= 2;
break;
case RENDER_STEREO_MODE_SPLIT_VERTICAL:
screenRect.x2 *= 2;
break;
default:
break;
}
return screenRect;
}
bool CWinRenderer::Configure(const VideoPicture &picture, float fps, unsigned int orientation)
{
m_sourceWidth = picture.iWidth;
m_sourceHeight = picture.iHeight;
m_renderOrientation = orientation;
m_fps = fps;
m_iFlags = GetFlagsChromaPosition(picture.chroma_position)
| GetFlagsColorMatrix(picture.color_space, picture.iWidth, picture.iHeight)
| GetFlagsColorPrimaries(picture.color_primaries)
| GetFlagsStereoMode(picture.stereoMode);
m_format = picture.videoBuffer->GetFormat();
// calculate the input frame aspect ratio
CalculateFrameAspectRatio(picture.iDisplayWidth, picture.iDisplayHeight);
SetViewMode(m_videoSettings.m_ViewMode);
// if (picture.hasDisplayMetadata || picture.hasLightMetadata) {
SetHdrMonitorMode(true);
// }
ManageRenderArea();
m_renderer.reset(SelectRenderer(picture));
if (!m_renderer || !m_renderer->Configure(picture, fps, orientation))
{
m_renderer.reset();
return false;
}
m_bConfigured = true;
return true;
}
static bool first = true;
void CWinRenderer::SetHdrMonitorMode(bool enableHDR)
{
if (first)
{
NvAPI_Initialize();
first = false;
}
NvAPI_Status nvStatus = NVAPI_OK;
NvDisplayHandle hNvDisplay = NULL;
// get first display handle which should work for all NVAPI calls for all GPUs
if ((nvStatus = NvAPI_EnumNvidiaDisplayHandle(0, &hNvDisplay)) != NVAPI_OK)
{
printf("NvAPI_EnumNvidiaDisplayHandle returned error code %d\r\n", nvStatus);
return;
}
NvU32 gpuCount = 0;
NvU32 maxDisplayIndex = 0;
NvPhysicalGpuHandle ahGPU[NVAPI_MAX_PHYSICAL_GPUS] = {};
// get the list of displays connected, populate the dynamic components
nvStatus = NvAPI_EnumPhysicalGPUs(ahGPU, &gpuCount);
if (NVAPI_OK != nvStatus)
{
printf("NvAPI_EnumPhysicalGPUs returned error code %d\r\n", nvStatus);
return;
}
for (NvU32 i = 0; i < gpuCount; ++i)
{
NvU32 displayIdCount = 16;
NvU32 flags = 0;
NV_GPU_DISPLAYIDS displayIdArray[16] = {};
displayIdArray[0].version = NV_GPU_DISPLAYIDS_VER;
nvStatus = NvAPI_GPU_GetConnectedDisplayIds(ahGPU, displayIdArray, &displayIdCount, flags);
if (NVAPI_OK == nvStatus)
{
printf("Display count %d\r\n", displayIdCount);
for (maxDisplayIndex = 0; maxDisplayIndex < displayIdCount; ++maxDisplayIndex)
{
printf("Display tested %d\r\n", maxDisplayIndex);
NV_HDR_CAPABILITIES hdrCapabilities = {};
hdrCapabilities.version = NV_HDR_CAPABILITIES_VER;
if (NVAPI_OK == NvAPI_Disp_GetHdrCapabilities(displayIdArray[maxDisplayIndex].displayId, &hdrCapabilities))
{
if (hdrCapabilities.isST2084EotfSupported)
{
printf("Display %d supports ST2084 EOTF\r\n", maxDisplayIndex);
NV_HDR_COLOR_DATA hdrColorData = {};
memset(&hdrColorData, 0, sizeof(hdrColorData));
hdrColorData.version = NV_HDR_COLOR_DATA_VER;
hdrColorData.cmd = NV_HDR_CMD_SET;
hdrColorData.static_metadata_descriptor_id = NV_STATIC_METADATA_TYPE_1;
hdrColorData.hdrMode = enableHDR ? NV_HDR_MODE_UHDBD : NV_HDR_MODE_OFF;
nvStatus = NvAPI_Disp_HdrColorControl(displayIdArray[maxDisplayIndex].displayId, &hdrColorData);
if (NVAPI_OK == nvStatus)
{
printf("NvAPI_Disp_SethdrColorData call has succeeded: ");
}
else
{
NvAPI_ShortString szDesc;
NvAPI_GetErrorMessage(nvStatus, szDesc);
printf("NvAPI_Disp_HdrColorControl returned %s (%x)\r\n", szDesc, nvStatus);
}
}
}
else
{
NvAPI_ShortString szDesc;
NvAPI_GetErrorMessage(nvStatus, szDesc);
printf("NvAPI_Disp_GetHdrCapabilities returned %s (%x)\r\n", szDesc, nvStatus);
}
}
}
else
{
NvAPI_ShortString szDesc;
NvAPI_GetErrorMessage(nvStatus, szDesc);
printf("NvAPI_GPU_GetConnectedDisplayIds returned %s (%x)\r\n", szDesc, nvStatus);
}
}
}
int CWinRenderer::NextBuffer() const
{
return m_renderer->NextBuffer();
}
void CWinRenderer::AddVideoPicture(const VideoPicture &picture, int index)
{
m_renderer->AddVideoPicture(picture, index);
}
void CWinRenderer::Update()
{
if (!m_bConfigured)
return;
ManageRenderArea();
m_renderer->ManageTextures();
}
void CWinRenderer::RenderUpdate(int index, int index2, bool clear, unsigned int flags, unsigned int alpha)
{
if (!m_bConfigured)
return;
if (clear)
CServiceBroker::GetWinSystem()->GetGfxContext().Clear(DX::Windowing()->UseLimitedColor() ? 0x101010 : 0);
DX::Windowing()->SetAlphaBlendEnable(alpha < 255);
ManageRenderArea();
m_renderer->Render(index, index2, DX::Windowing()->GetBackBuffer(),
m_sourceRect, m_destRect, GetScreenRect(), flags);
}
bool CWinRenderer::RenderCapture(CRenderCapture* capture)
{
if (!m_bConfigured)
return false;
capture->BeginRender();
if (capture->GetState() != CAPTURESTATE_FAILED)
{
const CRect destRect(0, 0, static_cast<float>(capture->GetWidth()), static_cast<float>(capture->GetHeight()));
m_renderer->Render(capture->GetTarget(), m_sourceRect, destRect, GetScreenRect());
capture->EndRender();
return true;
}
return false;
}
void CWinRenderer::SetBufferSize(int numBuffers)
{
if (!m_bConfigured)
return;
m_renderer->SetBufferSize(numBuffers);
}
void CWinRenderer::PreInit()
{
CSingleLock lock(CServiceBroker::GetWinSystem()->GetGfxContext());
m_bConfigured = false;
UnInit();
}
void CWinRenderer::UnInit()
{
CSingleLock lock(CServiceBroker::GetWinSystem()->GetGfxContext());
m_renderer.reset();
m_bConfigured = false;
}
bool CWinRenderer::Flush(bool saveBuffers)
{
if (!m_bConfigured)
return false;
return m_renderer->Flush(saveBuffers);
}
bool CWinRenderer::Supports(ERENDERFEATURE feature)
{
if(feature == RENDERFEATURE_BRIGHTNESS)
return true;
if(feature == RENDERFEATURE_CONTRAST)
return true;
if (feature == RENDERFEATURE_STRETCH ||
feature == RENDERFEATURE_NONLINSTRETCH ||
feature == RENDERFEATURE_ZOOM ||
feature == RENDERFEATURE_VERTICAL_SHIFT ||
feature == RENDERFEATURE_PIXEL_RATIO ||
feature == RENDERFEATURE_ROTATION ||
feature == RENDERFEATURE_POSTPROCESS ||
feature == RENDERFEATURE_TONEMAP)
return true;
return false;
}
bool CWinRenderer::Supports(ESCALINGMETHOD method)
{
if (!m_bConfigured)
return false;
return m_renderer->Supports(method);
}
bool CWinRenderer::WantsDoublePass()
{
if (!m_bConfigured)
return false;
return m_renderer->WantsDoublePass();
}
bool CWinRenderer::ConfigChanged(const VideoPicture& picture)
{
if (!m_bConfigured)
return true;
return picture.videoBuffer->GetFormat() != m_format;
}
CRenderInfo CWinRenderer::GetRenderInfo()
{
if (!m_bConfigured)
return {};
return m_renderer->GetRenderInfo();
}
void CWinRenderer::ReleaseBuffer(int idx)
{
if (!m_bConfigured)
return;
m_renderer->ReleaseBuffer(idx);
}
bool CWinRenderer::NeedBuffer(int idx)
{
if (!m_bConfigured)
return false;
return m_renderer->NeedBuffer(idx);
}
ยดยดยด
Change
nvStatus = NvAPI_GPU_GetConnectedDisplayIds(ahGPU, displayIdArray, &displayIdCount, flags);
to
nvStatus = NvAPI_GPU_GetConnectedDisplayIds(ahGPU[i], displayIdArray, &displayIdCount, flags);
Thanks to #1201ProgramAlarm
I need help with ODBC prepared queries. I working on Windows 10(x64). My VPS server is Windows Server 2012(x64). My compiled aplication is 32 bit. I need prepared queries to make SQL Injection not possible. But have one big problem.
Error:
[QueryManager] State (22001), Diagnostic: [Microsoft][ODBC SQL Server Driver]String data, right truncation
Code:
gQueryManager.BindParameterAsString(1,Name,sizeof(Name));
gQueryManager.ExecQuery("SELECT Value FROM Table WHERE Name=?");
gQueryManager.Fetch();
...
gQueryManager.Close();
This is source code of Query Manager I using:
// QueryManager.cpp: implementation of the CQueryManager class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "QueryManager.h"
#include "Util.h"
CQueryManager gQueryManager;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CQueryManager::CQueryManager() // OK
{
this->m_SQLEnvironment = SQL_NULL_HANDLE;
this->m_SQLConnection = SQL_NULL_HANDLE;
this->m_STMT = SQL_NULL_HANDLE;
this->m_RowCount = -1;
this->m_ColCount = -1;
memset(this->m_SQLColName,0,sizeof(this->m_SQLColName));
memset(this->m_SQLData,0,sizeof(this->m_SQLData));
SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&this->m_SQLEnvironment);
SQLSetEnvAttr(this->m_SQLEnvironment,SQL_ATTR_ODBC_VERSION,(SQLPOINTER)SQL_OV_ODBC3,SQL_IS_INTEGER);
}
CQueryManager::~CQueryManager() // OK
{
this->Disconnect();
}
bool CQueryManager::Connect(char* odbc,char* user,char* pass) // OK
{
strcpy_s(this->m_odbc,odbc);
strcpy_s(this->m_user,user);
strcpy_s(this->m_pass,pass);
if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_DBC,this->m_SQLEnvironment,&this->m_SQLConnection)) == 0)
{
return 0;
}
if(SQL_SUCCEEDED(SQLConnect(this->m_SQLConnection,(SQLCHAR*)this->m_odbc,SQL_NTS,(SQLCHAR*)this->m_user,SQL_NTS,(SQLCHAR*)this->m_pass,SQL_NTS)) == 0)
{
return 0;
}
if(SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_STMT,this->m_SQLConnection,&this->m_STMT)) == 0)
{
return 0;
}
else
{
return 1;
}
}
void CQueryManager::Disconnect() // OK
{
if(this->m_STMT != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_STMT,this->m_STMT);
this->m_STMT = SQL_NULL_HANDLE;
}
if(this->m_SQLConnection != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_DBC,this->m_SQLConnection);
this->m_SQLConnection = SQL_NULL_HANDLE;
}
if(this->m_SQLEnvironment != SQL_NULL_HANDLE)
{
SQLFreeHandle(SQL_HANDLE_ENV,this->m_SQLEnvironment);
this->m_SQLEnvironment = SQL_NULL_HANDLE;
}
}
void CQueryManager::Diagnostic(char* query) // OK
{
LogAdd(LOG_BLACK,"%s",query);
SQLINTEGER NativeError;
SQLSMALLINT RecNumber=1,BufferLength;
SQLCHAR SqlState[6],MessageText[SQL_MAX_MESSAGE_LENGTH];
while(SQLGetDiagRec(SQL_HANDLE_STMT,this->m_STMT,(RecNumber++),SqlState,&NativeError,MessageText,sizeof(MessageText),&BufferLength) != SQL_NO_DATA)
{
LogAdd(LOG_RED,"[QueryManager] State (%s), Diagnostic: %s",SqlState,MessageText);
}
if(strcmp((char*)SqlState,"08S01") == 0)
{
this->Connect(this->m_odbc,this->m_user,this->m_pass);
}
}
bool CQueryManager::ExecQuery(char* query,...) // OK
{
char buff[4096];
va_list arg;
va_start(arg,query);
vsprintf_s(buff,query,arg);
va_end(arg);
SQLRETURN result;
if(SQL_SUCCEEDED((result=SQLExecDirect(this->m_STMT,(SQLCHAR*)buff,SQL_NTS))) == 0 && result != SQL_NO_DATA)
{
this->Diagnostic(buff);
return 0;
}
SQLRowCount(this->m_STMT,&this->m_RowCount);
if(this->m_RowCount == 0){return 1;}
SQLNumResultCols(this->m_STMT,&this->m_ColCount);
if(this->m_ColCount == 0){return 1;}
if(this->m_ColCount > MAX_COLUMNS){return 0;}
memset(this->m_SQLColName,0,sizeof(this->m_SQLColName));
memset(this->m_SQLData,0,sizeof(this->m_SQLData));
for(int n=0;n < this->m_ColCount;n++)
{
SQLDescribeCol(this->m_STMT,(n+1),this->m_SQLColName[n],sizeof(this->m_SQLColName[n]),0,0,0,0,0);
SQLBindCol(this->m_STMT,(n+1),SQL_C_CHAR,this->m_SQLData[n],sizeof(this->m_SQLData[n]),&this->m_SQLDataLen[n]);
}
return 1;
}
void CQueryManager::Close() // OK
{
SQLCloseCursor(this->m_STMT);
SQLFreeStmt(this->m_STMT,SQL_UNBIND);
}
SQLRETURN CQueryManager::Fetch() // OK
{
return SQLFetch(this->m_STMT);
}
int CQueryManager::FindIndex(char* ColName) // OK
{
for(int n=0;n < this->m_ColCount;n++)
{
if(_stricmp(ColName,(char*)this->m_SQLColName[n]) == 0)
{
return n;
}
}
return -1;
}
int CQueryManager::GetResult(int index) // OK
{
return atoi(this->m_SQLData[index]);
}
int CQueryManager::GetAsInteger(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return index;
}
else
{
return atoi(this->m_SQLData[index]);
}
}
float CQueryManager::GetAsFloat(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return (float)index;
}
else
{
return (float)atof(this->m_SQLData[index]);
}
}
__int64 CQueryManager::GetAsInteger64(char* ColName) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
return index;
}
else
{
return _atoi64(this->m_SQLData[index]);
}
}
void CQueryManager::GetAsString(char* ColName,char* OutBuffer,int OutBufferSize) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
memset(OutBuffer,0,OutBufferSize);
}
else
{
strncpy_s(OutBuffer,OutBufferSize,this->m_SQLData[index],(OutBufferSize-1));
}
}
void CQueryManager::GetAsBinary(char* ColName,BYTE* OutBuffer,int OutBufferSize) // OK
{
int index = this->FindIndex(ColName);
if(index == -1)
{
memset(OutBuffer,0,OutBufferSize);
}
else
{
this->ConvertStringToBinary(this->m_SQLData[index],sizeof(this->m_SQLData[index]),OutBuffer,OutBufferSize);
}
}
void CQueryManager::BindParameterAsString(int ParamNumber,void* InBuffer,int ColumnSize) // OK
{
this->m_SQLBindValue[(ParamNumber-1)] = SQL_NTS;
SQLBindParameter(this->m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_CHAR,SQL_VARCHAR,ColumnSize,0,InBuffer,0,&this->m_SQLBindValue[(ParamNumber-1)]);
}
void CQueryManager::BindParameterAsBinary(int ParamNumber,void* InBuffer,int ColumnSize) // OK
{
this->m_SQLBindValue[(ParamNumber-1)] = ColumnSize;
SQLBindParameter(this->m_STMT,ParamNumber,SQL_PARAM_INPUT,SQL_C_BINARY,SQL_VARBINARY,ColumnSize,0,InBuffer,0,&this->m_SQLBindValue[(ParamNumber-1)]);
}
void CQueryManager::ConvertStringToBinary(char* InBuff,int InSize,BYTE* OutBuff,int OutSize) // OK
{
int size = 0;
memset(OutBuff,0,OutSize);
for(int n=0;n < InSize,size < OutSize;n++)
{
if(InBuff[n] == 0)
{
break;
}
if((n%2) == 0)
{
OutBuff[size] = ((InBuff[n]>='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'))*16;
size = size+0;
}
else
{
OutBuff[size] = OutBuff[size] | ((InBuff[n]>='A')?((InBuff[n]-'A')+10):(InBuff[n]-'0'));
size = size+1;
}
}
}
void CQueryManager::ConvertBinaryToString(BYTE* InBuff,int InSize,char* OutBuff,int OutSize) // OK
{
int size = 0;
memset(OutBuff,0,OutSize);
for(int n=0;n < OutSize,size < InSize;n++)
{
if((n%2) == 0)
{
OutBuff[n] = (((InBuff[size]/16)>=10)?('A'+((InBuff[size]/16)-10)):('0'+(InBuff[size]/16)));
size = size+0;
}
else
{
OutBuff[n] = (((InBuff[size]%16)>=10)?('A'+((InBuff[size]%16)-10)):('0'+(InBuff[size]%16)));
size = size+1;
}
}
}
I am searching how to open archive from memory buffer using minizip.
I found ioapi_mem_c.zip from their page http://www.winimage.com/zLibDll/minizip.html.
I can't understand how to use it. Can some one give me an example?
I solved my problem for unziping:
I added this function to unzip.c
extern unzFile ZEXPORT unzOpenBuffer (const void* buffer, uLong size)
{
char path[16] = {0};
zlib_filefunc64_32_def memory_file;
uLong base = (uLong)buffer;
sprintf(path, "%x+%x", base, size);
fill_memory_filefunc64_32(&memory_file);
return unzOpenInternal(path, &memory_file, 0);
}
And made some changes in ioapi_mem.c:
void fill_memory_filefunc64_32 (pzlib_filefunc_def)
zlib_filefunc64_32_def* pzlib_filefunc_def;
{
pzlib_filefunc_def->zopen32_file = fopen_mem_func;
pzlib_filefunc_def->zfile_func64.zopen64_file = fopen_mem_func;
pzlib_filefunc_def->zfile_func64.zread_file = fread_mem_func;
pzlib_filefunc_def->zfile_func64.zwrite_file = fwrite_mem_func;
pzlib_filefunc_def->ztell32_file = ftell_mem_func;
pzlib_filefunc_def->zseek32_file = fseek_mem_func;
pzlib_filefunc_def->zfile_func64.zseek64_file = NULL;
pzlib_filefunc_def->zfile_func64.zclose_file = fclose_mem_func;
pzlib_filefunc_def->zfile_func64.zerror_file = ferror_mem_func;
pzlib_filefunc_def->zfile_func64.opaque = NULL;
}
I hope this will help someone who will have the same problem.
And Here is simple class implementation how to use it:
void ZipArchiveImpl::OpenArchive()
{
ASSERT(!mInited, "Already opened.");
if ((mFileMode == FM_READ))
{
if (mArchiveName.size() == 0)
{
u32 sz = mFile->GetFileSize();
mUnzBlock.Resize(sz);
mFile->SetPosition(0);
mFile->Read(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes());
mUnzHandle = unzOpenBuffer(mUnzBlock.Data(), mUnzBlock.GetSizeInBytes());
}
else
{
mUnzHandle = unzOpen(mArchiveName.c_str());
}
if (!mUnzHandle) return;
FillMap();
}
else if (mFileMode == FM_WRITE)
{
ASSERT0(mArchiveName.size());
mZipHandle = zipOpen(mArchiveName.c_str(), 0);
if (!mZipHandle) return;
}
mInited = true;
}
IFile* ZipArchiveImpl::OpenRead(const std::string& name)
{
if (IsExist(name))
{
ZipFileInfo info = mFileMap.find(name)->second;
MemoryBlock block(1);
block.Resize(info.uncompressedSize);
int res = unzGoToFilePos(mUnzHandle, &info.filePosInfo);
if (UNZ_OK != res)
{
return false;
}
// open the current file with optional password
if (mArchivePassword != "")
{
res = unzOpenCurrentFilePassword(info.zipFileHandle, mArchivePassword.c_str());
}
else
{
res = unzOpenCurrentFile(info.zipFileHandle);
}
if (UNZ_OK != res)
{
return false;
}
// read uncompressed data
int readResult = unzReadCurrentFile(info.zipFileHandle, block.Data(), info.uncompressedSize);
// close the file
res = unzCloseCurrentFile(info.zipFileHandle);
if (UNZ_OK != res)
{
return false;
}
if (info.uncompressedSize == readResult)
{
return ROBE_NEW MemoryFile(block.Data(), info.uncompressedSize);
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}
IFile* ZipArchiveImpl::OpenRead(u32 id)
{
ASSERT0(mFileNames.size() > id);
if (IsExist(mFileNames[id]))
{
return OpenRead(mFileNames[id]);
}
else
{
return NULL;
}
}
void ZipArchiveImpl::FillMap()
{
s32 walkRes = unzGoToFirstFile(mUnzHandle);
unz_file_info info;
while (UNZ_OK == walkRes)
{
// get info about current file
char currentFileName[512];
s32 fileInfoRes = unzGetCurrentFileInfo(mUnzHandle, &info, currentFileName, sizeof(currentFileName), 0, 0, 0, 0);
std::string name = std::string(currentFileName);
mFileNames.push_back(name);
InitInfo(name, &info);
walkRes = unzGoToNextFile(mUnzHandle);
}
OpenRead(0);
if (UNZ_END_OF_LIST_OF_FILE != walkRes)
{
}
}
void ZipArchiveImpl::InitInfo(const std::string& name, unz_file_info* info)
{
ZipFileInfo zfi;
mFileMap.insert(std::pair<std::string, ZipFileInfo>(name, zfi));
mFileMap[name].zipFileHandle = mUnzHandle;
int res = unzGetFilePos(mFileMap[name].zipFileHandle, &mFileMap[name].filePosInfo);
mFileMap[name].uncompressedSize = info->uncompressed_size;
char lastsymbol = name[name.size() - 1];
if (lastsymbol == '/' || lastsymbol == '\\')
{
mFileMap[name].type = ZFT_DIR;
}
else
{
mFileMap[name].type = ZFT_FILE;
}
}
ZipArchiveImpl::~ZipArchiveImpl()
{
if (mInited)
{
if (mUnzHandle) unzClose(mUnzHandle);
if (mZipHandle) zipClose(mZipHandle, 0);
}
}
bool ZipArchiveImpl::IsExist(const std::string& name)
{
return (mFileMap.find(name) != mFileMap.end());
}
void ZipArchiveImpl::SaveFileToZip(const std::string& path, IFile* file)
{
const u32 DefaultFileAttribute = 32;
MemoryBlock block(1);
block.Resize(file->GetFileSize());
file->Read(block.Data(), block.GetSizeInBytes());
zip_fileinfo zinfo;
memset(&zinfo, 0, sizeof(zinfo));
zinfo.internal_fa = 0;
zinfo.external_fa = DefaultFileAttribute;
::boost::posix_time::ptime pt = ::boost::posix_time::from_time_t(time(0));
std::tm ptm = ::boost::posix_time::to_tm(pt);
zinfo.dosDate = 0;
zinfo.tmz_date.tm_year = ptm.tm_year;
zinfo.tmz_date.tm_mon = ptm.tm_mon;
zinfo.tmz_date.tm_mday = ptm.tm_mday;
zinfo.tmz_date.tm_hour = ptm.tm_hour;
zinfo.tmz_date.tm_min = ptm.tm_min;
zinfo.tmz_date.tm_sec = ptm.tm_sec;
zipOpenNewFileInZip(mZipHandle, path.c_str(), &zinfo, 0, 0, 0, 0, 0, Z_DEFLATED, Z_BEST_SPEED);
zipWriteInFileInZip(mZipHandle, block.Data(), block.GetSizeInBytes());
zipCloseFileInZip(mZipHandle);
}
unsigned long ZipArchiveImpl::GetFileAttributes(const std::string& filePath)
{
unsigned long attrib = 0;
#ifdef WIN32
attrib = ::GetFileAttributes(filePath.c_str());
#else
struct stat path_stat;
if (::stat(filePath.c_str(), &path_stat) == 0)
{
attrib = path_stat.st_mode;
}
#endif
return attrib;
}
added this function to unzip.c
extern unzFile ZEXPORT unzOpenBuffer(const void* buffer, uLong size)
{
zlib_filefunc_def filefunc32 = { 0 };
ourmemory_t *punzmem = (ourmemory_t*)malloc(sizeof(ourmemory_t));
punzmem->size = size;
punzmem->base = (char *)malloc(punzmem->size);
memcpy(punzmem->base, buffer, punzmem->size);
punzmem->grow = 0;
punzmem->cur_offset = 0;
punzmem->limit = 0;
fill_memory_filefunc(&filefunc32, punzmem);
return unzOpen2(NULL, &filefunc32);
}
Looking at the code in the link, there is no obvious way to pass a memory buffer. Save your memory buffer as a file, unzip it.
Or you could implement your own zlib_filefunc_def variant that operates on a lump of memory instead of a file. I don't think that is very hard to do.
Checkout the nmoinvaz fork of minizip: To unzip from a zip file in memory use fill_memory_filefunc and supply a proper ourmemory_t structure
zlib_filefunc_def filefunc32 = {0};
ourmemory_t unzmem = {0};
unzmem.size = bufsize;
unzmem.base = (char *)malloc(unzmem.size);
memcpy(unzmem.base, buffer, unzmem.size);
fill_memory_filefunc(&filefunc32, &unzmem);
unzOpen2("__notused__", &filefunc32);
Should I create two CFile objects and copy one into the other character by character? Or is there something in the library that will do this for me?
I would just use the CopyFile Win32 API function, but the example code in the CFile::Open documentation shows how to copy files with CFile (using pretty much the method you suggest).
It depends on what you want to do. There are a number of ways to copy files:
CopyFile()
CopyFileEx()
SHFileOperation()
IFileOperation (replaces SHFileOperation() in Vista)
While I appreciate the previous answers, I have found that this FileOperations is a nice wrapper that mimics the way copy operations are performed in Windows Explorer, which also includes Copy, Move and Delete files and rename directories:
http://www.ucancode.net/Visual_C_Source_Code/Copy-Move-Delete-files-rename-directories-SHFileOperation-CFileFind-FindFirstFile-FindNextFile-mfc-example.htm
#include "stdafx.h"
#include "FileOperations.h"
//
// this code copy 'c:\source' directory and
// all it's subdirectories and files
// to the 'c:\dest' directory.
//
CFileOperation fo; // create object
fo.SetOverwriteMode(false); // reset OverwriteMode flag (optional)
if (!fo.Copy("c:\\source", "c:\\dest")) // do Copy
{
fo.ShowError(); // if copy fails show error message
}
//
// this code delete 'c:\source' directory and
// all it's subdirectories and files.
//
fo.Setucancode.netIfReadOnly(); // set ucancode.netIfReadonly flag (optional)
if (!fo.Delete("c:\\source")) // do Copy
{
fo.ShowError(); // if copy fails show error message
}
Here is the source code for completeness:
#include "resource.h"
#define PATH_ERROR -1
#define PATH_NOT_FOUND 0
#define PATH_IS_FILE 1
#define PATH_IS_FOLDER 2
class CFExeption
{
public:
CFExeption(DWORD dwErrCode);
CFExeption(CString sErrText);
CString GetErrorText() {return m_sError;}
DWORD GetErrorCode() {return m_dwError;}
private:
CString m_sError;
DWORD m_dwError;
};
//*****************************************************************************************************
class CFileOperation
{
public:
CFileOperation(); // constructor
bool Delete(CString sPathName); // delete file or folder
bool Copy(CString sSource, CString sDest); // copy file or folder
bool Replace(CString sSource, CString sDest); // move file or folder
bool Rename(CString sSource, CString sDest); // rename file or folder
CString GetErrorString() {return m_sError;} // return error description
DWORD GetErrorCode() {return m_dwError;} // return error code
void ShowError() // show error message
{MessageBox(NULL, m_sError, _T("Error"), MB_OK | MB_ICONERROR);}
void SetAskIfReadOnly(bool bAsk = true) // sets behavior with readonly files(folders)
{m_bAskIfReadOnly = bAsk;}
bool IsAskIfReadOnly() // return current behavior with readonly files(folders)
{return m_bAskIfReadOnly;}
bool CanDelete(CString sPathName); // check attributes
void SetOverwriteMode(bool bOverwrite = false) // sets overwrite mode on/off
{m_bOverwriteMode = bOverwrite;}
bool IsOverwriteMode() {return m_bOverwriteMode;} // return current overwrite mode
int CheckPath(CString sPath);
bool IsAborted() {return m_bAborted;}
protected:
void DoDelete(CString sPathName);
void DoCopy(CString sSource, CString sDest, bool bDelteAfterCopy = false);
void DoFileCopy(CString sSourceFile, CString sDestFile, bool bDelteAfterCopy = false);
void DoFolderCopy(CString sSourceFolder, CString sDestFolder, bool bDelteAfterCopy = false);
void DoRename(CString sSource, CString sDest);
bool IsFileExist(CString sPathName);
void PreparePath(CString &sPath);
void Initialize();
void CheckSelfRecursion(CString sSource, CString sDest);
bool CheckSelfCopy(CString sSource, CString sDest);
CString ChangeFileName(CString sFileName);
CString ParseFolderName(CString sPathName);
private:
CString m_sError;
DWORD m_dwError;
bool m_bAskIfReadOnly;
bool m_bOverwriteMode;
bool m_bAborted;
int m_iRecursionLimit;
};
//*****************************************************************************************************
C++ file:
#include "stdafx.h"
#include "resource.h"
#include "FileOperations.h"
//************************************************************************************************************
CFExeption::CFExeption(DWORD dwErrCode)
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
m_sError = (LPTSTR)lpMsgBuf;
LocalFree(lpMsgBuf);
m_dwError = dwErrCode;
}
CFExeption::CFExeption(CString sErrText)
{
m_sError = sErrText;
m_dwError = 0;
}
//************************************************************************************************************
CFileOperation::CFileOperation()
{
Initialize();
}
void CFileOperation::Initialize()
{
m_sError = _T("No error");
m_dwError = 0;
m_bAskIfReadOnly = true;
m_bOverwriteMode = false;
m_bAborted = false;
m_iRecursionLimit = -1;
}
void CFileOperation::DoDelete(CString sPathName)
{
CFileFind ff;
CString sPath = sPathName;
if (CheckPath(sPath) == PATH_IS_FILE)
{
if (!CanDelete(sPath))
{
m_bAborted = true;
return;
}
if (!DeleteFile(sPath)) throw new CFExeption(GetLastError());
return;
}
PreparePath(sPath);
sPath += "*.*";
BOOL bRes = ff.FindFile(sPath);
while(bRes)
{
bRes = ff.FindNextFile();
if (ff.IsDots()) continue;
if (ff.IsDirectory())
{
sPath = ff.GetFilePath();
DoDelete(sPath);
}
else DoDelete(ff.GetFilePath());
}
ff.Close();
if (!RemoveDirectory(sPathName) && !m_bAborted) throw new CFExeption(GetLastError());
}
void CFileOperation::DoFolderCopy(CString sSourceFolder, CString sDestFolder, bool bDelteAfterCopy)
{
CFileFind ff;
CString sPathSource = sSourceFolder;
BOOL bRes = ff.FindFile(sPathSource);
while (bRes)
{
bRes = ff.FindNextFile();
if (ff.IsDots()) continue;
if (ff.IsDirectory()) // source is a folder
{
if (m_iRecursionLimit == 0) continue;
sPathSource = ff.GetFilePath() + CString("\\") + CString("*.*");
CString sPathDest = sDestFolder + ff.GetFileName() + CString("\\");
if (CheckPath(sPathDest) == PATH_NOT_FOUND)
{
if (!CreateDirectory(sPathDest, NULL))
{
ff.Close();
throw new CFExeption(GetLastError());
}
}
if (m_iRecursionLimit > 0) m_iRecursionLimit --;
DoFolderCopy(sPathSource, sPathDest, bDelteAfterCopy);
}
else // source is a file
{
CString sNewFileName = sDestFolder + ff.GetFileName();
DoFileCopy(ff.GetFilePath(), sNewFileName, bDelteAfterCopy);
}
}
ff.Close();
}
bool CFileOperation::Delete(CString sPathName)
{
try
{
DoDelete(sPathName);
}
catch(CFExeption* e)
{
m_sError = e->GetErrorText();
m_dwError = e->GetErrorCode();
delete e;
if (m_dwError == 0) return true;
return false;
}
return true;
}
bool CFileOperation::Rename(CString sSource, CString sDest)
{
try
{
DoRename(sSource, sDest);
}
catch(CFExeption* e)
{
m_sError = e->GetErrorText();
m_dwError = e->GetErrorCode();
delete e;
return false;
}
return true;
}
void CFileOperation::DoRename(CString sSource, CString sDest)
{
if (!MoveFile(sSource, sDest)) throw new CFExeption(GetLastError());
}
void CFileOperation::DoCopy(CString sSource, CString sDest, bool bDelteAfterCopy)
{
CheckSelfRecursion(sSource, sDest);
// source not found
if (CheckPath(sSource) == PATH_NOT_FOUND)
{
CString sError = sSource + CString(" not found");
throw new CFExeption(sError);
}
// dest not found
if (CheckPath(sDest) == PATH_NOT_FOUND)
{
CString sError = sDest + CString(" not found");
throw new CFExeption(sError);
}
// folder to file
if (CheckPath(sSource) == PATH_IS_FOLDER && CheckPath(sDest) == PATH_IS_FILE)
{
throw new CFExeption("Wrong operation");
}
// folder to folder
if (CheckPath(sSource) == PATH_IS_FOLDER && CheckPath(sDest) == PATH_IS_FOLDER)
{
CFileFind ff;
CString sError = sSource + CString(" not found");
PreparePath(sSource);
PreparePath(sDest);
sSource += "*.*";
if (!ff.FindFile(sSource))
{
ff.Close();
throw new CFExeption(sError);
}
if (!ff.FindNextFile())
{
ff.Close();
throw new CFExeption(sError);
}
CString sFolderName = ParseFolderName(sSource);
if (!sFolderName.IsEmpty()) // the source is not drive
{
sDest += sFolderName;
PreparePath(sDest);
if (!CreateDirectory(sDest, NULL))
{
DWORD dwErr = GetLastError();
if (dwErr != 183)
{
ff.Close();
throw new CFExeption(dwErr);
}
}
}
ff.Close();
DoFolderCopy(sSource, sDest, bDelteAfterCopy);
}
// file to file
if (CheckPath(sSource) == PATH_IS_FILE && CheckPath(sDest) == PATH_IS_FILE)
{
DoFileCopy(sSource, sDest);
}
// file to folder
if (CheckPath(sSource) == PATH_IS_FILE && CheckPath(sDest) == PATH_IS_FOLDER)
{
PreparePath(sDest);
char drive[MAX_PATH], dir[MAX_PATH], name[MAX_PATH], ext[MAX_PATH];
_splitpath(sSource, drive, dir, name, ext);
sDest = sDest + CString(name) + CString(ext);
DoFileCopy(sSource, sDest);
}
}
void CFileOperation::DoFileCopy(CString sSourceFile, CString sDestFile, bool bDelteAfterCopy)
{
BOOL bOvrwriteFails = FALSE;
if (!m_bOverwriteMode)
{
while (IsFileExist(sDestFile))
{
sDestFile = ChangeFileName(sDestFile);
}
bOvrwriteFails = TRUE;
}
if (!CopyFile(sSourceFile, sDestFile, bOvrwriteFails)) throw new CFExeption(GetLastError());
if (bDelteAfterCopy)
{
DoDelete(sSourceFile);
}
}
bool CFileOperation::Copy(CString sSource, CString sDest)
{
if (CheckSelfCopy(sSource, sDest)) return true;
bool bRes;
try
{
DoCopy(sSource, sDest);
bRes = true;
}
catch(CFExeption* e)
{
m_sError = e->GetErrorText();
m_dwError = e->GetErrorCode();
delete e;
if (m_dwError == 0) bRes = true;
bRes = false;
}
m_iRecursionLimit = -1;
return bRes;
}
bool CFileOperation::Replace(CString sSource, CString sDest)
{
if (CheckSelfCopy(sSource, sDest)) return true;
bool bRes;
try
{
bool b = m_bAskIfReadOnly;
m_bAskIfReadOnly = false;
DoCopy(sSource, sDest, true);
DoDelete(sSource);
m_bAskIfReadOnly = b;
bRes = true;
}
catch(CFExeption* e)
{
m_sError = e->GetErrorText();
m_dwError = e->GetErrorCode();
delete e;
if (m_dwError == 0) bRes = true;
bRes = false;
}
m_iRecursionLimit = -1;
return bRes;
}
CString CFileOperation::ChangeFileName(CString sFileName)
{
CString sName, sNewName, sResult;
char drive[MAX_PATH];
char dir [MAX_PATH];
char name [MAX_PATH];
char ext [MAX_PATH];
_splitpath((LPCTSTR)sFileName, drive, dir, name, ext);
sName = name;
int pos = sName.Find("Copy ");
if (pos == -1)
{
sNewName = CString("Copy of ") + sName + CString(ext);
}
else
{
int pos1 = sName.Find('(');
if (pos1 == -1)
{
sNewName = sName;
sNewName.Delete(0, 8);
sNewName = CString("Copy (1) of ") + sNewName + CString(ext);
}
else
{
CString sCount;
int pos2 = sName.Find(')');
if (pos2 == -1)
{
sNewName = CString("Copy of ") + sNewName + CString(ext);
}
else
{
sCount = sName.Mid(pos1 + 1, pos2 - pos1 - 1);
sName.Delete(0, pos2 + 5);
int iCount = atoi((LPCTSTR)sCount);
iCount ++;
sNewName.Format("%s%d%s%s%s", "Copy (", iCount, ") of ", (LPCTSTR)sName, ext);
}
}
}
sResult = CString(drive) + CString(dir) + sNewName;
return sResult;
}
bool CFileOperation::IsFileExist(CString sPathName)
{
HANDLE hFile;
hFile = CreateFile(sPathName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return false;
CloseHandle(hFile);
return true;
}
int CFileOperation::CheckPath(CString sPath)
{
DWORD dwAttr = GetFileAttributes(sPath);
if (dwAttr == 0xffffffff)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND)
return PATH_NOT_FOUND;
return PATH_ERROR;
}
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) return PATH_IS_FOLDER;
return PATH_IS_FILE;
}
void CFileOperation::PreparePath(CString &sPath)
{
if(sPath.Right(1) != "\\") sPath += "\\";
}
bool CFileOperation::CanDelete(CString sPathName)
{
DWORD dwAttr = GetFileAttributes(sPathName);
if (dwAttr == -1) return false;
if (dwAttr & FILE_ATTRIBUTE_READONLY)
{
if (m_bAskIfReadOnly)
{
CString sTmp = sPathName;
int pos = sTmp.ReverseFind('\\');
if (pos != -1) sTmp.Delete(0, pos + 1);
CString sText = sTmp + CString(" is read olny. Do you want delete it?");
int iRes = MessageBox(NULL, sText, _T("Warning"), MB_YESNOCANCEL | MB_ICONQUESTION);
switch (iRes)
{
case IDYES:
{
if (!SetFileAttributes(sPathName, FILE_ATTRIBUTE_NORMAL)) return false;
return true;
}
case IDNO:
{
return false;
}
case IDCANCEL:
{
m_bAborted = true;
throw new CFExeption(0);
return false;
}
}
}
else
{
if (!SetFileAttributes(sPathName, FILE_ATTRIBUTE_NORMAL)) return false;
return true;
}
}
return true;
}
CString CFileOperation::ParseFolderName(CString sPathName)
{
CString sFolderName = sPathName;
int pos = sFolderName.ReverseFind('\\');
if (pos != -1) sFolderName.Delete(pos, sFolderName.GetLength() - pos);
pos = sFolderName.ReverseFind('\\');
if (pos != -1) sFolderName = sFolderName.Right(sFolderName.GetLength() - pos - 1);
else sFolderName.Empty();
return sFolderName;
}
void CFileOperation::CheckSelfRecursion(CString sSource, CString sDest)
{
if (sDest.Find(sSource) != -1)
{
int i = 0, count1 = 0, count2 = 0;
for(i = 0; i < sSource.GetLength(); i ++) if (sSource[i] == '\\') count1 ++;
for(i = 0; i < sDest.GetLength(); i ++) if (sDest[i] == '\\') count2 ++;
if (count2 >= count1) m_iRecursionLimit = count2 - count1;
}
}
bool CFileOperation::CheckSelfCopy(CString sSource, CString sDest)
{
bool bRes = false;
if (CheckPath(sSource) == PATH_IS_FOLDER)
{
CString sTmp = sSource;
int pos = sTmp.ReverseFind('\\');
if (pos != -1)
{
sTmp.Delete(pos, sTmp.GetLength() - pos);
if (sTmp.CompareNoCase(sDest) == 0) bRes = true;
}
}
return bRes;
}
The Copy option in your code requires the dest file or folder to first exist otherwise this
if (CheckPath(sDest) == PATH_NOT_FOUND)
will always cause an error.