// MetaExp.cpp : Defines the entry point for the console application. // #define _WIN32_DCOM #include #include #include #include #include #include // COM Interface header file. #include // MD_ & IIS_MD_ #defines header file. #include #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 [/o /d: /a: /s /c]\n\n", image ); wprintf( L"\t/d: specify root directory path\n"); wprintf( L"\t/m: specify metabase path for target server\n"); wprintf( L"\t/a: specify app pool ID\n"); wprintf( L"\t/b: serverbindings string\n"); wprintf( L"\t/c copy IIS configuration only\n"); wprintf( L"\t/u: username to connect to source server\n"); wprintf( L"\t/p: 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; }