/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ #include "stdafx.h" #include #include extern "C" { #include #include } #include "afs_shl_ext.h" #include #include "help.h" #include "shell_ext.h" #include extern "C" { #include "WINNT\afsreg.h" } #define STRSAFE_NO_DEPRECATE #include #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif #ifndef _WIN64 // 32-bit static const IID IID_IShellExt = { 0xdc515c27, 0x6cac, 0x11d1, { 0xba, 0xe7, 0x0, 0xc0, 0x4f, 0xd1, 0x40, 0xd2 } }; #else // 64-bit static const IID IID_IShellExt = { 0x5f820ca1, 0x3dde, 0x11db, {0xb2, 0xce, 0x00, 0x15, 0x58, 0x09, 0x2d, 0xb5} }; #endif ///////////////////////////////////////////////////////////////////////////// // CAfsShlExt BEGIN_MESSAGE_MAP(CAfsShlExt, CWinApp) //{{AFX_MSG_MAP(CAfsShlExt) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CAfsShlExt construction CAfsShlExt::CAfsShlExt() { /* Start up sockets */ WSADATA WSAjunk; WSAStartup(0x0101, &WSAjunk); } ///////////////////////////////////////////////////////////////////////////// // The one and only CAfsShlExt object CAfsShlExt theApp; ///////////////////////////////////////////////////////////////////////////// // CAfsShlExt initialization HINSTANCE g_hInstance; BOOL CAfsShlExt::InitInstance() { extern EXPORTED HINSTANCE TaLocale_LoadCorrespondingModuleByName (HINSTANCE hInstance, LPSTR pszFilename, WORD wSearchPriority = MODULE_PRIORITY_BOOSTED); // Load our translated resources TaLocale_LoadCorrespondingModuleByName (m_hInstance, "afs_shl_ext.dll"); // Register all OLE server (factories) as running. This enables the // OLE libraries to create objects from other applications. COleObjectFactory::RegisterAll(); SetHelpPath(m_pszHelpFilePath); return TRUE; } ///////////////////////////////////////////////////////////////////////////// // Special entry points required for inproc servers STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); return AfxDllGetClassObject(rclsid, riid, ppv); } STDAPI DllCanUnloadNow(void) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); #ifdef COMMENT // This test is correct and we really do want to allow the extension to be loaded and // unloaded as needed. Unfortunately, the extension is being unloaded and never loaded // again which is disconcerting for many folks. For now we will prevent the unloading // until someone has time to figure out how to debug this. // Jeffrey Altman - 2 Oct 2005 if (!nCMRefCount && !nSERefCount && !nICRefCount && !nTPRefCount && !nXPRefCount) return S_OK; #endif return S_FALSE; } int WideCharToLocal(LPTSTR pLocal, LPCWSTR pWide, DWORD dwChars) { #ifdef UNICODE StringCchCopy(pLocal, dwChars, pWide); #else *pLocal = 0; WideCharToMultiByte( CP_ACP, 0, pWide, -1, pLocal, dwChars, NULL, NULL); #endif return lstrlen(pLocal); } LRESULT DoRegCLSID(HKEY hKey,PTCHAR szSubKey,PTCHAR szData,PTCHAR szValue=NULL) { DWORD dwDisp; LRESULT lResult; HKEY thKey; lResult = RegCreateKeyEx(hKey, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &thKey, &dwDisp); if(NOERROR == lResult) { lResult = RegSetValueEx(thKey, szValue, 0, REG_SZ, (LPBYTE)szData, (lstrlen(szData) + 1) * sizeof(TCHAR)); RegCloseKey(thKey); } RegCloseKey(hKey); return lResult; } // by exporting DllRegisterServer, you can use regsvr.exe STDAPI DllRegisterServer(void) { HKEY hKey; LRESULT lResult; DWORD dwDisp; TCHAR szSubKey[MAX_PATH]; TCHAR szCLSID[MAX_PATH]; TCHAR szModule[MAX_PATH]; LPWSTR pwsz; AFX_MANAGE_STATE(AfxGetStaticModuleState()); COleObjectFactory::UpdateRegistryAll(); StringFromIID(IID_IShellExt, &pwsz); if(pwsz) { #ifdef UNICODE StringCbCopy(szCLSID, sizeof(szCLSID), pwsz); #else WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL); #endif CoTaskMemFree(pwsz); } else { return E_FAIL; } /* [HKEY_CLASSES_ROOT\CLSID\{$CLSID}\InprocServer32] @="Y:\\DEST\\root.client\\usr\\vice\\etc\\afs_shl_ext.dll" "ThreadingModel"="Apartment" */ HMODULE hModule=GetModuleHandle(TEXT("afs_shl_ext.dll")); DWORD z=GetModuleFileName(hModule,szModule,sizeof(szModule)); wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szModule))!=NOERROR) return lResult; wsprintf(szSubKey, TEXT("CLSID\\%s\\InprocServer32"),szCLSID); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey, TEXT("Apartment"),TEXT("ThreadingModel")))!=NOERROR) return lResult; /* [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\AFS Client Shell Extension] @="{EA3775F2-28BE-11D3-9C8D-00105A24ED29}" */ wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE); if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,szCLSID))!=NOERROR) return lResult; //If running on NT, register the extension as approved. /* [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved] "{$(CLSID)}"="AFS Client Shell Extension" [HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\AFS Client Shell Extension] @="{$(CLSID)}" */ OSVERSIONINFO osvi; osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) { wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")); if ((lResult=DoRegCLSID(HKEY_LOCAL_MACHINE,szSubKey,_TEXT(STR_EXT_TITLE),szCLSID))!=NOERROR) return lResult; } wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR) return lResult; wsprintf(szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR) return lResult; wsprintf(szSubKey, TEXT("Directory\\Background\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR) return lResult; wsprintf(szSubKey, TEXT("LibraryFolder\\background\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR) return lResult; /* Register InfoTip [HKEY_CLASSES_ROOT\Folder\shellex\{00021500-0000-0000-C000-000000000046}] @="{$(CLSID)}" */ wsprintf(szSubKey, TEXT("Folder\\shellex\\{00021500-0000-0000-C000-000000000046}")); if ((lResult=DoRegCLSID(HKEY_CLASSES_ROOT,szSubKey,szCLSID))!=NOERROR) return lResult; /* Below needs to be merged with above */ wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE); lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp); if(NOERROR == lResult) { //Create the value string. lResult = RegSetValueEx( hKey, NULL, 0, REG_SZ, (LPBYTE)szCLSID, (lstrlen(szCLSID) + 1) * sizeof(TCHAR)); RegCloseKey(hKey); } else return SELFREG_E_CLASS; //If running on NT, register the extension as approved. osvi.dwOSVersionInfoSize = sizeof(osvi); GetVersionEx(&osvi); if(VER_PLATFORM_WIN32_NT == osvi.dwPlatformId) { lstrcpy( szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")); lResult = RegCreateKeyEx( HKEY_LOCAL_MACHINE, szSubKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hKey, &dwDisp); if(NOERROR == lResult) { TCHAR szData[MAX_PATH]; //Create the value string. lstrcpy(szData, _TEXT(STR_EXT_TITLE)); lResult = RegSetValueEx( hKey, szCLSID, 0, REG_SZ, (LPBYTE)szData, (lstrlen(szData) + 1) * sizeof(TCHAR)); RegCloseKey(hKey); } else return SELFREG_E_CLASS; } return S_OK; } //returnValue = RegOpenKeyEx (HKEY_CLASSES_ROOT, keyName, 0, KEY_ALL_ACCESS, ®istryKey); LRESULT DoValueDelete(HKEY hKey,PTCHAR pszSubKey,PTCHAR szValue=NULL) { LRESULT lResult; HKEY thKey; if (szValue==NULL) { lResult=RegDeleteKey(hKey, pszSubKey); return lResult; } lResult = RegOpenKeyEx( hKey, pszSubKey, 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_ALL_ACCESS, &thKey); if(NOERROR == lResult) { lResult=RegDeleteValue(hKey, szValue); RegCloseKey(thKey); } return lResult; } STDAPI DllUnregisterServer(void) { TCHAR szSubKey[MAX_PATH]; TCHAR szCLSID[MAX_PATH]; LPWSTR pwsz; AFX_MANAGE_STATE(AfxGetStaticModuleState()); COleObjectFactory::UpdateRegistryAll(FALSE); StringFromIID(IID_IShellExt, &pwsz); if(pwsz) { #ifdef UNICODE StringCbCopy(szCLSID, sizeof(szCLSID), pwsz); #else WideCharToMultiByte( CP_ACP, 0,pwsz, -1, szCLSID, sizeof(szCLSID), NULL, NULL); #endif CoTaskMemFree(pwsz); } else { return E_FAIL; } wsprintf(szSubKey, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")); DoValueDelete(HKEY_LOCAL_MACHINE,szSubKey,szCLSID); wsprintf(szSubKey, TEXT("*\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); DoValueDelete(HKEY_CLASSES_ROOT, szSubKey); wsprintf(szSubKey, TEXT("Folder\\shellex\\{00021500-0000-0000-C000-000000000046}")); DoValueDelete(HKEY_CLASSES_ROOT, szSubKey); wsprintf(szSubKey, TEXT("Folder\\shellex\\ContextMenuHandlers\\%s"),STR_EXT_TITLE); DoValueDelete(HKEY_CLASSES_ROOT, szSubKey); wsprintf(szSubKey, TEXT("%s\\%s"), STR_REG_PATH, STR_EXT_TITLE); DoValueDelete(HKEY_LOCAL_MACHINE, szSubKey); return S_OK; }