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.
291 lines
8.7 KiB
291 lines
8.7 KiB
// MetaExp.cpp : Defines the entry point for the console application.
|
|
//
|
|
|
|
#define _WIN32_DCOM
|
|
|
|
#include <atlbase.h>
|
|
#include <atlconv.h>
|
|
#include <initguid.h>
|
|
#include <comdef.h>
|
|
#include <stdio.h>
|
|
#include <iadmw.h> // COM Interface header file.
|
|
#include <iiscnfg.h> // MD_ & IIS_MD_ #defines header file.
|
|
#include <conio.h>
|
|
|
|
#include "util.h"
|
|
#include "auth.h"
|
|
#include "filecopy.h"
|
|
#include "mbase.h"
|
|
|
|
|
|
#define DEFAULT_APP_POOL_ID L"ImportedAppPool"
|
|
PXCOPYTASKITEM g_pTaskItemList;
|
|
|
|
void Usage(WCHAR* image)
|
|
{
|
|
wprintf( L"\nDescription: Utility for moving IIS web sites from server to server\n\n" );
|
|
wprintf( L"Usage: %s <source machine name> <metabase path> [/o /d:<root directory> /a:<app pool id> /s /c]\n\n", image );
|
|
wprintf( L"\t/d:<path> specify root directory path\n");
|
|
wprintf( L"\t/m:<metabase path> specify metabase path for target server\n");
|
|
wprintf( L"\t/a:<apppool> specify app pool ID\n");
|
|
wprintf( L"\t/b:<serverbinding> serverbindings string\n");
|
|
wprintf( L"\t/c copy IIS configuration only\n");
|
|
wprintf( L"\t/u:<user> username to connect to source server\n");
|
|
wprintf( L"\t/p:<pwd> password to connect to source server\n\n");
|
|
wprintf( L"Examples:\n\t%s IIS-01 /lm/w3svc/1\n", image );
|
|
wprintf( L"\t%s IIS-01 /lm/w3svc/2 /d:f:\\inetpub\\wwwroot /c\n", image );
|
|
wprintf( L"\t%s IIS-01 /lm/w3svc/2 /d:f:\\inetpub\\wwwroot /m:w3svc/3\n", image );
|
|
wprintf( L"\t%s IIS-01 /lm/w3svc/2 /d:f:\\inetpub\\wwwroot /a:MyAppPool\n", image );
|
|
wprintf( L"\t%s IIS-01 /lm/w3svc/2 /d:f:\\inetpub\\wwwroot /b:192.168.1.1:80:www.mysite.com\n", image );
|
|
wprintf( L"\n");
|
|
|
|
}
|
|
|
|
|
|
int
|
|
wmain(int argc, wchar_t* argv[])
|
|
{
|
|
|
|
HRESULT hRes = 0L;
|
|
wchar_t** argp;
|
|
|
|
_bstr_t bstrRootKey = L"/LM";
|
|
_bstr_t bstrSourceServer;
|
|
_bstr_t bstrSourceNode;
|
|
_bstr_t bstrArgz;
|
|
_bstr_t bstrTargetNode;
|
|
_bstr_t bstrTargetDir;
|
|
_bstr_t bstrAppPoolID = DEFAULT_APP_POOL_ID;
|
|
_bstr_t bstrRemoteUserName;
|
|
_bstr_t bstrRemoteUserPass;
|
|
_bstr_t bstrDomainName;
|
|
_bstr_t bstrServerBindings;
|
|
|
|
char userpassword[81];
|
|
|
|
BOOL bCopyContent = true;
|
|
BOOL bCopySubKeys = true;
|
|
BOOL bIsLocal = false;
|
|
BOOL bUsesImpersonation = false;
|
|
|
|
|
|
COSERVERINFO *pServerInfoSource = NULL;
|
|
COSERVERINFO *pServerInfoTarget = NULL;
|
|
PXCOPYTASKITEM pListItem = NULL;
|
|
|
|
g_pTaskItemList = NULL;
|
|
|
|
hRes = CoInitialize(NULL);
|
|
|
|
// check for the required command-line arguments
|
|
if( argc < 3) {
|
|
Usage( argv[0] );
|
|
return -1;
|
|
}
|
|
|
|
bstrSourceServer = argv[1];
|
|
// cannonicalize the node value
|
|
bstrSourceNode = argv[2];
|
|
//bstrSourceNode += wcsstr( _wcslwr( argv[2] ), L"w3svc") ;
|
|
|
|
for (argp = argv + 3; *argp != NULL; argp++ ) {
|
|
if( (**argp == '/') || (**argp == '-') )
|
|
{
|
|
bstrArgz = *argp+1;
|
|
if( !_strnicmp( (char*)bstrArgz, "M:", sizeof("M:")-1) )
|
|
{
|
|
bstrTargetNode = *argp + sizeof("M:") ;
|
|
_tprintf(_T("target metabase key: %s\n"),(char *)bstrTargetNode);
|
|
continue;
|
|
}
|
|
if( !_strnicmp( (char*)bstrArgz, "D:", sizeof("D:")-1) )
|
|
{
|
|
bstrTargetDir = *argp + sizeof("D:");
|
|
_tprintf(_T("target dir: %s\n"),(char *)bstrTargetDir);
|
|
continue;
|
|
}
|
|
if( !_strnicmp( (char*)bstrArgz, "C", sizeof("C")-1) )
|
|
{
|
|
bCopyContent = false;
|
|
_tprintf(_T("copy metabase configuration only: true\n"));
|
|
continue;
|
|
}
|
|
if( !_strnicmp( (char*)bstrArgz, "A:", sizeof("A:")-1) )
|
|
{
|
|
bstrAppPoolID = *argp + sizeof("A:");
|
|
_tprintf(_T("app pool ID: %s\n"),(char *)bstrAppPoolID);
|
|
continue;
|
|
}
|
|
if( !_strnicmp( (char*)bstrArgz, "B:", sizeof("B:")-1) )
|
|
{
|
|
bstrServerBindings = *argp + sizeof("B:");
|
|
_tprintf(_T("ServerBindings: %s\n"),(char *)bstrServerBindings);
|
|
continue;
|
|
}
|
|
|
|
if( !_strnicmp( (char*)bstrArgz, "U:", sizeof("U:")-1) )
|
|
{
|
|
bstrRemoteUserName = *argp + sizeof("U:");
|
|
bUsesImpersonation = true;
|
|
_tprintf(_T("Remote User Name: %s\n"), (char*)bstrRemoteUserName );
|
|
continue;
|
|
}
|
|
|
|
if( !_strnicmp( (char*)bstrArgz, "P:", sizeof("P:")-1) )
|
|
{
|
|
bstrRemoteUserPass = *argp + sizeof("U:");
|
|
_tprintf(_T("Remote User Name: *********\n"));
|
|
continue;
|
|
}
|
|
|
|
fprintf(stderr, "unknown option '%s'\n", *argp+1);
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
fprintf(stderr, "unknown option '%s'\n", (char *)bstrArgz);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// If the user password is not present, then read from the command line
|
|
// echo '*' characters to obfuscate passord
|
|
if( (bstrRemoteUserName.length() > 0) && (bstrRemoteUserPass.length() < 1) )
|
|
{
|
|
_tprintf(_T("Enter the password for %s "), (char*)bstrRemoteUserName);
|
|
char ch;
|
|
int i;
|
|
|
|
ch = getch();
|
|
for( i = 0;i < 80; i++)
|
|
{
|
|
if(ch == 13)
|
|
break;
|
|
userpassword[i] = ch;
|
|
putch('*');
|
|
ch = getch();
|
|
}
|
|
userpassword[i] = NULL;
|
|
bstrRemoteUserPass = userpassword;
|
|
}
|
|
|
|
// cannonicalize the source metabase node
|
|
if( NULL == wcsstr( _wcslwr( bstrSourceNode ), L"w3svc") )
|
|
{
|
|
fwprintf(stderr,L"source path value %s is invalid format\n", bstrSourceNode.GetBSTR() );
|
|
return 1;
|
|
}
|
|
bstrSourceNode = _bstr_t("/") + _bstr_t(wcsstr( _wcslwr( bstrSourceNode ), L"w3svc") ) ;
|
|
_tprintf(_T("Source metabase key: %s\n"), (char*)bstrSourceNode );
|
|
|
|
// cannonicalize the target metabase node if present, otherwise it is the source
|
|
if( bstrTargetNode.length() > 0 )
|
|
{
|
|
if( NULL == wcsstr( _wcslwr( bstrTargetNode ), L"w3svc") )
|
|
{
|
|
fwprintf(stderr,L"target path value %s is invalid format\n", bstrTargetNode.GetBSTR() );
|
|
return 1;
|
|
}
|
|
bstrTargetNode = _bstr_t("/") + _bstr_t(wcsstr( _wcslwr( bstrTargetNode ), L"w3svc") ) ;
|
|
_tprintf(_T("Target metabase key: %s\n"), (char*)bstrTargetNode );
|
|
}
|
|
|
|
|
|
if( IsServerLocal((char*)bstrSourceServer) )
|
|
{
|
|
bIsLocal = true;
|
|
if( bstrSourceNode == bstrTargetNode )
|
|
{
|
|
fwprintf(stderr,L"cannot import same node for local copy. Program exiting\n");
|
|
return 1;
|
|
}
|
|
|
|
if( bCopyContent && !bstrTargetDir)
|
|
{
|
|
fwprintf(stderr,L"cannot overwrite directory same node for local copy. Program exiting\n");
|
|
return 1;
|
|
}
|
|
|
|
}
|
|
|
|
// Create COSERVERINFO structs used for DCOM connection to source and
|
|
// target servers
|
|
pServerInfoSource = CreateServerInfoStruct(bstrSourceServer,bstrRemoteUserName,bstrDomainName,
|
|
bstrRemoteUserPass,RPC_C_AUTHN_LEVEL_CONNECT);
|
|
ATLASSERT( pServerInfoSource );
|
|
|
|
pServerInfoTarget = CreateServerInfoStruct(L"localhost",NULL,NULL,NULL,0,false);
|
|
ATLASSERT( pServerInfoTarget );
|
|
|
|
|
|
// check if user can connect and open a metabase key on the source machine
|
|
if( !AUTHUSER(pServerInfoSource) )
|
|
{
|
|
fwprintf(stderr,L"could not open metabase on server %s. Program exiting\n",
|
|
pServerInfoSource->pwszName );
|
|
return 1;
|
|
}
|
|
|
|
// check if user can connect and open a metabase key on the target machine
|
|
if( !AUTHUSER(pServerInfoTarget) )
|
|
{
|
|
fwprintf(stderr,L"could not open metabase on server %s. Program exiting\n",
|
|
pServerInfoTarget->pwszName );
|
|
goto cleanup;
|
|
}
|
|
|
|
// Check to see if the node is of type IIsWebServer
|
|
if( !ValidateNode(pServerInfoSource,bstrSourceNode,L"IIsWebServer") )
|
|
{
|
|
fwprintf(stderr,L"source key %s must be of type IIsWebServer. Program exiting\n",
|
|
bstrSourceNode );
|
|
goto cleanup;
|
|
}
|
|
|
|
if( bIsLocal && (bstrTargetDir.length() < 1) )
|
|
fwprintf(stderr,L"skipping content copy for local copy\n");
|
|
|
|
else
|
|
{
|
|
if( bUsesImpersonation ) // use "net use" command to connect to the remote comupter so Admin shares can
|
|
// be used
|
|
if ( ERROR_SUCCESS != NET(bstrSourceServer,bstrRemoteUserName,bstrRemoteUserPass) )
|
|
{
|
|
_tprintf( _T("Error encountered in NET USE operation\n") );
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
// if bCopyContent parameter is true, then this function will actually copy the content
|
|
// otherwise it just builds a TaskItemList of nodes that will need their Path parameter reset
|
|
CopyContent(pServerInfoSource,bstrSourceNode + _bstr_t(L"/root"),bstrTargetDir,
|
|
&pListItem, bCopyContent );
|
|
}
|
|
|
|
|
|
|
|
// bstrTarget node will be returned with the target node of the target, if it is passed in as blank.
|
|
hRes = CopyIISConfig(pServerInfoSource,pServerInfoTarget,bstrSourceNode,bstrTargetNode);
|
|
|
|
if( !SUCCEEDED(hRes) )
|
|
{
|
|
fwprintf(stderr,L"Error encountered with metabase copy. HRESULT = %x\n",hRes);
|
|
goto cleanup;
|
|
}
|
|
|
|
hRes = ApplyMBFixUp(pServerInfoTarget,bstrTargetNode,bstrAppPoolID,
|
|
pListItem, bstrServerBindings, true );
|
|
|
|
_tprintf(_T("finished.\n") );
|
|
|
|
|
|
cleanup:
|
|
|
|
FreeServerInfoStruct(pServerInfoSource);
|
|
FreeServerInfoStruct(pServerInfoTarget);
|
|
FreeXCOPYTaskList(pListItem);
|
|
|
|
CoUninitialize();
|
|
|
|
return 0;
|
|
}
|