Leaked source code of windows server 2003
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.

1795 lines
34 KiB

  1. /*++
  2. Copyright (C) Microsoft Corporation, 1997 - 1999
  3. All rights reserved.
  4. Module Name:
  5. shellext.cxx
  6. Abstract:
  7. Printer shell extension.
  8. Author:
  9. Steve Kiraly (SteveKi) 02-Feb-1997
  10. Revision History:
  11. --*/
  12. #include "precomp.hxx"
  13. #pragma hdrstop
  14. #include "portslv.hxx"
  15. #include "dsinterf.hxx"
  16. #include "prtprop.hxx"
  17. #include "physloc.hxx"
  18. #include "locprop.hxx"
  19. #include "findloc.hxx"
  20. #include "shellext.hxx"
  21. #include "spinterf.hxx"
  22. #include "prtshare.hxx"
  23. #include <initguid.h>
  24. #include "winprtp.h"
  25. /********************************************************************
  26. In-process server functions
  27. ********************************************************************/
  28. /*++
  29. Name:
  30. DllGetClassObject
  31. Description:
  32. DllGetClassObject is called by the shell to
  33. create a class factory object.
  34. Arguments:
  35. rclsid - Reference to class ID specifier
  36. riid - Reference to interface ID specifier
  37. ppv - Pointer to location to receive interface pointer
  38. Return Value:
  39. HRESULT code signifying success or failure
  40. --*/
  41. STDAPI
  42. DllGetClassObject(
  43. REFCLSID rclsid,
  44. REFIID riid,
  45. LPVOID *ppv
  46. )
  47. {
  48. *ppv = NULL;
  49. //
  50. // Make sure the class ID is CLSID_PrintUIExtension. Otherwise, the class
  51. // factory doesn't support the object type specified by rclsid.
  52. //
  53. if (!IsEqualCLSID (rclsid, CLSID_PrintUIShellExtension))
  54. return ResultFromScode (CLASS_E_CLASSNOTAVAILABLE);
  55. //
  56. // Instantiate a class factory object.
  57. //
  58. TClassFactory *pClassFactory = new TClassFactory ();
  59. if (pClassFactory == NULL)
  60. return ResultFromScode (E_OUTOFMEMORY);
  61. //
  62. // Get the interface pointer from QueryInterface and copy it to *ppv.
  63. //
  64. HRESULT hr = pClassFactory->QueryInterface (riid, ppv);
  65. pClassFactory->Release ();
  66. return hr;
  67. }
  68. /*++
  69. Name:
  70. DllCanUnloadNow
  71. Description:
  72. DllCanUnloadNow is called by the shell to find out if the
  73. DLL can be unloaded. The answer is yes if (and only if)
  74. the module reference count stored in gcRefThisDll is 0.
  75. Arguments:
  76. None
  77. Return Value:
  78. HRESULT code equal to S_OK if the DLL can be unloaded,
  79. S_FALSE if not.
  80. --*/
  81. STDAPI
  82. DllCanUnloadNow(
  83. VOID
  84. )
  85. {
  86. LONG lObjectsAlive = COMObjects_GetCount() + gcRefThisDll;
  87. return ResultFromScode( lObjectsAlive == 0 ? S_OK : S_FALSE );
  88. }
  89. ////////////////////////////////
  90. // QueryInterface tables
  91. // TClassFactory
  92. QITABLE_BEGIN(TClassFactory)
  93. QITABENT(TClassFactory, IClassFactory), // IID_IClassFactory
  94. QITABLE_END()
  95. // TShellExtension
  96. QITABLE_BEGIN(TShellExtension)
  97. QITABENT(TShellExtension, IShellExtInit), // IID_IShellExtInit
  98. QITABENT(TShellExtension, IContextMenu), // IID_IContextMenu
  99. QITABENT(TShellExtension, IShellPropSheetExt), // IID_IShellPropSheetExt
  100. QITABENT(TShellExtension, IDsFolderProperties), // IID_IDsFolderProperties
  101. QITABENT(TShellExtension, IDsPrinterProperties), // IID_IDsPrinterProperties
  102. QITABENT(TShellExtension, IFindPrinter), // IID_IFindPrinter
  103. QITABENT(TShellExtension, IPhysicalLocation), // IID_IPhysicalLocation
  104. QITABENT(TShellExtension, IPrnStream), // IID_IPrnStream
  105. QITABENT(TShellExtension, IStream), // IID_IStream
  106. QITABENT(TShellExtension, IPrintUIServices), // IID_IPrintUIServices
  107. QITABLE_END()
  108. /********************************************************************
  109. TClassFactory member functions
  110. ********************************************************************/
  111. TClassFactory::
  112. TClassFactory(
  113. VOID
  114. )
  115. {
  116. InterlockedIncrement( &gcRefThisDll );
  117. }
  118. TClassFactory::
  119. ~TClassFactory(
  120. VOID
  121. )
  122. {
  123. InterlockedDecrement( &gcRefThisDll );
  124. }
  125. /*++
  126. Name:
  127. CreateInstance
  128. Description:
  129. CreateInstance is called by the shell to create a
  130. shell extension object.
  131. Arguments:
  132. pUnkOuter - Pointer to controlling unknown
  133. riid - Reference to interface ID specifier
  134. ppvObj - Pointer to location to receive interface pointer
  135. Return Value:
  136. HRESULT code signifying success or failure
  137. --*/
  138. STDMETHODIMP
  139. TClassFactory::
  140. CreateInstance(
  141. LPUNKNOWN pUnkOuter,
  142. REFIID riid,
  143. LPVOID *ppvObj
  144. )
  145. {
  146. *ppvObj = NULL;
  147. //
  148. // Return an error code if pUnkOuter is not NULL,
  149. // we don't support aggregation.
  150. //
  151. if (pUnkOuter != NULL)
  152. {
  153. return CLASS_E_NOAGGREGATION;
  154. }
  155. //
  156. // Instantiate a shell extension object.
  157. // ref count == 1 after construction.
  158. //
  159. TShellExtension *pShellExtension = new TShellExtension ();
  160. if( pShellExtension == NULL )
  161. {
  162. return E_OUTOFMEMORY;
  163. }
  164. //
  165. // Get the specified interface pointer.
  166. //
  167. HRESULT hr = pShellExtension->QueryInterface( riid, ppvObj );
  168. //
  169. // Release initial reference.
  170. //
  171. pShellExtension->Release ();
  172. return hr;
  173. }
  174. /*++
  175. Name:
  176. LockServer
  177. Description:
  178. LockServer increments or decrements the DLL's lock count.
  179. Currently not implemented.
  180. Arguments:
  181. fLock - Increments or decrements the lock count.
  182. Return Value:
  183. This method supports the standard return values E_FAIL,
  184. E_OUTOFMEMORY, and E_UNEXPECTED, as well as the following:
  185. S_OK The specified object was either locked ( fLock = TRUE)
  186. or unlocked from memory ( fLock = FALSE).
  187. --*/
  188. STDMETHODIMP
  189. TClassFactory::
  190. LockServer(
  191. BOOL fLock
  192. )
  193. {
  194. return E_NOTIMPL;
  195. }
  196. /********************************************************************
  197. TShellExtension member functions
  198. ********************************************************************/
  199. TShellExtension::
  200. TShellExtension(
  201. VOID
  202. ): _lpdobj( NULL ),
  203. _pPhysicalLocation( NULL ),
  204. _pLocationPropertySheet( NULL ),
  205. _pLocationDlg( NULL )
  206. {
  207. DBGMSG( DBG_TRACE, ("TShellExtension::TShellExtension\n") );
  208. InterlockedIncrement( &gcRefThisDll );
  209. }
  210. TShellExtension::
  211. ~TShellExtension(
  212. VOID
  213. )
  214. {
  215. DBGMSG( DBG_TRACE, ("TShellExtension::~TShellExtension\n") );
  216. if( _lpdobj )
  217. {
  218. _lpdobj->Release();
  219. }
  220. delete _pPhysicalLocation;
  221. delete _pLocationDlg;
  222. TLocationPropertySheetFrontEnd::Destroy( &_pLocationPropertySheet );
  223. InterlockedDecrement( &gcRefThisDll );
  224. }
  225. /*++
  226. Name:
  227. Initialize
  228. Description:
  229. Initialize is called by the shell to initialize a shell extension.
  230. Arguments:
  231. pidlFolder - Pointer to ID list identifying parent folder
  232. lpdobj - Pointer to IDataObject interface for selected object(s)
  233. hKeyProgId - Registry key handle
  234. Return Value:
  235. HRESULT code signifying success or failure
  236. --*/
  237. STDMETHODIMP
  238. TShellExtension::
  239. Initialize(
  240. LPCITEMIDLIST pidlFolder,
  241. LPDATAOBJECT lpdobj,
  242. HKEY hKeyProgID
  243. )
  244. {
  245. DBGMSG( DBG_TRACE, ( "TShellExtension::Initialize\n" ) );
  246. if (_lpdobj)
  247. {
  248. _lpdobj->Release();
  249. }
  250. _lpdobj = lpdobj;
  251. if (_lpdobj)
  252. {
  253. _lpdobj->AddRef();
  254. }
  255. return NOERROR;
  256. }
  257. /*++
  258. Name:
  259. QueryContextMenu
  260. Description:
  261. QueryContextMenu is called before a context menu is displayed so the
  262. extension handler can add items to the menu.
  263. Arguments:
  264. hMenu - Context menu handle
  265. indexMenu - Index for first new menu item
  266. idCmdFirst - Item ID for first new menu item
  267. idCmdLast - Maximum menu item ID that can be used
  268. uFlags - Flags, are bit field specifying in what context the shell
  269. Return Value:
  270. HRESULT code signifying success or failure. If successful, the 'code'
  271. field specifies the number of items added to the context menu.
  272. --*/
  273. STDMETHODIMP
  274. TShellExtension::
  275. QueryContextMenu(
  276. HMENU hMenu,
  277. UINT indexMenu,
  278. UINT idCmdFirst,
  279. UINT idCmdLast,
  280. UINT uFlags
  281. )
  282. {
  283. DBGMSG( DBG_TRACE, ( "TShellExtension::QueryContextMenu\n" ) );
  284. HRESULT hr = E_FAIL;
  285. return hr;
  286. }
  287. /*++
  288. Name:
  289. InvokeCommand
  290. Description:
  291. InvokeCommand is called when a menu item added
  292. by the extension handler is selected.
  293. Arguments:
  294. lpcmi - Pointer to CMINVOKECOMMAND structure
  295. Return Value:
  296. HRESULT code signifying success or failure
  297. --*/
  298. STDMETHODIMP
  299. TShellExtension::
  300. InvokeCommand(
  301. LPCMINVOKECOMMANDINFO lpcmi
  302. )
  303. {
  304. DBGMSG( DBG_TRACE, ( "TShellExtension::InvokeCommand\n" ) );
  305. HRESULT hr = E_FAIL;
  306. return hr;
  307. }
  308. /*++
  309. Name:
  310. GetCommandString
  311. Description:
  312. GetCommandString is called to retrieve a string of help text or a
  313. language-independent command string for an item added to the context
  314. menu.
  315. Arguments:
  316. idCmd - 0-based offset of menu item identifier
  317. uFlags - Requested information type
  318. reserved - Pointer to reserved value (do not use)
  319. pszName - Pointer to buffer to receive the string
  320. cchMax - Buffer size
  321. Return Value:
  322. HRESULT code signifying success or failure
  323. --*/
  324. STDMETHODIMP
  325. TShellExtension::
  326. GetCommandString(
  327. UINT_PTR idCmd,
  328. UINT uFlags,
  329. UINT *Reserved,
  330. LPSTR pszName,
  331. UINT cchMax
  332. )
  333. {
  334. DBGMSG( DBG_TRACE, ( "TShellExtension::GetCommandString\n" ) );
  335. HRESULT hr = E_INVALIDARG;
  336. return hr;
  337. }
  338. /*++
  339. Name:
  340. AddPages
  341. Description:
  342. AddPages is called by the shell to give property sheet shell extensions
  343. the opportunity to add pages to a property sheet before it is displayed.
  344. Arguments:
  345. lpfnAddPage - Pointer to function called to add a page
  346. lParam - lParam parameter to be passed to lpfnAddPage
  347. Return Value:
  348. HRESULT code signifying success or failure
  349. --*/
  350. STDMETHODIMP
  351. TShellExtension::
  352. AddPages(
  353. LPFNADDPROPSHEETPAGE lpfnAddPage,
  354. LPARAM lParam
  355. )
  356. {
  357. DBGMSG( DBG_TRACE, ( "TShellExtension::AddPages\n" ) );
  358. return TLocationPropertySheetFrontEnd::Create( &_pLocationPropertySheet, this, _lpdobj, lpfnAddPage, lParam );
  359. }
  360. /*++
  361. Name:
  362. ReplacePage
  363. Description:
  364. ReplacePage is called by the shell to give control panel extensions the
  365. opportunity to replace control panel property sheet pages. It is never
  366. called for conventional property sheet extensions, so we simply return
  367. a failure code if called.
  368. Arguments:
  369. uPageID - Page to replace
  370. lpfnReplaceWith - Pointer to function called to replace a page
  371. lParam - lParam parameter to be passed to lpfnReplaceWith
  372. Return Value:
  373. HRESULT code signifying success or failure
  374. --*/
  375. STDMETHODIMP
  376. TShellExtension::
  377. ReplacePage(
  378. UINT uPageID,
  379. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  380. LPARAM lParam
  381. )
  382. {
  383. return E_NOTIMPL;
  384. }
  385. /*++
  386. Name:
  387. ShowProperties
  388. Description:
  389. This is a private interface used to override the "Properties" verb
  390. displayed in the DS client UI.
  391. Arguments:
  392. hwndParent - Window handle of the calling window.
  393. pDataObject - Pointer to an IDataObject from the DS name client UI.
  394. Return Value:
  395. S_FALSE no UI was displayed the the caller should display properties
  396. --*/
  397. STDMETHODIMP
  398. TShellExtension::
  399. ShowProperties(
  400. IN HWND hwndParent,
  401. IN IDataObject *pDataObject
  402. )
  403. {
  404. DBGMSG( DBG_TRACE, ( "TShellExtension::ShowProperties\n" ) );
  405. BOOL bDisplayed = FALSE;
  406. HRESULT hr = S_OK;
  407. DWORD dwStatus = dwPrinterPropPages( hwndParent, pDataObject, &bDisplayed );
  408. if( dwStatus != ERROR_SUCCESS )
  409. {
  410. if( !bDisplayed )
  411. {
  412. //
  413. // Display an error message indicating that properties cannot be displayed.
  414. //
  415. iMessage( hwndParent,
  416. IDS_ERR_PRINTER_PROP_TITLE,
  417. IDS_ERR_PRINTER_PROP_NONE,
  418. MB_OK|MB_ICONSTOP,
  419. kMsgNone,
  420. NULL );
  421. }
  422. hr = E_FAIL;
  423. }
  424. return hr;
  425. }
  426. /*++
  427. Name:
  428. ShowProperties
  429. Description:
  430. This is a private interface used to override the "Properties" verb
  431. displayed in the DS client UI.
  432. Arguments:
  433. hwndParent - Window handle of the calling window.
  434. pszObjectProperties - Pointer to either DS path or Unc Name
  435. Return Value:
  436. S_FALSE no UI was displayed the the caller should display properties
  437. --*/
  438. STDMETHODIMP
  439. TShellExtension::
  440. ShowProperties(
  441. IN HWND hwndParent,
  442. IN LPCTSTR pszObjectPath,
  443. IN PBOOL pbDisplayed
  444. )
  445. {
  446. DBGMSG( DBG_TRACE, ( "TShellExtension::ShowProperties\n" ) );
  447. HRESULT hr = S_OK;
  448. if( dwPrinterPropPages( hwndParent, pszObjectPath, pbDisplayed ) != ERROR_SUCCESS )
  449. {
  450. hr = E_FAIL;
  451. }
  452. return hr;
  453. }
  454. /*++
  455. Name:
  456. FindPrinter
  457. Description:
  458. This is a private interface used to find a printer either in the
  459. DS or on the network.
  460. Arguments:
  461. hwndParent - Window handle of the calling window.
  462. pszBuffer - pointer to buffer where to store returned printer name.
  463. puSize - input points to the size of the provided buffer in characters,
  464. on return points to the size of the returned printer name.
  465. Return Value:
  466. S_OK printer was found and buffer contains the returned name.
  467. --*/
  468. STDMETHODIMP
  469. TShellExtension::
  470. FindPrinter(
  471. IN HWND hwndParent,
  472. IN OUT LPTSTR pszBuffer,
  473. IN UINT *puSize
  474. )
  475. {
  476. DBGMSG( DBG_TRACE, ( "TShellExtension::ShowProperties\n" ) );
  477. HRESULT hr = E_FAIL;
  478. if( bPrinterSetup( hwndParent, MSP_FINDPRINTER, *puSize, pszBuffer, puSize, NULL ) )
  479. {
  480. hr = S_OK;
  481. }
  482. else if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  483. {
  484. hr = E_OUTOFMEMORY;
  485. }
  486. return hr;
  487. }
  488. /*++
  489. Name:
  490. DiscoverPhysicalLocation
  491. Description:
  492. This routine is used to start the physical location discovery
  493. process. The physical location discovery process will potentialy
  494. issue network calls which can take a large amount of time.
  495. Users of the IPhysicalLocation interface are required to call this
  496. method before getting the physical Location string, using
  497. GetPhyscialLocation.
  498. Arguments:
  499. none.
  500. Return Value:
  501. S_OK printer location was discovered, error code if the discovery
  502. process failed or a physical location string was not found.
  503. --*/
  504. STDMETHODIMP
  505. TShellExtension::
  506. DiscoverPhysicalLocation(
  507. VOID
  508. )
  509. {
  510. HRESULT hr = E_FAIL;
  511. //
  512. // Create the physical location object if this is the first call.
  513. //
  514. if (!_pPhysicalLocation)
  515. {
  516. _pPhysicalLocation = new TPhysicalLocation;
  517. }
  518. //
  519. // Invoke the discover method if the physical location
  520. // object was create successfully.
  521. //
  522. if (VALID_PTR(_pPhysicalLocation))
  523. {
  524. hr = _pPhysicalLocation->Discover() ? S_OK : E_FAIL;
  525. }
  526. else
  527. {
  528. hr = E_OUTOFMEMORY;
  529. }
  530. return hr;
  531. }
  532. /*++
  533. Name:
  534. GetExactPhysicalLocation
  535. Description:
  536. This routine gets the physical location string of this machine. Callers
  537. of this interface are required to call DiscoverPhysicalLocation prior to
  538. calling this method or this method will fail.
  539. Arguments:
  540. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  541. Return Value:
  542. S_OK physical location was discovered, error code if the discovery
  543. process failed or a physical location string was not found.
  544. --*/
  545. STDMETHODIMP
  546. TShellExtension::
  547. GetExactPhysicalLocation(
  548. IN OUT BSTR *pbsLocation
  549. )
  550. {
  551. DBGMSG( DBG_TRACE, ( "TShellExtension::GetExactPhysicalLocation.\n" ) );
  552. HRESULT hr = E_FAIL;
  553. //
  554. // Was Discover called, is object initialized?
  555. //
  556. if (_pPhysicalLocation)
  557. {
  558. TString strLocation;
  559. //
  560. // Get the physical location search string.
  561. //
  562. hr = _pPhysicalLocation->GetExact( strLocation ) ? S_OK : E_FAIL;
  563. if (SUCCEEDED(hr))
  564. {
  565. //
  566. // Allocate the location string.
  567. //
  568. *pbsLocation = SysAllocString( strLocation );
  569. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  570. }
  571. }
  572. else
  573. {
  574. hr = E_POINTER;
  575. }
  576. return hr;
  577. }
  578. /*++
  579. Name:
  580. GetSearchPhysicalLocation
  581. Description:
  582. This routine gets the best physical location search string for this machine.
  583. Users of this interface are required to call DiscoverPhysicalLocation
  584. prior to calling this method or this method will fail.
  585. Arguments:
  586. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  587. Return Value:
  588. S_OK physical location was discovered, error code if the discovery
  589. process failed or a physical location string was not found.
  590. --*/
  591. STDMETHODIMP
  592. TShellExtension::
  593. GetSearchPhysicalLocation(
  594. IN OUT BSTR *pbsLocation
  595. )
  596. {
  597. DBGMSG( DBG_TRACE, ( "TShellExtension::GetSearchPhysicalLocation.\n" ) );
  598. HRESULT hr = E_FAIL;
  599. //
  600. // Was Discover called, is object initialized?
  601. //
  602. if (_pPhysicalLocation)
  603. {
  604. TString strLocation;
  605. //
  606. // Get the physical location search string.
  607. //
  608. hr = _pPhysicalLocation->GetSearch( strLocation ) ? S_OK : E_FAIL;
  609. if (SUCCEEDED(hr))
  610. {
  611. //
  612. // Allocate the location string.
  613. //
  614. *pbsLocation = SysAllocString( strLocation );
  615. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  616. }
  617. }
  618. else
  619. {
  620. hr = E_POINTER;
  621. }
  622. return hr;
  623. }
  624. /*++
  625. Name:
  626. GetUserPhysicalLocation
  627. Description:
  628. This routine gets the physical location string of the user object in the DS
  629. Arguments:
  630. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  631. Return Value:
  632. S_OK physical location returned
  633. --*/
  634. STDMETHODIMP
  635. TShellExtension::
  636. GetUserPhysicalLocation(
  637. IN OUT BSTR *pbsLocation
  638. )
  639. {
  640. DBGMSG( DBG_TRACE, ( "TShellExtension::GetUserPhysicalLocation.\n" ) );
  641. HRESULT hr = E_FAIL;
  642. //
  643. // Create the physical location object if this is the first call.
  644. //
  645. if (!_pPhysicalLocation)
  646. {
  647. _pPhysicalLocation = new TPhysicalLocation;
  648. }
  649. if (VALID_PTR(_pPhysicalLocation))
  650. {
  651. TString strLocation;
  652. hr = _pPhysicalLocation->ReadUserLocationProperty( strLocation ) ? S_OK : E_FAIL;
  653. if (SUCCEEDED(hr))
  654. {
  655. //
  656. // Allocate the location string.
  657. //
  658. *pbsLocation = SysAllocString( strLocation );
  659. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  660. }
  661. }
  662. else
  663. {
  664. hr = E_OUTOFMEMORY;
  665. }
  666. return hr;
  667. }
  668. /*++
  669. Name:
  670. GetMachinePhysicalLocation
  671. Description:
  672. This routine gets the physical location string of this machine. The physical
  673. location string of this object may come from either group policy or the DS.
  674. Arguments:
  675. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  676. Return Value:
  677. S_OK physical location returned
  678. --*/
  679. STDMETHODIMP
  680. TShellExtension::
  681. GetMachinePhysicalLocation(
  682. IN OUT BSTR *pbsLocation
  683. )
  684. {
  685. DBGMSG( DBG_TRACE, ( "TShellExtension::GetMachinePhysicalLocation.\n" ) );
  686. HRESULT hr = E_FAIL;
  687. //
  688. // Create the physical location object if this is the first call.
  689. //
  690. if (!_pPhysicalLocation)
  691. {
  692. _pPhysicalLocation = new TPhysicalLocation;
  693. }
  694. if (VALID_PTR( _pPhysicalLocation ))
  695. {
  696. TString strLocation;
  697. //
  698. // First try the policy location.
  699. //
  700. hr = _pPhysicalLocation->ReadGroupPolicyLocationSetting( strLocation ) ? S_OK : E_FAIL;
  701. //
  702. // If the policy location was not found look in the DS.
  703. //
  704. if (FAILED(hr))
  705. {
  706. hr = _pPhysicalLocation->ReadMachinesLocationProperty( strLocation ) ? S_OK : E_FAIL;
  707. }
  708. if (SUCCEEDED(hr))
  709. {
  710. //
  711. // Allocate the location string.
  712. //
  713. *pbsLocation = SysAllocString( strLocation );
  714. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  715. }
  716. }
  717. else
  718. {
  719. hr = E_OUTOFMEMORY;
  720. }
  721. return hr;
  722. }
  723. /*++
  724. Name:
  725. GetSubnetPhysicalLocation
  726. Description:
  727. This routine gets the physical location string of the subnet object that closely
  728. matches this the subnet this machine is currently using.
  729. Arguments:
  730. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  731. Return Value:
  732. S_OK physical location returned
  733. --*/
  734. STDMETHODIMP
  735. TShellExtension::
  736. GetSubnetPhysicalLocation(
  737. IN OUT BSTR *pbsLocation
  738. )
  739. {
  740. DBGMSG( DBG_TRACE, ( "TShellExtension::GetSubnetPhysicalLocation.\n" ) );
  741. HRESULT hr = E_FAIL;
  742. //
  743. // Create the physical location object if this is the first call.
  744. //
  745. if (!_pPhysicalLocation)
  746. {
  747. _pPhysicalLocation = new TPhysicalLocation;
  748. }
  749. if (VALID_PTR( _pPhysicalLocation ))
  750. {
  751. TString strLocation;
  752. hr = _pPhysicalLocation->ReadSubnetLocationProperty( strLocation ) ? S_OK : E_FAIL;
  753. if (SUCCEEDED(hr))
  754. {
  755. //
  756. // Allocate the location string.
  757. //
  758. *pbsLocation = SysAllocString( strLocation );
  759. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  760. }
  761. }
  762. else
  763. {
  764. hr = E_OUTOFMEMORY;
  765. }
  766. return hr;
  767. }
  768. /*++
  769. Name:
  770. GetSitePhysicalLocation
  771. Description:
  772. This routine gets the physical location string of the size this machine
  773. belongs to.
  774. Arguments:
  775. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  776. Return Value:
  777. S_OK physical location returned
  778. --*/
  779. STDMETHODIMP
  780. TShellExtension::
  781. GetSitePhysicalLocation(
  782. IN OUT BSTR *pbsLocation
  783. )
  784. {
  785. DBGMSG( DBG_TRACE, ( "TShellExtension::GetSitePhysicalLocation.\n" ) );
  786. HRESULT hr = E_FAIL;
  787. //
  788. // Create the physical location object if this is the first call.
  789. //
  790. if (!_pPhysicalLocation)
  791. {
  792. _pPhysicalLocation = new TPhysicalLocation;
  793. }
  794. if (VALID_PTR( _pPhysicalLocation ))
  795. {
  796. TString strLocation;
  797. hr = _pPhysicalLocation->ReadSiteLocationProperty( strLocation ) ? S_OK : E_FAIL;
  798. if (SUCCEEDED(hr))
  799. {
  800. //
  801. // Allocate the location string.
  802. //
  803. *pbsLocation = SysAllocString( strLocation );
  804. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  805. }
  806. }
  807. else
  808. {
  809. hr = E_OUTOFMEMORY;
  810. }
  811. return hr;
  812. }
  813. /*++
  814. Name:
  815. BrowseForLocation
  816. Description:
  817. Displays UI for selecting a slash-delimited location name from among those
  818. specified by the DS admin for subnet objects
  819. Arguments:
  820. hParent - HWND to use as parent of dialog window
  821. bsDefault - location name to for initial tree expansion/selection
  822. pbsLocation - Receives selected location name
  823. Return Value:
  824. S_OK location returned
  825. Notes:
  826. --*/
  827. STDMETHODIMP
  828. TShellExtension::
  829. BrowseForLocation(
  830. IN HWND hParent,
  831. IN BSTR bsDefault,
  832. IN OUT BSTR *pbsLocation
  833. )
  834. {
  835. DBGMSG( DBG_TRACE, ( "TShellExtension::BrowseLocation.\n" ) );
  836. TStatusB bStatus;
  837. HRESULT hr = E_FAIL;
  838. //
  839. // Create the dialog object if this is the first call.
  840. //
  841. if (!_pLocationDlg)
  842. {
  843. _pLocationDlg = new TFindLocDlg;
  844. }
  845. //
  846. // Check if the location dialog is valid.
  847. //
  848. bStatus DBGNOCHK = VALID_PTR( _pLocationDlg );
  849. if( bStatus )
  850. {
  851. TString strLocation;
  852. TString strDefault;
  853. bStatus DBGCHK = strDefault.bUpdate( bsDefault );
  854. hr = _pLocationDlg->bDoModal( hParent, &strDefault ) ? S_OK : E_FAIL;
  855. if (SUCCEEDED(hr))
  856. {
  857. hr = _pLocationDlg->bGetLocation( strLocation ) ? S_OK : E_FAIL;
  858. if (SUCCEEDED(hr))
  859. {
  860. //
  861. // Allocate the location string.
  862. //
  863. *pbsLocation = SysAllocString( strLocation );
  864. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  865. }
  866. }
  867. }
  868. else
  869. {
  870. hr = E_OUTOFMEMORY;
  871. }
  872. return hr;
  873. }
  874. /*++
  875. Name:
  876. TShellExtension::ShowPhysicalLocationUI
  877. Description:
  878. Determine if Location Lite is enabled for this machine
  879. Arguments:
  880. None
  881. Return Value:
  882. S_OK if enabled
  883. Notes:
  884. --*/
  885. STDMETHODIMP
  886. TShellExtension::
  887. ShowPhysicalLocationUI(
  888. VOID
  889. )
  890. {
  891. HRESULT hr = E_FAIL;
  892. //
  893. // Create the physical location object if this is the first call.
  894. //
  895. if (!_pPhysicalLocation)
  896. {
  897. _pPhysicalLocation = new TPhysicalLocation;
  898. }
  899. if (VALID_PTR(_pPhysicalLocation))
  900. {
  901. hr = _pPhysicalLocation->bLocationEnabled() ? S_OK : E_FAIL;
  902. }
  903. else
  904. {
  905. hr = E_OUTOFMEMORY;
  906. }
  907. return hr;
  908. }
  909. /*++
  910. Name:
  911. TShellExtension::CheckToCreateStreams
  912. Description:
  913. Check to create m_spPrnStream & m_spStream
  914. Arguments:
  915. None
  916. Return Value:
  917. S_OK if succeeded
  918. --*/
  919. HRESULT
  920. TShellExtension::
  921. CheckToCreateStreams(
  922. VOID
  923. )
  924. {
  925. HRESULT hr = S_OK;
  926. if( !m_spPrnStream || !m_spStream )
  927. {
  928. // release the smart pointers first
  929. m_spPrnStream = NULL;
  930. m_spStream = NULL;
  931. // call into winspool.drv to create an instance
  932. hr = Winspool_CreateInstance(IID_IPrnStream, m_spPrnStream.GetPPV());
  933. if( SUCCEEDED(hr) )
  934. {
  935. hr = m_spPrnStream->QueryInterface(IID_IStream, m_spStream.GetPPV());
  936. }
  937. }
  938. return ((m_spPrnStream && m_spStream) ? hr : E_FAIL);
  939. }
  940. /*++
  941. Name:
  942. TShellExtension::BindPrinterAndFile
  943. Description:
  944. Creates a PrnStream object if it don't exists and bind it to a printer and a file
  945. Arguments:
  946. printer name
  947. file name
  948. Return Value:
  949. S_OK if succeeded
  950. --*/
  951. STDMETHODIMP
  952. TShellExtension::
  953. BindPrinterAndFile(
  954. IN LPCTSTR pszPrinter,
  955. IN LPCTSTR pszFile
  956. )
  957. {
  958. HRESULT hr = E_FAIL;
  959. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  960. {
  961. return m_spPrnStream->BindPrinterAndFile(pszPrinter, pszFile);
  962. }
  963. return hr;
  964. }
  965. /*++
  966. Name:
  967. TShellExtension::StorePrinterInfo
  968. Description:
  969. Creates a PrnStream object if it don't exists and invoke StorePrinterInfo
  970. Arguments:
  971. flags that specifies what settings to store
  972. Return Value:
  973. S_OK if succeeded
  974. --*/
  975. STDMETHODIMP
  976. TShellExtension::
  977. StorePrinterInfo(
  978. IN DWORD Flag
  979. )
  980. {
  981. HRESULT hr = E_FAIL;
  982. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  983. {
  984. return m_spPrnStream->StorePrinterInfo(Flag);
  985. }
  986. return hr;
  987. }
  988. /*++
  989. Name:
  990. TShellExtension::RestorePrinterInfo
  991. Description:
  992. Creates a PrnStream object if it don't exists and invoke RestorePrinterInfo
  993. Arguments:
  994. flags that specifies what settings to restore
  995. Return Value:
  996. S_OK if succeeded
  997. --*/
  998. STDMETHODIMP
  999. TShellExtension::
  1000. RestorePrinterInfo(
  1001. IN DWORD Flag
  1002. )
  1003. {
  1004. HRESULT hr = E_FAIL;
  1005. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1006. {
  1007. return m_spPrnStream->RestorePrinterInfo(Flag);
  1008. }
  1009. return hr;
  1010. }
  1011. /*++
  1012. Name:
  1013. TShellExtension::QueryPrinterInfo
  1014. Description:
  1015. Creates a PrnStream object if it don't exists and invoke QueryPrinterInfo
  1016. Arguments:
  1017. flags that specifies what settings to query
  1018. Return Value:
  1019. S_OK if succeeded
  1020. --*/
  1021. STDMETHODIMP
  1022. TShellExtension::
  1023. QueryPrinterInfo(
  1024. IN PrinterPersistentQueryFlag Flag,
  1025. OUT PersistentInfo *pPrstInfo
  1026. )
  1027. {
  1028. HRESULT hr = E_FAIL;
  1029. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1030. {
  1031. return m_spPrnStream->QueryPrinterInfo(Flag, pPrstInfo);
  1032. }
  1033. return hr;
  1034. }
  1035. /*++
  1036. Name:
  1037. TShellExtension::Read
  1038. Description:
  1039. Creates a PrnStream object if it don't exists and invoke Read
  1040. Arguments:
  1041. pv - The buffer that the bytes are read into
  1042. cb - The offset in the stream to begin reading from.
  1043. pcbRead - The number of bytes to read
  1044. Return Value:
  1045. S_OK if succeeded
  1046. --*/
  1047. STDMETHODIMP
  1048. TShellExtension::
  1049. Read(
  1050. VOID * pv,
  1051. ULONG cb,
  1052. ULONG * pcbRead
  1053. )
  1054. {
  1055. HRESULT hr = E_FAIL;
  1056. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1057. {
  1058. return m_spStream->Read(pv, cb, pcbRead);
  1059. }
  1060. return hr;
  1061. }
  1062. /*++
  1063. Name:
  1064. TShellExtension::Write
  1065. Description:
  1066. Creates a PrnStream object if it don't exists and invoke Write
  1067. Arguments:
  1068. pv - The buffer to write from.
  1069. cb - The offset in the array to begin writing from
  1070. pcbRead - The number of bytes to write
  1071. Return Value:
  1072. S_OK if succeeded
  1073. --*/
  1074. STDMETHODIMP
  1075. TShellExtension::
  1076. Write(
  1077. VOID const* pv,
  1078. ULONG cb,
  1079. ULONG * pcbWritten
  1080. )
  1081. {
  1082. HRESULT hr = E_FAIL;
  1083. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1084. {
  1085. return m_spStream->Write(pv, cb, pcbWritten);
  1086. }
  1087. return hr;
  1088. }
  1089. /*++
  1090. Name:
  1091. TShellExtension::Seek
  1092. Description:
  1093. Creates a PrnStream object if it don't exists and invoke Seek
  1094. Arguments:
  1095. dlibMove - The offset relative to dwOrigin
  1096. dwOrigin - The origin of the offset
  1097. plibNewPosition - Pointer to value of the new seek pointer from the beginning of the stream
  1098. Return Value:
  1099. S_OK if succeeded
  1100. --*/
  1101. STDMETHODIMP
  1102. TShellExtension::
  1103. Seek(
  1104. LARGE_INTEGER dlibMove,
  1105. DWORD dwOrigin,
  1106. ULARGE_INTEGER * plibNewPosition
  1107. )
  1108. {
  1109. HRESULT hr = E_FAIL;
  1110. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1111. {
  1112. return m_spStream->Seek(dlibMove, dwOrigin, plibNewPosition);
  1113. }
  1114. return hr;
  1115. }
  1116. /*++
  1117. Name:
  1118. TShellExtension::SetSize
  1119. Description:
  1120. Arguments:
  1121. Return Value:
  1122. E_NOTIMPL
  1123. --*/
  1124. STDMETHODIMP
  1125. TShellExtension::
  1126. SetSize(
  1127. ULARGE_INTEGER nSize
  1128. )
  1129. {
  1130. return E_NOTIMPL;
  1131. }
  1132. /*++
  1133. Name:
  1134. TShellExtension::CopyTo
  1135. Description:
  1136. Arguments:
  1137. Return Value:
  1138. E_NOTIMPL
  1139. --*/
  1140. STDMETHODIMP
  1141. TShellExtension::
  1142. CopyTo(
  1143. LPSTREAM pStrm,
  1144. ULARGE_INTEGER cb,
  1145. ULARGE_INTEGER * pcbRead,
  1146. ULARGE_INTEGER * pcbWritten
  1147. )
  1148. {
  1149. return E_NOTIMPL;
  1150. }
  1151. /*++
  1152. Name:
  1153. TShellExtension::Commit
  1154. Description:
  1155. Arguments:
  1156. Return Value:
  1157. E_NOTIMPL
  1158. --*/
  1159. STDMETHODIMP
  1160. TShellExtension::
  1161. Commit(
  1162. IN DWORD dwFlags
  1163. )
  1164. {
  1165. return E_NOTIMPL;
  1166. }
  1167. /*++
  1168. Name:
  1169. TShellExtension::Revert
  1170. Description:
  1171. Arguments:
  1172. Return Value:
  1173. E_NOTIMPL
  1174. --*/
  1175. STDMETHODIMP
  1176. TShellExtension::
  1177. Revert(
  1178. VOID
  1179. )
  1180. {
  1181. return E_NOTIMPL;
  1182. }
  1183. /*++
  1184. Name:
  1185. TShellExtension::LockRegion
  1186. Description:
  1187. Arguments:
  1188. Return Value:
  1189. E_NOTIMPL
  1190. --*/
  1191. STDMETHODIMP
  1192. TShellExtension::
  1193. LockRegion(
  1194. ULARGE_INTEGER cbOffset,
  1195. ULARGE_INTEGER cbLength,
  1196. DWORD dwFlags
  1197. )
  1198. {
  1199. return E_NOTIMPL;
  1200. }
  1201. /*++
  1202. Name:
  1203. TShellExtension::UnlockRegion
  1204. Description:
  1205. Arguments:
  1206. Return Value:
  1207. E_NOTIMPL
  1208. --*/
  1209. STDMETHODIMP
  1210. TShellExtension::
  1211. UnlockRegion(
  1212. ULARGE_INTEGER cbOffset,
  1213. ULARGE_INTEGER cbLength,
  1214. DWORD dwFlags
  1215. )
  1216. {
  1217. return E_NOTIMPL;
  1218. }
  1219. /*++
  1220. Name:
  1221. TShellExtension::Stat
  1222. Description:
  1223. Arguments:
  1224. Return Value:
  1225. E_NOTIMPL
  1226. --*/
  1227. STDMETHODIMP
  1228. TShellExtension::
  1229. Stat(
  1230. STATSTG * pStatStg,
  1231. DWORD dwFlags
  1232. )
  1233. {
  1234. return E_NOTIMPL;
  1235. }
  1236. /*++
  1237. Name:
  1238. TShellExtension::Clone
  1239. Description:
  1240. Arguments:
  1241. Return Value:
  1242. E_NOTIMPL
  1243. --*/
  1244. STDMETHODIMP
  1245. TShellExtension::
  1246. Clone(
  1247. LPSTREAM * ppStrm
  1248. )
  1249. {
  1250. return E_NOTIMPL;
  1251. }
  1252. /*++
  1253. Name:
  1254. TShellExtension::GenerateShareName
  1255. Description:
  1256. Arguments:
  1257. lpszServer - print server name
  1258. lpszBaseName - base name to start from
  1259. lpszOut - where to return the generated name
  1260. cchMaxChars - buffer size in characters
  1261. Return Value:
  1262. S_OK on success or OLE error otherwise
  1263. --*/
  1264. STDMETHODIMP
  1265. TShellExtension::
  1266. GenerateShareName(
  1267. LPCTSTR lpszServer,
  1268. LPCTSTR lpszBaseName,
  1269. LPTSTR lpszOut,
  1270. int cchMaxChars
  1271. )
  1272. {
  1273. HRESULT hr = E_INVALIDARG;
  1274. // lpszServer can be NULL to specify the local server,
  1275. // but lpszBaseName & lpszOut shouldn't be.
  1276. if( lpszBaseName && lpszOut )
  1277. {
  1278. TPrtShare prtShare(lpszServer);
  1279. TString strShareName, strBaseName;
  1280. strBaseName.bUpdate(lpszBaseName);
  1281. if( VALID_OBJ(prtShare) && VALID_OBJ(strBaseName) &&
  1282. prtShare.bNewShareName(strShareName, strBaseName) && strShareName.uLen() )
  1283. {
  1284. lstrcpyn(lpszOut, strShareName, cchMaxChars);
  1285. hr = (0 == lstrcmp(lpszOut, strShareName)) ? S_OK :
  1286. HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  1287. }
  1288. else
  1289. {
  1290. hr = E_FAIL;
  1291. }
  1292. }
  1293. return hr;
  1294. }