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.

225 lines
6.3 KiB

  1. // stdafx.cpp : source file that includes just the standard includes
  2. // stdafx.pch will be the pre-compiled header
  3. // stdafx.obj will contain the pre-compiled type information
  4. #include "stdafx.h"
  5. #ifdef _ATL_STATIC_REGISTRY
  6. #include <statreg.h>
  7. #include <statreg.cpp>
  8. #endif
  9. #include <atlimpl.cpp>
  10. #include "ShellExtensions.h"
  11. typedef DWORD (*PFNSHDeleteKeyW)(HKEY hkey, LPWSTR pszSubkey);
  12. HRESULT WINAPI
  13. CLayerUIModule::UpdateRegistryCLSID(
  14. const CLSID& clsid,
  15. BOOL bRegister
  16. )
  17. {
  18. static const TCHAR szIPS32[] = _T("InprocServer32");
  19. static const TCHAR szCLSID[] = _T("CLSID");
  20. static const TCHAR szPropPageExt[] = _T("ShimLayer Property Page");
  21. TCHAR* pszExtName;
  22. DWORD cbExtNameSize;
  23. HRESULT hRes = S_OK;
  24. LPOLESTR lpOleStrCLSIDValue;
  25. if (clsid != CLSID_ShimLayerPropertyPage) {
  26. LogMsg(_T("[UpdateRegistryCLSID] unknown CLSID!\n"));
  27. return E_FAIL;
  28. }
  29. ::StringFromCLSID(clsid, &lpOleStrCLSIDValue);
  30. HKEY hkey = NULL;
  31. LONG lRes;
  32. if (bRegister) {
  33. TCHAR szBuffer[MAX_PATH];
  34. DWORD keyType = 0;
  35. //
  36. // Write the key for registration. Include the value to specify
  37. // the threading model.
  38. //
  39. _stprintf(szBuffer, _T("%s\\%s\\%s"), szCLSID, lpOleStrCLSIDValue, szIPS32);
  40. lRes = RegCreateKey(HKEY_CLASSES_ROOT, szBuffer, &hkey);
  41. if (lRes != ERROR_SUCCESS) {
  42. LogMsg(_T("[UpdateRegistryCLSID] failed to open/create \"%s\"\n"),
  43. szBuffer);
  44. goto Exit;
  45. }
  46. ::GetModuleFileName(m_hInst, szBuffer, MAX_PATH);
  47. lRes = RegSetValueEx(hkey,
  48. NULL,
  49. 0,
  50. REG_SZ,
  51. (BYTE*)szBuffer,
  52. (lstrlen(szBuffer) + 1) * sizeof(TCHAR));
  53. if (lRes != ERROR_SUCCESS) {
  54. LogMsg(_T("[UpdateRegistryCLSID] failed to write value \"%s\"\n"),
  55. szBuffer);
  56. goto Exit;
  57. }
  58. lRes = RegSetValueEx(hkey,
  59. _T("ThreadingModel"),
  60. 0,
  61. REG_SZ,
  62. (BYTE*)_T("Apartment"),
  63. sizeof(_T("Apartment")));
  64. if (lRes != ERROR_SUCCESS) {
  65. LogMsg(_T("[UpdateRegistryCLSID] failed to write \"ThreadingModel\"\n"));
  66. goto Exit;
  67. }
  68. RegCloseKey(hkey);
  69. hkey = NULL;
  70. //
  71. // Open the key with the name of the .exe extension and
  72. // add the keys to support the shell extensions.
  73. //
  74. _stprintf(szBuffer,
  75. _T("lnkfile\\shellex\\PropertySheetHandlers\\%s"),
  76. szPropPageExt);
  77. pszExtName = (TCHAR*)szPropPageExt;
  78. cbExtNameSize = sizeof(szPropPageExt) + sizeof(TCHAR);
  79. lRes = RegCreateKey(HKEY_CLASSES_ROOT, szBuffer, &hkey);
  80. if (lRes != ERROR_SUCCESS) {
  81. goto Exit;
  82. }
  83. lRes = RegSetValueEx(hkey,
  84. NULL,
  85. 0,
  86. REG_SZ,
  87. (BYTE*)lpOleStrCLSIDValue,
  88. (lstrlen(lpOleStrCLSIDValue) + 1) * sizeof(TCHAR));
  89. if (lRes != ERROR_SUCCESS) {
  90. LogMsg(_T("[UpdateRegistryCLSID] failed to add the shell extension handler\n"));
  91. goto Exit;
  92. }
  93. RegCloseKey(hkey);
  94. hkey = NULL;
  95. //
  96. // Now add the shell extension to the approved list.
  97. //
  98. lRes = RegCreateKey(HKEY_LOCAL_MACHINE,
  99. _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"),
  100. &hkey);
  101. if (lRes != ERROR_SUCCESS) {
  102. LogMsg(_T("[UpdateRegistryCLSID] failed to approve the shell extension handler\n"));
  103. goto Exit;
  104. }
  105. lRes = RegSetValueEx(hkey,
  106. lpOleStrCLSIDValue,
  107. 0,
  108. REG_SZ,
  109. (BYTE*)pszExtName,
  110. cbExtNameSize);
  111. if (lRes != ERROR_SUCCESS) {
  112. LogMsg(_T("[UpdateRegistryCLSID] failed to approve the shell extension handler\n"));
  113. goto Exit;
  114. }
  115. Exit:
  116. if (hkey != NULL) {
  117. RegCloseKey(hkey);
  118. hkey = NULL;
  119. }
  120. hRes = HRESULT_FROM_WIN32(lRes);
  121. } else {
  122. //
  123. // Time to clean up.
  124. //
  125. PFNSHDeleteKeyW pfnSHDeleteKey;
  126. HMODULE hmod = LoadLibrary(_T("Shlwapi.dll"));
  127. if (hmod == NULL) {
  128. LogMsg(_T("[UpdateRegistryCLSID] failed to load Shlwapi.dll\n"));
  129. return E_FAIL;
  130. }
  131. pfnSHDeleteKey = (PFNSHDeleteKeyW)GetProcAddress(hmod, "SHDeleteKeyW");
  132. if (pfnSHDeleteKey == NULL) {
  133. FreeLibrary(hmod);
  134. LogMsg(_T("[UpdateRegistryCLSID] cannot get Shlwapi!SHDeleteKeyW\n"));
  135. return E_FAIL;
  136. }
  137. lRes = RegOpenKey(HKEY_CLASSES_ROOT, szCLSID, &hkey);
  138. if (lRes == ERROR_SUCCESS) {
  139. (*pfnSHDeleteKey)(hkey, lpOleStrCLSIDValue);
  140. RegCloseKey(hkey);
  141. hkey = NULL;
  142. }
  143. lRes = RegOpenKey(HKEY_CLASSES_ROOT, _T("lnkfile\\shellex"), &hkey);
  144. if (lRes == ERROR_SUCCESS) {
  145. (*pfnSHDeleteKey)(hkey, _T("PropertySheetHandlers\\ShimLayer Property Page"));
  146. RegCloseKey(hkey);
  147. hkey = NULL;
  148. }
  149. lRes = RegOpenKey(HKEY_LOCAL_MACHINE,
  150. _T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved"),
  151. &hkey);
  152. if (lRes == ERROR_SUCCESS) {
  153. RegDeleteValue(hkey, lpOleStrCLSIDValue);
  154. RegCloseKey(hkey);
  155. hkey = NULL;
  156. }
  157. FreeLibrary(hmod);
  158. }
  159. //
  160. // Delete the layer storage.
  161. //
  162. InitLayerStorage(TRUE);
  163. //
  164. // Notify the shell of our changes
  165. //
  166. SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
  167. ::CoTaskMemFree(lpOleStrCLSIDValue);
  168. return hRes;
  169. }