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.

235 lines
6.6 KiB

  1. #include "precomp.hxx"
  2. #pragma hdrstop
  3. #include <shguidp.h>
  4. #include <advpub.h> // RegInstall stuff
  5. #include "util.h"
  6. #include "resource.h"
  7. #include "version.h"
  8. // {ECF03A32-103D-11d2-854D-006008059367} CLSID_MyDocsDropTarget
  9. const CLSID CLSID_MyDocsDropTarget = { 0xecf03a32, 0x103d, 0x11d2, { 0x85, 0x4d, 0x0, 0x60, 0x8, 0x5, 0x93, 0x67 } };
  10. // {ECF03A33-103D-11d2-854D-006008059367} CLSID_MyDocsCopyHook
  11. const CLSID CLSID_MyDocsCopyHook = { 0xecf03a33, 0x103d, 0x11d2, { 0x85, 0x4d, 0x0, 0x60, 0x8, 0x5, 0x93, 0x67 } };
  12. // {4a7ded0a-ad25-11d0-98a8-0800361b1103} CLSID_MyDocsProp
  13. const CLSID CLSID_MyDocsProp = {0x4a7ded0a, 0xad25, 0x11d0, 0x98, 0xa8, 0x08, 0x00, 0x36, 0x1b, 0x11, 0x03};
  14. HINSTANCE g_hInstance = 0;
  15. LONG g_cRefThisDll = 0; // DLL global reference count
  16. STDAPI_(void) DllAddRef(void)
  17. {
  18. InterlockedIncrement(&g_cRefThisDll);
  19. }
  20. STDAPI_(void) DllRelease(void)
  21. {
  22. InterlockedDecrement(&g_cRefThisDll);
  23. }
  24. STDAPI DllCanUnloadNow(void)
  25. {
  26. return g_cRefThisDll ? S_FALSE : S_OK;
  27. }
  28. HRESULT CMyDocsCopyHook_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  29. HRESULT CMyDocsSendTo_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  30. HRESULT CMyDocsProp_CreateInstance(IUnknown *punkOuter, IUnknown **ppunk, LPCOBJECTINFO poi);
  31. CF_TABLE_BEGIN(g_ObjectInfo)
  32. CF_TABLE_ENTRY(&CLSID_MyDocsCopyHook, CMyDocsCopyHook_CreateInstance, COCREATEONLY),
  33. CF_TABLE_ENTRY(&CLSID_MyDocsDropTarget, CMyDocsSendTo_CreateInstance, COCREATEONLY),
  34. CF_TABLE_ENTRY(&CLSID_MyDocsProp, CMyDocsProp_CreateInstance, COCREATEONLY),
  35. CF_TABLE_END(g_ObjectInfo)
  36. STDMETHODIMP CClassFactory::QueryInterface(REFIID riid, void **ppvObj)
  37. {
  38. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  39. {
  40. *ppvObj = (void *)GET_ICLASSFACTORY(this);
  41. DllAddRef();
  42. return NOERROR;
  43. }
  44. *ppvObj = NULL;
  45. return E_NOINTERFACE;
  46. }
  47. STDMETHODIMP_(ULONG) CClassFactory::AddRef()
  48. {
  49. DllAddRef();
  50. return 2;
  51. }
  52. STDMETHODIMP_(ULONG) CClassFactory::Release()
  53. {
  54. DllRelease();
  55. return 1;
  56. }
  57. STDMETHODIMP CClassFactory::CreateInstance(IUnknown *punkOuter, REFIID riid, void **ppv)
  58. {
  59. *ppv = NULL;
  60. if (punkOuter && !IsEqualIID(riid, IID_IUnknown))
  61. {
  62. return CLASS_E_NOAGGREGATION;
  63. }
  64. else
  65. {
  66. LPOBJECTINFO pthisobj = (LPOBJECTINFO)this;
  67. if (punkOuter) // && !(pthisobj->dwClassFactFlags & OIF_ALLOWAGGREGATION))
  68. return CLASS_E_NOAGGREGATION;
  69. IUnknown *punk;
  70. HRESULT hr = pthisobj->pfnCreateInstance(punkOuter, &punk, pthisobj);
  71. if (SUCCEEDED(hr))
  72. {
  73. hr = punk->QueryInterface(riid, ppv);
  74. punk->Release();
  75. }
  76. return hr;
  77. }
  78. }
  79. STDMETHODIMP CClassFactory::LockServer(BOOL fLock)
  80. {
  81. if (fLock)
  82. DllAddRef();
  83. else
  84. DllRelease();
  85. return S_OK;
  86. }
  87. STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
  88. {
  89. if (IsEqualIID(riid, IID_IClassFactory) || IsEqualIID(riid, IID_IUnknown))
  90. {
  91. for (LPCOBJECTINFO pcls = g_ObjectInfo; pcls->pclsid; pcls++)
  92. {
  93. if (IsEqualGUID(rclsid, *(pcls->pclsid)))
  94. {
  95. *ppv = (void*)pcls;
  96. DllAddRef(); // class factory holds DLL ref count
  97. return NOERROR;
  98. }
  99. }
  100. }
  101. *ppv = NULL;
  102. return CLASS_E_CLASSNOTAVAILABLE;
  103. }
  104. // Call ADVPACK for the given section of our resource based INF>
  105. // hInstance = resource instance to get REGINST section from
  106. // szSection = section name to invoke
  107. HRESULT CallRegInstall(HINSTANCE hInstance, LPCSTR szSection)
  108. {
  109. HRESULT hr = E_FAIL;
  110. HINSTANCE hinstAdvPack = LoadLibrary(TEXT("ADVPACK.DLL"));
  111. if (hinstAdvPack)
  112. {
  113. REGINSTALL pfnri = (REGINSTALL)GetProcAddress(hinstAdvPack, "RegInstall");
  114. if (pfnri)
  115. {
  116. STRENTRY seReg[] =
  117. {
  118. // These two NT-specific entries must be at the end
  119. { "25", "%SystemRoot%" },
  120. { "11", "%SystemRoot%\\system32" },
  121. };
  122. STRTABLE stReg = { ARRAYSIZE(seReg), seReg };
  123. hr = pfnri(hInstance, szSection, &stReg);
  124. }
  125. FreeLibrary(hinstAdvPack);
  126. }
  127. return hr;
  128. }
  129. // export that ie4unit.exe calls at per user install time
  130. // this lets us execute code instead of depending on the "DefaultUser" template
  131. // that is used to init new accounts. this deals with upgrade cases too, very important
  132. STDAPI_(void) PerUserInit(void)
  133. {
  134. TCHAR szPath[MAX_PATH];
  135. SHGetFolderPath(NULL, CSIDL_PERSONAL | CSIDL_FLAG_CREATE | CSIDL_FLAG_PER_USER_INIT, NULL, SHGFP_TYPE_CURRENT, szPath);
  136. // Don't install these guys on server builds
  137. if (!IsOS(OS_ANYSERVER))
  138. {
  139. SHGetFolderPath(NULL, CSIDL_MYPICTURES | CSIDL_FLAG_CREATE | CSIDL_FLAG_PER_USER_INIT, NULL, SHGFP_TYPE_CURRENT, szPath);
  140. SHGetFolderPath(NULL, CSIDL_MYMUSIC | CSIDL_FLAG_CREATE | CSIDL_FLAG_PER_USER_INIT, NULL, SHGFP_TYPE_CURRENT, szPath);
  141. }
  142. UpdateSendToFile();
  143. }
  144. STDAPI DllRegisterServer(void)
  145. {
  146. CallRegInstall(g_hInstance, "RegDll");
  147. return S_OK;
  148. }
  149. STDAPI DllUnregisterServer(void)
  150. {
  151. CallRegInstall(g_hInstance, "UnregDll");
  152. return S_OK;
  153. }
  154. STDAPI DllInstall(BOOL bInstall, LPCWSTR pszCmdLine)
  155. {
  156. if (pszCmdLine && *pszCmdLine)
  157. {
  158. if (0 == StrCmpIW(pszCmdLine, L"UseReadOnly"))
  159. {
  160. // Add key for system to use read only bit on shell folders...
  161. HKEY hkey;
  162. if (ERROR_SUCCESS == RegCreateKey(HKEY_LOCAL_MACHINE, TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"), &hkey))
  163. {
  164. if (bInstall)
  165. {
  166. DWORD dwValue = 1;
  167. RegSetValueEx(hkey, TEXT("UseReadOnlyForSystemFolders"), 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue));
  168. }
  169. else
  170. {
  171. RegDeleteValue(hkey, TEXT("UseReadOnlyForSystemFolders"));
  172. }
  173. RegCloseKey(hkey);
  174. }
  175. }
  176. else if (0 == StrCmpIW(pszCmdLine, L"U"))
  177. {
  178. // not currently used, but for testing (and consistency with shell32.dll)
  179. // REGSVR32.EXE /n /i:U mydocs.dll
  180. PerUserInit();
  181. }
  182. }
  183. return S_OK;
  184. }
  185. STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, void *pReserved)
  186. {
  187. switch (dwReason)
  188. {
  189. case DLL_PROCESS_ATTACH:
  190. g_hInstance = hInstance;
  191. DisableThreadLibraryCalls(hInstance);
  192. SHFusionInitializeFromModule(hInstance);
  193. break;
  194. case DLL_PROCESS_DETACH:
  195. SHFusionUninitialize();
  196. break;
  197. }
  198. return TRUE;
  199. }