| 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 effectivelly,
 
-     // 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;
 
- }
 
 
  |