/*++ Copyright (c) 1998 Microsoft Corporation Module Name: batch.c Abstract: This module implements batch command processing. Author: Wesley Witt (wesw) 21-Oct-1998 Revision History: --*/ #include "cmdcons.h" #pragma hdrstop ULONG InBatchMode; HANDLE OutputFileHandle; LARGE_INTEGER OutputFileOffset; BOOLEAN RedirectToNULL; #ifdef DBG VOID RcDumpTokenizedLine( PTOKENIZED_LINE Line ) { if (Line) { PLINE_TOKEN Token = Line->Tokens; ULONG Index ; for(Index=0; ((Index < Line->TokenCount) && Token); Index++) { KdPrint(("%ws, ", Token->String)); Token = Token->Next; } KdPrint(("\n")); } else { KdPrint(("Line is null!!!\n")); } } #endif ULONG pRcExecuteBatchFile( IN PWSTR BatchFileName, IN PWSTR OutputFileName, IN BOOLEAN Quiet ) { NTSTATUS Status = 0; LPCWSTR Arg; HANDLE FileHandle = NULL; HANDLE SectionHandle; PVOID ViewBase; ULONG FileSize; ULONG rc; WCHAR *s; WCHAR *p; ULONG sz; WCHAR *pText; ULONG rVal = 1; // continue with RC BOOLEAN b = FALSE; UNICODE_STRING UnicodeString; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES Obja; PTOKENIZED_LINE TokenizedLine; BOOLEAN bCloseOutputFile = FALSE; if (!RcFormFullPath(BatchFileName,_CmdConsBlock->TemporaryBuffer,TRUE)) { RcMessageOut(MSG_INVALID_PATH); goto exit; } Status = SpOpenAndMapFile( _CmdConsBlock->TemporaryBuffer, &FileHandle, &SectionHandle, &ViewBase, &FileSize, FALSE ); if( !NT_SUCCESS(Status) ) { if (!Quiet) { RcNtError(Status,MSG_CANT_OPEN_FILE); } goto exit; } pText = SpMemAlloc((FileSize+16)*sizeof(WCHAR)); RtlZeroMemory(pText,(FileSize+16)*sizeof(WCHAR)); Status = RtlMultiByteToUnicodeN( pText, FileSize * sizeof(WCHAR), &FileSize, ViewBase, FileSize ); s = pText; sz = FileSize / sizeof(WCHAR); SpUnmapFile(SectionHandle,ViewBase); ZwClose(FileHandle); if (OutputFileName != NULL) { if (OutputFileHandle == NULL) { if (!RcFormFullPath(OutputFileName,_CmdConsBlock->TemporaryBuffer, TRUE)) { RcMessageOut(MSG_INVALID_PATH); if (pText) SpMemFree(pText); goto exit; } INIT_OBJA(&Obja,&UnicodeString,_CmdConsBlock->TemporaryBuffer); Status = ZwCreateFile( &OutputFileHandle, FILE_GENERIC_WRITE | SYNCHRONIZE, &Obja, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OVERWRITE_IF, FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY, NULL, 0 ); if (!NT_SUCCESS(Status)) { OutputFileHandle = NULL; RcMessageOut(Status); } else { bCloseOutputFile = TRUE; } OutputFileOffset.QuadPart = 0; } } InBatchMode += 1; // // get each line and invoke dispatch command // on that line after tokenizing the arguments // while (sz) { p = s; while (sz && (*p != L'\r')) { p += 1; sz--; } if (sz && (*p == L'\r')) { *p = 0; TokenizedLine = RcTokenizeLine(s); if (TokenizedLine->TokenCount) { rVal = RcDispatchCommand( TokenizedLine ); if (rVal == 0 || rVal == 2) { b = FALSE; } else { b = TRUE; } RcTextOut(L"\r\n"); } else { b = TRUE; } RcFreeTokenizedLine(&TokenizedLine); if (b == FALSE) { goto exit; } s = p + 1; sz--; if (sz && (*s == L'\n')) { s += 1; sz--; } } } SpMemFree(pText); InBatchMode -= 1; if (bCloseOutputFile) { ASSERT(OutputFileHandle != NULL); ZwClose(OutputFileHandle); OutputFileHandle = NULL; } exit: return rVal; } ULONG RcCmdBatch( IN PTOKENIZED_LINE TokenizedLine ) { if (RcCmdParseHelp( TokenizedLine, MSG_BATCH_HELP )) { return 1; } if (TokenizedLine->TokenCount < 2 || (InBatchMode != 0 && 3 == TokenizedLine->TokenCount)) { RcMessageOut( MSG_SYNTAX_ERROR ); return 1; } return pRcExecuteBatchFile( TokenizedLine->Tokens->Next->String, (TokenizedLine->TokenCount == 3) ? TokenizedLine->Tokens->Next->Next->String : NULL, FALSE ); }