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.

395 lines
9.9 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: ext.cxx
  7. //
  8. // Contents: Shell extension handler for network objects
  9. //
  10. // Classes: CNetObj
  11. //
  12. // History: 26-Sep-95 BruceFo Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #include "headers.hxx"
  16. #pragma hdrstop
  17. #include <pages.hxx>
  18. #define DONT_WANT_SHELLDEBUG
  19. #include <shlobjp.h>
  20. #include "resource.h"
  21. #include "ext.hxx"
  22. #include "util.hxx"
  23. //--------------------------------------------------------------------------
  24. //
  25. // Shell DLL communication
  26. //
  27. typedef
  28. UINT
  29. (WINAPI *SHELLGETNETRESOURCE)(
  30. HNRES hnres,
  31. UINT iItem,
  32. LPNETRESOURCE pnresOut,
  33. UINT cbMax
  34. );
  35. HINSTANCE g_hShellLibrary = NULL;
  36. SHELLGETNETRESOURCE g_pFuncGNR = NULL;
  37. UINT g_cfNetResource = 0;
  38. BOOL LoadShellDllEntries(VOID);
  39. //--------------------------------------------------------------------------
  40. /*
  41. * Helper functions used to communicate with shell32.dll
  42. */
  43. BOOL LoadShellDllEntries(VOID)
  44. {
  45. if (g_hShellLibrary)
  46. {
  47. return TRUE;
  48. }
  49. g_hShellLibrary = LoadLibrary(TEXT("shell32.dll"));
  50. if (NULL == g_hShellLibrary)
  51. {
  52. return FALSE;
  53. }
  54. g_pFuncGNR = (SHELLGETNETRESOURCE)GetProcAddress(g_hShellLibrary, (LPSTR)IntToPtr(SHGetNetResourceORD));
  55. if (NULL == g_pFuncGNR)
  56. {
  57. return FALSE;
  58. }
  59. return TRUE;
  60. }
  61. //+-------------------------------------------------------------------------
  62. //
  63. // Member: CNetObj::CNetObj
  64. //
  65. // Synopsis: Constructor
  66. //
  67. // History: 4-Apr-95 BruceFo Created
  68. //
  69. //--------------------------------------------------------------------------
  70. CNetObj::CNetObj(
  71. VOID
  72. )
  73. :
  74. _uRefs(0),
  75. _pDataObject(NULL),
  76. _hkeyProgID(NULL)
  77. {
  78. INIT_SIG(CNetObj);
  79. AddRef(); // give it the correct initial reference count. add to the DLL reference count
  80. }
  81. //+-------------------------------------------------------------------------
  82. //
  83. // Member: CNetObj::~CNetObj
  84. //
  85. // Synopsis: Destructor
  86. //
  87. // History: 4-Apr-95 BruceFo Created
  88. //
  89. //--------------------------------------------------------------------------
  90. CNetObj::~CNetObj()
  91. {
  92. CHECK_SIG(CNetObj);
  93. if (_pDataObject)
  94. {
  95. _pDataObject->Release();
  96. }
  97. if (_hkeyProgID)
  98. {
  99. LONG l = RegCloseKey(_hkeyProgID);
  100. if (l != ERROR_SUCCESS)
  101. {
  102. appDebugOut((DEB_ERROR, "CNetObj::destructor. Error closing registry key, 0x%08lx\n", l));
  103. }
  104. _hkeyProgID = NULL;
  105. }
  106. }
  107. //+-------------------------------------------------------------------------
  108. //
  109. // Member: CNetObj::Initialize
  110. //
  111. // Derivation: IShellExtInit
  112. //
  113. // Synopsis: Initialize the shell extension. Stashes away the argument data.
  114. //
  115. // History: 4-Apr-95 BruceFo Created
  116. //
  117. // Notes: This method can be called more than once.
  118. //
  119. //--------------------------------------------------------------------------
  120. STDMETHODIMP
  121. CNetObj::Initialize(
  122. LPCITEMIDLIST pidlFolder,
  123. LPDATAOBJECT pDataObject,
  124. HKEY hkeyProgID
  125. )
  126. {
  127. CHECK_SIG(CNetObj);
  128. CNetObj::~CNetObj();
  129. if (!LoadShellDllEntries())
  130. {
  131. return E_FAIL;
  132. }
  133. // Duplicate the pDataObject pointer
  134. _pDataObject = pDataObject;
  135. if (pDataObject)
  136. {
  137. pDataObject->AddRef();
  138. }
  139. // Duplicate the handle
  140. if (hkeyProgID)
  141. {
  142. LONG l = RegOpenKeyEx(hkeyProgID, NULL, 0L, MAXIMUM_ALLOWED, &_hkeyProgID);
  143. if (l != ERROR_SUCCESS)
  144. {
  145. appDebugOut((DEB_ERROR, "CNetObj::Initialize. Error duplicating registry key, 0x%08lx\n", l));
  146. }
  147. }
  148. return S_OK;
  149. }
  150. //+-------------------------------------------------------------------------
  151. //
  152. // Member: CNetObj::AddPages
  153. //
  154. // Derivation: IShellPropSheetExt
  155. //
  156. // Synopsis: (from shlobj.h)
  157. // "The explorer calls this member function when it finds a
  158. // registered property sheet extension for a particular type
  159. // of object. For each additional page, the extension creates
  160. // a page object by calling CreatePropertySheetPage API and
  161. // calls lpfnAddPage.
  162. //
  163. // Arguments: lpfnAddPage -- Specifies the callback function.
  164. // lParam -- Specifies the opaque handle to be passed to the
  165. // callback function.
  166. //
  167. // History: 4-Apr-95 BruceFo Created
  168. //
  169. //--------------------------------------------------------------------------
  170. STDMETHODIMP
  171. CNetObj::AddPages(
  172. LPFNADDPROPSHEETPAGE lpfnAddPage,
  173. LPARAM lParam
  174. )
  175. {
  176. CHECK_SIG(CNetObj);
  177. //
  178. // Call IDataObject::GetData asking for a g_cfNetResource (i.e., HNRES).
  179. //
  180. STGMEDIUM medium;
  181. FORMATETC fmte =
  182. {
  183. g_cfNetResource
  184. ? g_cfNetResource
  185. : (g_cfNetResource = RegisterClipboardFormat(CFSTR_NETRESOURCES)),
  186. NULL,
  187. DVASPECT_CONTENT,
  188. -1,
  189. TYMED_HGLOBAL
  190. };
  191. appAssert(NULL != _pDataObject);
  192. HRESULT hr = _pDataObject->GetData(&fmte, &medium);
  193. CHECK_HRESULT(hr);
  194. if (FAILED(hr))
  195. {
  196. return hr;
  197. }
  198. ///////////////// Now I have a 'medium' to release
  199. hr = S_OK;
  200. HNRES hnres = medium.hGlobal;
  201. // Get number of selected items
  202. if (NULL != g_pFuncGNR)
  203. {
  204. UINT cItems = (*g_pFuncGNR)(hnres, (UINT)-1, NULL, 0);
  205. if (cItems > 0)
  206. {
  207. // Retrieve NETRESOURCE object from clipboard
  208. LPNETRESOURCE pNetRes = (LPNETRESOURCE)_bufNetResource;
  209. UINT ret = (*g_pFuncGNR)(hnres, 0, pNetRes, MAX_ONE_RESOURCE); // Get first item
  210. if (ret == 0)
  211. {
  212. // bad hnres?
  213. appDebugOut((DEB_TRACE, "CNetObj::AddPages. SHGetNetResource returned 0\n"));
  214. // NOTE: this is really error
  215. }
  216. else if (ret > MAX_ONE_RESOURCE)
  217. {
  218. // FEATURE: Resize the buf and try again
  219. appDebugOut((DEB_TRACE, "CNetObj::AddPages. buffer too small, needs to be %d\n", ret));
  220. }
  221. else
  222. {
  223. LPTSTR pszTemplate = NULL;
  224. if (RESOURCEDISPLAYTYPE_NETWORK == pNetRes->dwDisplayType)
  225. {
  226. pszTemplate = MAKEINTRESOURCE(IDD_NETWORK_SUMMARYINFO);
  227. }
  228. else if (RESOURCEDISPLAYTYPE_DOMAIN == pNetRes->dwDisplayType)
  229. {
  230. pszTemplate = MAKEINTRESOURCE(IDD_WRKGRP_SUMMARYINFO);
  231. }
  232. else if (RESOURCEDISPLAYTYPE_SERVER == pNetRes->dwDisplayType)
  233. {
  234. pszTemplate = MAKEINTRESOURCE(IDD_SERVER_SUMMARYINFO);
  235. }
  236. else if (RESOURCEDISPLAYTYPE_SHARE == pNetRes->dwDisplayType)
  237. {
  238. pszTemplate = MAKEINTRESOURCE(IDD_SHARE_SUMMARYINFO);
  239. }
  240. else
  241. {
  242. appDebugOut((DEB_TRACE, "CNetObj::AddPages. Unknown net resource type!\n"));
  243. }
  244. //
  245. // Create a property sheet page object from a dialog box.
  246. //
  247. if (NULL != pszTemplate)
  248. {
  249. FillAndAddPage(
  250. lpfnAddPage,
  251. lParam,
  252. CPage::DlgProcPage,
  253. pszTemplate);
  254. }
  255. }
  256. }
  257. else
  258. {
  259. appDebugOut((DEB_TRACE, "CNetObj::AddPages. NO net resources!\n"));
  260. // NOTE: this is really error
  261. }
  262. }
  263. else
  264. {
  265. appDebugOut((DEB_TRACE, "CNetObj::AddPages. No SHGetNetResource function!\n"));
  266. // NOTE: this is really error
  267. }
  268. ReleaseStgMedium(&medium);
  269. return hr;
  270. }
  271. BOOL
  272. CNetObj::FillAndAddPage(
  273. LPFNADDPROPSHEETPAGE lpfnAddPage,
  274. LPARAM lParam,
  275. DLGPROC pfnDlg,
  276. LPTSTR pszTemplate
  277. )
  278. {
  279. PROPSHEETPAGE psp;
  280. HPROPSHEETPAGE hpage;
  281. psp.dwSize = sizeof(psp); // no extra data.
  282. psp.dwFlags = PSP_USEREFPARENT;
  283. psp.hInstance = g_hInstance;
  284. psp.pszTemplate = pszTemplate;
  285. psp.hIcon = NULL;
  286. psp.pszTitle = NULL;
  287. psp.pfnDlgProc = pfnDlg;
  288. psp.pfnCallback = NULL;
  289. psp.pcRefParent = &g_NonOLEDLLRefs;
  290. //
  291. // We need to backlink ourselves because we are using member variable
  292. // of this class.
  293. //
  294. psp.lParam = (LPARAM)this;
  295. this->AddRef();
  296. hpage = CreatePropertySheetPage(&psp);
  297. if (NULL != hpage)
  298. {
  299. if (!lpfnAddPage(hpage, lParam))
  300. {
  301. DestroyPropertySheetPage(hpage);
  302. }
  303. }
  304. return TRUE;
  305. }
  306. //+-------------------------------------------------------------------------
  307. //
  308. // Member: CNetObj::ReplacePages
  309. //
  310. // Derivation: IShellPropSheetExt
  311. //
  312. // Synopsis: (From shlobj.h)
  313. // "The explorer never calls this member of property sheet
  314. // extensions. The explorer calls this member of control panel
  315. // extensions, so that they can replace some of default control
  316. // panel pages (such as a page of mouse control panel)."
  317. //
  318. // Arguments: uPageID -- Specifies the page to be replaced.
  319. // lpfnReplace -- Specifies the callback function.
  320. // lParam -- Specifies the opaque handle to be passed to the
  321. // callback function.
  322. //
  323. // History: 4-Apr-95 BruceFo Created
  324. //
  325. //--------------------------------------------------------------------------
  326. STDMETHODIMP
  327. CNetObj::ReplacePage(
  328. UINT uPageID,
  329. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  330. LPARAM lParam
  331. )
  332. {
  333. CHECK_SIG(CNetObj);
  334. appAssert(!"CNetObj::ReplacePage called, not implemented");
  335. return E_NOTIMPL;
  336. }
  337. // dummy function to export to get linking to work
  338. HRESULT PropDummyFunction()
  339. {
  340. return S_OK;
  341. }