ReactOS  0.4.15-dev-1171-gab82533
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(StdOut, 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(StdOut, L"%s -- %s\n", szMsg, szMessage);
85  else
86  ConPrintf(StdOut, 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  wcscpy(pszFileName, findData.cFileName);
149 
151  L"%c %c%c%c %s\n",
152  (findData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? L'A' : L' ',
153  (findData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? L'S' : L' ',
154  (findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? L'H' : L' ',
155  (findData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? L'R' : L' ',
156  szFullName);
157  }
158  while(FindNextFileW(hFind, &findData));
159  FindClose(hFind);
160 
161  return 0;
162 }
163 
164 
165 static
166 BOOL
168  LPWSTR pszPath,
169  LPWSTR pszFile,
170  DWORD dwMask,
171  DWORD dwAttrib,
172  BOOL bRecurse,
173  BOOL bDirectories)
174 {
175  WIN32_FIND_DATAW findData;
176  HANDLE hFind;
177  DWORD dwAttribute;
178  WCHAR szFullName[MAX_PATH];
180  BOOL bWildcard = (wcschr(pszFile, L'*') || wcschr(pszFile, L'?'));
181 
182  /* prepare full file name buffer */
183  wcscpy(szFullName, pszPath);
184  pszFileName = szFullName + wcslen(szFullName);
185 
186  /* append file name */
187  wcscpy(pszFileName, pszFile);
188 
189  hFind = FindFirstFileW(szFullName, &findData);
190  if (hFind == INVALID_HANDLE_VALUE)
191  return FALSE;
192 
193  dwAttribute = findData.dwFileAttributes;
194 
195  if (!bWildcard)
196  {
197  FindClose(hFind);
198  if (dwAttribute & FILE_ATTRIBUTE_DIRECTORY)
199  {
200  dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
201  SetFileAttributes(szFullName, dwAttribute);
202  if (bRecurse)
203  {
204  if (bDirectories)
205  {
206  ChangeAttribute(szFullName, L"*", dwMask, dwAttrib,
207  bRecurse, bDirectories);
208  }
209  else
210  {
211  if (!ChangeAttribute(szFullName, L"*", dwMask, dwAttrib,
212  bRecurse, FALSE))
213  {
214  return FALSE;
215  }
216  }
217  }
218  else
219  {
220  if (!bDirectories)
221  {
222  ChangeAttribute(szFullName, L"*", dwMask, dwAttrib,
223  bRecurse, FALSE);
224  }
225  }
226  return TRUE;
227  }
228  else
229  {
230  dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
231  SetFileAttributes(szFullName, dwAttribute);
232  return TRUE;
233  }
234  }
235  else
236  {
237  if ((dwAttribute & FILE_ATTRIBUTE_DIRECTORY) && (!bRecurse || !bDirectories))
238  return FALSE;
239 
240  do
241  {
242  dwAttribute = findData.dwFileAttributes;
243  if (dwAttribute & FILE_ATTRIBUTE_DIRECTORY)
244  {
245  if (!bDirectories)
246  continue;
247 
248  if (!wcscmp(findData.cFileName, L".") ||
249  !wcscmp(findData.cFileName, L".."))
250  continue;
251 
252  wcscpy(pszFileName, findData.cFileName);
253  dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
254  SetFileAttributes(szFullName, dwAttribute);
255 
256  if (bRecurse)
257  {
258  ChangeAttribute(szFullName, findData.cFileName, dwMask,
259  dwAttrib, bRecurse, FALSE);
260  }
261  }
262  else
263  {
264  wcscpy(pszFileName, findData.cFileName);
265  dwAttribute = (dwAttribute & ~dwMask) | dwAttrib;
266  SetFileAttributes(szFullName, dwAttribute);
267  }
268  } while (FindNextFileW(hFind, &findData));
269 
270  FindClose(hFind);
271  }
272 
273  return TRUE;
274 }
275 
276 int wmain(int argc, WCHAR *argv[])
277 {
278  INT i;
280  WCHAR szFileName [MAX_PATH];
281  BOOL bRecurse = FALSE;
282  BOOL bDirectories = FALSE;
283  DWORD dwAttrib = 0;
284  DWORD dwMask = 0;
285  LPWSTR p;
286 
287  /* Initialize the Console Standard Streams */
289 
290  /* Print help */
291  if (argc > 1 && wcscmp(argv[1], L"/?") == 0)
292  {
294  return 0;
295  }
296 
297  /* check for options */
298  for (i = 1; i < argc; i++)
299  {
300  if (wcsicmp(argv[i], L"/s") == 0)
301  bRecurse = TRUE;
302  else if (wcsicmp(argv[i], L"/d") == 0)
303  bDirectories = TRUE;
304  }
305 
306  /* create attributes and mask */
307  for (i = 1; i < argc; i++)
308  {
309  if (*argv[i] == L'+')
310  {
311  if (wcslen(argv[i]) != 2)
312  {
314  return -1;
315  }
316 
317  switch (towupper(argv[i][1]))
318  {
319  case L'A':
320  dwMask |= FILE_ATTRIBUTE_ARCHIVE;
321  dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
322  break;
323 
324  case L'H':
325  dwMask |= FILE_ATTRIBUTE_HIDDEN;
326  dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
327  break;
328 
329  case L'R':
330  dwMask |= FILE_ATTRIBUTE_READONLY;
331  dwAttrib |= FILE_ATTRIBUTE_READONLY;
332  break;
333 
334  case L'S':
335  dwMask |= FILE_ATTRIBUTE_SYSTEM;
336  dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
337  break;
338 
339  default:
341  return -1;
342  }
343  }
344  else if (*argv[i] == L'-')
345  {
346  if (wcslen(argv[i]) != 2)
347  {
349  return -1;
350  }
351 
352  switch (towupper(argv[i][1]))
353  {
354  case L'A':
355  dwMask |= FILE_ATTRIBUTE_ARCHIVE;
356  dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
357  break;
358 
359  case L'H':
360  dwMask |= FILE_ATTRIBUTE_HIDDEN;
361  dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
362  break;
363 
364  case L'R':
365  dwMask |= FILE_ATTRIBUTE_READONLY;
366  dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
367  break;
368 
369  case L'S':
370  dwMask |= FILE_ATTRIBUTE_SYSTEM;
371  dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
372  break;
373 
374  default:
376  return -1;
377  }
378  }
379  }
380 
381  if (argc == 1)
382  {
383  DWORD len;
384 
386  if (szPath[len-1] != L'\\')
387  {
388  szPath[len] = L'\\';
389  szPath[len + 1] = UNICODE_NULL;
390  }
391  wcscpy(szFileName, L"*.*");
392  PrintAttribute(szPath, szFileName, bRecurse);
393  return 0;
394  }
395 
396  /* get full file name */
397  for (i = 1; i < argc; i++)
398  {
399  if (*argv[i] == L'+' || *argv[i] == L'-' || *argv[i] == L'/')
400  continue;
401 
403  wcscpy(szFileName, p);
404  *p = 0;
405 
406  if (dwMask == 0)
407  {
408  PrintAttribute(szPath, szFileName, bRecurse);
409  }
410  else if (!ChangeAttribute(szPath, szFileName, dwMask,
411  dwAttrib, bRecurse, bDirectories))
412  {
414  }
415  }
416 
417  return 0;
418 }
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 ERROR_SUCCESS
Definition: deptool.c:10
#define STRING_CONSOLE_ERROR
Definition: resource.h:6
#define TRUE
Definition: types.h:120
#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 BOOL ChangeAttribute(LPWSTR pszPath, LPWSTR pszFile, DWORD dwMask, DWORD dwAttrib, BOOL bRecurse, BOOL bDirectories)
Definition: attrib.c:167
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:479
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1044
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1105
#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:58
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:128
#define va_end(ap)
Definition: acmsvcex.h:90
#define FALSE
Definition: types.h:117
#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:3645
#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
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:404
int wmain(int argc, WCHAR *argv[])
Definition: attrib.c:276
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
INT __cdecl ConResPrintf(IN PCON_STREAM Stream, IN UINT uID,...)
Definition: outstream.c:781
_CONST_RETURN wchar_t *__cdecl wcschr(_In_z_ const wchar_t *_Str, wchar_t _Ch)
#define SetFileAttributes
Definition: winbase.h:3749
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define MAX_PATH
Definition: compat.h:34
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
unsigned long DWORD
Definition: ntddk_ex.h:95
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define wcsicmp
Definition: compat.h:15
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
#define STRING_FILE_NOT_FOUND
Definition: resource.h:8
GLenum GLsizei len
Definition: glext.h:6722
INT __cdecl ConPrintf(IN PCON_STREAM Stream, IN PCWSTR szStr,...)
Definition: outstream.c:520
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define GetModuleHandle
Definition: winbase.h:3667
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:82
#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