ReactOS  0.4.14-dev-293-g2b39b42
attrib.c
Go to the documentation of this file.
1 /*
2  * ATTRIB.C - attrib internal command.
3  *
4  *
5  * History:
6  *
7  * 04-Dec-1998 Eric Kohl
8  * started
9  *
10  * 09-Dec-1998 Eric Kohl
11  * implementation works, except recursion ("attrib /s").
12  *
13  * 05-Jan-1999 Eric Kohl
14  * major rewrite.
15  * fixed recursion ("attrib /s").
16  * started directory support ("attrib /s /d").
17  * updated help text.
18  *
19  * 14-Jan-1999 Eric Kohl
20  * Unicode ready!
21  *
22  * 19-Jan-1999 Eric Kohl
23  * Redirection ready!
24  *
25  * 21-Jan-1999 Eric Kohl
26  * Added check for invalid filenames.
27  *
28  * 23-Jan-1999 Eric Kohl
29  * Added handling of multiple filenames.
30  *
31  * 02-Apr-2005 (Magnus Olsen <magnus@greatlord.com>)
32  * Remove all hardcoded strings in En.rc
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 
38 #include <windef.h>
39 #include <winbase.h>
40 #include <wincon.h>
41 #include <winuser.h>
42 
43 #include <conutils.h>
44 
45 #include "resource.h"
46 
48 
49 static
50 VOID
52  DWORD dwErrorCode,
53  LPWSTR szFormat,
54  ...)
55 {
57  WCHAR szMessage[1024];
58  LPWSTR szError;
59  va_list arg_ptr;
60 
61  if (dwErrorCode == ERROR_SUCCESS)
62  return;
63 
64  if (szFormat)
65  {
66  va_start(arg_ptr, szFormat);
67  vswprintf(szMessage, szFormat, arg_ptr);
68  va_end(arg_ptr);
69  }
70 
73  (LPWSTR)&szError, 0, NULL))
74  {
75  ConPrintf(StdErr, L"%s %s\n", szError, szMessage);
76  if (szError)
77  LocalFree(szError);
78  return;
79  }
80 
81  /* Fall back just in case the error is not defined */
83  if (szFormat)
84  ConPrintf(StdErr, L"%s -- %s\n", szMsg, szMessage);
85  else
86  ConPrintf(StdErr, L"%s\n", szMsg);
87 }
88 
89 static
90 INT
92  LPWSTR pszPath,
93  LPWSTR pszFile,
94  BOOL bRecurse)
95 {
96  WIN32_FIND_DATAW findData;
97  HANDLE hFind;
98  WCHAR szFullName[MAX_PATH];
100 
101  /* prepare full file name buffer */
102  wcscpy(szFullName, pszPath);
103  pszFileName = szFullName + wcslen(szFullName);
104 
105  /* display all subdirectories */
106  if (bRecurse)
107  {
108  /* append file name */
109  wcscpy(pszFileName, pszFile);
110 
111  hFind = FindFirstFileW(szFullName, &findData);
112  if (hFind == INVALID_HANDLE_VALUE)
113  {
114  ErrorMessage(GetLastError(), pszFile);
115  return 1;
116  }
117 
118  do
119  {
120  if (!(findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
121  continue;
122 
123  if (!wcscmp(findData.cFileName, L".") ||
124  !wcscmp(findData.cFileName, L".."))
125  continue;
126 
127  wcscpy(pszFileName, findData.cFileName);
128  wcscat(pszFileName, L"\\");
129  PrintAttribute(szFullName, pszFile, bRecurse);
130  }
131  while(FindNextFileW(hFind, &findData));
132  FindClose(hFind);
133  }
134 
135  /* append file name */
136  wcscpy(pszFileName, pszFile);
137 
138  /* display current directory */
139  hFind = FindFirstFileW(szFullName, &findData);
140  if (hFind == INVALID_HANDLE_VALUE)
141  {
142  ErrorMessage(GetLastError(), pszFile);
143  return 1;
144  }
145 
146  do
147  {
148  if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
149  continue;
150 
151  wcscpy(pszFileName, findData.cFileName);
152 
154  L"%c %c%c%c %s\n",
155  (findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? L'A' : L' ',
156  (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? L'S' : L' ',
157  (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? L'H' : L' ',
158  (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? L'R' : L' ',
159  szFullName);
160  }
161  while(FindNextFileW(hFind, &findData));
162  FindClose(hFind);
163 
164  return 0;
165 }
166 
167 
168 static
169 INT
171  LPWSTR pszPath,
172  LPWSTR pszFile,
173  DWORD dwMask,
174  DWORD dwAttrib,
175  BOOL bRecurse,
176  BOOL bDirectories)
177 {
178  WIN32_FIND_DATAW findData;
179  HANDLE hFind;
180  DWORD dwAttribute;
181  WCHAR szFullName[MAX_PATH];
183 
184  /* prepare full file name buffer */
185  wcscpy(szFullName, pszPath);
186  pszFileName = szFullName + wcslen(szFullName);
187 
188  /* change all subdirectories */
189  if (bRecurse)
190  {
191  /* append file name */
192  wcscpy(pszFileName, L"*.*");
193 
194  hFind = FindFirstFileW(szFullName, &findData);
195  if (hFind == INVALID_HANDLE_VALUE)
196  {
197  ErrorMessage(GetLastError(), pszFile);
198  return 1;
199  }
200 
201  do
202  {
203  if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
204  {
205  if (!wcscmp(findData.cFileName, L".") ||
206  !wcscmp(findData.cFileName, L".."))
207  continue;
208 
209  wcscpy(pszFileName, findData.cFileName);
210  wcscat(pszFileName, L"\\");
211 
212  ChangeAttribute(szFullName, pszFile, dwMask,
213  dwAttrib, bRecurse, bDirectories);
214  }
215  }
216  while (FindNextFileW(hFind, &findData));
217  FindClose(hFind);
218  }
219 
220  /* append file name */
221  wcscpy(pszFileName, pszFile);
222 
223  hFind = FindFirstFileW(szFullName, &findData);
224  if (hFind == INVALID_HANDLE_VALUE)
225  {
226  ErrorMessage(GetLastError(), pszFile);
227  return 1;
228  }
229 
230  do
231  {
232  if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
233  continue;
234 
235  wcscpy(pszFileName, findData.cFileName);
236 
237  dwAttribute = GetFileAttributes (szFullName);
238 
239  if (dwAttribute != 0xFFFFFFFF)
240  {
241  dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
242  SetFileAttributes(szFullName, dwAttribute);
243  }
244  }
245  while (FindNextFileW(hFind, &findData));
246  FindClose(hFind);
247 
248  return 0;
249 }
250 
251 
252 int wmain(int argc, WCHAR *argv[])
253 {
254  INT i;
256  WCHAR szFileName [MAX_PATH];
257  BOOL bRecurse = FALSE;
258  BOOL bDirectories = FALSE;
259  DWORD dwAttrib = 0;
260  DWORD dwMask = 0;
261 
262  /* Initialize the Console Standard Streams */
264 
265  /* Print help */
266  if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
267  {
269  return 0;
270  }
271 
272  /* check for options */
273  for (i = 1; i < argc; i++)
274  {
275  if (wcsicmp(argv[i], L"/s") == 0)
276  bRecurse = TRUE;
277  else if (wcsicmp(argv[i], L"/d") == 0)
278  bDirectories = TRUE;
279  }
280 
281  /* create attributes and mask */
282  for (i = 1; i < argc; i++)
283  {
284  if (*argv[i] == L'+')
285  {
286  if (wcslen(argv[i]) != 2)
287  {
289  return -1;
290  }
291 
292  switch (towupper(argv[i][1]))
293  {
294  case L'A':
295  dwMask |= FILE_ATTRIBUTE_ARCHIVE;
296  dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
297  break;
298 
299  case L'H':
300  dwMask |= FILE_ATTRIBUTE_HIDDEN;
301  dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
302  break;
303 
304  case L'R':
305  dwMask |= FILE_ATTRIBUTE_READONLY;
306  dwAttrib |= FILE_ATTRIBUTE_READONLY;
307  break;
308 
309  case L'S':
310  dwMask |= FILE_ATTRIBUTE_SYSTEM;
311  dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
312  break;
313 
314  default:
316  return -1;
317  }
318  }
319  else if (*argv[i] == L'-')
320  {
321  if (wcslen(argv[i]) != 2)
322  {
324  return -1;
325  }
326 
327  switch (towupper(argv[i][1]))
328  {
329  case L'A':
330  dwMask |= FILE_ATTRIBUTE_ARCHIVE;
331  dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
332  break;
333 
334  case L'H':
335  dwMask |= FILE_ATTRIBUTE_HIDDEN;
336  dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
337  break;
338 
339  case L'R':
340  dwMask |= FILE_ATTRIBUTE_READONLY;
341  dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
342  break;
343 
344  case L'S':
345  dwMask |= FILE_ATTRIBUTE_SYSTEM;
346  dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
347  break;
348 
349  default:
351  return -1;
352  }
353  }
354  }
355 
356  if (argc == 1)
357  {
358  DWORD len;
359 
361  if (szPath[len-1] != L'\\')
362  {
363  szPath[len] = L'\\';
364  szPath[len + 1] = UNICODE_NULL;
365  }
366  wcscpy(szFileName, L"*.*");
367  PrintAttribute(szPath, szFileName, bRecurse);
368  return 0;
369  }
370 
371  /* get full file name */
372  for (i = 1; i < argc; i++)
373  {
374  if ((*argv[i] != L'+') && (*argv[i] != L'-') && (*argv[i] != L'/'))
375  {
376  LPWSTR p;
377 
379  p = wcsrchr(szPath, L'\\') + 1;
380  wcscpy(szFileName, p);
381  *p = L'\0';
382 
383  if (dwMask == 0)
384  PrintAttribute(szPath, szFileName, bRecurse);
385  else
386  ChangeAttribute(szPath, szFileName, dwMask,
387  dwAttrib, bRecurse, bDirectories);
388  }
389  }
390 
391  return 0;
392 }
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
static int argc
Definition: ServiceArgs.c:12
#define INIT_CON_SCREEN(pStream)
Definition: screen.h:49
#define TRUE
Definition: types.h:120
#define ERROR_SUCCESS
Definition: deptool.c:10
#define STRING_CONSOLE_ERROR
Definition: resource.h:6
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define LANG_NEUTRAL
Definition: nls.h:22
static VOID ErrorMessage(DWORD dwErrorCode, LPWSTR szFormat,...)
Definition: attrib.c:51
#define SUBLANG_DEFAULT
Definition: nls.h:168
static INT PrintAttribute(LPWSTR pszPath, LPWSTR pszFile, BOOL bRecurse)
Definition: attrib.c:91
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:391
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1059
#define argv
Definition: mplay32.c:18
DWORD WINAPI FormatMessageW(DWORD dwFlags, LPCVOID lpSource, DWORD dwMessageId, DWORD dwLanguageId, LPWSTR lpBuffer, DWORD nSize, __ms_va_list *args)
Definition: format_msg.c:583
int WINAPI LoadStringW(_In_opt_ HINSTANCE hInstance, _In_ UINT uID, _Out_writes_to_(cchBufferMax, return+1) LPWSTR lpBuffer, _In_ int cchBufferMax)
int32_t INT
Definition: typedefs.h:56
static INT ChangeAttribute(LPWSTR pszPath, LPWSTR pszFile, DWORD dwMask, DWORD dwAttrib, BOOL bRecurse, BOOL bDirectories)
Definition: attrib.c:170
CON_SCREEN StdOutScreen
Definition: attrib.c:47
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define ConInitStdStreams()
Definition: stream.h:122
#define va_end(ap)
Definition: acmsvcex.h:90
#define UNICODE_NULL
unsigned int BOOL
Definition: ntddk_ex.h:94
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:41
#define FORMAT_MESSAGE_ALLOCATE_BUFFER
Definition: winbase.h:400
#define GetCurrentDirectory
Definition: winbase.h:3629
INT __cdecl ConPrintf(IN PCON_STREAM Stream, IN LPWSTR szStr,...)
Definition: outstream.c:520
#define STRING_ATTRIB_HELP
Definition: resource.h:7
#define STRING_ERROR_INVALID_PARAM_FORMAT
Definition: resource.h:5
smooth NULL
Definition: ftsmooth.c:416
char * va_list
Definition: acmsvcex.h:78
_Check_return_ _CRTIMP _CONST_RETURN wchar_t *__cdecl wcsrchr(_In_z_ const wchar_t *_Str, _In_ wchar_t _Ch)
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
int wmain(int argc, WCHAR *argv[])
Definition: attrib.c:252
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
#define SetFileAttributes
Definition: winbase.h:3733
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:26
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned long DWORD
Definition: ntddk_ex.h:95
#define StdErr
Definition: stream.h:77
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
INT ConResPuts(IN PCON_STREAM Stream, IN UINT uID)
Definition: outstream.c:610
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
GLenum GLsizei len
Definition: glext.h:6722
#define GetFullPathName
Definition: winbase.h:3645
#define wcsicmp
Definition: string.h:1152
#define GetFileAttributes
Definition: winbase.h:3639
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define GetModuleHandle
Definition: winbase.h:3651
LPCWSTR szPath
Definition: env.c:35
HLOCAL NTAPI LocalFree(HLOCAL hMem)
Definition: heapmem.c:1577
_CRTIMP wchar_t *__cdecl wcscat(_Inout_updates_z_(_String_length_(_Dest)+_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define va_start(ap, A)
Definition: acmsvcex.h:91
#define StdOut
Definition: stream.h:76
#define MAKELANGID(p, s)
Definition: nls.h:15
#define towupper(c)
Definition: wctype.h:99
GLfloat GLfloat p
Definition: glext.h:8902
WCHAR * LPWSTR
Definition: xmlstorage.h:184
_CRTIMP int __cdecl vswprintf(_Out_ wchar_t *, const wchar_t *, va_list)
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
#define RC_STRING_MAX_SIZE
Definition: resource.h:3
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502