1377 lines
37 KiB
C++
1377 lines
37 KiB
C++
|
/*****************************************************************************\
|
||
|
* MODULE: inet.cxx
|
||
|
*
|
||
|
* The module contains routines for the setting up the WWW Printer Service during spooler start up.
|
||
|
*
|
||
|
* The entry point here should be called by localspl\init.c\InitializePrintProvidor() once it is done
|
||
|
* with its work.
|
||
|
*
|
||
|
* Copyright (C) 1996 Microsoft Corporation
|
||
|
*
|
||
|
* History:
|
||
|
* Dec-1996 BabakJ Wrote it for IIS 2.0.
|
||
|
* June-1997 BabakJ Rewrote to use IIS 4.0's new Metabase interface
|
||
|
* Feb-1998 Weihaic Modify the URL in default.htm
|
||
|
* Feb 1999 BabakJ Made metabase interface a global to avoi calling too many CoCreateInstance() for perfrmance.
|
||
|
\*****************************************************************************/
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Note: We cannot use precomp.h here since we requrie ATL which can only be included in C++ source files.
|
||
|
//
|
||
|
//
|
||
|
|
||
|
|
||
|
#define INITGUID // babakj: (see comments in objbase.h) Needed to do it to get GUID_NULL defined.
|
||
|
|
||
|
#include "precomp.h"
|
||
|
#pragma hdrstop
|
||
|
|
||
|
#include <iadmw.h> // Interface header
|
||
|
#include <iiscnfg.h> // MD_ & IIS_MD_ defines
|
||
|
|
||
|
#include "..\spllib\webutil.hxx"
|
||
|
|
||
|
#define MY_META_TIMEOUT 1000
|
||
|
|
||
|
PWCHAR szW3SvcRootPath = L"/LM/W3svc/1/Root";
|
||
|
|
||
|
|
||
|
BOOL fW3SvcInstalled = FALSE; // Gobal flag telling if IIS or "Peer eb Server" is installed on the local machine.
|
||
|
PWCHAR szW3Root = NULL; // The WWWRoot dir, e.g. d:\inetpub\wwwroot
|
||
|
|
||
|
|
||
|
static CRITICAL_SECTION ClientCS;
|
||
|
static CRITICAL_SECTION ServerCS;
|
||
|
static HANDLE hMetaBaseThdReady;
|
||
|
static IMSAdminBase *pIMeta = NULL; // Metabase interface pointer
|
||
|
|
||
|
|
||
|
class CWebShareData {
|
||
|
public:
|
||
|
LPWSTR m_pszShareName;
|
||
|
BOOL m_bValid;
|
||
|
public:
|
||
|
CWebShareData (LPWSTR pszShareName);
|
||
|
~CWebShareData ();
|
||
|
int Compare (CWebShareData *pSecond) {return 0;};
|
||
|
};
|
||
|
|
||
|
class CWebShareList :
|
||
|
public CSingleList<CWebShareData*>
|
||
|
{
|
||
|
public:
|
||
|
CWebShareList () {};
|
||
|
~CWebShareList () {};
|
||
|
|
||
|
void WebSharePrinterList (void);
|
||
|
};
|
||
|
|
||
|
LPWSTR
|
||
|
mystrstrni(
|
||
|
LPWSTR pSrc,
|
||
|
LPWSTR pSearch
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
CopyWebPrnFile(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
SetupWebPrnSvc(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
BOOL fWebPrnDesired,
|
||
|
BOOL *pfW3SvcInstalled
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AddWebPrnSvc(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
BOOL *pfW3SvcInstalled
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
RemoveWebPrnSvc(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
RemoveScript(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
RemoveVirtualDir(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
InstallWebPrnSvcWorker(
|
||
|
void
|
||
|
);
|
||
|
|
||
|
void
|
||
|
InstallWebPrnSvcWorkerThread(
|
||
|
PINISPOOLER pIniSpooler
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AddScriptAtPrinterVDir(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
AddVirtualDir(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
);
|
||
|
|
||
|
void
|
||
|
WebShareWorker(
|
||
|
LPWSTR pShareName
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
CreateVirtualDirForPrinterShare(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
LPWSTR pShareName
|
||
|
);
|
||
|
|
||
|
void
|
||
|
WebUnShareWorker(
|
||
|
LPWSTR pShareName
|
||
|
);
|
||
|
|
||
|
BOOL
|
||
|
RemoveVirtualDirForPrinterShare(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
LPWSTR pShareName
|
||
|
);
|
||
|
|
||
|
void
|
||
|
WebShareAllPrinters(
|
||
|
PINISPOOLER pIniSpooler
|
||
|
);
|
||
|
|
||
|
|
||
|
//
|
||
|
// This routine is called from init.c at localspl init time to kick start the whole thing.
|
||
|
//
|
||
|
// Make the COM activation on a separate thread in order not to slow down LocalSpl init process
|
||
|
//
|
||
|
void
|
||
|
InstallWebPrnSvc(
|
||
|
PINISPOOLER pIniSpooler
|
||
|
)
|
||
|
{
|
||
|
HANDLE ThreadHandle;
|
||
|
DWORD ThreadId;
|
||
|
HRESULT hr; // com error status
|
||
|
|
||
|
|
||
|
// Init the sync objects needed for device arrival thread management
|
||
|
InitializeCriticalSection( &ClientCS );
|
||
|
InitializeCriticalSection( &ServerCS );
|
||
|
hMetaBaseThdReady = CreateEvent( NULL, FALSE, FALSE, NULL); // Auto reset, non-signaled state
|
||
|
|
||
|
|
||
|
if (ThreadHandle = CreateThread( NULL,
|
||
|
INITIAL_STACK_COMMIT,
|
||
|
(LPTHREAD_START_ROUTINE)InstallWebPrnSvcWorkerThread,
|
||
|
pIniSpooler, 0, &ThreadId )) {
|
||
|
CloseHandle( ThreadHandle );
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// We cannot free our interface pointer becasue loading and unloading ADMWPROX.DLL is very slow.
|
||
|
// So we have to keep the interface pointer around. But due to COM Apt limitation, the thread that creates the interface has
|
||
|
// to be alive for other threads to be able to use the pointer. So here we are with this fancy thread management code:
|
||
|
//
|
||
|
// The thread stays alive for a while. Then it goes away. Then future WebShare/Unshare would invoke it again.
|
||
|
// So This thread could be invoked 2 ways: First by spooler init code (only once!), then by WebShare/Unshare code.
|
||
|
//
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#define EnterClient() EnterCriticalSection( &ClientCS );
|
||
|
#define EnterServer() EnterCriticalSection( &ServerCS );
|
||
|
#define LeaveClient() LeaveCriticalSection( &ClientCS );
|
||
|
#define LeaveServer() LeaveCriticalSection( &ServerCS );
|
||
|
|
||
|
static BOOL ThdAlive = FALSE;
|
||
|
|
||
|
|
||
|
///
|
||
|
/// Begin threading work
|
||
|
///
|
||
|
|
||
|
|
||
|
void
|
||
|
InstallWebPrnSvcWorkerThread(
|
||
|
PINISPOOLER pIniSpooler
|
||
|
)
|
||
|
{
|
||
|
IMSAdminBase *pILocalMetaBase = NULL;
|
||
|
|
||
|
SPLASSERT( (pIniSpooler == NULL) || (pIniSpooler == pLocalIniSpooler) ); // We only expect local pIniSpooler here!
|
||
|
|
||
|
EnterServer();
|
||
|
|
||
|
if( ThdAlive ) {
|
||
|
SPLASSERT( FALSE );
|
||
|
LeaveServer();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if( FAILED (CoInitializeEx( NULL, COINIT_MULTITHREADED )) ||
|
||
|
FAILED (::CoCreateInstance(CLSID_MSAdminBase,
|
||
|
NULL,
|
||
|
CLSCTX_ALL,
|
||
|
IID_IMSAdminBase,
|
||
|
(void **)&pIMeta))) {
|
||
|
|
||
|
if( fW3SvcInstalled )
|
||
|
SetEvent( hMetaBaseThdReady ); // We must have a client thread waiting in WebShare/UnShare, signal it!
|
||
|
LeaveServer();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
|
||
|
if( !fW3SvcInstalled ) { // must be the first time we are being called.
|
||
|
if (InstallWebPrnSvcWorker()) {
|
||
|
WebShareAllPrinters( pIniSpooler );
|
||
|
fW3SvcInstalled = TRUE; // Once this is set, we never unset it. It is an indication that the WEb init code has succeeded.
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
SetEvent( hMetaBaseThdReady ); // event reset after a waiting thread is released.
|
||
|
|
||
|
ThdAlive = TRUE;
|
||
|
|
||
|
LeaveServer();
|
||
|
|
||
|
Sleep( 15 * 60 * 1000 ); // Allow other threads to use the COM pointer for 15 minutes
|
||
|
|
||
|
//
|
||
|
// Now tear down the IISADMIN object and self terminate thread. Ensure that
|
||
|
// we do not release the pointer inside the CS since this could take a long
|
||
|
// time, this could potentially cause a large number of WorkerThreads queueing
|
||
|
// up and doing the Release(), but that cannot be helped.
|
||
|
//
|
||
|
EnterServer();
|
||
|
|
||
|
pILocalMetaBase = pIMeta;
|
||
|
|
||
|
//
|
||
|
// The client thread expects valid pointers to be non-NULL!
|
||
|
//
|
||
|
pIMeta = NULL;
|
||
|
ThdAlive = FALSE;
|
||
|
|
||
|
LeaveServer();
|
||
|
|
||
|
pILocalMetaBase->Release();
|
||
|
|
||
|
CoUninitialize();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WebShareManagement(
|
||
|
LPWSTR pShareName,
|
||
|
BOOL bShare // If TRUE, will share it, else unshare it.
|
||
|
) {
|
||
|
HANDLE ThreadHandle;
|
||
|
DWORD ThreadId;
|
||
|
|
||
|
if( !fW3SvcInstalled ) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if(FAILED (CoInitializeEx( NULL, COINIT_MULTITHREADED )))
|
||
|
return;
|
||
|
|
||
|
EnterClient();
|
||
|
EnterServer();
|
||
|
|
||
|
if( !ThdAlive ) {
|
||
|
LeaveServer();
|
||
|
|
||
|
if (ThreadHandle = CreateThread(NULL,
|
||
|
INITIAL_STACK_COMMIT,
|
||
|
(LPTHREAD_START_ROUTINE)InstallWebPrnSvcWorkerThread,
|
||
|
NULL,
|
||
|
0,
|
||
|
&ThreadId)) // sending NULL pIniSpooler since there is no need for it.
|
||
|
CloseHandle( ThreadHandle );
|
||
|
else {
|
||
|
LeaveClient();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
WaitForSingleObject( hMetaBaseThdReady, INFINITE ); // automatic reset event, so it is reset after a waiting thd released.
|
||
|
EnterServer();
|
||
|
}
|
||
|
|
||
|
// Now do the real work
|
||
|
if (pIMeta) {
|
||
|
if( bShare)
|
||
|
WebShareWorker( pShareName );
|
||
|
else
|
||
|
WebUnShareWorker( pShareName );
|
||
|
}
|
||
|
|
||
|
LeaveServer();
|
||
|
LeaveClient();
|
||
|
|
||
|
|
||
|
// No need to CoUninitialize();
|
||
|
}
|
||
|
|
||
|
|
||
|
///
|
||
|
/// End threading work
|
||
|
///
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
WebShareAllPrinters(
|
||
|
PINISPOOLER pIniSpooler
|
||
|
)
|
||
|
{
|
||
|
CWebShareList *pWebShareList = NULL;
|
||
|
BOOL bRet = TRUE;
|
||
|
PINIPRINTER pIniPrinter;
|
||
|
|
||
|
|
||
|
if (pWebShareList = new CWebShareList ()) {
|
||
|
|
||
|
// Go down the list of printers and share it out
|
||
|
|
||
|
EnterSplSem();
|
||
|
|
||
|
|
||
|
//
|
||
|
// Re-share all shared printers.
|
||
|
//
|
||
|
|
||
|
for( pIniPrinter = pIniSpooler->pIniPrinter;
|
||
|
pIniPrinter;
|
||
|
pIniPrinter = pIniPrinter->pNext ) {
|
||
|
|
||
|
if ( pIniPrinter->Attributes & PRINTER_ATTRIBUTE_SHARED ) {
|
||
|
|
||
|
CWebShareData *pData = new CWebShareData (pIniPrinter->pShareName);
|
||
|
|
||
|
if (pData && pData->m_bValid &&
|
||
|
pWebShareList->Insert (pData)) {
|
||
|
continue;
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
if (pData) {
|
||
|
delete pData;
|
||
|
}
|
||
|
|
||
|
bRet = FALSE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LeaveSplSem ();
|
||
|
|
||
|
if (bRet) {
|
||
|
pWebShareList->WebSharePrinterList ();
|
||
|
}
|
||
|
|
||
|
delete pWebShareList;
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
PWSTR
|
||
|
GetPrinterUrl(
|
||
|
PSPOOL pSpool
|
||
|
)
|
||
|
{
|
||
|
PINIPRINTER pIniPrinter = pSpool->pIniPrinter;
|
||
|
DWORD cb;
|
||
|
PWSTR pszURL = NULL;
|
||
|
PWSTR pszServerName = NULL;
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
SplInSem();
|
||
|
|
||
|
// http://machine/share
|
||
|
if (!pIniPrinter->pShareName)
|
||
|
goto error;
|
||
|
|
||
|
// Get FQDN of this machine
|
||
|
hr = GetDNSMachineName(pIniPrinter->pIniSpooler->pMachineName + 2, &pszServerName);
|
||
|
if (FAILED(hr)) {
|
||
|
SetLastError(HRESULT_CODE(hr));
|
||
|
goto error;
|
||
|
}
|
||
|
|
||
|
cb = 7 + wcslen(pszServerName); // http://machine
|
||
|
cb += 1 + wcslen(pIniPrinter->pShareName) + 1; // /share + NULL
|
||
|
cb *= sizeof(WCHAR);
|
||
|
|
||
|
if (pszURL = (PWSTR) AllocSplMem(cb)) {
|
||
|
wsprintf(pszURL, L"http://%ws/%ws", pszServerName, pIniPrinter->pShareName);
|
||
|
}
|
||
|
|
||
|
|
||
|
error:
|
||
|
|
||
|
FreeSplStr(pszServerName);
|
||
|
|
||
|
return pszURL;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Reads the policy bit. Returns TRUE if Web Printing wanted, FASLE if not.
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
IsWebPrintingDesired(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
static PWCHAR szRegPolicyBitForDisableWebPrinting = L"Software\\Policies\\Microsoft\\Windows NT\\Printers";
|
||
|
|
||
|
|
||
|
HKEY hKey;
|
||
|
DWORD dwType;
|
||
|
DWORD cbData;
|
||
|
DWORD dwDataValue;
|
||
|
BOOL fRet = TRUE;
|
||
|
|
||
|
if( ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||
|
szRegPolicyBitForDisableWebPrinting, 0, KEY_READ, &hKey)) {
|
||
|
cbData = sizeof(dwDataValue);
|
||
|
|
||
|
if( RegQueryValueEx(hKey, L"DisableWebPrinting" , NULL, &dwType, (LPBYTE)&dwDataValue, &cbData) == ERROR_SUCCESS ) {
|
||
|
// As long as the value does not exist, it means that web printing is enabled
|
||
|
// If the value is a DWORD, then if it is TRUE, Web Printing is Disabled
|
||
|
|
||
|
if (dwType == REG_DWORD && dwDataValue) fRet = FALSE;
|
||
|
}
|
||
|
RegCloseKey( hKey );
|
||
|
}
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
InstallWebPrnSvcWorker(
|
||
|
VOID
|
||
|
)
|
||
|
{
|
||
|
WCHAR szTmpData[MAX_PATH];
|
||
|
HRESULT hr; // com error status
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
BOOL fW3Svc = FALSE;
|
||
|
DWORD dwMDRequiredDataLen;
|
||
|
METADATA_RECORD mr;
|
||
|
|
||
|
|
||
|
// open key to ROOT on website #1 (default)
|
||
|
hr = pIMeta->OpenKey(METADATA_MASTER_ROOT_HANDLE,
|
||
|
L"/LM/W3svc/1",
|
||
|
METADATA_PERMISSION_READ,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta);
|
||
|
if( SUCCEEDED( hr )) {
|
||
|
|
||
|
// Get the physical path for the WWWROOT
|
||
|
mr.dwMDIdentifier = MD_VR_PATH;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = sizeof( szTmpData );
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szTmpData);
|
||
|
|
||
|
hr = pIMeta->GetData( hMeta, L"/ROOT", &mr, &dwMDRequiredDataLen );
|
||
|
pIMeta->CloseKey( hMeta );
|
||
|
|
||
|
if( SUCCEEDED( hr )) {
|
||
|
szW3Root = AllocSplStr( szTmpData );
|
||
|
|
||
|
// Pass the inner dumb pointer for the callee to use
|
||
|
if( SetupWebPrnSvc( pIMeta, IsWebPrintingDesired(), &fW3Svc ))
|
||
|
DBGMSG(DBG_INFO, ("Setup of WWW Print Service successful.\n"));
|
||
|
else
|
||
|
DBGMSG(DBG_INFO, ("Setup of WWW Print Service failed.\n"));
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return fW3Svc;
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Given that the WWW server is installed on local machine, it installs/removes the Web Printing service.
|
||
|
//
|
||
|
// Won't reinstall if it is already installed.
|
||
|
//
|
||
|
// Installation involves:
|
||
|
//
|
||
|
// - Add msw3prt as .printer. Just need to get the Win\sys dir.
|
||
|
// - Add the virtual dis .printer
|
||
|
//
|
||
|
// Uninstall means the removal of the above two.
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
SetupWebPrnSvc(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
BOOL fWebPrnDesired, // whether Web Printing is desired by the caller
|
||
|
BOOL *pfW3SvcInstalled // Whether Web Printing actually got installed by this routine.
|
||
|
)
|
||
|
{
|
||
|
if( fWebPrnDesired ) {
|
||
|
|
||
|
return AddWebPrnSvc( pIMSAdminBase, pfW3SvcInstalled );
|
||
|
}
|
||
|
else {
|
||
|
|
||
|
*pfW3SvcInstalled = FALSE;
|
||
|
return RemoveWebPrnSvc( pIMSAdminBase );
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
AddWebPrnSvc(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
BOOL *pfW3SvcInstalled // Whether Web Printing actually got installed by this routine.
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr; // com error status
|
||
|
|
||
|
|
||
|
*pfW3SvcInstalled = FALSE; // Assume failure
|
||
|
|
||
|
//
|
||
|
// This is to remove the .printer script from the root
|
||
|
//
|
||
|
if( !RemoveScript( pIMSAdminBase ))
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
if( !AddVirtualDir( pIMSAdminBase ))
|
||
|
return FALSE;
|
||
|
|
||
|
//
|
||
|
// Add ".printer" as a script map to the printers virtual directory
|
||
|
//
|
||
|
if( !AddScriptAtPrinterVDir( pIMSAdminBase ))
|
||
|
return FALSE;
|
||
|
|
||
|
// Flush out the changes and close
|
||
|
// Call SaveData() after making bulk changes, do not call it on each update
|
||
|
hr = pIMSAdminBase->SaveData();
|
||
|
if( FAILED( hr ))
|
||
|
return FALSE;
|
||
|
|
||
|
return( *pfW3SvcInstalled = TRUE ); // Web Printing installed.
|
||
|
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
RemoveWebPrnSvc(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr; // com error status
|
||
|
|
||
|
|
||
|
// Remove ".printer" as a script map from the website #1 (default)
|
||
|
if( !RemoveScript( pIMSAdminBase ))
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
if( !RemoveVirtualDir( pIMSAdminBase ))
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
// Flush out the changes and close
|
||
|
// Call SaveData() after making bulk changes, do not call it on each update
|
||
|
hr = pIMSAdminBase->SaveData();
|
||
|
if( FAILED( hr ))
|
||
|
return FALSE;
|
||
|
|
||
|
return( TRUE ); // Web Printing removed
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Finds the string pSearch in pSrc buffer and returns a ptr to the occurance of pSearch in pSrc.
|
||
|
//
|
||
|
//
|
||
|
LPWSTR mystrstrni( LPWSTR pSrc, LPWSTR pSearch )
|
||
|
{
|
||
|
UINT uSearchSize = wcslen( pSearch );
|
||
|
UINT uSrcSize = wcslen( pSrc );
|
||
|
LPCTSTR pEnd;
|
||
|
|
||
|
if( uSrcSize < uSearchSize )
|
||
|
return(NULL);
|
||
|
|
||
|
pEnd = pSrc + uSrcSize - uSearchSize;
|
||
|
|
||
|
for( ; pSrc <= pEnd; ++pSrc ) {
|
||
|
if( !_wcsnicmp( pSrc, pSearch, uSearchSize ))
|
||
|
return((LPWSTR)pSrc);
|
||
|
}
|
||
|
|
||
|
return(NULL);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Determines if the string pSearch can be found inside of a MULTI_SZ string. If it can, it retunrs a
|
||
|
// pointer to the beginning of the string in multi-sz that contains pSearch.
|
||
|
//
|
||
|
LPWSTR IsStrInMultiSZ( LPWSTR pMultiSzSrc, LPWSTR pSearch )
|
||
|
{
|
||
|
LPWSTR pTmp = pMultiSzSrc;
|
||
|
|
||
|
while( TRUE ) {
|
||
|
if( mystrstrni( pTmp, pSearch )) // See pSearch (i.e. ".printer" appears anywhere within this string. If it does, it must be ours.
|
||
|
return pTmp;
|
||
|
|
||
|
pTmp = pTmp + (wcslen(pTmp) + 1); // Point to the beginning of the next string in the MULTI_SZ
|
||
|
|
||
|
if( !*pTmp )
|
||
|
return FALSE; // reached the end of the MULTI_SZ string.
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#define W3SVC L"w3svc"
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Name:
|
||
|
|
||
|
AddScriptAtPrinterVDir
|
||
|
|
||
|
Description:
|
||
|
|
||
|
Add the .printer and .asp script mapping at printers virtual directory
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
pIMSAdminBase - Pointer to the IIS Admin base
|
||
|
|
||
|
Returns:
|
||
|
|
||
|
An HRESULT
|
||
|
|
||
|
--*/
|
||
|
BOOL
|
||
|
AddScriptAtPrinterVDir(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
)
|
||
|
{
|
||
|
static WCHAR szScritMapFmt[] = L"%ws%c.printer,%ws\\msw3prt.dll,1,GET,POST%c";
|
||
|
static WCHAR szPrinterVDir[] = L"w3svc/1/root/printers";
|
||
|
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
PWCHAR szFullFormat = NULL;
|
||
|
DWORD dwMDRequiredDataLen;
|
||
|
METADATA_RECORD mr;
|
||
|
HRESULT hr = S_OK;
|
||
|
DWORD nLen;
|
||
|
WCHAR szSystemDir[MAX_PATH];
|
||
|
PWCHAR pAspMapping = NULL;
|
||
|
DWORD dwMapingLen = 0;
|
||
|
PWCHAR pScriptMap = NULL;
|
||
|
|
||
|
|
||
|
//
|
||
|
// Read any script map set at the top, on LM\w3svc where all other default ones are (e.g. .asp, etc.)
|
||
|
//
|
||
|
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
||
|
L"/LM",
|
||
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta);
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
mr.dwMDIdentifier = MD_SCRIPT_MAPS;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = MULTISZ_METADATA;
|
||
|
mr.dwMDDataLen = 0;
|
||
|
mr.pbMDData = NULL;
|
||
|
|
||
|
hr = pIMSAdminBase->GetData( hMeta, W3SVC, &mr, &dwMDRequiredDataLen );
|
||
|
|
||
|
hr = hr == HRESULT_FROM_WIN32 (ERROR_INSUFFICIENT_BUFFER) ? S_OK : E_FAIL;
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// allocate for existing stuff plus our new script map.
|
||
|
//
|
||
|
szFullFormat = new WCHAR[dwMDRequiredDataLen];
|
||
|
hr = szFullFormat? S_OK : E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
mr.dwMDIdentifier = MD_SCRIPT_MAPS;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = MULTISZ_METADATA;
|
||
|
mr.dwMDDataLen = dwMDRequiredDataLen * sizeof (WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szFullFormat);
|
||
|
|
||
|
hr = pIMSAdminBase->GetData( hMeta, W3SVC, &mr, &dwMDRequiredDataLen );
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
pAspMapping = IsStrInMultiSZ( szFullFormat, L".asp" );
|
||
|
|
||
|
hr = pAspMapping? S_OK: E_FAIL;
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
nLen = COUNTOF (szScritMapFmt) + MAX_PATH + lstrlen (pAspMapping);
|
||
|
|
||
|
pScriptMap = new WCHAR[nLen];
|
||
|
|
||
|
hr = pScriptMap ? S_OK : E_OUTOFMEMORY;
|
||
|
}
|
||
|
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// Return value is the length in chars w/o null char.
|
||
|
//
|
||
|
hr = GetSystemDirectory( szSystemDir, COUNTOF (szSystemDir)) > 0 ? S_OK : E_FAIL;
|
||
|
}
|
||
|
|
||
|
if(SUCCEEDED(hr))
|
||
|
{
|
||
|
dwMapingLen = wsprintf( pScriptMap, szScritMapFmt, pAspMapping, L'\0', szSystemDir, L'\0');
|
||
|
|
||
|
hr = dwMapingLen > COUNTOF (szScritMapFmt) ? S_OK : E_FAIL;
|
||
|
}
|
||
|
|
||
|
if (SUCCEEDED(hr))
|
||
|
{
|
||
|
//
|
||
|
// Write the new SCRIPT value
|
||
|
//
|
||
|
mr.dwMDIdentifier = MD_SCRIPT_MAPS;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = MULTISZ_METADATA;
|
||
|
mr.dwMDDataLen = sizeof (WCHAR) * (dwMapingLen + 1) ;
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(pScriptMap);
|
||
|
|
||
|
hr = pIMSAdminBase->SetData( hMeta, szPrinterVDir, &mr );
|
||
|
}
|
||
|
|
||
|
if (hMeta)
|
||
|
{
|
||
|
pIMSAdminBase->CloseKey( hMeta );
|
||
|
hMeta = NULL;
|
||
|
}
|
||
|
|
||
|
delete [] pScriptMap;
|
||
|
delete [] szFullFormat;
|
||
|
|
||
|
return SUCCEEDED (hr);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Finds and removed our script map from the multi_sz, and writes it back to the metabase.
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
WriteStrippedScriptValue(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
METADATA_HANDLE hMeta, // Handle to /LM tree
|
||
|
PWCHAR szFullFormat // MULTI_SZ string already there
|
||
|
)
|
||
|
{
|
||
|
LPWSTR pStrToKill, pNextStr;
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
DBGMSG(DBG_INFO, ("Removing our script if already added.\n"));
|
||
|
|
||
|
// See if our script map is already there.
|
||
|
if( !(pStrToKill = IsStrInMultiSZ( szFullFormat, L".printer" )))
|
||
|
return TRUE;
|
||
|
|
||
|
// Find the next string (could be the final NULL char)
|
||
|
pNextStr = pStrToKill + (wcslen(pStrToKill) + 1);
|
||
|
|
||
|
if( !*pNextStr )
|
||
|
*pStrToKill = 0; // Our scipt map was at the end of multi_sz. Write the 2nd NULL char and we are done.
|
||
|
else
|
||
|
CopyMemory( pStrToKill, // Remove our script map by copying the remainder of the multi_sz on top of the string containing the map.
|
||
|
pNextStr,
|
||
|
GetMultiSZLen(pNextStr) * sizeof(WCHAR));
|
||
|
|
||
|
// Write the new SCRIPT value
|
||
|
METADATA_RECORD mr;
|
||
|
mr.dwMDIdentifier = MD_SCRIPT_MAPS;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = MULTISZ_METADATA;
|
||
|
mr.dwMDDataLen = GetMultiSZLen(szFullFormat) * sizeof(WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szFullFormat);
|
||
|
|
||
|
hr = pIMSAdminBase->SetData( hMeta, W3SVC, &mr );
|
||
|
|
||
|
return( SUCCEEDED( hr ));
|
||
|
}
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Removes ".printer" as a script map from the website #1 (default) if alreaedy there
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
RemoveScript(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
)
|
||
|
{
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
PWCHAR szFullFormat;
|
||
|
DWORD dwMDRequiredDataLen;
|
||
|
METADATA_RECORD mr;
|
||
|
HRESULT hr;
|
||
|
BOOL fRet = FALSE;
|
||
|
|
||
|
|
||
|
// Read any script map set at the top, on LM\w3svc where all other default ones are (e.g. .asp, etc.)
|
||
|
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
||
|
L"/LM",
|
||
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta);
|
||
|
|
||
|
if( SUCCEEDED( hr )) {
|
||
|
|
||
|
mr.dwMDIdentifier = MD_SCRIPT_MAPS;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = MULTISZ_METADATA;
|
||
|
mr.dwMDDataLen = 0;
|
||
|
mr.pbMDData = NULL;
|
||
|
|
||
|
hr = pIMSAdminBase->GetData( hMeta, W3SVC, &mr, &dwMDRequiredDataLen );
|
||
|
|
||
|
if( FAILED( hr )) {
|
||
|
|
||
|
if( HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER ) {
|
||
|
|
||
|
if( szFullFormat = (PWCHAR)AllocSplMem( dwMDRequiredDataLen )) { // allocate for existing stuff plus our new script map.
|
||
|
|
||
|
mr.dwMDIdentifier = MD_SCRIPT_MAPS;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = MULTISZ_METADATA;
|
||
|
mr.dwMDDataLen = dwMDRequiredDataLen;
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szFullFormat);
|
||
|
|
||
|
hr = pIMSAdminBase->GetData( hMeta, W3SVC, &mr, &dwMDRequiredDataLen );
|
||
|
|
||
|
if( SUCCEEDED( hr ))
|
||
|
fRet = WriteStrippedScriptValue( pIMSAdminBase, hMeta, szFullFormat ); // Remove the .printer map from the multi_sz if there;
|
||
|
|
||
|
FreeSplMem( szFullFormat );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pIMSAdminBase->CloseKey( hMeta );
|
||
|
}
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
|
||
|
static PWCHAR szPrinters = L"Printers";
|
||
|
#define PRINTERS szPrinters // Name of Printers virtual dir.
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
AddVirtualDir(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
)
|
||
|
{
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
WCHAR szVirPath[MAX_PATH];
|
||
|
WCHAR szPath[MAX_PATH];
|
||
|
DWORD dwMDRequiredDataLen;
|
||
|
DWORD dwAccessPerm;
|
||
|
METADATA_RECORD mr;
|
||
|
HRESULT hr;
|
||
|
BOOL fRet;
|
||
|
|
||
|
|
||
|
// Attempt to open the virtual dir set on Web server #1 (default server)
|
||
|
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
||
|
szW3SvcRootPath,
|
||
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta );
|
||
|
|
||
|
// Create the key if it does not exist.
|
||
|
if( FAILED( hr ))
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
fRet = TRUE;
|
||
|
|
||
|
mr.dwMDIdentifier = MD_VR_PATH;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = sizeof( szVirPath );
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szVirPath);
|
||
|
|
||
|
// Read LM/W3Svc/1/Root/Printers see if MD_VR_PATH exists.
|
||
|
hr = pIMSAdminBase->GetData( hMeta, PRINTERS, &mr, &dwMDRequiredDataLen );
|
||
|
|
||
|
if( FAILED( hr )) {
|
||
|
|
||
|
fRet = FALSE;
|
||
|
if( hr == MD_ERROR_DATA_NOT_FOUND ||
|
||
|
HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND ) {
|
||
|
|
||
|
// Write both the key and the values if GetData() failed with any of the two errors.
|
||
|
|
||
|
pIMSAdminBase->AddKey( hMeta, PRINTERS );
|
||
|
|
||
|
if( GetWindowsDirectory( szPath, sizeof(szPath) / sizeof (TCHAR))) { // Return value is the length in chars w/o null char.
|
||
|
|
||
|
DBGMSG(DBG_INFO, ("Writing our virtual dir.\n"));
|
||
|
|
||
|
wsprintf( szVirPath, L"%ws\\web\\printers", szPath );
|
||
|
|
||
|
mr.dwMDIdentifier = MD_VR_PATH;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = (wcslen(szVirPath) + 1) * sizeof(WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szVirPath);
|
||
|
|
||
|
// Write MD_VR_PATH value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, PRINTERS, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
|
||
|
// Set the default authentication method
|
||
|
if( fRet ) {
|
||
|
|
||
|
DWORD dwAuthorization = MD_AUTH_NT; // NTLM only.
|
||
|
|
||
|
mr.dwMDIdentifier = MD_AUTHORIZATION;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT; // need to inherit so that all subdirs are also protected.
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = DWORD_METADATA;
|
||
|
mr.dwMDDataLen = sizeof(DWORD);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAuthorization);
|
||
|
|
||
|
// Write MD_AUTHORIZATION value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, PRINTERS, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// In the following, do the stuff that we always want to do to the virtual dir, regardless of Admin's setting.
|
||
|
|
||
|
|
||
|
if( fRet ) {
|
||
|
|
||
|
dwAccessPerm = MD_ACCESS_READ | MD_ACCESS_SCRIPT;
|
||
|
|
||
|
mr.dwMDIdentifier = MD_ACCESS_PERM;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT; // Make it inheritable so all subdirectories will have the same rights.
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = DWORD_METADATA;
|
||
|
mr.dwMDDataLen = sizeof(DWORD);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAccessPerm);
|
||
|
|
||
|
// Write MD_ACCESS_PERM value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, PRINTERS, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
}
|
||
|
|
||
|
if( fRet ) {
|
||
|
|
||
|
PWCHAR szDefLoadFile = L"ipp_0001.asp";
|
||
|
|
||
|
mr.dwMDIdentifier = MD_DEFAULT_LOAD_FILE;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = (wcslen(szDefLoadFile) + 1) * sizeof(WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szDefLoadFile);
|
||
|
|
||
|
// Write MD_DEFAULT_LOAD_FILE value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, PRINTERS, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
}
|
||
|
|
||
|
if( fRet ) {
|
||
|
|
||
|
PWCHAR szKeyType = IIS_CLASS_WEB_VDIR_W;
|
||
|
|
||
|
mr.dwMDIdentifier = MD_KEY_TYPE;
|
||
|
mr.dwMDAttributes = METADATA_INHERIT;
|
||
|
mr.dwMDUserType = IIS_MD_UT_SERVER;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = (wcslen(szKeyType) + 1) * sizeof(WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szKeyType);
|
||
|
|
||
|
// Write MD_DEFAULT_LOAD_FILE value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, PRINTERS, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
}
|
||
|
|
||
|
pIMSAdminBase->CloseKey( hMeta );
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
//
|
||
|
// Removes "printers" virtual dir from IIS metabase ws3vc\1\root\printers
|
||
|
//
|
||
|
//
|
||
|
BOOL
|
||
|
RemoveVirtualDir(
|
||
|
IMSAdminBase *pIMSAdminBase
|
||
|
)
|
||
|
{
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
// Attempt to open the virtual dir set on Web server #1 (default server)
|
||
|
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
||
|
szW3SvcRootPath,
|
||
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta );
|
||
|
|
||
|
// Create the key if it does not exist.
|
||
|
if( FAILED( hr ))
|
||
|
return FALSE;
|
||
|
|
||
|
pIMSAdminBase->DeleteKey( hMeta, PRINTERS ); // We don't check the retrun value since the key may already not exist and we could get an error for that reason.
|
||
|
|
||
|
pIMSAdminBase->CloseKey( hMeta );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
//
|
||
|
// Adding printer shares:
|
||
|
//
|
||
|
// To support http://<server>/<share>, we create a virtual directory with a redirect property.
|
||
|
//
|
||
|
//
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
|
||
|
//=====================================================================================================
|
||
|
//
|
||
|
// This function may be called during initialization time after fW3SvcInstalled is set,
|
||
|
// which means, a printer maybe webshared twice (once in InstallWebPrnSvcWorkerThread,
|
||
|
// and the other time when WebShare () is calleb by ShareThisPrinter() in net.c by
|
||
|
// FinalInitAfterRouterInitCompleteThread () during localspl initialization time.
|
||
|
//
|
||
|
//=====================================================================================================
|
||
|
|
||
|
void
|
||
|
WebShare(
|
||
|
LPWSTR pShareName
|
||
|
)
|
||
|
{
|
||
|
WebShareManagement( pShareName, TRUE );
|
||
|
}
|
||
|
|
||
|
void
|
||
|
WebShareWorker(
|
||
|
LPWSTR pShareName
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr; // com error status
|
||
|
|
||
|
SPLASSERT( pIMeta != NULL );
|
||
|
|
||
|
// Pass the inner dumb pointer for the callee to use
|
||
|
if( CreateVirtualDirForPrinterShare( pIMeta, pShareName ))
|
||
|
|
||
|
// Flush out the changes and close
|
||
|
// Call SaveData() after making bulk changes, do not call it on each update
|
||
|
hr = pIMeta->SaveData();
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CreateVirtualDirForPrinterShare(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
LPWSTR pShareName
|
||
|
)
|
||
|
{
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
WCHAR szOldURL[MAX_PATH];
|
||
|
WCHAR szPath[MAX_PATH];
|
||
|
DWORD dwMDRequiredDataLen;
|
||
|
DWORD dwAccessPerm;
|
||
|
METADATA_RECORD mr;
|
||
|
HRESULT hr;
|
||
|
BOOL fRet;
|
||
|
|
||
|
|
||
|
// Attempt to open the virtual dir set on Web server #1 (default server)
|
||
|
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
||
|
szW3SvcRootPath,
|
||
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta );
|
||
|
|
||
|
// Create the key if it does not exist.
|
||
|
if( FAILED( hr ))
|
||
|
return FALSE;
|
||
|
|
||
|
|
||
|
fRet = TRUE;
|
||
|
|
||
|
mr.dwMDIdentifier = MD_HTTP_REDIRECT;
|
||
|
mr.dwMDAttributes = 0;
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = sizeof( szOldURL );
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szOldURL);
|
||
|
|
||
|
// Read LM/W3Svc/1/Root/Printers to see if MD_HTTP_REDIRECT exists.
|
||
|
// Note that we are only concerned with the presence of the vir dir,
|
||
|
// not any properties it might have.
|
||
|
//
|
||
|
hr = pIMSAdminBase->GetData( hMeta, pShareName, &mr, &dwMDRequiredDataLen );
|
||
|
|
||
|
if( FAILED( hr )) {
|
||
|
|
||
|
fRet = FALSE;
|
||
|
|
||
|
// Notice if the virtual dir exists, we won't touch it. One scenario is
|
||
|
// if there is a name collision between a printer sharename and an existing,
|
||
|
// unrelated virtual dir.
|
||
|
if( HRESULT_CODE(hr) == ERROR_PATH_NOT_FOUND ) {
|
||
|
|
||
|
// Write both the key and the values if GetData() failed with any of the two errors.
|
||
|
|
||
|
pIMSAdminBase->AddKey( hMeta, pShareName );
|
||
|
|
||
|
|
||
|
dwAccessPerm = MD_ACCESS_READ;
|
||
|
|
||
|
mr.dwMDIdentifier = MD_ACCESS_PERM;
|
||
|
mr.dwMDAttributes = 0; // no need for inheritence
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = DWORD_METADATA;
|
||
|
mr.dwMDDataLen = sizeof(DWORD);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(&dwAccessPerm);
|
||
|
|
||
|
// Write MD_ACCESS_PERM value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, pShareName, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
|
||
|
if( fRet ) {
|
||
|
|
||
|
PWCHAR szKeyType = IIS_CLASS_WEB_VDIR_W;
|
||
|
|
||
|
mr.dwMDIdentifier = MD_KEY_TYPE;
|
||
|
mr.dwMDAttributes = 0; // no need for inheritence
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = (wcslen(szKeyType) + 1) * sizeof(WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szKeyType);
|
||
|
|
||
|
// Write MD_DEFAULT_LOAD_FILE value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, pShareName, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
}
|
||
|
|
||
|
if( fRet ) {
|
||
|
|
||
|
|
||
|
WCHAR szURL[MAX_PATH];
|
||
|
|
||
|
wsprintf( szURL, L"/printers/%ws/.printer", pShareName );
|
||
|
|
||
|
mr.dwMDIdentifier = MD_HTTP_REDIRECT;
|
||
|
mr.dwMDAttributes = 0; // no need for inheritence
|
||
|
mr.dwMDUserType = IIS_MD_UT_FILE;
|
||
|
mr.dwMDDataType = STRING_METADATA;
|
||
|
mr.dwMDDataLen = (wcslen(szURL) + 1) * sizeof(WCHAR);
|
||
|
mr.pbMDData = reinterpret_cast<unsigned char *>(szURL);
|
||
|
|
||
|
// Write MD_DEFAULT_LOAD_FILE value
|
||
|
hr = pIMSAdminBase->SetData( hMeta, pShareName, &mr );
|
||
|
fRet = SUCCEEDED( hr );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pIMSAdminBase->CloseKey( hMeta );
|
||
|
|
||
|
return fRet;
|
||
|
}
|
||
|
|
||
|
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
//
|
||
|
// Removing printer shares
|
||
|
//
|
||
|
//
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
//=====================================================================================================
|
||
|
|
||
|
void
|
||
|
WebUnShare(
|
||
|
LPWSTR pShareName
|
||
|
)
|
||
|
{
|
||
|
WebShareManagement( pShareName, FALSE );
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
WebUnShareWorker(
|
||
|
LPWSTR pShareName
|
||
|
)
|
||
|
{
|
||
|
HRESULT hr; // com error status
|
||
|
|
||
|
SPLASSERT( pIMeta != NULL );
|
||
|
|
||
|
// Pass the inner dumb pointer for the callee to use
|
||
|
if( RemoveVirtualDirForPrinterShare( pIMeta, pShareName ))
|
||
|
|
||
|
// Flush out the changes and close
|
||
|
// Call SaveData() after making bulk changes, do not call it on each update
|
||
|
hr = pIMeta->SaveData();
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
RemoveVirtualDirForPrinterShare(
|
||
|
IMSAdminBase *pIMSAdminBase,
|
||
|
LPWSTR pShareName
|
||
|
)
|
||
|
{
|
||
|
METADATA_HANDLE hMeta = NULL; // handle to metabase
|
||
|
HRESULT hr;
|
||
|
|
||
|
|
||
|
// Attempt to open the virtual dir set on Web server #1 (default server)
|
||
|
hr = pIMSAdminBase->OpenKey( METADATA_MASTER_ROOT_HANDLE,
|
||
|
szW3SvcRootPath,
|
||
|
METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE,
|
||
|
MY_META_TIMEOUT,
|
||
|
&hMeta );
|
||
|
|
||
|
// Create the key if it does not exist.
|
||
|
if( FAILED( hr ))
|
||
|
return FALSE;
|
||
|
|
||
|
pIMSAdminBase->DeleteKey( hMeta, pShareName ); // We don't check the retrun value since the key may already not exist and we could get an error for that reason.
|
||
|
pIMSAdminBase->CloseKey( hMeta );
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
CWebShareData::CWebShareData (LPWSTR pszShareName)
|
||
|
{
|
||
|
m_bValid = FALSE;
|
||
|
m_pszShareName = NULL;
|
||
|
|
||
|
if (m_pszShareName = new WCHAR[lstrlen (pszShareName) +1]) {
|
||
|
lstrcpy (m_pszShareName, pszShareName);
|
||
|
m_bValid = TRUE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
CWebShareData::~CWebShareData ()
|
||
|
{
|
||
|
if (m_pszShareName) {
|
||
|
delete [] m_pszShareName;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CWebShareList::WebSharePrinterList ()
|
||
|
{
|
||
|
CSingleItem<CWebShareData*> * pItem = m_Dummy.GetNext();
|
||
|
|
||
|
CWebShareData * pData = NULL;
|
||
|
|
||
|
while (pItem && (pData = pItem->GetData ()) && pData->m_bValid) {
|
||
|
|
||
|
WebShareWorker (pData->m_pszShareName);
|
||
|
pItem = pItem->GetNext ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|