1321 lines
39 KiB
C++
1321 lines
39 KiB
C++
// this is the internal content-specific stuff related to the
|
|
// CShellExt object
|
|
|
|
#include "priv.h"
|
|
#include <stdio.h>
|
|
#include <tchar.h>
|
|
#include <iiscnfgp.h>
|
|
//#include <inetinfo.h>
|
|
#include <winsvc.h>
|
|
#include <pwsdata.hxx>
|
|
#include <iwamreg.h>
|
|
#include <shlwapi.h>
|
|
|
|
#include "wrapmb.h"
|
|
#include "Sink.h"
|
|
#include "eddir.h"
|
|
#include "shellext.h"
|
|
|
|
#include "wrapmb.h"
|
|
|
|
extern HINSTANCE g_hmodThisDll; // Handle to this DLL itself.
|
|
|
|
#define SZ_MB_SERVICE _T("/LM/W3SVC/")
|
|
#define SZ_ROOT _T("/ROOT")
|
|
#define SZ_SERVER_KEYTYPE _T("IIsWebServer")
|
|
|
|
|
|
#define IIS_CAP1_10_CONNECTION_LIMIT 0x00000040
|
|
|
|
|
|
BOOL MakeWAMApplication( IN LPCTSTR pszPath, IN BOOL fCreate );
|
|
BOOL MyFormatString1( IN LPTSTR pszSource, IN DWORD cchMax, LPTSTR pszReplace );
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// test if we have proper access to the metabase
|
|
BOOL CShellExt::FIsAdmin()
|
|
{
|
|
BOOL fAnswer = FALSE;
|
|
CWrapMetaBase mb;
|
|
|
|
FInitMetabase();
|
|
|
|
// first things first. get the state of the server
|
|
// init the mb object. If it fails then the server app is probably not running
|
|
if ( mb.FInit(m_pMBCom) )
|
|
{
|
|
BOOL fOpen = mb.Open(_T("/LM/W3SVC"), METADATA_PERMISSION_READ | METADATA_PERMISSION_WRITE);
|
|
if ( fOpen )
|
|
{
|
|
// Write some nonsense
|
|
DWORD dwDummy = 0x1234;
|
|
fAnswer = mb.SetDword( _T(""), MD_ISM_ACCESS_CHECK, IIS_MD_UT_FILE, dwDummy, 0 );
|
|
|
|
// close the metabase object
|
|
mb.Close();
|
|
}
|
|
}
|
|
|
|
// Grrrrr!! Boyd, you should clean up after youself
|
|
FCloseMetabase();
|
|
|
|
// return the answer
|
|
return fAnswer;
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------------------------------
|
|
// return FALSE if we do NOT handle the message
|
|
BOOL CShellExt::OnCommand(HWND hDlg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (LOWORD(wParam))
|
|
{
|
|
case IDC_LIST:
|
|
return OnListBoxNotify(hDlg, LOWORD(wParam), HIWORD(wParam), (HWND)lParam);
|
|
|
|
case IDC_ADD:
|
|
OnAdd();
|
|
return TRUE;
|
|
|
|
case IDC_EDIT:
|
|
OnEdit();
|
|
return TRUE;
|
|
|
|
case IDC_REMOVE:
|
|
OnRemove();
|
|
return TRUE;
|
|
|
|
case IDC_RDO_NOT:
|
|
OnRdoNot();
|
|
break;
|
|
|
|
case IDC_RDO_SHARE:
|
|
OnRdoShare();
|
|
break;
|
|
|
|
case IDC_COMBO_SERVER:
|
|
if ( HIWORD(wParam) == CBN_SELCHANGE )
|
|
{
|
|
OnSelchangeComboServer();
|
|
}
|
|
break;
|
|
}
|
|
// we did not handle it
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
// return FALSE if we do NOT handle the message
|
|
BOOL CShellExt::OnListBoxNotify(HWND hDlg, int idCtrl, WORD code, HWND hwndControl)
|
|
{
|
|
switch (code)
|
|
{
|
|
case LBN_DBLCLK:
|
|
{
|
|
OnEdit();
|
|
return TRUE;
|
|
}
|
|
case LBN_SELCHANGE:
|
|
{
|
|
EnableItems();
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
// return FALSE if we do NOT handle the message
|
|
BOOL CShellExt::OnMessage(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL fHandledMessage = FALSE;
|
|
|
|
// the BIG dialog switch statement....
|
|
switch( uMsg )
|
|
{
|
|
case WM_INITDIALOG:
|
|
m_hwnd = hDlg;
|
|
// init the controls
|
|
if ( !InitControls() )
|
|
return FALSE;
|
|
|
|
// the big init
|
|
if ( FInitMetabase() )
|
|
{
|
|
Init();
|
|
m_fInitialized = TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
|
|
// return success
|
|
fHandledMessage = TRUE;
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
ResetListContent();
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
fHandledMessage = OnCommand(hDlg, wParam, lParam);
|
|
break;
|
|
case WM_UPDATE_SERVER_STATE:
|
|
UpdateState();
|
|
EnableItems();
|
|
return TRUE;
|
|
case WM_UPDATE_ALIAS_LIST:
|
|
EmptyList();
|
|
BuildAliasList();
|
|
EnableItems();
|
|
return TRUE;
|
|
case WM_SHUTDOWN_NOTIFY:
|
|
EnterShutdownMode();
|
|
return TRUE;
|
|
case WM_INSPECT_SERVER_LIST:
|
|
InspectServerList();
|
|
return TRUE;
|
|
case WM_TIMER:
|
|
if ( wParam == PWS_TIMER_CHECKFORSERVERRESTART )
|
|
{
|
|
OnTimer( (UINT)wParam );
|
|
fHandledMessage = TRUE;
|
|
}
|
|
break;
|
|
};
|
|
|
|
// return whether or not we handled the message
|
|
return fHandledMessage;
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
// obtain all the control handles that we will need as the dialog goes along
|
|
BOOL CShellExt::InitControls()
|
|
{
|
|
m_icon_pws = GetDlgItem( m_hwnd, IDC_STATIC_ICON_PWS );
|
|
m_icon_iis = GetDlgItem( m_hwnd, IDC_STATIC_ICON_IIS );
|
|
m_static_share_on_title = GetDlgItem( m_hwnd, IDC_STATIC_SHARE_ON );
|
|
m_ccombo_server = GetDlgItem( m_hwnd, IDC_COMBO_SERVER );
|
|
m_cbtn_share = GetDlgItem( m_hwnd, IDC_RDO_SHARE );
|
|
m_cbtn_not = GetDlgItem( m_hwnd, IDC_RDO_NOT );
|
|
m_cstatic_alias_title = GetDlgItem( m_hwnd, IDC_STATIC_ALIAS_TITLE );
|
|
m_cbtn_add = GetDlgItem( m_hwnd, IDC_ADD );
|
|
m_cbtn_remove = GetDlgItem( m_hwnd, IDC_REMOVE );
|
|
m_cbtn_edit = GetDlgItem( m_hwnd, IDC_EDIT );
|
|
m_clist_list = GetDlgItem( m_hwnd, IDC_LIST );
|
|
m_static_status = GetDlgItem( m_hwnd, IDC_STATIC_STATUS );
|
|
return TRUE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// remove all the alias items in the list
|
|
void CShellExt::EmptyList()
|
|
{
|
|
ListBox_ResetContent( m_clist_list );
|
|
}
|
|
|
|
//---------------------------------------------------------------
|
|
// CDialog simulation routines
|
|
void CShellExt::UpdateData( BOOL fDialogToData )
|
|
{
|
|
// get the data
|
|
if ( fDialogToData )
|
|
{
|
|
// set the data
|
|
m_int_share = (SendMessage( m_cbtn_share, BM_GETCHECK, 0, 0 ) == BST_CHECKED);
|
|
m_int_server = (int)SendMessage( m_ccombo_server, CB_GETCURSEL, 0, 0 );
|
|
if ( m_int_server < 0 )
|
|
m_int_server = 0;
|
|
}
|
|
else
|
|
{
|
|
// set the data
|
|
SendMessage( m_ccombo_server, CB_SETCURSEL, m_int_server, 0 );
|
|
if ( m_int_share )
|
|
{
|
|
SendMessage( m_cbtn_not, BM_SETCHECK, BST_UNCHECKED, 0 );
|
|
SendMessage( m_cbtn_share, BM_SETCHECK, BST_CHECKED, 0 );
|
|
}
|
|
else
|
|
{
|
|
SendMessage( m_cbtn_share, BM_SETCHECK, BST_UNCHECKED, 0 );
|
|
SendMessage( m_cbtn_not, BM_SETCHECK, BST_CHECKED, 0 );
|
|
}
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// This method gets called when an object in the metabase has been
|
|
// deleted. The purpose is to see if the current virtual directory in
|
|
// the metabase has been deleted or not. If it has been deleted, then
|
|
// we go to the default sever. Or the first one. Or whatever is there.
|
|
void CShellExt::InspectServerList()
|
|
{
|
|
BOOL fItsGone = FALSE;
|
|
TCHAR szRoot[200];
|
|
|
|
CWrapMetaBase mb;
|
|
if ( !mb.FInit(m_pMBCom) )
|
|
return;
|
|
|
|
// Attempt to open the root. If that fails, its otta here
|
|
GetRootString( szRoot, 100 );
|
|
if (!mb.Open(szRoot))
|
|
return;
|
|
mb.Close();
|
|
|
|
// it is gone. Default to the first one
|
|
SendMessage( m_ccombo_server, CB_SETCURSEL, 0, 0 );
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// This routine builds the correct metabase path up to /LM/W3SVC/*/ROOT
|
|
// where the * is the current virtual server selected in the drop down.
|
|
// There are two versions of this routine. One where the string is passed
|
|
// in as a variable, and the other returns it
|
|
void CShellExt::GetRootString( LPTSTR sz, DWORD cchMax )
|
|
{
|
|
// get the service part
|
|
GetVirtServerString(sz, cchMax);
|
|
|
|
// add on the ROOT part
|
|
StrCatBuff(sz, SZ_ROOT, cchMax);
|
|
}
|
|
|
|
//------------------------------------------------------------------
|
|
// This routine builds the correct metabase path up to /LM/W3SVC/*
|
|
// where the * is the current virtual server selected in the drop down.
|
|
// There are two versions of this routine. One where the string is passed
|
|
// in as a variable, and the other returns it
|
|
void CShellExt::GetVirtServerString(LPTSTR sz, DWORD cchMax)
|
|
{
|
|
*sz = 0;
|
|
StrCatBuff(sz, SZ_MB_SERVICE, cchMax);
|
|
UpdateData( TRUE );
|
|
|
|
// the private string data on the item
|
|
PTCHAR pch = (PTCHAR)SendMessage( m_ccombo_server, CB_GETITEMDATA, m_int_server, 0 );
|
|
|
|
// do something if it fails
|
|
if ( !pch || (pch == (PTCHAR)CB_ERR) )
|
|
return;
|
|
|
|
// the virtual server is indicated by the current selection in the
|
|
// server combo box. We get its index and retrieve the path from the
|
|
// private data attached to the item in the list
|
|
StrCat(sz, pch);
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::ResetListContent()
|
|
{
|
|
PTCHAR psz;
|
|
|
|
// first, get the number of strings
|
|
DWORD nNumStrings = (DWORD)SendMessage( m_ccombo_server, CB_GETCOUNT, 0, 0 );
|
|
if ( nNumStrings == CB_ERR ) return;
|
|
|
|
// delete all the hidden server path strings
|
|
for ( DWORD i = 0; i < nNumStrings; i++ )
|
|
{
|
|
// get the string pointer
|
|
psz = (PTCHAR)SendMessage( m_ccombo_server, CB_GETITEMDATA, i, 0 );
|
|
// if it is there, delete it
|
|
if (psz != NULL)
|
|
LocalFree(psz);
|
|
}
|
|
|
|
// wipe out any items currently in the box before re-adding
|
|
SendMessage( m_ccombo_server, CB_RESETCONTENT, 0, 0 );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// initialize the combo box so the user can select which virtual server
|
|
// to administer from the shell extension.
|
|
void CShellExt::InitSeverInfo()
|
|
{
|
|
DWORD err;
|
|
CWrapMetaBase mb;
|
|
INT i;
|
|
|
|
if ( !mb.FInit(m_pMBCom) )
|
|
return;
|
|
|
|
TCHAR szKey[MAX_PATH];
|
|
TCHAR szDescription[MAX_PATH];
|
|
|
|
ZeroMemory( szKey, MAX_PATH );
|
|
ZeroMemory( szDescription, MAX_PATH );
|
|
|
|
// wipe out any items currently in the box before re-adding
|
|
ResetListContent();
|
|
|
|
// first open the metabase and get the server capabilities
|
|
if ( mb.Open(_T("/LM/W3SVC/")) )
|
|
{
|
|
DWORD dw;
|
|
// test if there is a 10 connection limit and use
|
|
// that flag as a test for IIS vs. PWS
|
|
|
|
|
|
if ( mb.GetDword( _T("Info"), MD_SERVER_CAPABILITIES, IIS_MD_UT_SERVER, &dw ) )
|
|
m_fIsPWS = (dw & IIS_CAP1_10_CONNECTION_LIMIT) != 0;
|
|
|
|
#ifdef DEBUG_ALWAYS_IIS
|
|
m_fIsPWS = FALSE;
|
|
#endif
|
|
// now enumerate the children to build the drop down list. Since there could
|
|
// be gaps in the list 1,2,4,5,6,8 etc (some may have been deleted) we need
|
|
// to keep an additional list of path names that correspond to the positions
|
|
// in the combo box. The list of names is stored in m_rgbszServerPaths
|
|
TCHAR szServer[MAX_PATH];
|
|
DWORD index = 0;
|
|
while (mb.EnumObjects( _T(""), szServer, MAX_PATH, index))
|
|
{
|
|
// before we can add this key we need to inspect its keytype to
|
|
// make sure that it is a virtual server
|
|
// get the type
|
|
BOOL f = mb.GetString( szServer, MD_KEY_TYPE, IIS_MD_UT_SERVER,
|
|
szDescription, MAX_PATH, 0 );
|
|
|
|
// check the type
|
|
if ( !f || (StrCmp(szDescription, SZ_SERVER_KEYTYPE) != 0) )
|
|
{
|
|
// increment to the next key
|
|
index++;
|
|
continue;
|
|
}
|
|
|
|
// now get the description of the virtual server
|
|
f = mb.GetString( szServer, MD_SERVER_COMMENT, IIS_MD_UT_SERVER,
|
|
szDescription, MAX_PATH, 0 );
|
|
|
|
// if the description isn't there, load the default description
|
|
if ( !f )
|
|
{
|
|
LoadString(g_hmodThisDll, IDS_DEFAULT_SERVER_DESCRIPTION, szDescription, MAX_PATH);
|
|
StrCatBuff(szDescription, szServer, MAX_PATH);
|
|
}
|
|
// add the description to the combo box
|
|
i = (INT)SendMessage( m_ccombo_server, CB_ADDSTRING, 0, (LPARAM)szDescription );
|
|
|
|
// hide the server path as private data
|
|
LRESULT err = SendMessage( m_ccombo_server, CB_SETITEMDATA, i, (LPARAM)StrDup(szServer));
|
|
|
|
// increment to the next key
|
|
index++;
|
|
}
|
|
|
|
// close the metabase
|
|
mb.Close();
|
|
|
|
// default to selecting the first item in the combo box
|
|
SendMessage( m_ccombo_server, CB_SETCURSEL, 0, 0 );
|
|
}
|
|
else
|
|
{
|
|
err = GetLastError();
|
|
}
|
|
|
|
// show the correct icon
|
|
if ( m_fIsPWS )
|
|
ShowWindow( m_icon_iis, SW_HIDE );
|
|
else
|
|
ShowWindow( m_icon_pws, SW_HIDE );
|
|
|
|
// if it is pws, then hide the server drop-down
|
|
if ( m_fIsPWS )
|
|
{
|
|
ShowWindow( m_static_share_on_title, SW_HIDE );
|
|
ShowWindow( m_ccombo_server, SW_HIDE );
|
|
}
|
|
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// initialize the page's data - read in any existing info from the metabase
|
|
// - or determine that it is not in the metabase
|
|
void CShellExt::Init()
|
|
{
|
|
// attempt to set up the sink
|
|
m_fInitializedSink = InitializeSink();
|
|
|
|
// prepare to set up the data
|
|
UpdateData( TRUE );
|
|
|
|
// initialize the server information and combo box
|
|
InitSeverInfo();
|
|
|
|
// fill in the list of aliases
|
|
BuildAliasList();
|
|
|
|
// set the data into place
|
|
UpdateData( FALSE );
|
|
|
|
// update the state of the server
|
|
UpdateState();
|
|
EnableItems();
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// update the state of the server
|
|
void CShellExt::UpdateState()
|
|
{
|
|
BOOL fUpdate = FALSE;
|
|
CWrapMetaBase mb;
|
|
|
|
TCHAR sz[MAX_PATH];
|
|
TCHAR szVirtServer[MAX_PATH];
|
|
TCHAR szStatus[MAX_PATH];
|
|
|
|
m_state = MD_SERVER_STATE_STOPPED;
|
|
|
|
// first things first. get the state of the server
|
|
// init the mb object. If it fails then the server app is probably not running
|
|
if ( mb.FInit(m_pMBCom) )
|
|
{
|
|
GetVirtServerString( szVirtServer, MAX_PATH );
|
|
if ( mb.Open(szVirtServer) )
|
|
{
|
|
if ( !mb.GetDword( _T(""), MD_SERVER_STATE, IIS_MD_UT_SERVER, &m_state ) )
|
|
{
|
|
DWORD err = GetLastError( );
|
|
if ( err == RPC_E_SERVERCALL_RETRYLATER )
|
|
{
|
|
// try again later....
|
|
mb.Close();
|
|
PostMessage( m_hwnd, WM_UPDATE_SERVER_STATE, 0, 0 );
|
|
return;
|
|
}
|
|
}
|
|
// close the metabase object
|
|
mb.Close();
|
|
}
|
|
}
|
|
|
|
// show the appropriate items
|
|
switch( m_state )
|
|
{
|
|
case MD_SERVER_STATE_STARTING:
|
|
if ( m_fIsPWS )
|
|
LoadString( g_hmodThisDll, IDS_STATUS_STARTING, szStatus, MAX_PATH );
|
|
else
|
|
LoadString( g_hmodThisDll, IDS_STATUS_IIS_STARTING, szStatus, MAX_PATH );
|
|
break;
|
|
case MD_SERVER_STATE_STARTED:
|
|
if ( m_fIsPWS )
|
|
LoadString( g_hmodThisDll, IDS_STATUS_STARTED, szStatus, MAX_PATH );
|
|
else
|
|
LoadString( g_hmodThisDll, IDS_STATUS_IIS_STARTED, szStatus, MAX_PATH );
|
|
break;
|
|
case MD_SERVER_STATE_STOPPED:
|
|
case MD_SERVER_STATE_STOPPING:
|
|
if ( m_fIsPWS )
|
|
LoadString( g_hmodThisDll, IDS_STATUS_STOPPED, szStatus, MAX_PATH );
|
|
else
|
|
LoadString( g_hmodThisDll, IDS_STATUS_IIS_STOPPED, szStatus, MAX_PATH );
|
|
break;
|
|
case MD_SERVER_STATE_PAUSED:
|
|
if ( m_fIsPWS )
|
|
LoadString( g_hmodThisDll, IDS_STATUS_PAUSED, szStatus, MAX_PATH );
|
|
else
|
|
LoadString( g_hmodThisDll, IDS_STATUS_IIS_PAUSED, szStatus, MAX_PATH );
|
|
break;
|
|
};
|
|
|
|
// set the string into the dialog
|
|
SetWindowText( m_static_status, szStatus );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// enable items as appropriate
|
|
void CShellExt::EnableItems()
|
|
{
|
|
UpdateData( TRUE );
|
|
|
|
// if the virtual server is not running, disable most of the items
|
|
if ( m_state != MD_SERVER_STATE_STARTED )
|
|
{
|
|
EnableWindow( m_cbtn_share, FALSE );
|
|
EnableWindow( m_cbtn_not, FALSE );
|
|
|
|
EnableWindow( m_cstatic_alias_title, FALSE );
|
|
EnableWindow( m_cbtn_add, FALSE );
|
|
EnableWindow( m_cbtn_remove, FALSE );
|
|
EnableWindow( m_cbtn_edit, FALSE );
|
|
EnableWindow( m_clist_list, FALSE );
|
|
}
|
|
else
|
|
{
|
|
EnableWindow( m_cbtn_share, TRUE );
|
|
EnableWindow( m_cbtn_not, TRUE );
|
|
EnableWindow( m_ccombo_server, TRUE );
|
|
EnableWindow( m_static_share_on_title, TRUE );
|
|
|
|
EnableWindow( m_clist_list, TRUE);
|
|
EnableWindow( m_cbtn_add, FALSE);
|
|
EnableWindow( m_cbtn_remove, FALSE);
|
|
EnableWindow( m_cbtn_edit, FALSE);
|
|
m_int_share = 0;
|
|
// the virtual server is running. Do the normal thing.
|
|
// first, check the overall count of the items in the list
|
|
if ( ListBox_GetCount(m_clist_list) > 0 )
|
|
{
|
|
m_int_share = 1;
|
|
// there is stuff in the list - sharing is on
|
|
EnableWindow( m_cstatic_alias_title, TRUE );
|
|
EnableWindow( m_cbtn_add, TRUE );
|
|
// we shouldn't enable Remove for the root directory
|
|
TCHAR buffer[MAX_PATH];
|
|
int idx = ListBox_GetCurSel(m_clist_list);
|
|
if (idx != LB_ERR)
|
|
{
|
|
EnableWindow( m_cbtn_edit, TRUE );
|
|
ListBox_GetText(m_clist_list, idx, buffer);
|
|
if (StrCmp(_T("/"), buffer) != 0)
|
|
EnableWindow(m_cbtn_remove, TRUE );
|
|
}
|
|
}
|
|
}
|
|
|
|
UpdateData( FALSE );
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
BOOL CShellExt::InitializeSink()
|
|
{
|
|
IConnectionPointContainer * pConnPointContainer = NULL;
|
|
HRESULT hRes;
|
|
BOOL fSinkConnected = FALSE;
|
|
|
|
// m_pMBCom is defined in webshrpg.h
|
|
IUnknown * pmb = (IUnknown*)m_pMBCom;
|
|
|
|
m_pEventSink = new CImpIMSAdminBaseSink();
|
|
|
|
if ( !m_pEventSink )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// First query the object for its Connection Point Container. This
|
|
// essentially asks the object in the server if it is connectable.
|
|
//
|
|
|
|
hRes = pmb->QueryInterface( IID_IConnectionPointContainer,
|
|
(PVOID *)&pConnPointContainer);
|
|
if SUCCEEDED(hRes)
|
|
{
|
|
// Find the requested Connection Point. This AddRef's the
|
|
// returned pointer.
|
|
|
|
hRes = pConnPointContainer->FindConnectionPoint( IID_IMSAdminBaseSink,
|
|
&m_pConnPoint);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
hRes = m_pConnPoint->Advise( (IUnknown *)m_pEventSink,
|
|
&m_dwSinkCookie);
|
|
|
|
if (SUCCEEDED(hRes))
|
|
{
|
|
fSinkConnected = TRUE;
|
|
}
|
|
}
|
|
|
|
if ( pConnPointContainer )
|
|
{
|
|
pConnPointContainer->Release();
|
|
pConnPointContainer = NULL;
|
|
}
|
|
}
|
|
|
|
if ( !fSinkConnected )
|
|
{
|
|
delete m_pEventSink;
|
|
m_pEventSink = NULL;
|
|
}
|
|
else
|
|
{
|
|
// we are connected. Tell it where to send the udpates
|
|
m_pEventSink->SetPage( this );
|
|
}
|
|
|
|
return fSinkConnected;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------
|
|
void CShellExt::TerminateSink()
|
|
{
|
|
if (m_dwSinkCookie)
|
|
{
|
|
m_pConnPoint->Unadvise( m_dwSinkCookie );
|
|
}
|
|
if (m_pEventSink)
|
|
{
|
|
delete m_pEventSink;
|
|
m_pEventSink = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
// recursively add all the items to the tree
|
|
void CShellExt::RecurseAddVDItems(CWrapMetaBase * pmb, LPCTSTR szMB)
|
|
{
|
|
DWORD index = 0;
|
|
BOOL fAddAlias;
|
|
|
|
TCHAR sz[MAX_PATH];
|
|
TCHAR szMBPath[MAX_PATH];
|
|
|
|
// now we need to see if this is already points to us
|
|
fAddAlias = FALSE;
|
|
if ( pmb->GetString(szMB, MD_VR_PATH, IIS_MD_UT_FILE, sz, MAX_PATH, 0) )
|
|
{
|
|
// do the comparison - without regard to case
|
|
if (StrCmpI(m_szPropSheetFileUserClickedOn, sz) == 0)
|
|
{
|
|
ListBox_AddString(m_clist_list, *szMB == 0 ? _T("/") : (LPTSTR)szMB);
|
|
}
|
|
}
|
|
|
|
// enumerate the sub-directories of the open directory and add them
|
|
// to the tree. Recurse each to add its children as well
|
|
// enumerate the directories, adding each to the list
|
|
while (pmb->EnumObjects(szMB, sz, MAX_PATH, index))
|
|
{
|
|
// build the display name for this item
|
|
StrCpy(szMBPath, szMB);
|
|
PathAppend(szMBPath, sz);
|
|
|
|
// recurse the item
|
|
RecurseAddVDItems(pmb, szMBPath);
|
|
|
|
// advance the index
|
|
index++;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// rebuild all the alias items in the list
|
|
// NOTE: The only way (for now) to edit the Home directory is in the pws application
|
|
void CShellExt::BuildAliasList()
|
|
{
|
|
DWORD err;
|
|
TCHAR szRoot[200];
|
|
|
|
// create the metabase wrapper
|
|
CWrapMetaBase mb;
|
|
if ( !mb.FInit(m_pMBCom) )
|
|
return;
|
|
|
|
// go for the root directory first
|
|
GetRootString(szRoot, 100);
|
|
if ( mb.Open(szRoot) )
|
|
{
|
|
// do the recursive adding thing
|
|
RecurseAddVDItems( &mb, _T("") );
|
|
// close the metabase object
|
|
mb.Close();
|
|
}
|
|
else
|
|
err = GetLastError();
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::OnRemove()
|
|
{
|
|
int nItem;
|
|
CWrapMetaBase mb;
|
|
|
|
TCHAR szItem[MAX_PATH];
|
|
TCHAR szWAMPath[MAX_PATH];
|
|
ZeroMemory( szItem, MAX_PATH );
|
|
ZeroMemory( szWAMPath, MAX_PATH );
|
|
|
|
// get the root string once
|
|
TCHAR szRoot[200];
|
|
GetRootString( szRoot, 100 );
|
|
|
|
// get the string of the selected item
|
|
nItem = ListBox_GetCurSel(m_clist_list);
|
|
ListBox_GetText(m_clist_list, nItem, szItem);
|
|
|
|
// create the metabase wrapper
|
|
if ( !mb.FInit(m_pMBCom) )
|
|
return;
|
|
|
|
// munge the name into the confirm string - reuse the existing wampath string
|
|
LoadString( g_hmodThisDll, IDS_CONFIRM_REMOVE, szWAMPath, MAX_PATH );
|
|
TCHAR szCaption[80];
|
|
LoadString(g_hmodThisDll, IDS_PAGE_TITLE, szCaption, 80);
|
|
MyFormatString1( szWAMPath, MAX_PATH, szItem );
|
|
|
|
// ask the user if the really want to do this
|
|
if ( MessageBox( m_hwnd, szWAMPath, szCaption, MB_YESNO ) == IDYES )
|
|
{
|
|
// the WAM stuff can take some time, so put up the wait cursor
|
|
SetCursor( LoadCursor(NULL, IDC_WAIT) );
|
|
|
|
// remove the WAM application first
|
|
StrCpy( szWAMPath, szRoot );
|
|
StrCat( szWAMPath, szItem );
|
|
MakeWAMApplication( szWAMPath, FALSE );
|
|
|
|
// open the metabase at the root
|
|
if ( mb.Open(szRoot, METADATA_PERMISSION_WRITE) )
|
|
{
|
|
// remove the item from the metabase
|
|
mb.DeleteObject( szItem );
|
|
|
|
// close the metabase object
|
|
mb.Close();
|
|
}
|
|
|
|
// remove the item from the tree
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW) );
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::OnRdoNot()
|
|
{
|
|
DWORD nItems;
|
|
CWrapMetaBase mb;
|
|
|
|
TCHAR szItem[MAX_PATH];
|
|
TCHAR szWAMPath[MAX_PATH];
|
|
ZeroMemory( szItem, WIDE_MAX_PATH );
|
|
ZeroMemory( szWAMPath, WIDE_MAX_PATH );
|
|
|
|
// if there already are no aliases - don't bother
|
|
nItems = ListBox_GetCount(m_clist_list);
|
|
if ( nItems <= 0 )
|
|
return;
|
|
|
|
// create the metabase wrapper
|
|
if ( !mb.FInit(m_pMBCom) )
|
|
return;
|
|
|
|
TCHAR szCaption[80];
|
|
LoadString(g_hmodThisDll, IDS_PAGE_TITLE, szCaption, 80);
|
|
// reuse the szWAMPath
|
|
LoadString( g_hmodThisDll, IDS_CONFIRM_SHARENOT, szWAMPath, MAX_PATH );
|
|
|
|
// make sure the user wants to do this
|
|
if ( MessageBox( m_hwnd, szWAMPath, szCaption, MB_YESNO ) == IDYES )
|
|
{
|
|
// the WAM stuff can take some time, so put up the wait cursor
|
|
SetCursor( LoadCursor(NULL, IDC_WAIT) );
|
|
|
|
// open the metabase at the root
|
|
TCHAR szRoot[200];
|
|
GetRootString(szRoot, 100);
|
|
if ( mb.Open(szRoot, METADATA_PERMISSION_WRITE) )
|
|
{
|
|
// loop through the list, deleting each item
|
|
for ( DWORD iItem = 0; iItem < nItems; iItem++ )
|
|
{
|
|
// get the relative path
|
|
ListBox_GetText(m_clist_list, iItem, szItem);
|
|
|
|
// remove the WAM application first
|
|
StrCpy( szWAMPath, szRoot );
|
|
StrCat( szWAMPath, szItem );
|
|
MakeWAMApplication( szWAMPath, FALSE );
|
|
|
|
// blast it out of existence
|
|
mb.DeleteObject( szItem );
|
|
}
|
|
|
|
// close the metabase
|
|
mb.Close();
|
|
}
|
|
|
|
// update the display
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW) );
|
|
}
|
|
else
|
|
EnableItems();
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::OnAdd()
|
|
{
|
|
CEditDirectory dlgEdit(m_hwnd);
|
|
CWrapMetaBase mb;
|
|
DWORD i;
|
|
|
|
PTCHAR psz, psz2 = NULL;
|
|
|
|
TCHAR szRoot[MAX_PATH];
|
|
TCHAR szFolder[MAX_PATH];
|
|
TCHAR szTestName[MAX_PATH];
|
|
|
|
ZeroMemory(szRoot, MAX_PATH);
|
|
ZeroMemory(szFolder, MAX_PATH);
|
|
ZeroMemory(szTestName, MAX_PATH);
|
|
|
|
// get the root string once
|
|
GetRootString(dlgEdit.m_szRoot, MAX_PATH);
|
|
|
|
// get ready //m_sz_alias
|
|
dlgEdit.m_fNewItem = TRUE;
|
|
dlgEdit.m_pMBCom = m_pMBCom;
|
|
StrCpy(dlgEdit.m_sz_path, m_szPropSheetFileUserClickedOn);
|
|
|
|
// the initial name for the new alias should be the name of the directory itself.
|
|
// if there already is a virtual directory with that name, then we append a 2 to
|
|
// it. if that exists, increment until we get a valid name.
|
|
|
|
// find the part after the last '\\' character in the path
|
|
psz = PathFindFileName(m_szPropSheetFileUserClickedOn);
|
|
|
|
// put the short file name into place temporarily
|
|
StrCpy(szFolder, psz);
|
|
PathMakePretty(szFolder);
|
|
|
|
// prepare the metabase - as that is where we have to check to see if it is there
|
|
// create the metabase wrapper
|
|
if ( !mb.FInit(m_pMBCom) )
|
|
return;
|
|
|
|
// prep the test name
|
|
StrCpy(dlgEdit.m_sz_alias, szFolder);
|
|
wsprintf(szTestName, _T("%s/%s"), dlgEdit.m_szRoot, dlgEdit.m_sz_alias);
|
|
|
|
// increment the name of the directory until it is valid
|
|
i = 1;
|
|
while ( mb.Open(szTestName) )
|
|
{
|
|
// close it right away
|
|
mb.Close();
|
|
|
|
// increment the counter
|
|
i++;
|
|
|
|
// prep the test name
|
|
wsprintf(dlgEdit.m_sz_alias, _T("%s%d"), szFolder, i);
|
|
wsprintf(szTestName, _T("%s/%s"), dlgEdit.m_szRoot, dlgEdit.m_sz_alias);
|
|
}
|
|
|
|
// record the pointer to alias dlg in case a shutdown event happens
|
|
m_pEditAliasDlg = &dlgEdit;
|
|
|
|
// run it - the dialog handles writing to the metabase
|
|
if ( dlgEdit.DoModal() == IDOK )
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
|
|
m_pEditAliasDlg = NULL;
|
|
SetCursor( LoadCursor(NULL, IDC_ARROW) );
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::OnEdit()
|
|
{
|
|
CEditDirectory dlg( m_hwnd );
|
|
TCHAR szItem[MAX_PATH];
|
|
ZeroMemory( szItem, MAX_PATH );
|
|
int nItem;
|
|
|
|
// get the string of the selected item
|
|
nItem = ListBox_GetCurSel(m_clist_list);
|
|
ListBox_GetText(m_clist_list, nItem, szItem);
|
|
|
|
// get ready
|
|
dlg.m_pMBCom = m_pMBCom;
|
|
StrCpy( dlg.m_sz_alias, szItem );
|
|
StrCpy( dlg.m_sz_path, m_szPropSheetFileUserClickedOn );
|
|
GetRootString( dlg.m_szRoot, 100 );
|
|
|
|
// record the pointer to alias dlg in case a shutdown event happens
|
|
m_pEditAliasDlg = &dlg;
|
|
|
|
// run it - the dialog handles writing to the metabase
|
|
if ( dlg.DoModal() == IDOK )
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
m_pEditAliasDlg = NULL;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// to share an item - all we really have to do is add an alias
|
|
void CShellExt::OnRdoShare()
|
|
{
|
|
if ( ListBox_GetCount(m_clist_list) <= 0 )
|
|
OnAdd();
|
|
EnableItems();
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// the selection in the server combo box has just changed. This means
|
|
// we need to rebuild the alias lsit based on this new server
|
|
void CShellExt::OnSelchangeComboServer()
|
|
{
|
|
PostMessage( m_hwnd, WM_UPDATE_SERVER_STATE, 0, 0 );
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
void CShellExt::SinkNotify(
|
|
/* [in] */ DWORD dwMDNumElements,
|
|
/* [size_is][in] */ MD_CHANGE_OBJECT __RPC_FAR pcoChangeList[ ])
|
|
{
|
|
BOOL fPostedState = FALSE;
|
|
|
|
// if a key has been deleted, make sure it wasn't our virtual server
|
|
if ( pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_DELETE_OBJECT )
|
|
{
|
|
PostMessage( m_hwnd, WM_INSPECT_SERVER_LIST, 0, 0 );
|
|
}
|
|
|
|
// do the appropriate action based on the type of change
|
|
if ( (pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_DELETE_OBJECT) ||
|
|
(pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_ADD_OBJECT) ||
|
|
(pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_RENAME_OBJECT) )
|
|
{
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
}
|
|
else if ( pcoChangeList->dwMDChangeType & MD_CHANGE_TYPE_SET_DATA )
|
|
{
|
|
for ( DWORD iElement = 0; iElement < dwMDNumElements; iElement++ )
|
|
{
|
|
// each change has a list of IDs...
|
|
for ( DWORD iID = 0; iID < pcoChangeList[iElement].dwMDNumDataIDs; iID++ )
|
|
{
|
|
// look for the ids that we are interested in
|
|
switch( pcoChangeList[iElement].pdwMDDataIDs[iID] )
|
|
{
|
|
case MD_SERVER_STATE:
|
|
if ( !fPostedState )
|
|
PostMessage( m_hwnd, WM_UPDATE_SERVER_STATE, 0, 0 );
|
|
fPostedState = TRUE;
|
|
break;
|
|
default:
|
|
// do nothing
|
|
break;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// only arrives if shutdown notify has happened
|
|
void CShellExt::OnTimer( UINT nIDEvent )
|
|
{
|
|
CheckIfServerIsRunningAgain();
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
// This routine is called called when we process the shutdown notify
|
|
// windows message that we posted to our queue when we got the shutdown
|
|
// notification event from the metabase. We cant just do this when we
|
|
// get the shutdown notify because that could leave the metabse in
|
|
// a funky state, and that would be bad.
|
|
void CShellExt::EnterShutdownMode()
|
|
{
|
|
TCHAR szStatus[400];
|
|
|
|
// if the edit alias dialog is open, start by closing it
|
|
if ( m_pEditAliasDlg )
|
|
{
|
|
m_pEditAliasDlg->EndDialog(IDCANCEL);
|
|
m_pEditAliasDlg = NULL;
|
|
}
|
|
|
|
// shutdown the sink attached to the document
|
|
TerminateSink();
|
|
m_fInitializedSink = FALSE;
|
|
|
|
// close the link to the metabase - it is going away after all
|
|
FCloseMetabase();
|
|
|
|
// record that we are in shutdown mode
|
|
m_fShutdownMode = TRUE;
|
|
|
|
// start up the timer mechanism
|
|
SetTimer( m_hwnd, PWS_TIMER_CHECKFORSERVERRESTART, TIMER_RESTART, NULL );
|
|
|
|
// empty all the items in the list
|
|
EmptyList();
|
|
|
|
// set the current status string
|
|
if ( m_fIsPWS )
|
|
LoadString( g_hmodThisDll, IDS_STATUS_SHUTDOWN, szStatus, 200 );
|
|
else
|
|
LoadString( g_hmodThisDll, IDS_STATUS_IIS_SHUTDOWN, szStatus, 200 );
|
|
|
|
// disable everything
|
|
EnableWindow( m_cbtn_share, FALSE );
|
|
EnableWindow( m_cbtn_not, FALSE );
|
|
EnableWindow( m_cstatic_alias_title, FALSE );
|
|
EnableWindow( m_cbtn_add, FALSE );
|
|
EnableWindow( m_cbtn_remove, FALSE );
|
|
EnableWindow( m_cbtn_edit, FALSE );
|
|
EnableWindow( m_clist_list, FALSE );
|
|
EnableWindow( m_static_share_on_title, FALSE );
|
|
EnableWindow( m_ccombo_server, FALSE );
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
// This routine is called on a timer event. The timer events only come if we
|
|
// have received a shutdown notify callback from the metabase. So the server
|
|
// is down. We need to wait around until it comes back up, then show ourselves.
|
|
void CShellExt::CheckIfServerIsRunningAgain()
|
|
{
|
|
// see if the server is running. If it is, show the icon and stop the timer.
|
|
if ( FIsW3Running() )
|
|
{
|
|
// if we can't use the metabase, there is no point in this
|
|
if ( !FInitMetabase() )
|
|
return;
|
|
|
|
// attempt to set up the sink
|
|
m_fInitializedSink = InitializeSink();
|
|
|
|
// clear the shutdown mode flag
|
|
m_fShutdownMode = FALSE;
|
|
|
|
// stop the timer mechanism
|
|
KillTimer( m_hwnd, PWS_TIMER_CHECKFORSERVERRESTART );
|
|
|
|
// enable any items that need it
|
|
EnableWindow( m_cbtn_share, TRUE );
|
|
EnableWindow( m_cbtn_not, TRUE );
|
|
EnableWindow( m_static_share_on_title, TRUE );
|
|
EnableWindow( m_ccombo_server, TRUE );
|
|
|
|
// tell the main page to update itself
|
|
PostMessage( m_hwnd, WM_UPDATE_SERVER_STATE, 0, 0 );
|
|
PostMessage( m_hwnd, WM_UPDATE_ALIAS_LIST, 0, 0 );
|
|
}
|
|
}
|
|
|
|
// routine to see if w3svc is running
|
|
//--------------------------------------------------------------------
|
|
// the method we use to see if the service is running is different on
|
|
// windows NT from win95
|
|
BOOL CShellExt::FIsW3Running()
|
|
{
|
|
OSVERSIONINFO info_os;
|
|
info_os.dwOSVersionInfoSize = sizeof(info_os);
|
|
|
|
if ( !GetVersionEx( &info_os ) )
|
|
return FALSE;
|
|
|
|
// if the platform is NT, query the service control manager
|
|
if ( info_os.dwPlatformId == VER_PLATFORM_WIN32_NT )
|
|
{
|
|
BOOL fRunning = FALSE;
|
|
|
|
// open the service manager
|
|
SC_HANDLE sch = OpenSCManager(NULL, NULL, GENERIC_READ );
|
|
if ( sch == NULL ) return FALSE;
|
|
|
|
// get the service
|
|
SC_HANDLE schW3 = OpenService(sch, _T("W3SVC"), SERVICE_QUERY_STATUS );
|
|
if ( sch == NULL )
|
|
{
|
|
CloseServiceHandle( sch );
|
|
return FALSE;
|
|
}
|
|
|
|
// query the service status
|
|
SERVICE_STATUS status;
|
|
ZeroMemory( &status, sizeof(status) );
|
|
if ( QueryServiceStatus(schW3, &status) )
|
|
{
|
|
fRunning = (status.dwCurrentState == SERVICE_RUNNING);
|
|
}
|
|
|
|
CloseServiceHandle( schW3 );
|
|
CloseServiceHandle( sch );
|
|
|
|
// return the answer
|
|
return fRunning;
|
|
}
|
|
|
|
// if the platform is Windows95, see if the object exists
|
|
if ( info_os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS )
|
|
{
|
|
HANDLE hEvent;
|
|
BOOL fFound = FALSE;
|
|
hEvent = CreateEvent(NULL, TRUE, FALSE, _T(PWS_SHUTDOWN_EVENT));
|
|
if ( hEvent != NULL )
|
|
{
|
|
fFound = (GetLastError() == ERROR_ALREADY_EXISTS);
|
|
CloseHandle(hEvent);
|
|
}
|
|
return(fFound);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::OnFinalRelease()
|
|
{
|
|
CleanUpConnections();
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
void CShellExt::CleanUpConnections()
|
|
{
|
|
// if we have the metabase, release it
|
|
if ( m_fInitializedSink )
|
|
{
|
|
TerminateSink();
|
|
m_fInitializedSink = FALSE;
|
|
}
|
|
if ( m_fInitialized )
|
|
{
|
|
FCloseMetabase();
|
|
m_fInitialized = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
BOOL CShellExt::FInitMetabase()
|
|
{
|
|
BOOL f = TRUE;
|
|
HRESULT hres;
|
|
|
|
if ( !m_pMBCom )
|
|
{
|
|
hres = CoInitialize(NULL);
|
|
if ( SUCCEEDED(hres) )
|
|
{
|
|
f = FInitMetabaseWrapperEx( NULL, &m_pMBCom );
|
|
}
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
//--------------------------------------------------------------------
|
|
BOOL CShellExt::FCloseMetabase()
|
|
{
|
|
BOOL f = TRUE;
|
|
|
|
if ( m_pMBCom )
|
|
{
|
|
f = FCloseMetabaseWrapperEx( &m_pMBCom );
|
|
m_pMBCom = NULL;
|
|
CoUninitialize();
|
|
}
|
|
|
|
return f;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
// This routine takes a path to a virutal directory in the metabase and creates
|
|
// a WAM application there. Most of the code is actually obtaining and maintaining
|
|
// the interface to the WAM ole object
|
|
// szPath The path to the metabase
|
|
// fCreate True if creating an application, FALSE if deleting an existing app
|
|
BOOL MakeWAMApplication( IN LPCTSTR pszPath, IN BOOL fCreate )
|
|
{
|
|
IClassFactory* pcsfFactory = NULL;
|
|
IWamAdmin2* pWAM;
|
|
HRESULT hresError;
|
|
BOOL fAnswer = FALSE;
|
|
|
|
hresError = CoGetClassObject( CLSID_WamAdmin, CLSCTX_SERVER, NULL,
|
|
IID_IClassFactory, (void**) &pcsfFactory);
|
|
if (FAILED(hresError))
|
|
return FALSE;
|
|
|
|
// create the instance of the interface
|
|
hresError = pcsfFactory->CreateInstance(NULL, IID_IWamAdmin2, (void **)&pWAM);
|
|
if (FAILED(hresError))
|
|
return FALSE;
|
|
|
|
// release the factory
|
|
pcsfFactory->Release();
|
|
|
|
// calc the string length just once
|
|
DWORD szLen = _tcslen(pszPath);
|
|
|
|
// this part will be nicer after it is converted to unicode
|
|
WCHAR* pwch;
|
|
// allocate the name buffer
|
|
pwch = new WCHAR[szLen + 2];
|
|
if ( !pwch )
|
|
{
|
|
pWAM->Release();
|
|
return FALSE;
|
|
}
|
|
ZeroMemory( pwch, (szLen + 2)*sizeof(WCHAR) );
|
|
|
|
// unicodize the name into the buffer
|
|
if ( pwch )
|
|
{
|
|
|
|
#ifdef _UNICODE
|
|
|
|
//
|
|
// UNICODE conversion by RonaldM
|
|
//
|
|
// This is actually probably not needed.
|
|
//
|
|
lstrcpy(pwch, pszPath);
|
|
|
|
#else
|
|
|
|
MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pszPath, -1,
|
|
pwch, szLen );
|
|
|
|
#endif // _UNICODE
|
|
|
|
// create the in-proc application, if requested
|
|
if ( fCreate )
|
|
{
|
|
hresError = pWAM->AppCreate2( pwch, eAppRunOutProcInDefaultPool );
|
|
}
|
|
else
|
|
{
|
|
// delete the application. Because the whole virtual dir is going away,
|
|
// delete any applications lower down in the tree as well
|
|
hresError = pWAM->AppDelete( pwch, TRUE );
|
|
}
|
|
|
|
// check the error code
|
|
fAnswer = SUCCEEDED( hresError );
|
|
|
|
// clean up
|
|
delete pwch;
|
|
}
|
|
|
|
// release the logging ui
|
|
pWAM->Release();
|
|
|
|
// return the answer
|
|
return fAnswer;
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
BOOL MyFormatString1( IN LPTSTR pszSource, IN DWORD cchMax, LPTSTR pszReplace )
|
|
{
|
|
return FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
|
|
pszSource,
|
|
NULL,
|
|
NULL,
|
|
pszSource,
|
|
cchMax,
|
|
(va_list*)&pszReplace
|
|
) > 0;
|
|
}
|