123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880 |
- //---------------------------------------------------------------------------
- #pragma hdrstop
- //---------------------------------------------------------------------------
- #ifndef STRICT
- #define STRICT
- #endif
- //---------------------------------------------------------------------------
- #define LENOF(x) ( (sizeof((x))) / (sizeof(*(x))))
- //---------------------------------------------------------------------------
- #include <initguid.h>
- #include <shlguid.h>
- #include <stdlib.h>
- #include <stdio.h>
- #pragma warn -inl
- #include <shlobj.h>
- #pragma warn .inl
- #include <olectl.h>
- #include <time.h>
- #include "DragExt.h"
- //---------------------------------------------------------------------------
- #ifdef __BORLANDC__
- #undef STDAPI
- #define STDAPI EXTERN_C __declspec(dllexport) HRESULT STDAPICALLTYPE
- #endif
- //---------------------------------------------------------------------------
- #define Debug(MSG) \
- if (GLogOn) \
- { \
- DoDebug(__FUNC__, MSG); \
- }
- //---------------------------------------------------------------------------
- #define DRAG_EXT_REG_KEY L"Software\\Martin Prikryl\\WinSCP 2\\DragExt"
- #define DRAG_EXT_NAME L"WinSCP Shell Extension"
- #define THREADING_MODEL L"Apartment"
- #define CLSID_SIZE 39
- //---------------------------------------------------------------------------
- class CShellExtClassFactory : public IClassFactory
- {
- public:
- CShellExtClassFactory();
- virtual ~CShellExtClassFactory();
- // IUnknown members
- STDMETHODIMP QueryInterface(REFIID, LPVOID FAR*);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
- // IClassFactory members
- STDMETHODIMP CreateInstance(LPUNKNOWN, REFIID, LPVOID FAR*);
- STDMETHODIMP LockServer(BOOL);
- protected:
- unsigned long FReferenceCounter;
- };
- //---------------------------------------------------------------------------
- #ifdef _WIN64
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wpadded"
- #endif
- //---------------------------------------------------------------------------
- class CShellExt : public IShellExtInit, ICopyHook
- {
- public:
- CShellExt();
- virtual ~CShellExt();
- // IUnknown members
- STDMETHODIMP QueryInterface(REFIID, LPVOID FAR*);
- STDMETHODIMP_(ULONG) AddRef();
- STDMETHODIMP_(ULONG) Release();
- // IShellExtInit methods
- STDMETHODIMP Initialize(LPCITEMIDLIST pIDFolder, LPDATAOBJECT pDataObj, HKEY hKeyID);
- // ICopyHook method
- STDMETHODIMP_(UINT) CopyCallback(HWND Hwnd, UINT Func, UINT Flags,
- LPCWSTR SrcFile, DWORD SrcAttribs, LPCWSTR DestFile, DWORD DestAttribs);
- protected:
- unsigned long FReferenceCounter;
- LPDATAOBJECT FDataObj;
- HANDLE FMutex;
- unsigned long FLastTicks;
- };
- //---------------------------------------------------------------------------
- #ifdef WIN64
- #pragma clang diagnostic pop
- #endif
- //---------------------------------------------------------------------------
- unsigned int GRefThisDll = 0;
- bool GEnabled = false;
- wchar_t GLogFile[MAX_PATH] = L"";
- bool GLogOn = false;
- FILE* GLogHandle = NULL;
- HANDLE GLogMutex;
- HINSTANCE GInstance;
- //---------------------------------------------------------------------------
- static void DoDebug(const char* Func, const wchar_t* Message)
- {
- if (GLogOn)
- {
- unsigned long WaitResult = WaitForSingleObject(GLogMutex, 1000);
- if (WaitResult != WAIT_TIMEOUT)
- {
- try
- {
- if (GLogHandle == NULL)
- {
- if (wcslen(GLogFile) == 0)
- {
- GLogOn = false;
- }
- else
- {
- GLogHandle = _wfopen(GLogFile, L"at");
- if (GLogHandle == NULL)
- {
- GLogOn = false;
- }
- else
- {
- setbuf(GLogHandle, NULL);
- fwprintf(GLogHandle, L"----------------------------\n");
- }
- }
- }
- if (GLogOn)
- {
- SYSTEMTIME Time;
- GetSystemTime(&Time);
- // cannot use TEXT(__FUNC__) as that does not work in clang,
- // where __FUCT__ behaves like a static variable
- const size_t FuncLen = strlen(Func) + 1;
- wchar_t* WideFunc = new wchar_t[FuncLen];
- mbstowcs(WideFunc, Func, FuncLen);
- fwprintf(GLogHandle, L"[%2d/%2d/%4d %2d:%02d:%02d.%03d][%04x] [%s] %s\n",
- Time.wDay, Time.wMonth, Time.wYear, Time.wHour, Time.wMinute,
- Time.wSecond, Time.wMilliseconds, GetCurrentThreadId(), WideFunc, Message);
- delete[] WideFunc;
- }
- }
- catch(...)
- {
- }
- ReleaseMutex(GLogMutex);
- }
- }
- }
- //---------------------------------------------------------------------------
- static void LogVersion(HINSTANCE HInstance)
- {
- if (GLogOn)
- {
- wchar_t FileName[MAX_PATH];
- if (GetModuleFileName(HInstance, FileName, LENOF(FileName)) > 0)
- {
- Debug(FileName);
- unsigned long InfoHandle, Size;
- Size = GetFileVersionInfoSize(FileName, &InfoHandle);
- if (Size > 0)
- {
- void* Info;
- Info = new wchar_t[Size];
- if (GetFileVersionInfo(FileName, InfoHandle, Size, Info) != 0)
- {
- VS_FIXEDFILEINFO* VersionInfo;
- unsigned int VersionInfoSize;
- if (VerQueryValue(Info, L"\\", reinterpret_cast<void**>(&VersionInfo),
- &VersionInfoSize) != 0)
- {
- wchar_t VersionStr[100];
- snwprintf(VersionStr, LENOF(VersionStr), L"%d.%d.%d.%d",
- HIWORD(VersionInfo->dwFileVersionMS),
- LOWORD(VersionInfo->dwFileVersionMS),
- HIWORD(VersionInfo->dwFileVersionLS),
- LOWORD(VersionInfo->dwFileVersionLS));
- Debug(VersionStr);
- }
- else
- {
- Debug(L"no fixed version info");
- }
- }
- else
- {
- Debug(L"cannot read version info");
- }
- }
- else
- {
- Debug(L"no version info");
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- extern "C" int APIENTRY
- DllMain(HINSTANCE HInstance, DWORD Reason, LPVOID /*Reserved*/)
- {
- if (Reason == DLL_PROCESS_ATTACH)
- {
- GInstance = HInstance;
- if (GRefThisDll == 0)
- {
- GLogMutex = CreateMutex(NULL, false, DRAG_EXT_RUNNING_MUTEX);
- for (int Root = 0; Root <= 1; Root++)
- {
- HKEY Key;
- if (RegOpenKeyEx(Root == 0 ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
- DRAG_EXT_REG_KEY, 0,
- STANDARD_RIGHTS_READ | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
- &Key) == ERROR_SUCCESS)
- {
- unsigned long Type;
- unsigned long Value;
- unsigned long Size;
- wchar_t Buf[MAX_PATH];
- Size = sizeof(Value);
- if ((RegQueryValueEx(Key, L"Enable", NULL, &Type,
- reinterpret_cast<unsigned char*>(&Value), &Size) == ERROR_SUCCESS) &&
- (Type == REG_DWORD))
- {
- GEnabled = (Value != 0);
- }
- Size = sizeof(Buf);
- if ((RegQueryValueEx(Key, L"LogFile", NULL, &Type,
- reinterpret_cast<unsigned char*>(&Buf), &Size) == ERROR_SUCCESS) &&
- (Type == REG_SZ))
- {
- wcsncpy(GLogFile, Buf, LENOF(GLogFile));
- GLogFile[LENOF(GLogFile) - 1] = L'\0';
- GLogOn = true;
- }
- RegCloseKey(Key);
- }
- }
- if (GLogOn)
- {
- Debug(L"loaded settings");
- Debug(GEnabled ? L"enabled" : L"disabled");
- #ifdef UNICODE
- Debug(L"Unicode");
- #else
- Debug(L"Ansi");
- #endif
- #ifdef _WIN64
- Debug(L"Win64");
- #else
- Debug(L"Win32");
- #endif
- LogVersion(HInstance);
- TDragExtCommStruct CommStruct;
- const char * CommStructPtr = reinterpret_cast<const char *>(&CommStruct);
- wchar_t Buf[1024];
- swprintf(Buf, L"Comm struct layout - Size %d - Version @%d + %d - Dragging @%d + %d - DropDest @%d + %d",
- sizeof(CommStruct), reinterpret_cast<const char *>(&CommStruct.Version) - CommStructPtr, sizeof(CommStruct.Version),
- reinterpret_cast<const char *>(&CommStruct.Dragging) - CommStructPtr, sizeof(CommStruct.Dragging),
- reinterpret_cast<const char *>(&CommStruct.DropDest) - CommStructPtr, sizeof(CommStruct.DropDest));
- Debug(Buf);
- }
- }
- else
- {
- Debug(L"settings already loaded");
- }
- Debug(L"attach leave");
- }
- else if (Reason == DLL_PROCESS_DETACH)
- {
- Debug(L"detach enter");
- CloseHandle(GLogMutex);
- }
- return 1; // ok
- }
- //---------------------------------------------------------------------------
- STDAPI DllCanUnloadNow(void)
- {
- bool CanUnload = (GRefThisDll == 0);
- Debug(CanUnload ? L"can" : L"cannot");
- return (CanUnload ? S_OK : S_FALSE);
- }
- //---------------------------------------------------------------------------
- STDAPI DllGetClassObject(REFCLSID Rclsid, REFIID Riid, LPVOID* PpvOut)
- {
- Debug(L"enter");
- *PpvOut = NULL;
- if (IsEqualIID(Rclsid, CLSID_ShellExtension))
- {
- Debug(L"is ShellExtension");
- CShellExtClassFactory* Pcf = new CShellExtClassFactory;
- return Pcf->QueryInterface(Riid, PpvOut);
- }
- return CLASS_E_CLASSNOTAVAILABLE;
- }
- //---------------------------------------------------------------------------
- static bool RegisterServer(bool AllUsers)
- {
- Debug(L"enter");
- Debug(AllUsers ? L"all users" : L"current users");
- bool Result = false;
- HKEY RootKey = AllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- HKEY HKey;
- DWORD Unused;
- wchar_t ClassID[CLSID_SIZE];
- StringFromGUID2(CLSID_ShellExtension, ClassID, LENOF(ClassID));
- if ((RegOpenKeyEx(RootKey, L"Software\\Classes", 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS) &&
- (RegCreateKeyEx(HKey, L"CLSID", 0, NULL,
- REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &HKey, &Unused) ==
- ERROR_SUCCESS))
- {
- Debug(L"CLSID created");
- if (RegCreateKey(HKey, ClassID, &HKey) == ERROR_SUCCESS)
- {
- Debug(L"class ID created");
- RegSetValueEx(HKey, NULL, 0, REG_SZ,
- reinterpret_cast<const unsigned char*>(DRAG_EXT_NAME), sizeof(DRAG_EXT_NAME));
- if (RegCreateKey(HKey, L"InProcServer32", &HKey) == ERROR_SUCCESS)
- {
- Debug(L"InProcServer32 created");
- wchar_t Filename[MAX_PATH];
- GetModuleFileName(GInstance, Filename, LENOF(Filename));
- RegSetValueEx(HKey, NULL, 0, REG_SZ,
- reinterpret_cast<unsigned char*>(Filename), (wcslen(Filename) + 1) * sizeof(wchar_t));
- RegSetValueEx(HKey, L"ThreadingModel", 0, REG_SZ,
- reinterpret_cast<const unsigned char*>(THREADING_MODEL),
- sizeof(THREADING_MODEL));
- }
- }
- RegCloseKey(HKey);
- if ((RegOpenKeyEx(RootKey, L"Software\\Classes",
- 0, KEY_WRITE, &HKey) == ERROR_SUCCESS) &&
- (RegCreateKeyEx(HKey,
- L"directory\\shellex\\CopyHookHandlers\\WinSCPCopyHook",
- 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &HKey,
- &Unused) == ERROR_SUCCESS))
- {
- Debug(L"WinSCPCopyHook created");
- RegSetValueEx(HKey, NULL, 0, REG_SZ,
- reinterpret_cast<unsigned char*>(ClassID), (wcslen(ClassID) + 1) * sizeof(wchar_t));
- RegCloseKey(HKey);
- if ((RegCreateKeyEx(RootKey, DRAG_EXT_REG_KEY,
- 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &HKey,
- &Unused) == ERROR_SUCCESS))
- {
- Debug(L"drag ext key created");
- unsigned long Value = 1;
- RegSetValueEx(HKey, L"Enable", 0, REG_DWORD,
- reinterpret_cast<unsigned char*>(&Value), sizeof(Value));
- RegCloseKey(HKey);
- Result = true;
- }
- SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
- }
- }
- Debug(L"leave");
- return Result;
- }
- //---------------------------------------------------------------------------
- STDAPI DllRegisterServer()
- {
- Debug(L"enter");
- HRESULT Result;
- if (RegisterServer(true) || RegisterServer(false))
- {
- Result = S_OK;
- }
- else
- {
- Result = SELFREG_E_CLASS;
- }
- Debug(L"leave");
- return Result;
- }
- //---------------------------------------------------------------------------
- static bool UnregisterServer(bool AllUsers)
- {
- Debug(L"enter");
- Debug(AllUsers ? L"all users" : L"current users");
- bool Result = false;
- wchar_t ClassID[CLSID_SIZE];
- StringFromGUID2(CLSID_ShellExtension, ClassID, LENOF(ClassID));
- HKEY RootKey = AllUsers ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER;
- HKEY HKey;
- if ((RegOpenKeyEx(RootKey, L"Software\\Classes", 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS) &&
- (RegOpenKeyEx(HKey, L"directory\\shellex\\CopyHookHandlers",
- 0, KEY_WRITE, &HKey) == ERROR_SUCCESS))
- {
- RegDeleteKey(HKey, L"WinSCPCopyHook");
- RegCloseKey(HKey);
- }
- if ((RegOpenKeyEx(RootKey, L"Software\\Classes", 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS) &&
- (RegOpenKeyEx(HKey, L"CLSID", 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS))
- {
- if (RegOpenKeyEx(HKey, ClassID, 0, KEY_WRITE, &HKey) == ERROR_SUCCESS)
- {
- RegDeleteKey(HKey, L"InProcServer32");
- RegCloseKey(HKey);
- if ((RegOpenKeyEx(RootKey, L"Software\\Classes", 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS) &&
- (RegOpenKeyEx(HKey, L"CLSID", 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS))
- {
- RegDeleteKey(HKey, ClassID);
- RegCloseKey(HKey);
- Result = true;
- }
- }
- }
- if (RegOpenKeyEx(RootKey, DRAG_EXT_REG_KEY, 0, KEY_WRITE, &HKey) ==
- ERROR_SUCCESS)
- {
- // Previously we were setting the value explicitly to 0,
- // but doing that for both HKLM and HKCU.
- // While on register, we set it to 1 for HKLM only,
- // what makes the extension disabled effectively,
- // as KHCU value 0, is kept even after re-registration
- RegDeleteValue(HKey, L"Enable");
- RegCloseKey(HKey);
- Result = true;
- }
- SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
- Debug(L"leave");
- return Result;
- }
- //---------------------------------------------------------------------------
- STDAPI DllUnregisterServer()
- {
- Debug(L"enter");
- HRESULT Result = SELFREG_E_CLASS;
- if (UnregisterServer(true))
- {
- Result = S_OK;
- }
- if (UnregisterServer(false))
- {
- Result = S_OK;
- }
- Debug(L"leave");
- return Result;
- }
- //---------------------------------------------------------------------------
- CShellExtClassFactory::CShellExtClassFactory()
- {
- Debug(L"enter");
- FReferenceCounter = 0;
- GRefThisDll++;
- }
- //---------------------------------------------------------------------------
- CShellExtClassFactory::~CShellExtClassFactory()
- {
- Debug(L"enter");
- GRefThisDll--;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP CShellExtClassFactory::QueryInterface(REFIID Riid, LPVOID FAR* Ppv)
- {
- Debug(L"enter");
- *Ppv = NULL;
- // Any interface on this object is the object pointer
- if (IsEqualIID(Riid, IID_IUnknown) || IsEqualIID(Riid, IID_IClassFactory))
- {
- Debug(L"is IUnknown or IClassFactory");
- *Ppv = (LPCLASSFACTORY)this;
- AddRef();
- return NOERROR;
- }
- return E_NOINTERFACE;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CShellExtClassFactory::AddRef()
- {
- Debug(L"enter");
- return ++FReferenceCounter;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CShellExtClassFactory::Release()
- {
- Debug(L"enter");
- if (--FReferenceCounter)
- {
- return FReferenceCounter;
- }
- delete this;
- return 0;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP CShellExtClassFactory::CreateInstance(LPUNKNOWN UnkOuter,
- REFIID Riid, LPVOID* PpvObj)
- {
- Debug(L"enter");
- *PpvObj = NULL;
- // Shell extensions typically don't support aggregation (inheritance)
- if (UnkOuter)
- {
- return CLASS_E_NOAGGREGATION;
- }
- // Create the main shell extension object. The shell will then call
- // QueryInterface with IID_IShellExtInit--this is how shell extensions are
- // initialized.
- CShellExt* ShellExt = new CShellExt(); //Create the CShellExt object
- return ShellExt->QueryInterface(Riid, PpvObj);
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP CShellExtClassFactory::LockServer(BOOL /*Lock*/)
- {
- Debug(L"enter");
- return NOERROR;
- }
- //---------------------------------------------------------------------------
- // CShellExt
- CShellExt::CShellExt()
- {
- Debug(L"enter");
- FReferenceCounter = 0L;
- FDataObj = NULL;
- FMutex = CreateMutex(NULL, false, DRAG_EXT_MUTEX);
- FLastTicks = 0;
- GRefThisDll++;
- Debug(L"leave");
- }
- //---------------------------------------------------------------------------
- CShellExt::~CShellExt()
- {
- Debug(L"enter");
- if (FDataObj)
- {
- FDataObj->Release();
- }
- CloseHandle(FMutex);
- GRefThisDll--;
- Debug(L"leave");
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP CShellExt::QueryInterface(REFIID Riid, LPVOID FAR* Ppv)
- {
- Debug(L"enter");
- HRESULT Result = E_NOINTERFACE;
- *Ppv = NULL;
- if (!GEnabled)
- {
- Debug(L"shellext disabled");
- }
- else
- {
- if (IsEqualIID(Riid, IID_IShellExtInit) || IsEqualIID(Riid, IID_IUnknown))
- {
- Debug(L"is IShellExtInit or IUnknown");
- *Ppv = (LPSHELLEXTINIT)this;
- }
- else if (IsEqualIID(Riid, IID_IShellCopyHook))
- {
- Debug(L"is IShellCopyHook");
- *Ppv = (LPCOPYHOOK)this;
- }
- if (*Ppv)
- {
- AddRef();
- Result = NOERROR;
- }
- }
- Debug(L"leave");
- return Result;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CShellExt::AddRef()
- {
- Debug(L"enter");
- return ++FReferenceCounter;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CShellExt::Release()
- {
- Debug(L"enter");
- if (--FReferenceCounter)
- {
- return FReferenceCounter;
- }
- delete this;
- return 0;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST /*IDFolder*/,
- LPDATAOBJECT DataObj, HKEY /*RegKey*/)
- {
- Debug(L"enter");
- if (FDataObj != NULL)
- {
- FDataObj->Release();
- FDataObj = NULL;
- }
- // duplicate the object pointer and registry handle
- if (DataObj != NULL)
- {
- FDataObj = DataObj;
- DataObj->AddRef();
- }
- Debug(L"leave");
- return NOERROR;
- }
- //---------------------------------------------------------------------------
- STDMETHODIMP_(UINT) CShellExt::CopyCallback(HWND /*Hwnd*/, UINT Func, UINT /*Flags*/,
- LPCWSTR SrcFile, DWORD /*SrcAttribs*/, LPCWSTR DestFile, DWORD /*DestAttribs*/)
- {
- Debug(L"enter");
- UINT Result = IDYES;
- if (GEnabled && ((Func == FO_COPY) || (Func == FO_MOVE)))
- {
- Debug(L"copy or move");
- unsigned long Ticks = GetTickCount();
- if (((Ticks - FLastTicks) >= 100) ||
- (FLastTicks > Ticks))
- {
- Debug(L"interval elapsed");
- Debug(L"source / dest:");
- Debug(SrcFile);
- Debug(DestFile);
- FLastTicks = Ticks;
- const wchar_t* BackPtr = wcsrchr(SrcFile, L'\\');
- // WORKAROUND: Windows 10 1803 sends empty DestFile
- if (wcslen(DestFile) == 0)
- {
- Debug(L"empty dest file");
- }
- else if ((BackPtr != NULL) &&
- (wcsncmp(BackPtr + 1, DRAG_EXT_DUMMY_DIR_PREFIX,
- DRAG_EXT_DUMMY_DIR_PREFIX_LEN) == 0))
- {
- Debug(L"filename has prefix");
- HANDLE MapFile = OpenFileMapping(FILE_MAP_ALL_ACCESS,
- false, DRAG_EXT_MAPPING);
- if (MapFile != NULL)
- {
- Debug(L"mapfile found");
- TDragExtCommStruct* CommStruct;
- CommStruct = static_cast<TDragExtCommStruct*>(MapViewOfFile(MapFile,
- FILE_MAP_ALL_ACCESS, 0, 0, 0));
- if (CommStruct != NULL)
- {
- Debug(L"mapview created");
- unsigned long WaitResult = WaitForSingleObject(FMutex, 1000);
- if (WaitResult != WAIT_TIMEOUT)
- {
- Debug(L"mutex got");
- if (CommStruct->Version >= TDragExtCommStruct::MinVersion)
- {
- Debug(L"supported structure version");
- if (CommStruct->Dragging)
- {
- Debug(L"dragging");
- Debug(CommStruct->DropDest);
- bool IsDropDest;
- if (_wcsicmp(CommStruct->DropDest, SrcFile) == 0)
- {
- IsDropDest = true;
- Debug(L"dragged file match as is");
- }
- else
- {
- wchar_t DropDestShort[MAX_PATH];
- wchar_t SrcFileShort[MAX_PATH];
- size_t DropDestSize = GetShortPathName(CommStruct->DropDest,
- DropDestShort, LENOF(DropDestShort));
- size_t SrcFileSize = GetShortPathName(SrcFile,
- SrcFileShort, LENOF(SrcFileShort));
- if ((DropDestSize == 0) || (SrcFileSize == 0))
- {
- Debug(L"cannot convert paths to short form");
- IsDropDest = false;
- }
- else if ((DropDestSize >= LENOF(DropDestShort)) ||
- (SrcFileSize >= LENOF(SrcFileShort)))
- {
- Debug(L"short paths too long");
- IsDropDest = false;
- }
- else
- {
- Debug(DropDestShort);
- Debug(SrcFileShort);
- if (_wcsicmp(DropDestShort, SrcFileShort) == 0)
- {
- Debug(L"dragged file match after converted to short form");
- IsDropDest = true;
- }
- else
- {
- Debug(L"dragged file does NOT match");
- IsDropDest = false;
- }
- }
- }
- if (IsDropDest)
- {
- CommStruct->Dragging = false;
- wcsncpy(CommStruct->DropDest, DestFile, LENOF(CommStruct->DropDest));
- CommStruct->DropDest[LENOF(CommStruct->DropDest)-1] = L'\0';
- Result = IDNO;
- Debug(L"dragging refused");
- }
- }
- else
- {
- Debug(L"NOT dragging");
- }
- }
- else
- {
- Debug(L"unsupported structure version");
- }
- ReleaseMutex(FMutex);
- Debug(L"mutex released");
- }
- else
- {
- Debug(L"mutex timeout");
- }
- UnmapViewOfFile(CommStruct);
- }
- else
- {
- Debug(L"mapview NOT created");
- }
- CloseHandle(MapFile);
- }
- else
- {
- Debug(L"mapfile NOT found");
- }
- }
- else
- {
- Debug(L"filename has NOT prefix");
- }
- }
- else
- {
- Debug(L"interval NOT elapsed");
- }
- }
- else
- {
- if (GLogOn)
- {
- if (!GEnabled)
- {
- Debug(L"disabled");
- }
- else
- {
- wchar_t Buf[1024];
- swprintf(Buf, L"NOT copy nor move - %d", Func);
- Debug(Buf);
- }
- }
- }
- Debug(L"leave");
- return Result;
- }
|