ReactOS  0.4.15-dev-1171-gab82533
if.c
Go to the documentation of this file.
1 /*
2  * IF.C - if internal batch command.
3  *
4  *
5  * History:
6  *
7  * 16 Jul 1998 (Hans B Pufal)
8  * started.
9  *
10  * 16 Jul 1998 (John P Price)
11  * Separated commands into individual files.
12  *
13  * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>)
14  * added config.h include
15  *
16  * 07-Jan-1999 (Eric Kohl)
17  * Added help text ("if /?") and cleaned up.
18  *
19  * 21-Jan-1999 (Eric Kohl)
20  * Unicode and redirection ready!
21  *
22  * 01-Sep-1999 (Eric Kohl)
23  * Fixed help text.
24  *
25  * 17-Feb-2001 (ea)
26  * IF DEFINED variable command
27  *
28  * 28-Apr-2005 (Magnus Olsen) <magnus@greatlord.com>
29  * Remove all hardcoded strings in En.rc
30  *
31  */
32 
33 #include "precomp.h"
34 
35 static INT GenericCmp(INT (WINAPI *StringCmp)(LPCTSTR, LPCTSTR),
36  LPCTSTR Left, LPCTSTR Right)
37 {
38  TCHAR *end;
39  INT nLeft = _tcstol(Left, &end, 0);
40  if (*end == _T('\0'))
41  {
42  INT nRight = _tcstol(Right, &end, 0);
43  if (*end == _T('\0'))
44  {
45  /* both arguments are numeric */
46  return (nLeft < nRight) ? -1 : (nLeft > nRight);
47  }
48  }
49  return StringCmp(Left, Right);
50 }
51 
53 {
54  TRACE("cmd_if(\'%s\')\n", debugstr_aw(param));
55 
56  if (!_tcsncmp (param, _T("/?"), 2))
57  {
59  return 0;
60  }
61 
63  return 1;
64 }
65 
67 {
68  INT result = FALSE; /* when set cause 'then' clause to be executed */
69  LPTSTR param;
70  LPTSTR Left = NULL, Right;
71 
72  if (Cmd->If.LeftArg)
73  {
74  Left = DoDelayedExpansion(Cmd->If.LeftArg);
75  if (!Left)
76  return 1;
77  }
78  Right = DoDelayedExpansion(Cmd->If.RightArg);
79  if (!Right)
80  {
81  if (Left) cmd_free(Left);
82  return 1;
83  }
84 
85  if (bEnableExtensions && (Cmd->If.Operator == IF_CMDEXTVERSION))
86  {
87  /* IF CMDEXTVERSION n: check if Command Extensions
88  * version is greater or equal to n. */
89  DWORD n = _tcstoul(Right, &param, 10);
90  if (*param != _T('\0'))
91  {
92  error_syntax(Right);
93  goto fail;
94  }
95  result = (CMDEXTVERSION >= n);
96  }
97  else if (bEnableExtensions && (Cmd->If.Operator == IF_DEFINED))
98  {
99  /* IF DEFINED var: check if environment variable exists */
100  result = (GetEnvVarOrSpecial(Right) != NULL);
101  }
102  else if (Cmd->If.Operator == IF_ERRORLEVEL)
103  {
104  /* IF ERRORLEVEL n: check if last exit code is greater or equal to n */
105  INT n = _tcstol(Right, &param, 10);
106  if (*param != _T('\0'))
107  {
108  error_syntax(Right);
109  goto fail;
110  }
111  result = (nErrorLevel >= n);
112  }
113  else if (Cmd->If.Operator == IF_EXIST)
114  {
115  BOOL IsDir;
116  SIZE_T Size;
118  HANDLE hFind;
119  DWORD attrs;
120 
121  /* IF EXIST filename: check if file exists (wildcards allowed) */
122  StripQuotes(Right);
123 
124  Size = _tcslen(Right);
125  IsDir = (Right[Size - 1] == '\\');
126  if (IsDir)
127  Right[Size - 1] = 0;
128 
129  hFind = FindFirstFile(Right, &f);
130  if (hFind != INVALID_HANDLE_VALUE)
131  {
132  attrs = f.dwFileAttributes;
133  FindClose(hFind);
134  }
135  else
136  {
137  /* FindFirstFile fails at the root directory. */
138  attrs = GetFileAttributes(Right);
139  }
140 
141  if (attrs == INVALID_FILE_ATTRIBUTES)
142  result = FALSE;
143  else if (IsDir)
145  else
146  result = TRUE;
147 
148  if (IsDir)
149  Right[Size - 1] = '\\';
150  }
151  else
152  {
153  /*
154  * Do case-insensitive string comparisons if /I specified.
155  *
156  * Since both strings are user-specific, use kernel32!lstrcmp(i)
157  * instead of CRT!_tcs(i)cmp, so as to use the correct
158  * current thread locale information.
159  */
160  INT (WINAPI *StringCmp)(LPCTSTR, LPCTSTR) =
161  (Cmd->If.Flags & IFFLAG_IGNORECASE) ? lstrcmpi : lstrcmp;
162 
163  if (Cmd->If.Operator == IF_STRINGEQ)
164  {
165  /* IF str1 == str2 */
166  result = (StringCmp(Left, Right) == 0);
167  }
168  else if (bEnableExtensions)
169  {
170  result = GenericCmp(StringCmp, Left, Right);
171  switch (Cmd->If.Operator)
172  {
173  case IF_EQU: result = (result == 0); break;
174  case IF_NEQ: result = (result != 0); break;
175  case IF_LSS: result = (result < 0); break;
176  case IF_LEQ: result = (result <= 0); break;
177  case IF_GTR: result = (result > 0); break;
178  case IF_GEQ: result = (result >= 0); break;
179  default: goto unknownOp;
180  }
181  }
182  else
183  {
184 unknownOp:
185  ERR("Unknown IF operator 0x%x\n", Cmd->If.Operator);
186  ASSERT(FALSE);
187  goto fail;
188  }
189  }
190 
191  if (Left) cmd_free(Left);
192  cmd_free(Right);
193 
194  if (result ^ ((Cmd->If.Flags & IFFLAG_NEGATE) != 0))
195  {
196  /* Full condition was true, do the command */
197  return ExecuteCommand(Cmd->Subcommands);
198  }
199  else
200  {
201  /* Full condition was false, do the "else" command if there is one */
202  return ExecuteCommand(Cmd->Subcommands->Next);
203  }
204 
205 fail:
206  if (Left) cmd_free(Left);
207  cmd_free(Right);
208  return 1;
209 }
210 
211 /* EOF */
INT nErrorLevel
Definition: cmd.c:158
INT ExecuteCommand(IN PARSED_COMMAND *Cmd)
Definition: cmd.c:778
INT ExecuteIf(PARSED_COMMAND *Cmd)
Definition: if.c:66
const CHAR * LPCTSTR
Definition: xmlstorage.h:193
#define lstrcmpi
Definition: winbase.h:3713
PTSTR DoDelayedExpansion(IN PCTSTR Line)
Definition: cmd.c:1638
#define IFFLAG_IGNORECASE
Definition: cmd.h:261
#define TRUE
Definition: types.h:120
#define _tcstol
Definition: tchar.h:594
static INT GenericCmp(INT(WINAPI *StringCmp)(LPCTSTR, LPCTSTR), LPCTSTR Left, LPCTSTR Right)
Definition: if.c:35
#define INT
Definition: polytest.cpp:20
#define debugstr_aw
Definition: precomp.h:43
GLdouble n
Definition: glext.h:7729
#define INVALID_HANDLE_VALUE
Definition: compat.h:479
VOID ConOutResPaging(BOOL StartPaging, UINT resID)
Definition: console.c:182
GLuint GLuint end
Definition: gl.h:1545
INT cmd_if(LPTSTR param)
Definition: if.c:52
static VOID StripQuotes(LPSTR in)
Definition: cmdcons.c:116
int32_t INT
Definition: typedefs.h:58
CHAR * LPTSTR
Definition: xmlstorage.h:192
#define FALSE
Definition: types.h:117
unsigned int BOOL
Definition: ntddk_ex.h:94
Definition: cmd.h:274
LPCTSTR GetEnvVarOrSpecial(LPCTSTR varName)
Definition: cmd.c:900
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
#define FindFirstFile
Definition: winbase.h:3622
#define STRING_IF_HELP1
Definition: resource.h:133
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define CMDEXTVERSION
Definition: cmd.h:32
char TCHAR
Definition: xmlstorage.h:189
GLfloat f
Definition: glext.h:7540
#define _T(x)
Definition: vfdio.h:22
#define TRACE(s)
Definition: solgame.cpp:4
Definition: cmd.h:274
Definition: cmd.h:274
GLfloat param
Definition: glext.h:5796
#define WINAPI
Definition: msvc.h:6
#define IFFLAG_NEGATE
Definition: cmd.h:260
unsigned long DWORD
Definition: ntddk_ex.h:95
VOID ParseErrorEx(IN PCTSTR s)
Definition: parser.c:227
#define INVALID_FILE_ATTRIBUTES
Definition: vfdcmd.c:23
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BOOL bEnableExtensions
Definition: cmd.c:161
#define _tcstoul
Definition: tchar.h:595
Definition: sacdrv.h:277
Definition: cmd.h:274
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:361
#define GetFileAttributes
Definition: winbase.h:3655
#define lstrcmp
Definition: winbase.h:3712
#define ERR(fmt,...)
Definition: debug.h:110
ULONG_PTR SIZE_T
Definition: typedefs.h:80
#define cmd_free(ptr)
Definition: cmddbg.h:31
#define f
Definition: ke_i.h:83
Definition: cmd.h:266
VOID error_syntax(PCTSTR s)
Definition: error.c:152
GLuint64EXT * result
Definition: glext.h:11304
int _tcsncmp(const _TCHAR *s1, const _TCHAR *s2, size_t n)
Definition: tcsncmp.h:9
Definition: cmd.h:274
Definition: cmd.h:274
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502