📄 qdrive.cpp
字号:
//
// QDrive.cpp : Defines the DLL's Entry point and Self-registration code
#define INC_OLE2
#include <windows.h>
#include <initguid.h>
// #define _WIN32_IE as 0x0400 if you want ShellVersion 4.71 specific interfaces
// to be declared in shlobj.h
#include <shlobj.h>
#include <tchar.h>
#include <stdlib.h>
#include "QDrive.h"
#include "ShellFolder.h"
#include "resource.h"
#include "ContextMenu.h"
//
// Global variables
//
UINT g_uiRefThisDll = 0; // Reference count for this DLL
HINSTANCE g_hInstance; // Instance handle for this DLL
HIMAGELIST g_hImageListSmall = NULL;
HIMAGELIST g_hImageListLarge = NULL;
void createImageLists();
class CQDriveClassFactory : public IClassFactory
{
protected:
ULONG m_ulRef; // Object reference count
public:
CQDriveClassFactory();
~CQDriveClassFactory();
// IUnknown methods
STDMETHODIMP QueryInterface (REFIID, LPVOID FAR *);
STDMETHODIMP_(ULONG) AddRef ();
STDMETHODIMP_(ULONG) Release ();
// IClassFactory methods
STDMETHODIMP CreateInstance (LPUNKNOWN, REFIID, LPVOID FAR *);
STDMETHODIMP LockServer (BOOL);
};
extern "C" int APIENTRY DllMain (HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hInstance;
createImageLists();
}
return TRUE;
}
// Helper functions
// TODO : Modify to suit your needs
void createImageLists()
{
int nSmallCx = GetSystemMetrics(SM_CXSMICON);
int nSmallCy = GetSystemMetrics(SM_CYSMICON);
if(g_hImageListSmall)
{
ImageList_Destroy(g_hImageListSmall);
}
//set the small image list
g_hImageListSmall = ImageList_Create(nSmallCx, nSmallCy, ILC_COLORDDB | ILC_MASK, 4, 0);
if(g_hImageListSmall)
{
HICON hIcon;
hIcon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ICON_ROOT),
IMAGE_ICON, nSmallCx, nSmallCy, LR_DEFAULTCOLOR);
ImageList_AddIcon(g_hImageListSmall, hIcon);
hIcon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ICON_FOLDER_CLOSE),
IMAGE_ICON, nSmallCx, nSmallCy, LR_DEFAULTCOLOR);
ImageList_AddIcon(g_hImageListSmall, hIcon);
}
if(g_hImageListLarge)
{
ImageList_Destroy(g_hImageListLarge);
}
int nCx = GetSystemMetrics(SM_CXICON);
int nCy = GetSystemMetrics(SM_CYICON);
//set the large image list
g_hImageListLarge = ImageList_Create(nCx, nCy, ILC_COLORDDB | ILC_MASK, 4, 0);
if(g_hImageListSmall)
{
HICON hIcon;
hIcon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ICON_ROOT),
IMAGE_ICON, nCx, nCy, LR_DEFAULTCOLOR);
ImageList_AddIcon(g_hImageListLarge, hIcon);
hIcon = (HICON)LoadImage(g_hInstance, MAKEINTRESOURCE(IDI_ICON_FOLDER_CLOSE),
IMAGE_ICON, nCx, nCy, LR_DEFAULTCOLOR);
ImageList_AddIcon(g_hImageListLarge, hIcon);
}
}
STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID *ppv)
{
*ppv = NULL;
if (!IsEqualCLSID (rclsid, CLSID_Shell_Extension_QDrive))
{
return ResultFromScode (CLASS_E_CLASSNOTAVAILABLE);
}
CQDriveClassFactory *pClassFactory = new CQDriveClassFactory;
if (pClassFactory == NULL)
{
return ResultFromScode (E_OUTOFMEMORY);
}
HRESULT hr = pClassFactory->QueryInterface (riid, ppv);
pClassFactory->Release ();
return hr;
}
STDAPI DllCanUnloadNow (void)
{
return ResultFromScode ((g_uiRefThisDll == 0) ? S_OK : S_FALSE);
}
#define SZ_CLSID _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}")
#define SZ_INPROCSERVER32 _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}\\InprocServer32")
#define SZ_DEFAULT _T("")
#define SZ_DEFAULTICON _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}\\DefaultIcon")
#define SZ_THREADINGMODEL _T("ThreadingModel")
#define SZ_APARTMENT _T("Apartment")
#define SZ_SHELLFOLDER _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}\\ShellFolder")
#define SZ_ATTRIBUTES _T("Attributes")
#define SZ_APPROVED _T("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")
#define SZ_ERRMSG _T("Unable to add ClassId {A79EBF22-97C6-11d2-A6CA-204C4F4F5020} to Registry\nAdministrative Privileges Needed")
#define SZ_ERROR _T("Error")
#define SZ_SHELLEX _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}\\shellex")
#define SZ_SHELLEX_CTX _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}\\shellex\\ContextMenuHandlers")
#define SZ_CTXMENUHDLR _T("CLSID\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}\\shellex\\ContextMenuHandlers\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}")
#define SZ_NAMESPACE_DT _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\Namespace\\{A79EBF22-97C6-11d2-A6CA-204C4F4F5020}")
STDAPI DllRegisterServer(void)
{
HRESULT hr = E_UNEXPECTED;
static TCHAR szDescr[] = _T("Q:\\");
TCHAR szFilePath[_MAX_PATH];
GetModuleFileName(g_hInstance, szFilePath, _MAX_PATH);
// Create SZ_CLSID
HKEY hKeyCLSID = NULL;
if (::RegCreateKey(HKEY_CLASSES_ROOT, SZ_CLSID, &hKeyCLSID) != ERROR_SUCCESS)
{
return E_UNEXPECTED; // No point in continuing further
}
if (::RegSetValueEx(hKeyCLSID, SZ_DEFAULT, 0, REG_SZ, (const BYTE*)szDescr,
(lstrlen(szDescr)+1) * sizeof(TCHAR)) != ERROR_SUCCESS)
{
return E_UNEXPECTED; // No point in continuing further
}
::RegCloseKey(hKeyCLSID);
HKEY hkeyInprocServer32 = NULL;
if (::RegCreateKey(HKEY_CLASSES_ROOT, SZ_INPROCSERVER32, &hkeyInprocServer32) == ERROR_SUCCESS)
{
static TCHAR szApartment[] = SZ_APARTMENT;
if (::RegSetValueEx(hkeyInprocServer32, SZ_DEFAULT, 0, REG_SZ,
(const BYTE*)szFilePath, (lstrlen(szFilePath)+1) * sizeof(TCHAR)) == ERROR_SUCCESS)
{
if (::RegSetValueEx(hkeyInprocServer32, SZ_THREADINGMODEL, 0, REG_SZ,
(const BYTE*)szApartment, (lstrlen(szApartment)+1) * sizeof(TCHAR)) == ERROR_SUCCESS)
{
hr = S_OK;
}
}
::RegCloseKey(hkeyInprocServer32);
}
// Set the default icon for the NameSpace extension folder
HKEY hkeyDefaultIcon = NULL;
if (::RegCreateKey(HKEY_CLASSES_ROOT, SZ_DEFAULTICON, &hkeyDefaultIcon) == ERROR_SUCCESS)
{
static TCHAR szDefaultIcon[MAX_PATH];
strcpy(szDefaultIcon, szFilePath);
strcat(szDefaultIcon, ",0");
if (::RegSetValueEx(hkeyDefaultIcon, SZ_DEFAULT, 0, REG_SZ,
(const BYTE*)szDefaultIcon, (lstrlen(szDefaultIcon)+1) * sizeof(TCHAR)) == ERROR_SUCCESS)
{
hr = S_OK;
}
::RegCloseKey(hkeyDefaultIcon);
}
else
{
hr = E_UNEXPECTED;
}
HKEY hKeyApproved = NULL;
LONG lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_APPROVED, 0, KEY_SET_VALUE, &hKeyApproved);
if (lRet == ERROR_ACCESS_DENIED)
{
MessageBox(NULL, SZ_ERRMSG, SZ_ERROR, MB_OK);
hr = E_UNEXPECTED;
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
// Its okay.. The key doesn't exist. May be its Win95/98 or older verion of NT
}
if (hKeyApproved)
{
if (RegSetValueEx(hKeyApproved, SZ_GUID, 0, REG_SZ,
(const BYTE*) szDescr, (lstrlen(szDescr) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS)
{
hr = S_OK;
}
else
{
hr = E_UNEXPECTED;
}
}
// create SZ_NAMESPACE_DT
HKEY hKeyNameSpaceDT = NULL;
if (::RegCreateKey(HKEY_LOCAL_MACHINE, SZ_NAMESPACE_DT,
&hKeyNameSpaceDT) == ERROR_SUCCESS)
{
if (::RegSetValueEx(hKeyNameSpaceDT, SZ_DEFAULT, 0, REG_SZ,
(const BYTE*)szDescr, (lstrlen(szDescr)+1) * sizeof(TCHAR)) == ERROR_SUCCESS)
{
hr &= S_OK;
}
else
{
hr &= E_UNEXPECTED;
}
::RegCloseKey(hKeyNameSpaceDT);
}
// Register ShellFolder Attributes
HKEY hKeyShellFolder = NULL;
DWORD dwDisposition = 0;
if (::RegCreateKeyEx(HKEY_CLASSES_ROOT, SZ_SHELLFOLDER, NULL, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKeyShellFolder,
&dwDisposition) == ERROR_SUCCESS)
{
DWORD dwAttr = SFGAO_HASSUBFOLDER | SFGAO_FOLDER | SFGAO_DROPTARGET;
if (::RegSetValueEx(hKeyShellFolder, SZ_ATTRIBUTES, 0, REG_BINARY,
(LPBYTE)&dwAttr, sizeof(dwAttr)) == ERROR_SUCCESS)
{
hr = S_OK;
}
else
{
hr = E_UNEXPECTED;
}
::RegCloseKey(hKeyShellFolder);
}
// Register context menu handler
// create SZ_CTXMENUHDLR
HKEY hKeyCtxMenuHdlr = NULL;
if (::RegCreateKey(HKEY_CLASSES_ROOT, SZ_CTXMENUHDLR, &hKeyCtxMenuHdlr) != ERROR_SUCCESS)
{
hr = E_UNEXPECTED;
}
::RegCloseKey(hKeyCtxMenuHdlr);
//TODO: Add extra registrations here.. like HKCR\\.MyExt etc
return hr;
}
STDAPI DllUnregisterServer(void)
{
HRESULT hr = E_UNEXPECTED;
::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_INPROCSERVER32);
::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_DEFAULTICON);
::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_CTXMENUHDLR);
::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_SHELLEX_CTX);
::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_SHELLEX);
::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_SHELLFOLDER);
if (::RegDeleteKey(HKEY_CLASSES_ROOT, SZ_CLSID) == ERROR_SUCCESS)
{
hr = S_OK;
}
HKEY hKeyApproved = NULL;
LONG lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, SZ_APPROVED, 0, KEY_SET_VALUE, &hKeyApproved);
if (lRet == ERROR_ACCESS_DENIED)
{
MessageBox(NULL, SZ_ERRMSG, SZ_ERROR, MB_OK);
hr = E_UNEXPECTED;
}
else if (lRet == ERROR_FILE_NOT_FOUND)
{
// Its okay.. The key doesn't exist. May be its Win95 or older verion of NT
}
if (hKeyApproved)
{
if (::RegDeleteValue(hKeyApproved, SZ_GUID) != ERROR_SUCCESS)
{
hr &= E_UNEXPECTED;
}
::RegCloseKey(hKeyApproved);
}
// create SZ_NAMESPACE_DT
::RegDeleteKey(HKEY_LOCAL_MACHINE, SZ_NAMESPACE_DT);
return hr;
}
///////////////////////////////////////////////////////////
// CQDriveClassFactory member functions
CQDriveClassFactory::CQDriveClassFactory()
{
m_ulRef = 1;
g_uiRefThisDll++;
}
CQDriveClassFactory::~CQDriveClassFactory()
{
g_uiRefThisDll--;
}
///////////////////////////////////////////////////////////
// IUnknown implementation
//
STDMETHODIMP CQDriveClassFactory::QueryInterface (REFIID riid, LPVOID FAR *ppv)
{
if (IsEqualIID (riid, IID_IUnknown))
{
*ppv = (LPUNKNOWN) (LPCLASSFACTORY) this;
m_ulRef++;
return NOERROR;
}
else if (IsEqualIID (riid, IID_IClassFactory))
{
*ppv = (LPCLASSFACTORY) this;
m_ulRef++;
return NOERROR;
}
else
{
*ppv = NULL;
return ResultFromScode (E_NOINTERFACE);
}
}
STDMETHODIMP_(ULONG) CQDriveClassFactory::AddRef ()
{
return ++m_ulRef;
}
STDMETHODIMP_(ULONG) CQDriveClassFactory::Release ()
{
if (--m_ulRef == 0)
{
delete this;
}
return m_ulRef;
}
STDMETHODIMP CQDriveClassFactory::CreateInstance (LPUNKNOWN pUnkOuter, REFIID riid,
LPVOID FAR *ppvObj)
{
*ppvObj = NULL;
//
// Return an error code if pUnkOuter is not NULL, because we don't
// support aggregation.
//
if (pUnkOuter != NULL)
return ResultFromScode (CLASS_E_NOAGGREGATION);
//
// Instantiate a ContextMenu extension this ShellFolder supports.
//
if (IsEqualIID (riid, IID_IShellExtInit))
{
CContextMenu *pCtxMenu = new CContextMenu(NULL, 0, NULL);
if (NULL == pCtxMenu)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pCtxMenu->QueryInterface(riid, ppvObj);
pCtxMenu->Release();
return hr;
}
else if (IsEqualIID (riid, IID_IContextMenu))
{
*ppvObj = (LPCONTEXTMENU) this;
m_ulRef++;
return NOERROR;
}
CShellFolder *pShellFolder = new CShellFolder(NULL, NULL);
if(NULL == pShellFolder)
{
return E_OUTOFMEMORY;
}
HRESULT hr = pShellFolder->QueryInterface(riid, ppvObj);
pShellFolder->Release();
return hr;
}
STDMETHODIMP CQDriveClassFactory::LockServer (BOOL fLock)
{
return ResultFromScode (E_NOTIMPL);
}
//EOF
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -