/*++ Copyright (c) 1990 Microsoft Corporation Module Name: SC.C Abstract: Test Routines for the Service Controller. Author: Dan Lafferty (danl) 08-May-1991 Environment: User Mode - Win32 Revision History: 08-May-1991 danl created --*/ // // INCLUDES // #include // DbgPrint prototype #include // DbgPrint prototype #include // needed for winbase.h #include // atoi #include // printf #include // strcmp #include #include // NERR_ error codes #include #include #include // Unicode #include // Unicode // // FUNCTION PROTOTYPES // VOID DisplayStatus ( IN LPBYTE InfoStruct2, IN DWORD level ); BOOL ConvertToUnicode( OUT LPWSTR *UnicodeOut, IN LPSTR AnsiIn ); BOOL MakeArgsUnicode ( DWORD argc, PCHAR argv[] ); LONG wtol( IN LPWSTR string ); VOID Usage( VOID); /****************************************************************************/ VOID _CRTAPI1 main ( DWORD argc, PCHAR argv[] ) /*++ Routine Description: Allows manual testing of the Service Controller by typing commands on the command line such as: sc start workstation - Starts the workstation service sc pause workstation - Pauses the workstation service sc continue workstation - Continues the workstation service sc stop workstation - Stops the workstation service sc query workstation - Does a GetInfo on workstation service sc query - Does a Enum of all active services sc start server arg1 arg2 - Starts the server service with args Currently, all information is returned as Level 2 information. All of these API functions are supposed to allow a computername to be passed in as an argument. However, I don't currently have any routines to parse throught the command arguments and pick out the computername information. So for now all these calls are LOCAL. Arguments: Return Value: --*/ { NET_API_STATUS status; LPTSTR *argPtr; LPSERVICE_INFO_2 InfoStruct2=NULL; LPBYTE InfoStruct=NULL; LPTSTR pServerName=NULL; DWORD entriesRead; DWORD totalEntries; DWORD resumeHandle; DWORD prefMaxLen; DWORD level; DWORD specialFlag = FALSE; DWORD i; DWORD argCount; DWORD argIndex; LPTSTR *FixArgv; if (argc <2) { printf("ERROR: no command was given! (start, pause, continue, stop, query)\n"); Usage(); return; } // // Make the arguments unicode if necessary. // #ifdef UNICODE if (!MakeArgsUnicode(argc, argv)) { return; } #endif FixArgv = (LPTSTR *)argv; pServerName = NULL; argCount = argc - 1; argIndex = 1; if (STRNCMP (FixArgv[1], TEXT("\\\\"), 2) == 0) { pServerName = FixArgv[1]; argCount--; argIndex++; } // // At this point we have the following variables: // argCount = the number of array args (excluding pgm name & srv name). // argIndex = index into the array for the arg we are interested in. // if (STRICMP (FixArgv[argIndex], TEXT("query") ) == 0 ) { // // SYNTAX EXAMPLES (default level = 2 ) // (default resumeHandle = 0) // (default prefMaxLen = -1 ) // // sc query - Does an Enum with resume handle = 0 // sc query messenger - Does a GetInfo on the messenger // sc query rh= 14 - Does an Enum with resume handle = 14 // sc query level= 1 - Does an Enum with level = 1 // sc query level= 1 logon - Does a level1 GetInfo on logon service // sc query maxlen= 50 - Does an Enum with a 50 byte buffer. // resumeHandle = 0; level = 2; prefMaxLen = 0xffffffff; if (argCount > 1) { argIndex++; if (STRCMP (FixArgv[argIndex], TEXT("rh=")) == 0) { specialFlag = TRUE; if (argc > 3) { resumeHandle = ATOL(FixArgv[3]); } } else if (STRCMP (FixArgv[argIndex], TEXT("level=")) == 0) { specialFlag = TRUE; if (argCount > 2) { argIndex++; level = ATOL(FixArgv[argIndex]); } } else if (STRCMP (FixArgv[argIndex], TEXT("maxlen=")) == 0) { specialFlag = TRUE; if (argCount > 2) { argIndex++; prefMaxLen = ATOL(FixArgv[argIndex]); } } } if ( (argCount < 2) || (specialFlag == TRUE) && (argCount < 4) ) { status = NetServiceEnum ( pServerName, // ServerName - Local version level, // Level &InfoStruct, // return status buffer pointer prefMaxLen, // preferred max length &entriesRead, // entries read &totalEntries, // total entries &resumeHandle); // resume handle if ( (status == NERR_Success) || (status == ERROR_MORE_DATA) ){ printf("Enum: entriesRead = %d\n", entriesRead); printf("Enum: totalEntries = %d\n", totalEntries); printf("Enum: resumeHandle = %d\n", resumeHandle); for (i=0; i 2) { argPtr = (LPTSTR *)&FixArgv[argIndex]; } // else { //TEST // *argPtr = (LPTSTR)1; //TEST // } //TEST status = NetServiceInstall ( pServerName, // ServerName Local version FixArgv[argIndex], // ServiceName argCount-2, // numArgs argPtr, // cmdArgs (LPBYTE *)&InfoStruct2); // return status buffer pointer if (status == NERR_Success) { DisplayStatus((LPBYTE)InfoStruct2, 2); } else { printf("[sc] NetrServiceInstall FAILED, rc = %ld\n", status); } } else if (STRICMP (FixArgv[argIndex], TEXT("pause")) == 0) { argIndex++; status = NetServiceControl ( pServerName, // ServerName Local version FixArgv[argIndex], // ServiceName SERVICE_CTRL_PAUSE, // opcode 0, // extra arg (LPBYTE *)&InfoStruct2); // return status buffer pointer if (status == NERR_Success) { if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } else { printf("[sc] NetrServiceControl FAILED, rc = %ld\n", status); if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } } else if (STRICMP (FixArgv[argIndex], TEXT("interrogate")) == 0) { argIndex++; status = NetServiceControl ( pServerName, // ServerName Local version FixArgv[argIndex], // ServiceName SERVICE_CTRL_INTERROGATE, // opcode 0, // extra arg (LPBYTE *)&InfoStruct2); // return status buffer pointer if (status == NERR_Success) { if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } else { printf("[sc] NetrServiceControl FAILED, rc = %ld\n", status); if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } } else if (STRICMP (FixArgv[argIndex], TEXT("continue")) == 0) { argIndex++; status = NetServiceControl ( pServerName, // ServerName Local version FixArgv[argIndex], // ServiceName SERVICE_CTRL_CONTINUE, // opcode 0, // extra arg (LPBYTE *)&InfoStruct2); // return status buffer pointer if (status == NERR_Success) { if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } else { printf("[sc] NetrServiceControl FAILED, rc = %ld\n", status); if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } } else if (STRICMP (FixArgv[argIndex], TEXT("stop")) == 0) { argIndex++; if (STRICMP (FixArgv[argIndex], TEXT("svcctrl")) == 0) { status = NetServiceControl ( pServerName, FixArgv[2], 0x73746f70, // special shutdown opcode (internal use only) 0, (LPBYTE *)&InfoStruct2); printf("Service Controller Should Have Terminated, rc=%d\n",status); } else { status = NetServiceControl ( pServerName, // ServerName Local version FixArgv[argIndex], // ServiceName SERVICE_CTRL_UNINSTALL, // opcode 0, // extra arg (LPBYTE *)&InfoStruct2); // return status buffer pointer if (status == NERR_Success) { if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } else { printf("[sc] NetrServiceControl FAILED, rc = %ld\n", status); if (InfoStruct2 != NULL) { DisplayStatus((LPBYTE)InfoStruct2, 2); } } } } else { printf("[sc] Unrecognized Command\n"); } return; } /****************************************************************************/ VOID DisplayStatus ( IN LPBYTE InfoStruct, IN DWORD level ) /*++ Routine Description: Displays the returned info buffer. Arguments: InfoStruct2 - This is a pointer to a SERVICE_INFO_2 structure from which information is to be displayed. Return Value: none. --*/ { DWORD installState; DWORD pauseState; LPSERVICE_INFO_0 InfoStruct0; LPSERVICE_INFO_1 InfoStruct1; LPSERVICE_INFO_2 InfoStruct2; switch(level) { case 0: InfoStruct0 = (LPSERVICE_INFO_0)InfoStruct; printf("\nSERVICE_NAME: %ws\n", InfoStruct0->svci0_name); break; case 1: InfoStruct1 = (LPSERVICE_INFO_1)InfoStruct; printf("\nSERVICE_NAME: %ws\n", InfoStruct1->svci1_name); installState = InfoStruct1->svci1_status & SERVICE_INSTALL_STATE; pauseState = InfoStruct1->svci1_status & SERVICE_PAUSE_STATE; printf(" STATUS: %lx ", InfoStruct1->svci1_status); switch(installState){ case SERVICE_UNINSTALLED: printf("UNINSTALLED "); break; case SERVICE_INSTALL_PENDING: printf("INSTALL_PENDING "); break; case SERVICE_UNINSTALL_PENDING: printf("UNINSTALL_PENDING "); break; case SERVICE_INSTALLED: printf("INSTALLED "); break; default: printf(" ERROR "); } switch(pauseState){ case LM20_SERVICE_ACTIVE: printf("ACTIVE "); break; case LM20_SERVICE_CONTINUE_PENDING: printf("CONTINUE_PENDING "); break; case LM20_SERVICE_PAUSE_PENDING: printf("PAUSE_PENDING "); break; case LM20_SERVICE_PAUSED: printf("PAUSED "); break; default: printf(" ERROR "); } if(InfoStruct1->svci1_status & SERVICE_UNINSTALLABLE) { printf("\n SERVICE_UNINSTALLABLE"); } else{ printf("\n SERVICE_NOT_UNINSTALLABLE"); } if(InfoStruct1->svci1_status & SERVICE_PAUSABLE) { printf(" SERVICE_PAUSABLE\n"); } else{ printf(" SERVICE_NOT_PAUSABLE\n"); } printf(" CODE : %lx\n", InfoStruct1->svci1_code ); printf(" PID : %lx\n", InfoStruct1->svci1_pid ); break; case 2: InfoStruct2 = (LPSERVICE_INFO_2)InfoStruct; printf("\nSERVICE_NAME: %ws\n", InfoStruct2->svci2_name); printf("DISPLAY_NAME: %ws\n", InfoStruct2->svci2_display_name); installState = InfoStruct2->svci2_status & SERVICE_INSTALL_STATE; pauseState = InfoStruct2->svci2_status & SERVICE_PAUSE_STATE; printf(" STATUS: %lx ", InfoStruct2->svci2_status); switch(installState){ case SERVICE_UNINSTALLED: printf("UNINSTALLED "); break; case SERVICE_INSTALL_PENDING: printf("INSTALL_PENDING "); break; case SERVICE_UNINSTALL_PENDING: printf("UNINSTALL_PENDING "); break; case SERVICE_INSTALLED: printf("INSTALLED "); break; default: printf(" ERROR "); } switch(pauseState){ case LM20_SERVICE_ACTIVE: printf("ACTIVE "); break; case LM20_SERVICE_CONTINUE_PENDING: printf("CONTINUE_PENDING "); break; case LM20_SERVICE_PAUSE_PENDING: printf("PAUSE_PENDING "); break; case LM20_SERVICE_PAUSED: printf("PAUSED "); break; default: printf(" ERROR "); } if(InfoStruct2->svci2_status & SERVICE_UNINSTALLABLE) { printf("\n SERVICE_UNINSTALLABLE"); } else{ printf("\n SERVICE_NOT_UNINSTALLABLE"); } if(InfoStruct2->svci2_status & SERVICE_PAUSABLE) { printf(" SERVICE_PAUSABLE\n"); } else{ printf(" SERVICE_NOT_PAUSABLE\n"); } printf(" CODE : 0x%lx\n", InfoStruct2->svci2_code ); printf(" PID : 0x%lx\n", InfoStruct2->svci2_pid ); printf(" TEXT : %ls\n\n", InfoStruct2->svci2_text ); break; default: printf("DisplayStatus: illegal level\n"); } return; } BOOL MakeArgsUnicode ( DWORD argc, PCHAR argv[] ) /*++ Routine Description: Arguments: Return Value: Note: --*/ { DWORD i; // // ScConvertToUnicode allocates storage for each string. // We will rely on process termination to free the memory. // for(i=0; i ...\n"); } LONG wtol( IN LPWSTR string ) { LONG value = 0; while((*string != L'\0') && (*string >= L'0') && ( *string <= L'9')) { value = value * 10 + (*string - L'0'); string++; } return(value); }