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.

2113 lines
39 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. _cItem( 0 ),
  204. _pPhysicalLocation( NULL ),
  205. _pLocationPropertySheet( NULL ),
  206. _pLocationDlg( NULL )
  207. {
  208. DBGMSG( DBG_TRACE, ("TShellExtension::TShellExtension\n") );
  209. _szContextName[0] = 0;
  210. InterlockedIncrement( &gcRefThisDll );
  211. }
  212. TShellExtension::
  213. ~TShellExtension(
  214. VOID
  215. )
  216. {
  217. DBGMSG( DBG_TRACE, ("TShellExtension::~TShellExtension\n") );
  218. if( _lpdobj )
  219. {
  220. _lpdobj->Release();
  221. }
  222. delete _pPhysicalLocation;
  223. delete _pLocationDlg;
  224. TLocationPropertySheetFrontEnd::Destroy( &_pLocationPropertySheet );
  225. InterlockedDecrement( &gcRefThisDll );
  226. }
  227. /*++
  228. Name:
  229. Initialize
  230. Description:
  231. Initialize is called by the shell to initialize a shell extension.
  232. Arguments:
  233. pidlFolder - Pointer to ID list identifying parent folder
  234. lpdobj - Pointer to IDataObject interface for selected object(s)
  235. hKeyProgId - Registry key handle
  236. Return Value:
  237. HRESULT code signifying success or failure
  238. --*/
  239. STDMETHODIMP
  240. TShellExtension::
  241. Initialize(
  242. LPCITEMIDLIST pidlFolder,
  243. LPDATAOBJECT lpdobj,
  244. HKEY hKeyProgID
  245. )
  246. {
  247. DBGMSG( DBG_TRACE, ( "TShellExtension::Initialize\n" ) );
  248. if (_lpdobj)
  249. {
  250. _lpdobj->Release();
  251. }
  252. _lpdobj = lpdobj;
  253. if (_lpdobj)
  254. {
  255. _lpdobj->AddRef();
  256. }
  257. return NOERROR;
  258. }
  259. /*++
  260. Name:
  261. QueryContextMenu
  262. Description:
  263. QueryContextMenu is called before a context menu is displayed so the
  264. extension handler can add items to the menu.
  265. Arguments:
  266. hMenu - Context menu handle
  267. indexMenu - Index for first new menu item
  268. idCmdFirst - Item ID for first new menu item
  269. idCmdLast - Maximum menu item ID that can be used
  270. uFlags - Flags, are bit field specifying in what context the shell
  271. Return Value:
  272. HRESULT code signifying success or failure. If successful, the 'code'
  273. field specifies the number of items added to the context menu.
  274. --*/
  275. STDMETHODIMP
  276. TShellExtension::
  277. QueryContextMenu(
  278. HMENU hMenu,
  279. UINT indexMenu,
  280. UINT idCmdFirst,
  281. UINT idCmdLast,
  282. UINT uFlags
  283. )
  284. {
  285. DBGMSG( DBG_TRACE, ( "TShellExtension::QueryContextMenu\n" ) );
  286. HRESULT hr = E_FAIL;
  287. return hr;
  288. }
  289. /*++
  290. Name:
  291. InvokeCommand
  292. Description:
  293. InvokeCommand is called when a menu item added
  294. by the extension handler is selected.
  295. Arguments:
  296. lpcmi - Pointer to CMINVOKECOMMAND structure
  297. Return Value:
  298. HRESULT code signifying success or failure
  299. --*/
  300. STDMETHODIMP
  301. TShellExtension::
  302. InvokeCommand(
  303. LPCMINVOKECOMMANDINFO lpcmi
  304. )
  305. {
  306. DBGMSG( DBG_TRACE, ( "TShellExtension::InvokeCommand\n" ) );
  307. HRESULT hr = E_FAIL;
  308. //
  309. // Return an error code if we've been called programmatically.
  310. //
  311. if( !HIWORD( (ULONG_PTR)lpcmi->lpVerb ) )
  312. {
  313. //
  314. // Dispatch to the correct command.
  315. //
  316. switch( LOWORD( (ULONG_PTR)lpcmi->lpVerb ) )
  317. {
  318. case 1:
  319. default:
  320. hr = E_INVALIDARG;
  321. break;
  322. }
  323. }
  324. return hr;
  325. }
  326. /*++
  327. Name:
  328. GetCommandString
  329. Description:
  330. GetCommandString is called to retrieve a string of help text or a
  331. language-independent command string for an item added to the context
  332. menu.
  333. Arguments:
  334. idCmd - 0-based offset of menu item identifier
  335. uFlags - Requested information type
  336. reserved - Pointer to reserved value (do not use)
  337. pszName - Pointer to buffer to receive the string
  338. cchMax - Buffer size
  339. Return Value:
  340. HRESULT code signifying success or failure
  341. --*/
  342. STDMETHODIMP
  343. TShellExtension::
  344. GetCommandString(
  345. UINT_PTR idCmd,
  346. UINT uFlags,
  347. UINT *Reserved,
  348. LPSTR pszName,
  349. UINT cchMax
  350. )
  351. {
  352. DBGMSG( DBG_TRACE, ( "TShellExtension::GetCommandString\n" ) );
  353. HRESULT hr = E_INVALIDARG;
  354. TString strCmdString;
  355. switch( uFlags )
  356. {
  357. case GCS_HELPTEXT:
  358. case GCS_VALIDATE:
  359. case GCS_VERB:
  360. default:
  361. hr = E_INVALIDARG;
  362. break;
  363. }
  364. return hr;
  365. }
  366. /*++
  367. Name:
  368. ContextMenuFormatToNumeric
  369. Description:
  370. Converts the context menu format bit field to a numeric
  371. value. The bit field is broken because CMF_NORMAL
  372. is definded as zero which need to be special cased.
  373. Arguments:
  374. uFlags - Flags passed to QueryContextMenu()
  375. Return Value:
  376. Context menu fromat enumeration.
  377. --*/
  378. UINT
  379. TShellExtension::
  380. ContextMenuFormatToNumeric(
  381. IN UINT uFlags
  382. ) const
  383. {
  384. UINT ContextMenuFormat = kUnknown;
  385. //
  386. // The normal value is 0, This is
  387. // so bogus, to define a bit field and
  388. // make one of the bits zero.
  389. //
  390. if( ( uFlags & 0x000F ) == CMF_NORMAL )
  391. {
  392. ContextMenuFormat = k_CMF_NORMAL;
  393. }
  394. else if( uFlags & CMF_VERBSONLY )
  395. {
  396. ContextMenuFormat = k_CMF_VERBSONLY;
  397. }
  398. else if( uFlags & CMF_EXPLORE )
  399. {
  400. ContextMenuFormat = k_CMF_EXPLORE;
  401. }
  402. else if( uFlags & CMF_DEFAULTONLY )
  403. {
  404. ContextMenuFormat = k_CMF_DEFAULTONLY;
  405. }
  406. else
  407. {
  408. ContextMenuFormat = kUnknown;
  409. }
  410. return ContextMenuFormat;
  411. }
  412. /*++
  413. Name:
  414. bIsAddPrinterWizard
  415. Description:
  416. bIsAddPrinterWizard checks if the object selected by this
  417. shell extension is actually the add printer wizard object.
  418. Arguments:
  419. Nothing.
  420. Return Value:
  421. TRUE object is add printer wizard, FALSE not add printer wizard.
  422. --*/
  423. BOOL
  424. TShellExtension::
  425. bIsAddPrinterWizard(
  426. VOID
  427. ) const
  428. {
  429. FORMATETC fe = { (WORD)RegisterClipboardFormat( CFSTR_PRINTERGROUP ),
  430. NULL,
  431. DVASPECT_CONTENT,
  432. -1,
  433. TYMED_HGLOBAL };
  434. BOOL bRetval = FALSE;
  435. STGMEDIUM medium;
  436. TCHAR szFile[MAX_PATH];
  437. //
  438. // Fail the call if m_lpdobj is NULL.
  439. //
  440. if( _lpdobj && SUCCEEDED( _lpdobj->GetData( &fe, &medium ) ) )
  441. {
  442. //
  443. // Get the selected item name.
  444. //
  445. if( DragQueryFile( (HDROP)medium.hGlobal, 0, szFile, COUNTOF( szFile ) ) )
  446. {
  447. //
  448. // Check if this is the magic Add Printer Wizard shell object.
  449. // The check is not case sensitive.
  450. //
  451. if( !_tcscmp( szFile, gszNewObject ) )
  452. {
  453. DBGMSG( DBG_TRACE, ( "Magical Add Printer Wizard object found.\n" ) );
  454. bRetval = TRUE;
  455. }
  456. }
  457. //
  458. // Release the storge medium.
  459. //
  460. ReleaseStgMedium( &medium );
  461. }
  462. return bRetval;
  463. }
  464. /*++
  465. Name:
  466. bGetContextName
  467. Description:
  468. Routine to get the context name of the object in the shell.
  469. This routine will work properly with the remote printers folder.
  470. Arguments:
  471. Nothing.
  472. Return Value:
  473. TRUE context menu name retrieved and stored in the _szContextName
  474. buffer. FLASE if name not retrieved.
  475. --*/
  476. BOOL
  477. TShellExtension::
  478. bGetContextName(
  479. VOID
  480. )
  481. {
  482. FORMATETC fe = { (WORD)RegisterClipboardFormat( CFSTR_SHELLIDLIST ),
  483. NULL,
  484. DVASPECT_CONTENT,
  485. -1,
  486. TYMED_HGLOBAL };
  487. BOOL bRetval = FALSE;
  488. STGMEDIUM medium;
  489. //
  490. // Fail the call if m_lpdobj is NULL.
  491. //
  492. if( _lpdobj && SUCCEEDED( _lpdobj->GetData( &fe, &medium ) ) )
  493. {
  494. if (medium.hGlobal)
  495. {
  496. LPIDA pIDA = (LPIDA)medium.hGlobal;
  497. //
  498. // Save the item count.
  499. //
  500. _cItem = pIDA->cidl;
  501. LPCITEMIDLIST pidlContainer = (LPCITEMIDLIST)((LPBYTE)pIDA + pIDA->aoffset[0]);
  502. LPCITEMIDLIST pidl = (LPCITEMIDLIST)((LPBYTE)pIDA + pIDA->aoffset[1]);
  503. //
  504. // Get the printer object context name. Note: A remote printers
  505. // folder object needs the full context information on the object.
  506. // i.e. \\server_name\printer_name
  507. //
  508. if( bGetDisplayName( pidlContainer, pidl, _szContextName, COUNTOF( _szContextName ) ) )
  509. {
  510. DBGMSG( DBG_TRACE, ( "Context Name " TSTR "\n", _szContextName ) );
  511. bRetval = TRUE;
  512. }
  513. }
  514. //
  515. // Release the medium storage.
  516. //
  517. ReleaseStgMedium (&medium);
  518. }
  519. return bRetval;
  520. }
  521. /*++
  522. Name:
  523. bGetDisplayName
  524. Description:
  525. Routine to get the context name of the object in the shell.
  526. This routine will work properly with the remote printers folder.
  527. Arguments:
  528. pidlContainer - pidle of containter,
  529. pidl - relative pidle passed by shell,
  530. pszDisplayName - pointer to display name buffer,
  531. cchSize - size in characters of display name buffer.
  532. Return Value:
  533. TRUE display name fill into provided display name buffer.
  534. FLASE if display name was not returned in buffer.
  535. --*/
  536. BOOL
  537. TShellExtension::
  538. bGetDisplayName(
  539. LPCITEMIDLIST pidlContainer,
  540. LPCITEMIDLIST pidl,
  541. LPTSTR pszDisplayName,
  542. UINT cchSize
  543. )
  544. {
  545. HRESULT hres;
  546. LPSHELLFOLDER psfDesktop;
  547. LPSHELLFOLDER psf;
  548. if( !pidlContainer || !pidl )
  549. {
  550. DBGMSG( DBG_TRACE, ( "NULL pidl as argument\n" ) );
  551. return FALSE;
  552. }
  553. hres = SHGetDesktopFolder(&psfDesktop);
  554. if (SUCCEEDED(hres))
  555. {
  556. hres = psfDesktop->BindToObject(pidlContainer, NULL, IID_IShellFolder, (PVOID*)&psf);
  557. if (SUCCEEDED(hres))
  558. {
  559. STRRET str;
  560. hres = psf->GetDisplayNameOf(pidl, SHGDN_FORPARSING, &str);
  561. if (SUCCEEDED(hres))
  562. {
  563. if( str.uType == STRRET_WSTR )
  564. {
  565. _tcsncpy( pszDisplayName, (LPTSTR)str.pOleStr, cchSize-1 );
  566. //
  567. // Since this string was alocated from the IMalloc heap
  568. // we must free it to the same place.
  569. //
  570. IMalloc *pMalloc;
  571. hres = CoGetMalloc( 1, &pMalloc );
  572. if( SUCCEEDED(hres))
  573. {
  574. pMalloc->Free( str.pOleStr );
  575. pMalloc->Release();
  576. }
  577. }
  578. else if( str.uType == STRRET_CSTR )
  579. {
  580. _tcsncpy( pszDisplayName, (LPTSTR)str.cStr, cchSize-1 );
  581. }
  582. }
  583. psf->Release();
  584. }
  585. psfDesktop->Release();
  586. }
  587. return SUCCEEDED(hres) ? TRUE : FALSE;
  588. }
  589. /*++
  590. Name:
  591. AddPages
  592. Description:
  593. AddPages is called by the shell to give property sheet shell extensions
  594. the opportunity to add pages to a property sheet before it is displayed.
  595. Arguments:
  596. lpfnAddPage - Pointer to function called to add a page
  597. lParam - lParam parameter to be passed to lpfnAddPage
  598. Return Value:
  599. HRESULT code signifying success or failure
  600. --*/
  601. STDMETHODIMP
  602. TShellExtension::
  603. AddPages(
  604. LPFNADDPROPSHEETPAGE lpfnAddPage,
  605. LPARAM lParam
  606. )
  607. {
  608. DBGMSG( DBG_TRACE, ( "TShellExtension::AddPages\n" ) );
  609. return TLocationPropertySheetFrontEnd::Create( &_pLocationPropertySheet, this, _lpdobj, lpfnAddPage, lParam );
  610. }
  611. /*++
  612. Name:
  613. ReplacePage
  614. Description:
  615. ReplacePage is called by the shell to give control panel extensions the
  616. opportunity to replace control panel property sheet pages. It is never
  617. called for conventional property sheet extensions, so we simply return
  618. a failure code if called.
  619. Arguments:
  620. uPageID - Page to replace
  621. lpfnReplaceWith - Pointer to function called to replace a page
  622. lParam - lParam parameter to be passed to lpfnReplaceWith
  623. Return Value:
  624. HRESULT code signifying success or failure
  625. --*/
  626. STDMETHODIMP
  627. TShellExtension::
  628. ReplacePage(
  629. UINT uPageID,
  630. LPFNADDPROPSHEETPAGE lpfnReplaceWith,
  631. LPARAM lParam
  632. )
  633. {
  634. return E_NOTIMPL;
  635. }
  636. /*++
  637. Name:
  638. ShowProperties
  639. Description:
  640. This is a private interface used to override the "Properties" verb
  641. displayed in the DS client UI.
  642. Arguments:
  643. hwndParent - Window handle of the calling window.
  644. pDataObject - Pointer to an IDataObject from the DS name client UI.
  645. Return Value:
  646. S_FALSE no UI was displayed the the caller should display properties
  647. --*/
  648. STDMETHODIMP
  649. TShellExtension::
  650. ShowProperties(
  651. IN HWND hwndParent,
  652. IN IDataObject *pDataObject
  653. )
  654. {
  655. DBGMSG( DBG_TRACE, ( "TShellExtension::ShowProperties\n" ) );
  656. BOOL bDisplayed = FALSE;
  657. HRESULT hr = S_OK;
  658. DWORD dwStatus = dwPrinterPropPages( hwndParent, pDataObject, &bDisplayed );
  659. if( dwStatus != ERROR_SUCCESS )
  660. {
  661. if( !bDisplayed )
  662. {
  663. //
  664. // Display an error message indicating that properties cannot be displayed.
  665. //
  666. iMessage( hwndParent,
  667. IDS_ERR_PRINTER_PROP_TITLE,
  668. IDS_ERR_PRINTER_PROP_NONE,
  669. MB_OK|MB_ICONSTOP,
  670. kMsgNone,
  671. NULL );
  672. }
  673. hr = E_FAIL;
  674. }
  675. return hr;
  676. }
  677. /*++
  678. Name:
  679. ShowProperties
  680. Description:
  681. This is a private interface used to override the "Properties" verb
  682. displayed in the DS client UI.
  683. Arguments:
  684. hwndParent - Window handle of the calling window.
  685. pszObjectProperties - Pointer to either DS path or Unc Name
  686. Return Value:
  687. S_FALSE no UI was displayed the the caller should display properties
  688. --*/
  689. STDMETHODIMP
  690. TShellExtension::
  691. ShowProperties(
  692. IN HWND hwndParent,
  693. IN LPCTSTR pszObjectPath,
  694. IN PBOOL pbDisplayed
  695. )
  696. {
  697. DBGMSG( DBG_TRACE, ( "TShellExtension::ShowProperties\n" ) );
  698. HRESULT hr = S_OK;
  699. if( dwPrinterPropPages( hwndParent, pszObjectPath, pbDisplayed ) != ERROR_SUCCESS )
  700. {
  701. hr = E_FAIL;
  702. }
  703. return hr;
  704. }
  705. /*++
  706. Name:
  707. FindPrinter
  708. Description:
  709. This is a private interface used to find a printer either in the
  710. DS or on the network.
  711. Arguments:
  712. hwndParent - Window handle of the calling window.
  713. pszBuffer - pointer to buffer where to store returned printer name.
  714. puSize - input points to the size of the provided buffer in characters,
  715. on return points to the size of the returned printer name.
  716. Return Value:
  717. S_OK printer was found and buffer contains the returned name.
  718. --*/
  719. STDMETHODIMP
  720. TShellExtension::
  721. FindPrinter(
  722. IN HWND hwndParent,
  723. IN OUT LPTSTR pszBuffer,
  724. IN UINT *puSize
  725. )
  726. {
  727. DBGMSG( DBG_TRACE, ( "TShellExtension::ShowProperties\n" ) );
  728. HRESULT hr = E_FAIL;
  729. if( bPrinterSetup( hwndParent, MSP_FINDPRINTER, *puSize, pszBuffer, puSize, NULL ) )
  730. {
  731. hr = S_OK;
  732. }
  733. else if( GetLastError() == ERROR_INSUFFICIENT_BUFFER )
  734. {
  735. hr = E_OUTOFMEMORY;
  736. }
  737. return hr;
  738. }
  739. /*++
  740. Name:
  741. DiscoverPhysicalLocation
  742. Description:
  743. This routine is used to start the physical location discovery
  744. process. The physical location discovery process will potentialy
  745. issue network calls which can take a large amount of time.
  746. Users of the IPhysicalLocation interface are required to call this
  747. method before getting the physical Location string, using
  748. GetPhyscialLocation.
  749. Arguments:
  750. none.
  751. Return Value:
  752. S_OK printer location was discovered, error code if the discovery
  753. process failed or a physical location string was not found.
  754. --*/
  755. STDMETHODIMP
  756. TShellExtension::
  757. DiscoverPhysicalLocation(
  758. VOID
  759. )
  760. {
  761. HRESULT hr = E_FAIL;
  762. //
  763. // Create the physical location object if this is the first call.
  764. //
  765. if (!_pPhysicalLocation)
  766. {
  767. _pPhysicalLocation = new TPhysicalLocation;
  768. }
  769. //
  770. // Invoke the discover method if the physical location
  771. // object was create successfully.
  772. //
  773. if (VALID_PTR(_pPhysicalLocation))
  774. {
  775. hr = _pPhysicalLocation->Discover() ? S_OK : E_FAIL;
  776. }
  777. else
  778. {
  779. hr = E_OUTOFMEMORY;
  780. }
  781. return hr;
  782. }
  783. /*++
  784. Name:
  785. GetExactPhysicalLocation
  786. Description:
  787. This routine gets the physical location string of this machine. Callers
  788. of this interface are required to call DiscoverPhysicalLocation prior to
  789. calling this method or this method will fail.
  790. Arguments:
  791. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  792. Return Value:
  793. S_OK physical location was discovered, error code if the discovery
  794. process failed or a physical location string was not found.
  795. --*/
  796. STDMETHODIMP
  797. TShellExtension::
  798. GetExactPhysicalLocation(
  799. IN OUT BSTR *pbsLocation
  800. )
  801. {
  802. DBGMSG( DBG_TRACE, ( "TShellExtension::GetExactPhysicalLocation.\n" ) );
  803. HRESULT hr = E_FAIL;
  804. //
  805. // Was Discover called, is object initialized?
  806. //
  807. if (_pPhysicalLocation)
  808. {
  809. TString strLocation;
  810. //
  811. // Get the physical location search string.
  812. //
  813. hr = _pPhysicalLocation->GetExact( strLocation ) ? S_OK : E_FAIL;
  814. if (SUCCEEDED(hr))
  815. {
  816. //
  817. // Allocate the location string.
  818. //
  819. *pbsLocation = SysAllocString( strLocation );
  820. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  821. }
  822. }
  823. else
  824. {
  825. hr = E_POINTER;
  826. }
  827. return hr;
  828. }
  829. /*++
  830. Name:
  831. GetSearchPhysicalLocation
  832. Description:
  833. This routine gets the best physical location search string for this machine.
  834. Users of this interface are required to call DiscoverPhysicalLocation
  835. prior to calling this method or this method will fail.
  836. Arguments:
  837. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  838. Return Value:
  839. S_OK physical location was discovered, error code if the discovery
  840. process failed or a physical location string was not found.
  841. --*/
  842. STDMETHODIMP
  843. TShellExtension::
  844. GetSearchPhysicalLocation(
  845. IN OUT BSTR *pbsLocation
  846. )
  847. {
  848. DBGMSG( DBG_TRACE, ( "TShellExtension::GetSearchPhysicalLocation.\n" ) );
  849. HRESULT hr = E_FAIL;
  850. //
  851. // Was Discover called, is object initialized?
  852. //
  853. if (_pPhysicalLocation)
  854. {
  855. TString strLocation;
  856. //
  857. // Get the physical location search string.
  858. //
  859. hr = _pPhysicalLocation->GetSearch( strLocation ) ? S_OK : E_FAIL;
  860. if (SUCCEEDED(hr))
  861. {
  862. //
  863. // Allocate the location string.
  864. //
  865. *pbsLocation = SysAllocString( strLocation );
  866. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  867. }
  868. }
  869. else
  870. {
  871. hr = E_POINTER;
  872. }
  873. return hr;
  874. }
  875. /*++
  876. Name:
  877. GetUserPhysicalLocation
  878. Description:
  879. This routine gets the physical location string of the user object in the DS
  880. Arguments:
  881. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  882. Return Value:
  883. S_OK physical location returned
  884. --*/
  885. STDMETHODIMP
  886. TShellExtension::
  887. GetUserPhysicalLocation(
  888. IN OUT BSTR *pbsLocation
  889. )
  890. {
  891. DBGMSG( DBG_TRACE, ( "TShellExtension::GetUserPhysicalLocation.\n" ) );
  892. HRESULT hr = E_FAIL;
  893. //
  894. // Create the physical location object if this is the first call.
  895. //
  896. if (!_pPhysicalLocation)
  897. {
  898. _pPhysicalLocation = new TPhysicalLocation;
  899. }
  900. if (VALID_PTR(_pPhysicalLocation))
  901. {
  902. TString strLocation;
  903. hr = _pPhysicalLocation->ReadUserLocationProperty( strLocation ) ? S_OK : E_FAIL;
  904. if (SUCCEEDED(hr))
  905. {
  906. //
  907. // Allocate the location string.
  908. //
  909. *pbsLocation = SysAllocString( strLocation );
  910. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  911. }
  912. }
  913. else
  914. {
  915. hr = E_OUTOFMEMORY;
  916. }
  917. return hr;
  918. }
  919. /*++
  920. Name:
  921. GetMachinePhysicalLocation
  922. Description:
  923. This routine gets the physical location string of this machine. The physical
  924. location string of this object may come from either group policy or the DS.
  925. Arguments:
  926. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  927. Return Value:
  928. S_OK physical location returned
  929. --*/
  930. STDMETHODIMP
  931. TShellExtension::
  932. GetMachinePhysicalLocation(
  933. IN OUT BSTR *pbsLocation
  934. )
  935. {
  936. DBGMSG( DBG_TRACE, ( "TShellExtension::GetMachinePhysicalLocation.\n" ) );
  937. HRESULT hr = E_FAIL;
  938. //
  939. // Create the physical location object if this is the first call.
  940. //
  941. if (!_pPhysicalLocation)
  942. {
  943. _pPhysicalLocation = new TPhysicalLocation;
  944. }
  945. if (VALID_PTR( _pPhysicalLocation ))
  946. {
  947. TString strLocation;
  948. //
  949. // First try the policy location.
  950. //
  951. hr = _pPhysicalLocation->ReadGroupPolicyLocationSetting( strLocation ) ? S_OK : E_FAIL;
  952. //
  953. // If the policy location was not found look in the DS.
  954. //
  955. if (FAILED(hr))
  956. {
  957. hr = _pPhysicalLocation->ReadMachinesLocationProperty( strLocation ) ? S_OK : E_FAIL;
  958. }
  959. if (SUCCEEDED(hr))
  960. {
  961. //
  962. // Allocate the location string.
  963. //
  964. *pbsLocation = SysAllocString( strLocation );
  965. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  966. }
  967. }
  968. else
  969. {
  970. hr = E_OUTOFMEMORY;
  971. }
  972. return hr;
  973. }
  974. /*++
  975. Name:
  976. GetSubnetPhysicalLocation
  977. Description:
  978. This routine gets the physical location string of the subnet object that closely
  979. matches this the subnet this machine is currently using.
  980. Arguments:
  981. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  982. Return Value:
  983. S_OK physical location returned
  984. --*/
  985. STDMETHODIMP
  986. TShellExtension::
  987. GetSubnetPhysicalLocation(
  988. IN OUT BSTR *pbsLocation
  989. )
  990. {
  991. DBGMSG( DBG_TRACE, ( "TShellExtension::GetSubnetPhysicalLocation.\n" ) );
  992. HRESULT hr = E_FAIL;
  993. //
  994. // Create the physical location object if this is the first call.
  995. //
  996. if (!_pPhysicalLocation)
  997. {
  998. _pPhysicalLocation = new TPhysicalLocation;
  999. }
  1000. if (VALID_PTR( _pPhysicalLocation ))
  1001. {
  1002. TString strLocation;
  1003. hr = _pPhysicalLocation->ReadSubnetLocationProperty( strLocation ) ? S_OK : E_FAIL;
  1004. if (SUCCEEDED(hr))
  1005. {
  1006. //
  1007. // Allocate the location string.
  1008. //
  1009. *pbsLocation = SysAllocString( strLocation );
  1010. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  1011. }
  1012. }
  1013. else
  1014. {
  1015. hr = E_OUTOFMEMORY;
  1016. }
  1017. return hr;
  1018. }
  1019. /*++
  1020. Name:
  1021. GetSitePhysicalLocation
  1022. Description:
  1023. This routine gets the physical location string of the size this machine
  1024. belongs to.
  1025. Arguments:
  1026. pbsLocation - Contains a pointer to a BSTR where to return the location string.
  1027. Return Value:
  1028. S_OK physical location returned
  1029. --*/
  1030. STDMETHODIMP
  1031. TShellExtension::
  1032. GetSitePhysicalLocation(
  1033. IN OUT BSTR *pbsLocation
  1034. )
  1035. {
  1036. DBGMSG( DBG_TRACE, ( "TShellExtension::GetSitePhysicalLocation.\n" ) );
  1037. HRESULT hr = E_FAIL;
  1038. //
  1039. // Create the physical location object if this is the first call.
  1040. //
  1041. if (!_pPhysicalLocation)
  1042. {
  1043. _pPhysicalLocation = new TPhysicalLocation;
  1044. }
  1045. if (VALID_PTR( _pPhysicalLocation ))
  1046. {
  1047. TString strLocation;
  1048. hr = _pPhysicalLocation->ReadSiteLocationProperty( strLocation ) ? S_OK : E_FAIL;
  1049. if (SUCCEEDED(hr))
  1050. {
  1051. //
  1052. // Allocate the location string.
  1053. //
  1054. *pbsLocation = SysAllocString( strLocation );
  1055. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  1056. }
  1057. }
  1058. else
  1059. {
  1060. hr = E_OUTOFMEMORY;
  1061. }
  1062. return hr;
  1063. }
  1064. /*++
  1065. Name:
  1066. BrowseForLocation
  1067. Description:
  1068. Displays UI for selecting a slash-delimited location name from among those
  1069. specified by the DS admin for subnet objects
  1070. Arguments:
  1071. hParent - HWND to use as parent of dialog window
  1072. bsDefault - location name to for initial tree expansion/selection
  1073. pbsLocation - Receives selected location name
  1074. Return Value:
  1075. S_OK location returned
  1076. Notes:
  1077. --*/
  1078. STDMETHODIMP
  1079. TShellExtension::
  1080. BrowseForLocation(
  1081. IN HWND hParent,
  1082. IN BSTR bsDefault,
  1083. IN OUT BSTR *pbsLocation
  1084. )
  1085. {
  1086. DBGMSG( DBG_TRACE, ( "TShellExtension::BrowseLocation.\n" ) );
  1087. TStatusB bStatus;
  1088. HRESULT hr = E_FAIL;
  1089. //
  1090. // Create the dialog object if this is the first call.
  1091. //
  1092. if (!_pLocationDlg)
  1093. {
  1094. _pLocationDlg = new TFindLocDlg;
  1095. }
  1096. //
  1097. // Check if the location dialog is valid.
  1098. //
  1099. bStatus DBGNOCHK = VALID_PTR( _pLocationDlg );
  1100. if( bStatus )
  1101. {
  1102. TString strLocation;
  1103. TString strDefault;
  1104. bStatus DBGCHK = strDefault.bUpdate( bsDefault );
  1105. hr = _pLocationDlg->bDoModal( hParent, &strDefault ) ? S_OK : E_FAIL;
  1106. if (SUCCEEDED(hr))
  1107. {
  1108. hr = _pLocationDlg->bGetLocation( strLocation ) ? S_OK : E_FAIL;
  1109. if (SUCCEEDED(hr))
  1110. {
  1111. //
  1112. // Allocate the location string.
  1113. //
  1114. *pbsLocation = SysAllocString( strLocation );
  1115. hr = (*pbsLocation) ? S_OK : E_OUTOFMEMORY;
  1116. }
  1117. }
  1118. }
  1119. else
  1120. {
  1121. hr = E_OUTOFMEMORY;
  1122. }
  1123. return hr;
  1124. }
  1125. /*++
  1126. Name:
  1127. TShellExtension::ShowPhysicalLocationUI
  1128. Description:
  1129. Determine if Location Lite is enabled for this machine
  1130. Arguments:
  1131. None
  1132. Return Value:
  1133. S_OK if enabled
  1134. Notes:
  1135. --*/
  1136. STDMETHODIMP
  1137. TShellExtension::
  1138. ShowPhysicalLocationUI(
  1139. VOID
  1140. )
  1141. {
  1142. HRESULT hr = E_FAIL;
  1143. //
  1144. // Create the physical location object if this is the first call.
  1145. //
  1146. if (!_pPhysicalLocation)
  1147. {
  1148. _pPhysicalLocation = new TPhysicalLocation;
  1149. }
  1150. if (VALID_PTR(_pPhysicalLocation))
  1151. {
  1152. hr = _pPhysicalLocation->bLocationEnabled() ? S_OK : E_FAIL;
  1153. }
  1154. else
  1155. {
  1156. hr = E_OUTOFMEMORY;
  1157. }
  1158. return hr;
  1159. }
  1160. /*++
  1161. Name:
  1162. TShellExtension::CheckToCreateStreams
  1163. Description:
  1164. Check to create m_spPrnStream & m_spStream
  1165. Arguments:
  1166. None
  1167. Return Value:
  1168. S_OK if succeeded
  1169. --*/
  1170. HRESULT
  1171. TShellExtension::
  1172. CheckToCreateStreams(
  1173. VOID
  1174. )
  1175. {
  1176. HRESULT hr = S_OK;
  1177. if( !m_spPrnStream || !m_spStream )
  1178. {
  1179. // release the smart pointers first
  1180. m_spPrnStream = NULL;
  1181. m_spStream = NULL;
  1182. // call into winspool.drv to create an instance
  1183. hr = Winspool_CreateInstance(IID_IPrnStream, m_spPrnStream.GetPPV());
  1184. if( SUCCEEDED(hr) )
  1185. {
  1186. hr = m_spPrnStream->QueryInterface(IID_IStream, m_spStream.GetPPV());
  1187. }
  1188. }
  1189. return ((m_spPrnStream && m_spStream) ? hr : E_FAIL);
  1190. }
  1191. /*++
  1192. Name:
  1193. TShellExtension::BindPrinterAndFile
  1194. Description:
  1195. Creates a PrnStream object if it don't exists and bind it to a printer and a file
  1196. Arguments:
  1197. printer name
  1198. file name
  1199. Return Value:
  1200. S_OK if succeeded
  1201. --*/
  1202. STDMETHODIMP
  1203. TShellExtension::
  1204. BindPrinterAndFile(
  1205. IN LPCTSTR pszPrinter,
  1206. IN LPCTSTR pszFile
  1207. )
  1208. {
  1209. HRESULT hr = E_FAIL;
  1210. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1211. {
  1212. return m_spPrnStream->BindPrinterAndFile(pszPrinter, pszFile);
  1213. }
  1214. return hr;
  1215. }
  1216. /*++
  1217. Name:
  1218. TShellExtension::StorePrinterInfo
  1219. Description:
  1220. Creates a PrnStream object if it don't exists and invoke StorePrinterInfo
  1221. Arguments:
  1222. flags that specifies what settings to store
  1223. Return Value:
  1224. S_OK if succeeded
  1225. --*/
  1226. STDMETHODIMP
  1227. TShellExtension::
  1228. StorePrinterInfo(
  1229. IN DWORD Flag
  1230. )
  1231. {
  1232. HRESULT hr = E_FAIL;
  1233. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1234. {
  1235. return m_spPrnStream->StorePrinterInfo(Flag);
  1236. }
  1237. return hr;
  1238. }
  1239. /*++
  1240. Name:
  1241. TShellExtension::RestorePrinterInfo
  1242. Description:
  1243. Creates a PrnStream object if it don't exists and invoke RestorePrinterInfo
  1244. Arguments:
  1245. flags that specifies what settings to restore
  1246. Return Value:
  1247. S_OK if succeeded
  1248. --*/
  1249. STDMETHODIMP
  1250. TShellExtension::
  1251. RestorePrinterInfo(
  1252. IN DWORD Flag
  1253. )
  1254. {
  1255. HRESULT hr = E_FAIL;
  1256. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1257. {
  1258. return m_spPrnStream->RestorePrinterInfo(Flag);
  1259. }
  1260. return hr;
  1261. }
  1262. /*++
  1263. Name:
  1264. TShellExtension::QueryPrinterInfo
  1265. Description:
  1266. Creates a PrnStream object if it don't exists and invoke QueryPrinterInfo
  1267. Arguments:
  1268. flags that specifies what settings to query
  1269. Return Value:
  1270. S_OK if succeeded
  1271. --*/
  1272. STDMETHODIMP
  1273. TShellExtension::
  1274. QueryPrinterInfo(
  1275. IN PrinterPersistentQueryFlag Flag,
  1276. OUT PersistentInfo *pPrstInfo
  1277. )
  1278. {
  1279. HRESULT hr = E_FAIL;
  1280. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1281. {
  1282. return m_spPrnStream->QueryPrinterInfo(Flag, pPrstInfo);
  1283. }
  1284. return hr;
  1285. }
  1286. /*++
  1287. Name:
  1288. TShellExtension::Read
  1289. Description:
  1290. Creates a PrnStream object if it don't exists and invoke Read
  1291. Arguments:
  1292. pv - The buffer that the bytes are read into
  1293. cb - The offset in the stream to begin reading from.
  1294. pcbRead - The number of bytes to read
  1295. Return Value:
  1296. S_OK if succeeded
  1297. --*/
  1298. STDMETHODIMP
  1299. TShellExtension::
  1300. Read(
  1301. VOID * pv,
  1302. ULONG cb,
  1303. ULONG * pcbRead
  1304. )
  1305. {
  1306. HRESULT hr = E_FAIL;
  1307. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1308. {
  1309. return m_spStream->Read(pv, cb, pcbRead);
  1310. }
  1311. return hr;
  1312. }
  1313. /*++
  1314. Name:
  1315. TShellExtension::Write
  1316. Description:
  1317. Creates a PrnStream object if it don't exists and invoke Write
  1318. Arguments:
  1319. pv - The buffer to write from.
  1320. cb - The offset in the array to begin writing from
  1321. pcbRead - The number of bytes to write
  1322. Return Value:
  1323. S_OK if succeeded
  1324. --*/
  1325. STDMETHODIMP
  1326. TShellExtension::
  1327. Write(
  1328. VOID const* pv,
  1329. ULONG cb,
  1330. ULONG * pcbWritten
  1331. )
  1332. {
  1333. HRESULT hr = E_FAIL;
  1334. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1335. {
  1336. return m_spStream->Write(pv, cb, pcbWritten);
  1337. }
  1338. return hr;
  1339. }
  1340. /*++
  1341. Name:
  1342. TShellExtension::Seek
  1343. Description:
  1344. Creates a PrnStream object if it don't exists and invoke Seek
  1345. Arguments:
  1346. dlibMove - The offset relative to dwOrigin
  1347. dwOrigin - The origin of the offset
  1348. plibNewPosition - Pointer to value of the new seek pointer from the beginning of the stream
  1349. Return Value:
  1350. S_OK if succeeded
  1351. --*/
  1352. STDMETHODIMP
  1353. TShellExtension::
  1354. Seek(
  1355. LARGE_INTEGER dlibMove,
  1356. DWORD dwOrigin,
  1357. ULARGE_INTEGER * plibNewPosition
  1358. )
  1359. {
  1360. HRESULT hr = E_FAIL;
  1361. if( SUCCEEDED(hr = CheckToCreateStreams()) )
  1362. {
  1363. return m_spStream->Seek(dlibMove, dwOrigin, plibNewPosition);
  1364. }
  1365. return hr;
  1366. }
  1367. /*++
  1368. Name:
  1369. TShellExtension::SetSize
  1370. Description:
  1371. Arguments:
  1372. Return Value:
  1373. E_NOTIMPL
  1374. --*/
  1375. STDMETHODIMP
  1376. TShellExtension::
  1377. SetSize(
  1378. ULARGE_INTEGER nSize
  1379. )
  1380. {
  1381. return E_NOTIMPL;
  1382. }
  1383. /*++
  1384. Name:
  1385. TShellExtension::CopyTo
  1386. Description:
  1387. Arguments:
  1388. Return Value:
  1389. E_NOTIMPL
  1390. --*/
  1391. STDMETHODIMP
  1392. TShellExtension::
  1393. CopyTo(
  1394. LPSTREAM pStrm,
  1395. ULARGE_INTEGER cb,
  1396. ULARGE_INTEGER * pcbRead,
  1397. ULARGE_INTEGER * pcbWritten
  1398. )
  1399. {
  1400. return E_NOTIMPL;
  1401. }
  1402. /*++
  1403. Name:
  1404. TShellExtension::Commit
  1405. Description:
  1406. Arguments:
  1407. Return Value:
  1408. E_NOTIMPL
  1409. --*/
  1410. STDMETHODIMP
  1411. TShellExtension::
  1412. Commit(
  1413. IN DWORD dwFlags
  1414. )
  1415. {
  1416. return E_NOTIMPL;
  1417. }
  1418. /*++
  1419. Name:
  1420. TShellExtension::Revert
  1421. Description:
  1422. Arguments:
  1423. Return Value:
  1424. E_NOTIMPL
  1425. --*/
  1426. STDMETHODIMP
  1427. TShellExtension::
  1428. Revert(
  1429. VOID
  1430. )
  1431. {
  1432. return E_NOTIMPL;
  1433. }
  1434. /*++
  1435. Name:
  1436. TShellExtension::LockRegion
  1437. Description:
  1438. Arguments:
  1439. Return Value:
  1440. E_NOTIMPL
  1441. --*/
  1442. STDMETHODIMP
  1443. TShellExtension::
  1444. LockRegion(
  1445. ULARGE_INTEGER cbOffset,
  1446. ULARGE_INTEGER cbLength,
  1447. DWORD dwFlags
  1448. )
  1449. {
  1450. return E_NOTIMPL;
  1451. }
  1452. /*++
  1453. Name:
  1454. TShellExtension::UnlockRegion
  1455. Description:
  1456. Arguments:
  1457. Return Value:
  1458. E_NOTIMPL
  1459. --*/
  1460. STDMETHODIMP
  1461. TShellExtension::
  1462. UnlockRegion(
  1463. ULARGE_INTEGER cbOffset,
  1464. ULARGE_INTEGER cbLength,
  1465. DWORD dwFlags
  1466. )
  1467. {
  1468. return E_NOTIMPL;
  1469. }
  1470. /*++
  1471. Name:
  1472. TShellExtension::Stat
  1473. Description:
  1474. Arguments:
  1475. Return Value:
  1476. E_NOTIMPL
  1477. --*/
  1478. STDMETHODIMP
  1479. TShellExtension::
  1480. Stat(
  1481. STATSTG * pStatStg,
  1482. DWORD dwFlags
  1483. )
  1484. {
  1485. return E_NOTIMPL;
  1486. }
  1487. /*++
  1488. Name:
  1489. TShellExtension::Clone
  1490. Description:
  1491. Arguments:
  1492. Return Value:
  1493. E_NOTIMPL
  1494. --*/
  1495. STDMETHODIMP
  1496. TShellExtension::
  1497. Clone(
  1498. LPSTREAM * ppStrm
  1499. )
  1500. {
  1501. return E_NOTIMPL;
  1502. }
  1503. /*++
  1504. Name:
  1505. TShellExtension::GenerateShareName
  1506. Description:
  1507. Arguments:
  1508. lpszServer - print server name
  1509. lpszBaseName - base name to start from
  1510. lpszOut - where to return the generated name
  1511. cchMaxChars - buffer size in characters
  1512. Return Value:
  1513. S_OK on success or OLE error otherwise
  1514. --*/
  1515. STDMETHODIMP
  1516. TShellExtension::
  1517. GenerateShareName(
  1518. LPCTSTR lpszServer,
  1519. LPCTSTR lpszBaseName,
  1520. LPTSTR lpszOut,
  1521. int cchMaxChars
  1522. )
  1523. {
  1524. HRESULT hr = E_INVALIDARG;
  1525. // lpszServer can be NULL to specify the local server,
  1526. // but lpszBaseName & lpszOut shouldn't be.
  1527. if( lpszBaseName && lpszOut )
  1528. {
  1529. TPrtShare prtShare(lpszServer);
  1530. TString strShareName, strBaseName;
  1531. strBaseName.bUpdate(lpszBaseName);
  1532. if( VALID_OBJ(prtShare) && VALID_OBJ(strBaseName) &&
  1533. prtShare.bNewShareName(strShareName, strBaseName) && strShareName.uLen() )
  1534. {
  1535. lstrcpyn(lpszOut, strShareName, cchMaxChars);
  1536. hr = (0 == lstrcmp(lpszOut, strShareName)) ? S_OK :
  1537. HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
  1538. }
  1539. else
  1540. {
  1541. hr = E_FAIL;
  1542. }
  1543. }
  1544. return hr;
  1545. }