Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

287 lines
7.7 KiB

  1. #include "precomp.h" // pch file
  2. #include "cfdefs.h" // CClassFactory, LPOBJECTINFO
  3. #pragma hdrstop
  4. STDAPI MailRecipient_RegUnReg(BOOL bReg, HKEY hkCLSID, LPCTSTR pszCLSID, LPCTSTR pszModule);
  5. STDAPI MailRecipient_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  6. STDAPI DesktopShortcut_RegUnReg(BOOL bReg, HKEY hkCLSID, LPCTSTR pszCLSID, LPCTSTR pszModule);
  7. STDAPI DesktopShortcut_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  8. // tables for object construction and registration
  9. CF_TABLE_BEGIN( g_ObjectInfo )
  10. CF_TABLE_ENTRY(&CLSID_MailRecipient, MailRecipient_CreateInstance, COCREATEONLY),
  11. CF_TABLE_ENTRY(&CLSID_DesktopShortcut, DesktopShortcut_CreateInstance, COCREATEONLY),
  12. CF_TABLE_END( g_ObjectInfo )
  13. typedef struct
  14. {
  15. const CLSID *pclsid;
  16. HRESULT (STDMETHODCALLTYPE *pfnRegUnReg)(BOOL bReg, HKEY hkCLSID, LPCTSTR pszCLSID, LPCTSTR pszModule);
  17. } REGISTRATIONINFO;
  18. const REGISTRATIONINFO c_ri[] =
  19. {
  20. { &CLSID_MailRecipient, MailRecipient_RegUnReg },
  21. { &CLSID_DesktopShortcut, DesktopShortcut_RegUnReg },
  22. { NULL },
  23. };
  24. LONG g_cRefDll = 0; // reference count for this DLL
  25. HINSTANCE g_hinst = NULL; // HMODULE for this DLL
  26. // life-time manangement and registration
  27. STDAPI_(void) DllAddRef()
  28. {
  29. InterlockedIncrement(&g_cRefDll);
  30. }
  31. STDAPI_(void) DllRelease()
  32. {
  33. InterlockedDecrement(&g_cRefDll);
  34. }
  35. STDAPI DllCanUnloadNow(void)
  36. {
  37. return g_cRefDll == 0 ? S_OK : S_FALSE;
  38. }
  39. STDAPI_(BOOL) DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpReserved)
  40. {
  41. if (dwReason == DLL_PROCESS_ATTACH)
  42. {
  43. g_hinst = hDll;
  44. SHFusionInitializeFromModule(hDll);
  45. DisableThreadLibraryCalls(hDll);
  46. }
  47. else if (dwReason == DLL_PROCESS_DETACH)
  48. {
  49. SHFusionUninitialize();
  50. }
  51. return TRUE;
  52. }
  53. void StringFromGUID(const CLSID* piid, LPTSTR pszBuf)
  54. {
  55. wnsprintf(pszBuf, MAX_PATH, TEXT("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}"), piid->Data1,
  56. piid->Data2, piid->Data3, piid->Data4[0], piid->Data4[1], piid->Data4[2],
  57. piid->Data4[3], piid->Data4[4], piid->Data4[5], piid->Data4[6], piid->Data4[7]);
  58. }
  59. BOOL DeleteKeyAndSubKeys(HKEY hkIn, LPCTSTR pszSubKey)
  60. {
  61. HKEY hk;
  62. TCHAR szTmp[MAX_PATH];
  63. DWORD dwTmpSize;
  64. long l;
  65. BOOL f;
  66. int x;
  67. l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hk);
  68. if (l != ERROR_SUCCESS)
  69. return FALSE;
  70. // loop through all subkeys, blowing them away.
  71. //
  72. f = TRUE;
  73. x = 0;
  74. while (f) {
  75. dwTmpSize = MAX_PATH;
  76. l = RegEnumKeyEx(hk, x, szTmp, &dwTmpSize, 0, NULL, NULL, NULL);
  77. if (l != ERROR_SUCCESS)
  78. break;
  79. f = DeleteKeyAndSubKeys(hk, szTmp);
  80. x++;
  81. }
  82. // there are no subkeys left, [or we'll just generate an error and return FALSE].
  83. // let's go blow this dude away.
  84. //
  85. RegCloseKey(hk);
  86. l = RegDeleteKey(hkIn, pszSubKey);
  87. return (l == ERROR_SUCCESS) ? TRUE : FALSE;
  88. }
  89. #define INPROCSERVER32 TEXT("InProcServer32")
  90. #define CLSID TEXT("CLSID")
  91. #define THREADINGMODEL TEXT("ThreadingModel")
  92. #define APARTMENT TEXT("Apartment")
  93. #define APPROVED TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved")
  94. #define DESC TEXT("Sendmail service")
  95. STDAPI DllRegisterServer(void)
  96. {
  97. const REGISTRATIONINFO *pcls;
  98. TCHAR szPath[MAX_PATH];
  99. GetModuleFileName(g_hinst, szPath, ARRAYSIZE(szPath)); // get path to this DLL
  100. for (pcls = c_ri; pcls->pclsid; pcls++)
  101. {
  102. HKEY hkCLSID;
  103. if (RegOpenKey(HKEY_CLASSES_ROOT, CLSID, &hkCLSID) == ERROR_SUCCESS)
  104. {
  105. HKEY hkOurs;
  106. LONG err;
  107. TCHAR szGUID[80];
  108. StringFromGUID(pcls->pclsid, szGUID);
  109. err = RegCreateKey(hkCLSID, szGUID, &hkOurs);
  110. if (err == ERROR_SUCCESS)
  111. {
  112. HKEY hkInproc;
  113. err = RegCreateKey(hkOurs, INPROCSERVER32, &hkInproc);
  114. if (err == ERROR_SUCCESS)
  115. {
  116. err = RegSetValueEx(hkInproc, NULL, 0, REG_SZ, (LPBYTE)szPath, (lstrlen(szPath) + 1) * sizeof(TCHAR));
  117. if (err == ERROR_SUCCESS)
  118. {
  119. err = RegSetValueEx(hkInproc, THREADINGMODEL, 0, REG_SZ, (LPBYTE)APARTMENT, sizeof(APARTMENT));
  120. }
  121. RegCloseKey(hkInproc);
  122. }
  123. if (pcls->pfnRegUnReg)
  124. pcls->pfnRegUnReg(TRUE, hkOurs, szGUID, szPath);
  125. if (err == ERROR_SUCCESS)
  126. {
  127. HKEY hkApproved;
  128. err = RegOpenKey(HKEY_LOCAL_MACHINE, APPROVED, &hkApproved);
  129. if (err == ERROR_SUCCESS)
  130. {
  131. err = RegSetValueEx(hkApproved, szGUID, 0, REG_SZ, (LPBYTE)DESC, sizeof(DESC));
  132. RegCloseKey(hkApproved);
  133. }
  134. }
  135. RegCloseKey(hkOurs);
  136. }
  137. RegCloseKey(hkCLSID);
  138. if (err != ERROR_SUCCESS)
  139. return HRESULT_FROM_WIN32(err);
  140. }
  141. }
  142. return S_OK;
  143. }
  144. STDAPI DllUnregisterServer(void)
  145. {
  146. const REGISTRATIONINFO *pcls;
  147. for (pcls = c_ri; pcls->pclsid; pcls++)
  148. {
  149. HKEY hkCLSID;
  150. if (RegOpenKey(HKEY_CLASSES_ROOT, CLSID, &hkCLSID) == ERROR_SUCCESS)
  151. {
  152. TCHAR szGUID[80];
  153. HKEY hkApproved;
  154. StringFromGUID(pcls->pclsid, szGUID);
  155. DeleteKeyAndSubKeys(hkCLSID, szGUID);
  156. if (RegOpenKey(HKEY_LOCAL_MACHINE, APPROVED, &hkApproved) == ERROR_SUCCESS)
  157. {
  158. RegDeleteValue(hkApproved, szGUID);
  159. RegCloseKey(hkApproved);
  160. }
  161. RegCloseKey(hkCLSID);
  162. if (pcls->pfnRegUnReg)
  163. pcls->pfnRegUnReg(FALSE, NULL, szGUID, NULL);
  164. }
  165. }
  166. return S_OK;
  167. }
  168. // class factory stuff
  169. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid,void**ppvObj)
  170. {
  171. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  172. {
  173. *ppvObj = (void *)GET_ICLASSFACTORY(this);
  174. DllAddRef();
  175. return NOERROR;
  176. }
  177. *ppvObj = NULL;
  178. return E_NOINTERFACE;
  179. }
  180. STDMETHODIMP_(ULONG) CClassFactory::AddRef()
  181. {
  182. DllAddRef();
  183. return 2;
  184. }
  185. STDMETHODIMP_(ULONG) CClassFactory::Release()
  186. {
  187. DllRelease();
  188. return 1;
  189. }
  190. STDMETHODIMP CClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid,void**ppv)
  191. {
  192. *ppv = NULL;
  193. if (punkOuter && !IsEqualIID(riid, IID_IUnknown))
  194. {
  195. return CLASS_E_NOAGGREGATION;
  196. }
  197. else
  198. {
  199. LPOBJECTINFO pthisobj = (LPOBJECTINFO)this;
  200. if (punkOuter) // && !(pthisobj->dwClassFactFlags & OIF_ALLOWAGGREGATION))
  201. return CLASS_E_NOAGGREGATION;
  202. IUnknown *punk;
  203. HRESULT hr = pthisobj->pfnCreateInstance(punkOuter, &punk, pthisobj);
  204. if (SUCCEEDED(hr))
  205. {
  206. hr = punk->QueryInterface(riid, ppv);
  207. punk->Release();
  208. }
  209. return hr;
  210. }
  211. }
  212. STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
  213. {
  214. if (fLock)
  215. DllAddRef();
  216. else
  217. DllRelease();
  218. return S_OK;
  219. }
  220. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid,void**ppv)
  221. {
  222. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  223. {
  224. for (LPCOBJECTINFO pcls = g_ObjectInfo; pcls->pclsid; pcls++)
  225. {
  226. if (IsEqualGUID(rclsid, *(pcls->pclsid)))
  227. {
  228. *ppv = (void*)pcls;
  229. DllAddRef(); // class factory holds DLL ref count
  230. return NOERROR;
  231. }
  232. }
  233. }
  234. *ppv = NULL;
  235. return CLASS_E_CLASSNOTAVAILABLE;
  236. }