/******************************************************************* * WCMD_call - processes a batch call statement * * If there is a leading ':', calls within this batch program * otherwise launches another program. */ void WCMD_call (WCHAR *command) { /* Run other program if no leading ':' */ if (*command != ':') { WCMD_run_program(command, 1); } else { WCHAR gotoLabel[MAX_PATH]; strcpyW(gotoLabel, param1); if (context) { LARGE_INTEGER li; /* Save the current file position, call the same file, restore position */ li.QuadPart = 0; li.u.LowPart = SetFilePointer(context -> h, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); WCMD_batch (param1, command, 1, gotoLabel, context->h); SetFilePointer(context -> h, li.u.LowPart, &li.u.HighPart, FILE_BEGIN); } else { WCMD_output_asis( WCMD_LoadMessage(WCMD_CALLINSCRIPT)); } } }
/******************************************************************* * WCMD_call - processes a batch call statement * * If there is a leading ':', calls within this batch program * otherwise launches another program. */ void WCMD_call (WCHAR *command) { /* Run other program if no leading ':' */ if (*command != ':') { WCMD_run_program(command, TRUE); /* If the thing we try to run does not exist, call returns 1 */ if (errorlevel) errorlevel=1; } else { WCHAR gotoLabel[MAX_PATH]; strcpyW(gotoLabel, param1); if (context) { LARGE_INTEGER li; FOR_CONTEXT oldcontext; /* Save the for variable context, then start with an empty context as for loop variables do not survive a call */ oldcontext = forloopcontext; memset(&forloopcontext, 0, sizeof(forloopcontext)); /* Save the current file position, call the same file, restore position */ li.QuadPart = 0; li.u.LowPart = SetFilePointer(context -> h, li.u.LowPart, &li.u.HighPart, FILE_CURRENT); WCMD_batch (param1, command, TRUE, gotoLabel, context->h); SetFilePointer(context -> h, li.u.LowPart, &li.u.HighPart, FILE_BEGIN); /* Restore the for loop context */ forloopcontext = oldcontext; } else { WCMD_output_asis_stderr(WCMD_LoadMessage(WCMD_CALLINSCRIPT)); } } }
void WCMD_batch (WCHAR *file, WCHAR *command, int called, WCHAR *startLabel, HANDLE pgmHandle) { #define WCMD_BATCH_EXT_SIZE 5 HANDLE h = INVALID_HANDLE_VALUE; WCHAR string[MAXSTRING]; static const WCHAR extension_batch[][WCMD_BATCH_EXT_SIZE] = {{'.','b','a','t','\0'}, {'.','c','m','d','\0'}}; static const WCHAR extension_exe[WCMD_BATCH_EXT_SIZE] = {'.','e','x','e','\0'}; unsigned int i; BATCH_CONTEXT *prev_context; if (startLabel == NULL) { for(i=0; (i<sizeof(extension_batch)/(WCMD_BATCH_EXT_SIZE * sizeof(WCHAR))) && (h == INVALID_HANDLE_VALUE); i++) { strcpyW (string, file); CharLower (string); if (strstrW (string, extension_batch[i]) == NULL) strcatW (string, extension_batch[i]); h = CreateFile (string, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); } if (h == INVALID_HANDLE_VALUE) { strcpyW (string, file); CharLower (string); if (strstrW (string, extension_exe) == NULL) strcatW (string, extension_exe); if (GetFileAttributes (string) != INVALID_FILE_ATTRIBUTES) { WCMD_run_program (command, 0); } else { SetLastError (ERROR_FILE_NOT_FOUND); WCMD_print_error (); } return; } } else { DuplicateHandle(GetCurrentProcess(), pgmHandle, GetCurrentProcess(), &h, 0, FALSE, DUPLICATE_SAME_ACCESS); } /* * Create a context structure for this batch file. */ prev_context = context; context = (BATCH_CONTEXT *)LocalAlloc (LMEM_FIXED, sizeof (BATCH_CONTEXT)); context -> h = h; context -> command = command; memset(context -> shift_count, 0x00, sizeof(context -> shift_count)); context -> prev_context = prev_context; context -> skip_rest = FALSE; /* If processing a call :label, 'goto' the label in question */ if (startLabel) { strcpyW(param1, startLabel); WCMD_goto(NULL); } /* * Work through the file line by line. Specific batch commands are processed here, * the rest are handled by the main command processor. */ while (context -> skip_rest == FALSE) { CMD_LIST *toExecute = NULL; /* Commands left to be executed */ if (WCMD_ReadAndParseLine(NULL, &toExecute, h) == NULL) break; WCMD_process_commands(toExecute, FALSE, NULL, NULL); WCMD_free_commands(toExecute); toExecute = NULL; } CloseHandle (h); /* * If invoked by a CALL, we return to the context of our caller. Otherwise return * to the caller's caller. */ LocalFree ((HANDLE)context); if ((prev_context != NULL) && (!called)) { prev_context -> skip_rest = TRUE; context = prev_context; } context = prev_context; }