/*++ Copyright (c) 1997 Microsoft Corporation Module Name : main.cpp Abstract: command line admin tool main function Environment: Win32 User Mode Author: jaroslad (jan 1997) --*/ #include #include #include #include #include #include "admutil.h" #include "tables.h" #include "jd_misc.h" CAdmUtil oAdmin; //admin object #define MAX_NUMBER_OF_SMALL_VALUES 100 #define MAX_NUMBER_OF_VALUES 10100 #define MAX_NUMBER_OF_DEFAULT_ARGS 10110 //structure stores the command line arguments struct tAdmutilParams { WORD fHelp; //print help - flag WORD fFullHelp; //print help - flag WORD fNoSave; //do not save metabase LPCTSTR lpszCommand; LPCTSTR lpszComputer; WORD wInstance; LPCTSTR lpszService; LPCTSTR lpszPath; LPCTSTR lpszComputerDst; //for COPY destination WORD wInstanceDst; //for COPY destination LPCTSTR lpszServiceDst; //for COPY destination LPCTSTR lpszPathDst; //for COPY destination LPCTSTR lplpszDefaultArg[MAX_NUMBER_OF_DEFAULT_ARGS]; WORD wDefaultArgCount; LPCTSTR lpszPropName; LPCTSTR lplpszPropAttrib[MAX_NUMBER_OF_SMALL_VALUES]; WORD wPropAttribCount; LPCTSTR lplpszPropDataType[MAX_NUMBER_OF_SMALL_VALUES]; WORD wPropDataTypeCount; LPCTSTR lplpszPropUserType[MAX_NUMBER_OF_SMALL_VALUES]; WORD wPropUserTypeCount; LPCTSTR lplpszPropValue[MAX_NUMBER_OF_VALUES]; //pointer to array of values (e.g multisz type allows the multiple values for one property DWORD lpdwPropValueLength[MAX_NUMBER_OF_VALUES]; WORD wPropValueCount; WORD wPropFileValueCount; }; tAdmutilParams Params; _TCHAR **g_argv; int g_argc; static BOOL CompareOutput(_TCHAR *FileToCompare,_TCHAR* FileTemplate); // definition of command line syntax with some help text -this is the input for ParseParam() TParamDef CmdLineArgDesc[]= { {_TEXT(""),MAX_NUMBER_OF_DEFAULT_ARGS, (void *) Params.lplpszDefaultArg,TYPE_LPCTSTR,OPT, _TEXT("Command [param ...]"),_TEXT("CMD [param param]"),&Params.wDefaultArgCount}, {_TEXT("svc") ,1, (void *) &Params.lpszService,TYPE_LPCTSTR,OPT,_TEXT("service (MSFTPSVC, W3SVC)")}, {_TEXT("s"), 1, (void *) &Params.lpszComputer,TYPE_LPCTSTR,OPT, _TEXT("name of computer to administer"),_TEXT("comp"),}, {_TEXT("i") ,1, &Params.wInstance, TYPE_WORD, OPT,_TEXT("instance number"),_TEXT("inst")}, {_TEXT("path"),1, (void *) &Params.lpszPath, TYPE_LPCTSTR,OPT, _TEXT("path "),_TEXT("path")}, {_TEXT("pathdst"),1, (void *) &Params.lpszPathDst, TYPE_LPCTSTR,OPT, _TEXT("destination path (use for COPY only)"),_TEXT("path")}, {_TEXT("prop"),1, (void *) &Params.lpszPropName, TYPE_LPCTSTR,OPT, _T("property (IIS parameter) name")}, {_TEXT("attrib"),MAX_NUMBER_OF_SMALL_VALUES, (void *) Params.lplpszPropAttrib,TYPE_LPCTSTR,OPT, _T("property attributes"),_T(""),&Params.wPropAttribCount}, {_TEXT("utype"),MAX_NUMBER_OF_SMALL_VALUES, (void *) Params.lplpszPropUserType,TYPE_LPCTSTR,OPT, _T("property user type"),_T(""),&Params.wPropUserTypeCount}, {_TEXT("dtype"),MAX_NUMBER_OF_SMALL_VALUES, (void *) Params.lplpszPropDataType,TYPE_LPCTSTR,OPT, _T("property data type"),_T(""),&Params.wPropDataTypeCount}, {_TEXT("value"),MAX_NUMBER_OF_VALUES, (void *) Params.lplpszPropValue,TYPE_LPCTSTR,OPT, _T("property values"),_T(""),&Params.wPropValueCount}, {_TEXT("fvalue"),MAX_NUMBER_OF_VALUES, (void *) Params.lplpszPropValue,TYPE_LPCTSTR,OPT, _T("property values as files"),_T(""),&Params.wPropFileValueCount}, {_TEXT("nosave"),0, &Params.fNoSave,TYPE_WORD,OPT, _T("do not save metabase"),_T("")}, {_TEXT("timeout"),1, &g_dwTIMEOUT_VALUE,TYPE_DWORD,OPT, _T("timeout for metabase access in ms (default is 30000 sec"),_T("")}, {_TEXT("delayafteropen"),1, &g_dwDELAY_AFTER_OPEN_VALUE,TYPE_DWORD,OPT, _T("delay after opening node (default is 0 sec)"),_T("")}, {_TEXT("help"),0, &Params.fFullHelp,TYPE_WORD,OPT, _T("print full help"),_T("")}, {_TEXT("?"),0, &Params.fHelp,TYPE_WORD,OPT, _T("print help"),_T("")}, {NULL,0, NULL , TYPE_TCHAR, OPT, _T("IIS K2 administration utility that enables the manipulation with metabase parameters\n") _T("\n") _T("Notes:\n") _T(" Simpified usage of mdutil doesn't require any switches.\n") _T(" \n") _T(" mdutil GET path - display chosen parameter\n") _T(" mdutil SET path value ... - assign the new value\n") _T(" mdutil ENUM path - enumerate all parameters for given path\n") _T(" mdutil ENUM_ALL path - recursively enumerate all parameters\n") _T(" mdutil DELETE path - delete given path or parameter\n") _T(" mdutil CREATE path - create given path\n") _T(" mdutil COPY pathsrc pathdst - copy all from pathsrc to pathdst (will create pathdst)\n") _T(" mdutil RENAME pathsrc pathdst - rename chosen path\n") _T(" mdutil SCRIPT scriptname - runs the script\n") _T(" mdutil APPCREATEINPROC w3svc/1/root - Create an in-proc application \n") _T(" mdutil APPCREATEOUTPROC w3svc/1/root - Create an out-proc application\n") _T(" mdutil APPDELETE w3svc/1/root - Delete the application if there is one\n") _T(" mdutil APPRENAME w3svc/1/root/dira w3svc/1/root/dirb - Rename the application \n") _T(" mdutil APPUNLOAD w3svc/1/root - Unload an application from w3svc runtime lookup table.\n") _T(" mdutil APPGETSTATUS w3svc/1/root - Get status of the application\n") _T("\n") _T(" -path has format: {computer}/{service}/{instance}/{URL}/{Parameter}\n") _T("\n") _T("Samples:\n") _T(" mdutil GET W3SVC/1/ServerBindings \n") _T(" mdutil SET JAROSLAD2/W3SVC/1/ServerBindings \":81:\"\n") _T(" mdutil COPY W3SVC/1/ROOT/iisadmin W3SVC/2/ROOT/adm\n") _T(" mdutil ENUM_ALL W3SVC\n") _T(" mdutil ENUM W3SVC/1\n") _T("\n") _T("Additional features\n") _T(" set MDUTIL_BLOCK_ON_ERROR environment variable to block mdutil.exe after error (except ERROR_PATH_NOT_FOUND)\n") _T(" set MDUTIL_ASCENT_LOG environment variable to force mdutil.exe to append errors to ascent log\n") _T(" set MDUTIL_PRINT_ID environment variable to force mdutil.exe to print metadata numeric identifiers along with friendly names\n") } }; BOOL ReadFromFiles( LPTSTR* lplpszPropValue, DWORD* lpdwPropValueLength, DWORD dwPropFileValueCount ) { DWORD dwL; while ( dwPropFileValueCount-- ) { FILE* fIn = _tfopen( lplpszPropValue[dwPropFileValueCount], _T("rb") ); if ( fIn == NULL ) { return FALSE; } if ( fseek( fIn, 0, SEEK_END ) == 0 ) { dwL = ftell( fIn ); fseek( fIn, 0, SEEK_SET ); } else { fclose( fIn ); return FALSE; } if ( (lplpszPropValue[dwPropFileValueCount] = (LPTSTR)malloc( dwL )) == NULL ) { fclose( fIn ); return FALSE; } if ( fread( lplpszPropValue[dwPropFileValueCount], 1, dwL, fIn ) != dwL ) { fclose( fIn ); return FALSE; } fclose( fIn ); lpdwPropValueLength[dwPropFileValueCount] = dwL; } return TRUE; } /////////////////////////////// class CScript { FILE * m_fpScript; void GetNextToken(/*OUT*/ LPTSTR * lplpszToken); DWORD CleanWhiteSpaces(void); public: CScript(void) {m_fpScript=0;}; DWORD Open(LPCTSTR lpszFile); DWORD Close(void); DWORD GetNextLineTokens(int *argc, /*OUT*/ _TCHAR *** argv); }; DWORD CScript::CleanWhiteSpaces() { if(m_fpScript!=NULL) { int LastChar=0; _TINT c=0; while(1) { LastChar=c; c=_fgettc(m_fpScript); if(c==_T('\t') || c==_T(' ') || c==_T('\r')) { continue; } if(c==_T('\\')) { int cc=_fgettc(m_fpScript); if (cc==_T('\r')) //continue with the next line of the file { if(_fgettc(m_fpScript)!=_T('\n')) { fseek( m_fpScript, -1, SEEK_CUR ); } continue; } else if (cc==_T('\n')) //continue with the next line of the file { continue; } else { fseek( m_fpScript, -2, SEEK_CUR ); break; } } if(c==WEOF) { break; } else { fseek( m_fpScript, -1, SEEK_CUR ); //return back one position break; } } } return 0; } void CScript::GetNextToken(LPTSTR * lplpszToken) { enum {TERMINATE_QUOTE, TERMINATE_WHITESPACE}; long flag=TERMINATE_WHITESPACE; //clean white spaces CleanWhiteSpaces(); //store the beginning offset of token long Offset = ftell(m_fpScript); _TINT c=_fgettc(m_fpScript); long CurrentOffset=0; if(c==WEOF) { *lplpszToken=NULL; return ; } if (c==_T('\n')){ *lplpszToken=_T("\n"); return ; } else { if (c==_T('\"')) { //token ends with " or the end of the line flag=TERMINATE_QUOTE; Offset = ftell(m_fpScript); } else { flag=TERMINATE_WHITESPACE; } // find the end of the token while(1) { CurrentOffset=ftell(m_fpScript); c=_fgettc(m_fpScript); if(c==_T('\n')){ break; } if(c==WEOF) { break; } if( (flag==TERMINATE_QUOTE && c==_T('\"')) || ( flag==TERMINATE_WHITESPACE && (c==_T(' ') || c==_T('\t') || c==_T('\r')) ) ){ break; } } //get the token size long TokenSize = CurrentOffset - Offset; if(TokenSize!=0) { // allocate mamory for the token *lplpszToken = new _TCHAR[ TokenSize+1 ]; //read the token fseek( m_fpScript, Offset, SEEK_SET); for(int i=0;i0) { //first default has to be command Params.lpszCommand=Params.lplpszDefaultArg[0]; dwCommandCode = tCommandNameTable::MapNameToCode(Params.lplpszDefaultArg[0]); if( Params.wDefaultArgCount>1) { //second default Params.lpszPath=Params.lplpszDefaultArg[1]; } if(dwCommandCode==CMD_SCRIPT) //process script { tAdmutilParams StoredParams=Params; CScript Script; DWORD dwRes; if((dwRes=Script.Open(Params.lpszPath))!=ERROR_SUCCESS) fatal_error_printf(_T("cannot open script file %s (error %d)\n"),Params.lpszPath,dwRes); int l_argc=0; _TCHAR ** l_argv=NULL; while(1) { Script.GetNextLineTokens(&l_argc,&l_argv); if(l_argc==1) //end of script file break; Params=StoredParams; _tprintf(_T(">")); for(int i=1;i0) { //first default has to be command Params.lpszCommand=Params.lplpszDefaultArg[0]; dwCommandCode = tCommandNameTable::MapNameToCode(Params.lplpszDefaultArg[0]); if( Params.wDefaultArgCount>1) {//second deault has to be path Params.lpszPath=Params.lplpszDefaultArg[1]; } if( Params.wDefaultArgCount>2) { switch(dwCommandCode) { case CMD_SET: //the rest of default args are values Params.wPropValueCount=0; for(i=2;i2) { error_printf(_T("maximum default arguments number exceeds expected (2)\n")); return 1; } break; case CMD_COPY: case CMD_RENAME: case CMD_APPRENAME: if( Params.wDefaultArgCount>3) { error_printf(_T("maximum default arguments number exceeds expected (3)\n")); return 1; } else Params.lpszPathDst=Params.lplpszDefaultArg[2]; break; default: error_printf(_T("command not recognized: %s or number of parameters doesn't match\n"),Params.lpszCommand); return 1; } } } //end of default argument handling //extract computer,service,instance, if stored in Path AdmNode.SetPath(Params.lpszPath); //valid only for copy function AdmDstNode.SetPath(Params.lpszPathDst); //process computer, service, instance, property name arguments if(Params.lpszComputer!=NULL) { if(!AdmNode.GetComputer().IsEmpty()) { error_printf(_T("computer name entered more than once\n")); return 1; } else AdmNode.SetComputer(Params.lpszComputer); } if(Params.lpszService!=NULL) { if(!AdmNode.GetService().IsEmpty()) { error_printf(_T("service name entered more than once\n")); return 1; } else { if(IsServiceName(Params.lpszService)) AdmNode.SetService(Params.lpszService); else { error_printf(_T("service name not recognized: %s\n"), Params.lpszService); return 1; } } } if(Params.wInstance!=0) { if(!AdmNode.GetInstance().IsEmpty()) { error_printf(_T("instance entered more than once\n")); return 1; } else { _TCHAR buf[30]; //!!! maybe ltoa should be used AdmNode.SetInstance(_itot(Params.wInstance,buf,10)); } } //****************************************** //process attrib, utype, dtype, value //property name first CString strProp=AdmNode.GetProperty(); if(Params.lpszPropName!=NULL && !strProp.IsEmpty()) { error_printf(_T("property name entered more than once\n")); return 1; } else if (Params.lpszPropName!=NULL) { AdmNode.SetProperty(Params.lpszPropName); } if(IsNumber(AdmNode.GetProperty())) { AdmProp.SetIdentifier(_ttol(AdmNode.GetProperty())); } else { DWORD dwIdentifier=MapPropertyNameToCode(AdmNode.GetProperty()); if(dwIdentifier==NAME_NOT_FOUND) {} else AdmProp.SetIdentifier(dwIdentifier) ; } //process the attrib entered on command line if(Params.wPropAttribCount!=0) { DWORD dwAttrib=0; for (i=0;i