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.

406 lines
10 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 <shsemip.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)(MAKELONG(SHGetNetResourceORD, 0)));
  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. _pDataObject = NULL;
  97. }
  98. if (_hkeyProgID)
  99. {
  100. LONG l = RegCloseKey(_hkeyProgID);
  101. if (l != ERROR_SUCCESS)
  102. {
  103. appDebugOut((DEB_ERROR, "CNetObj::destructor. Error closing registry key, 0x%08lx\n", l));
  104. }
  105. _hkeyProgID = NULL;
  106. }
  107. }
  108. //+-------------------------------------------------------------------------
  109. //
  110. // Member: CNetObj::Initialize
  111. //
  112. // Derivation: IShellExtInit
  113. //
  114. // Synopsis: Initialize the shell extension. Stashes away the argument data.
  115. //
  116. // History: 4-Apr-95 BruceFo Created
  117. //
  118. // Notes: This method can be called more than once.
  119. //
  120. //--------------------------------------------------------------------------
  121. STDMETHODIMP
  122. CNetObj::Initialize(
  123. LPCITEMIDLIST pidlFolder,
  124. LPDATAOBJECT pDataObject,
  125. HKEY hkeyProgID
  126. )
  127. {
  128. CHECK_SIG(CNetObj);
  129. CNetObj::~CNetObj();
  130. if (!LoadShellDllEntries())
  131. {
  132. return E_FAIL;
  133. }
  134. // Duplicate the pDataObject pointer
  135. _pDataObject = pDataObject;
  136. if (pDataObject)
  137. {
  138. pDataObject->AddRef();
  139. }
  140. // Duplicate the handle
  141. if (hkeyProgID)
  142. {
  143. LONG l = RegOpenKeyEx(hkeyProgID, NULL, 0L, MAXIMUM_ALLOWED, &_hkeyProgID);
  144. if (l != ERROR_SUCCESS)
  145. {
  146. appDebugOut((DEB_ERROR, "CNetObj::Initialize. Error duplicating registry key, 0x%08lx\n", l));
  147. }
  148. }
  149. return S_OK;
  150. }
  151. //+-------------------------------------------------------------------------
  152. //
  153. // Member: CNetObj::AddPages
  154. //
  155. // Derivation: IShellPropSheetExt
  156. //
  157. // Synopsis: (from shlobj.h)
  158. // "The explorer calls this member function when it finds a
  159. // registered property sheet extension for a particular type
  160. // of object. For each additional page, the extension creates
  161. // a page object by calling CreatePropertySheetPage API and
  162. // calls lpfnAddPage.
  163. //
  164. // Arguments: lpfnAddPage -- Specifies the callback function.
  165. // lParam -- Specifies the opaque handle to be passed to the
  166. // callback function.
  167. //
  168. // History: 4-Apr-95 BruceFo Created
  169. //
  170. //--------------------------------------------------------------------------
  171. STDMETHODIMP
  172. CNetObj::AddPages(
  173. LPFNADDPROPSHEETPAGE lpfnAddPage,
  174. LPARAM lParam
  175. )
  176. {
  177. CHECK_SIG(CNetObj);
  178. //
  179. // Call IDataObject::GetData asking for a g_cfNetResource (i.e., HNRES).
  180. //
  181. STGMEDIUM medium;
  182. FORMATETC fmte =
  183. {
  184. g_cfNetResource
  185. ? g_cfNetResource
  186. : (g_cfNetResource = RegisterClipboardFormat(CFSTR_NETRESOURCES)),
  187. NULL,
  188. DVASPECT_CONTENT,
  189. -1,
  190. TYMED_HGLOBAL
  191. };
  192. appAssert(NULL != _pDataObject);
  193. HRESULT hr = _pDataObject->GetData(&fmte, &medium);
  194. CHECK_HRESULT(hr);
  195. if (FAILED(hr))
  196. {
  197. return hr;
  198. }
  199. ///////////////// Now I have a 'medium' to release
  200. hr = S_OK;
  201. HNRES hnres = medium.hGlobal;
  202. // Get number of selected items
  203. if (NULL != g_pFuncGNR)
  204. {
  205. UINT cItems = (*g_pFuncGNR)(hnres, (UINT)-1, NULL, 0);
  206. if (cItems > 0)
  207. {
  208. // Retrieve NETRESOURCE object from clipboard
  209. LPNETRESOURCE pNetRes = (LPNETRESOURCE)_bufNetResource;
  210. UINT ret = (*g_pFuncGNR)(hnres, 0, pNetRes, MAX_ONE_RESOURCE); // Get first item
  211. if (ret == 0)
  212. {
  213. // bad hnres?
  214. appDebugOut((DEB_TRACE, "CNetObj::AddPages. SHGetNetResource returned 0\n"));
  215. // NOTE: this is really error
  216. }
  217. else if (ret > MAX_ONE_RESOURCE)
  218. {
  219. // FEATURE: Resize the buf and try again
  220. appDebugOut((DEB_TRACE, "CNetObj::AddPages. buffer too small, needs to be %d\n", ret));
  221. }
  222. else
  223. {
  224. LPTSTR pszTemplate = NULL;
  225. if (RESOURCEDISPLAYTYPE_NETWORK == pNetRes->dwDisplayType)
  226. {
  227. pszTemplate = MAKEINTRESOURCE(IDD_NETWORK_SUMMARYINFO);
  228. }
  229. else if (RESOURCEDISPLAYTYPE_DOMAIN == pNetRes->dwDisplayType)
  230. {
  231. pszTemplate = MAKEINTRESOURCE(IDD_WRKGRP_SUMMARYINFO);
  232. }
  233. else if (RESOURCEDISPLAYTYPE_SERVER == pNetRes->dwDisplayType)
  234. {
  235. pszTemplate = MAKEINTRESOURCE(IDD_SERVER_SUMMARYINFO);
  236. }
  237. else if (RESOURCEDISPLAYTYPE_SHARE == pNetRes->dwDisplayType)
  238. {
  239. pszTemplate = MAKEINTRESOURCE(IDD_SHARE_SUMMARYINFO);
  240. }
  241. else
  242. {
  243. appDebugOut((DEB_TRACE, "CNetObj::AddPages. Unknown net resource type!\n"));
  244. }
  245. //
  246. // Create a property sheet page object from a dialog box.
  247. //
  248. if (NULL != pszTemplate)
  249. {
  250. hr = FillAndAddPage(
  251. lpfnAddPage,
  252. lParam,
  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. HRESULT
  272. CNetObj::FillAndAddPage(
  273. LPFNADDPROPSHEETPAGE lpfnAddPage,
  274. LPARAM lParam,
  275. LPTSTR pszTemplate
  276. )
  277. {
  278. PROPSHEETPAGE psp;
  279. HPROPSHEETPAGE hpage;
  280. CPage* pPage = new CPage(this);
  281. if (NULL == pPage)
  282. {
  283. return E_OUTOFMEMORY;
  284. }
  285. HRESULT hr = pPage->InitInstance();
  286. if (FAILED(hr))
  287. {
  288. delete pPage;
  289. return E_OUTOFMEMORY;
  290. }
  291. psp.dwSize = sizeof(psp); // no extra data.
  292. psp.dwFlags = PSP_USEREFPARENT | PSP_USECALLBACK;
  293. psp.hInstance = g_hInstance;
  294. psp.pszTemplate = pszTemplate;
  295. psp.hIcon = NULL;
  296. psp.pszTitle = NULL;
  297. psp.pfnDlgProc = CPage::DlgProcPage;
  298. psp.pfnCallback = CPage::PageCallback;
  299. psp.pcRefParent = &g_NonOLEDLLRefs;
  300. psp.lParam = (LPARAM)pPage;
  301. hpage = CreatePropertySheetPage(&psp);
  302. if (NULL == hpage)
  303. {
  304. delete pPage;
  305. return E_OUTOFMEMORY;
  306. }
  307. BOOL fAdded = (*lpfnAddPage)(hpage, lParam);
  308. if (!fAdded)
  309. {
  310. DestroyPropertySheetPage(hpage);
  311. return E_OUTOFMEMORY;
  312. }
  313. return S_OK;
  314. }
  315. //+-------------------------------------------------------------------------
  316. //
  317. // Member: CNetObj::ReplacePages
  318. //
  319. // Derivation: IShellPropSheetExt
  320. //
  321. // Synopsis: (From shlobj.h)
  322. // "The explorer never calls this member of property sheet
  323. // extensions. The explorer calls this member of control panel
  324. // extensions, so that they can replace some of default control
  325. // panel pages (such as a page of mouse control panel)."
  326. //
  327. // Arguments: uPageID -- Specifies the page to be replaced.
  328. // lpfnReplace -- Specifies the callback function.
  329. // lParam -- Specifies the opaque handle to be passed to the
  330. // callback function.
  331. //
  332. // History: 4-Apr-95 BruceFo Created
  333. //
  334. //--------------------------------------------------------------------------
  335. STDMETHODIMP
  336. CNetObj::ReplacePage(
  337. UINT uPageID,
  338. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  339. LPARAM lParam
  340. )
  341. {
  342. CHECK_SIG(CNetObj);
  343. appAssert(!"CNetObj::ReplacePage called, not implemented");
  344. return E_NOTIMPL;
  345. }
  346. // dummy function to export to get linking to work
  347. HRESULT PropDummyFunction()
  348. {
  349. return S_OK;
  350. }