ReactOS 0.4.16-dev-197-g92996da
attrib.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Attrib Command
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Displays or changes file attributes recursively.
5 * COPYRIGHT: Copyright 1998-2019 Eric Kohl <eric.kohl@reactos.org>
6 * Copyright 2021 Doug Lyons <douglyons@douglyons.com>
7 * Copyright 2021-2023 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
8 */
9
10#include <stdio.h>
11#include <stdlib.h>
12
13#include <windef.h>
14#include <winbase.h>
15#include <wincon.h>
16#include <winuser.h>
17#include <strsafe.h>
18
19#include <conutils.h>
20
21#include "resource.h"
22
23/* Enable to support extended attributes.
24 * See https://ss64.com/nt/attrib.html for an exhaustive list. */
25// TODO: If you enable this, translations need to be updated as well!
26//#define EXTENDED_ATTRIBUTES
27
28#define ALL_FILES_PATTERN L"*.*" // It may also be possible to use L"*" (shorter)
29
31
32static VOID
34 _In_ DWORD dwErrorCode,
35 _In_opt_ PCWSTR pszMsg,
36 ...)
37{
38 INT Len;
39 va_list arg_ptr;
40
41 if (dwErrorCode == ERROR_SUCCESS)
42 return;
43
44 va_start(arg_ptr, pszMsg);
47 NULL,
48 dwErrorCode,
50 &arg_ptr);
51 va_end(arg_ptr);
52
53 /* Fall back just in case the error is not defined */
54 if (Len <= 0)
56
57 /* Display the extra optional message if necessary */
58 if (pszMsg)
59 ConPrintf(StdErr, L" %s\n", pszMsg);
60}
61
62
67static BOOL
69 _In_ PWIN32_FIND_DATAW pFindData,
70 _In_ PCWSTR pszFullName,
72{
73 DWORD dwAttributes = pFindData->dwFileAttributes;
74
76
78#ifdef EXTENDED_ATTRIBUTES
79 L"%c %c%c%c %c %s\n",
80#else
81 L"%c %c%c%c %s\n",
82#endif
87#ifdef EXTENDED_ATTRIBUTES
89#endif
90 pszFullName);
91
92 return TRUE;
93}
94
95typedef struct _ATTRIBS_MASKS
96{
100
105static BOOL
107 _In_ PWIN32_FIND_DATAW pFindData,
108 _In_ PCWSTR pszFullName,
110{
111 PATTRIBS_MASKS AttribsMasks = (PATTRIBS_MASKS)Context;
113
114 dwAttributes = ((pFindData->dwFileAttributes & ~AttribsMasks->dwMask) | AttribsMasks->dwAttrib);
115 return SetFileAttributesW(pszFullName, dwAttributes);
116}
117
118
119#define ENUM_RECURSE 0x01
120#define ENUM_DIRECTORIES 0x02
121
122typedef BOOL
124 _In_ PWIN32_FIND_DATAW pFindData,
125 _In_ PCWSTR pszFullName,
127
128typedef struct _ENUMFILES_CTX
129{
130 /* Fixed data */
133
134 /* Callback invoked on each enumerated file/directory */
137
138 /* Dynamic data */
141
142 /* The full path buffer the function will act recursively */
143 // PWSTR FullPath; // Use a relocated buffer once long paths become supported!
144 size_t cchBuffer; // Buffer size
146
148
149/* Returns TRUE if anything is done, FALSE otherwise */
150static BOOL
152 _Inout_ PENUMFILES_CTX EnumCtx,
153 _Inout_ _off_t offFilePart) // Offset to the file name inside FullPathBuffer
154{
155 BOOL bFound = FALSE;
156 HRESULT hRes;
157 HANDLE hFind;
158 PWSTR findFileName = EnumCtx->findData.cFileName;
159 PWSTR pFilePart = EnumCtx->FullPathBuffer + offFilePart;
160 size_t cchRemaining = EnumCtx->cchBuffer - offFilePart;
161
162 /* Recurse over all subdirectories */
163 if (EnumCtx->Flags & ENUM_RECURSE)
164 {
165 /* Append '*.*' */
166 hRes = StringCchCopyW(pFilePart, cchRemaining, ALL_FILES_PATTERN);
167 if (hRes != S_OK)
168 {
170 {
171 // TODO: If this fails, try to reallocate EnumCtx->FullPathBuffer by
172 // increasing its size by _countof(EnumCtx->findData.cFileName) + 1
173 // to satisfy this copy, as well as the one made in the loop below.
174 }
175 // else
176 ConPrintf(StdErr, L"Directory level too deep: %s\n", EnumCtx->FullPathBuffer);
177 return FALSE;
178 }
179
180 hFind = FindFirstFileW(EnumCtx->FullPathBuffer, &EnumCtx->findData);
181 if (hFind == INVALID_HANDLE_VALUE)
182 {
184 if ((Error != ERROR_DIRECTORY) &&
187 {
188 ErrorMessage(Error, EnumCtx->FullPathBuffer);
189 }
190 return FALSE;
191 }
192
193 do
194 {
195 BOOL bIsReparse;
196 size_t offNewFilePart;
197
198 if (!(EnumCtx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
199 continue;
200
201 if (!wcscmp(findFileName, L".") || !wcscmp(findFileName, L".."))
202 continue;
203
204 /* Allow at most 2 levels of reparse points / symbolic links */
205 bIsReparse = !!(EnumCtx->findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);
206 if (bIsReparse)
207 {
208 if (EnumCtx->uReparseLevel < 2)
209 EnumCtx->uReparseLevel++;
210 else
211 continue;
212 }
213
214 hRes = StringCchPrintfExW(pFilePart, cchRemaining,
215 NULL, &offNewFilePart, 0,
216 L"%s\\", findFileName);
217 /* Offset to the new file name part */
218 offNewFilePart = EnumCtx->cchBuffer - offNewFilePart;
219
220 bFound |= EnumFilesWorker(EnumCtx, offNewFilePart);
221
222 /* Recalculate the file part pointer and the number of characters
223 * remaining: the buffer may have been enlarged and relocated. */
224 pFilePart = EnumCtx->FullPathBuffer + offFilePart;
225 cchRemaining = EnumCtx->cchBuffer - offFilePart;
226
227 /* If we went through a reparse point / symbolic link, decrease level */
228 if (bIsReparse)
229 EnumCtx->uReparseLevel--;
230 }
231 while (FindNextFileW(hFind, &EnumCtx->findData));
232 FindClose(hFind);
233 }
234
235 /* Append the file name pattern to search for */
236 hRes = StringCchCopyW(pFilePart, cchRemaining, EnumCtx->FileName);
237
238 /* Search in the current directory */
239 hFind = FindFirstFileW(EnumCtx->FullPathBuffer, &EnumCtx->findData);
240 if (hFind == INVALID_HANDLE_VALUE)
241 return bFound;
242
243 do
244 {
245 BOOL bIsDir = !!(EnumCtx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
246 BOOL bExactMatch = (_wcsicmp(findFileName, EnumCtx->FileName) == 0);
247
248 if (bIsDir && !(EnumCtx->Flags & ENUM_DIRECTORIES) && !bExactMatch)
249 continue;
250
251 if (!wcscmp(findFileName, L".") || !wcscmp(findFileName, L".."))
252 continue;
253
254 /* If we recursively enumerate files excluding directories,
255 * exclude any directory from the enumeration. */
256 if (bIsDir && !(EnumCtx->Flags & ENUM_DIRECTORIES) && (EnumCtx->Flags & ENUM_RECURSE))
257 continue;
258
259 StringCchCopyW(pFilePart, cchRemaining, findFileName);
260 /* bFound = */ EnumCtx->Callback(&EnumCtx->findData, EnumCtx->FullPathBuffer, EnumCtx->Context);
261 bFound = TRUE;
262 }
263 while (FindNextFileW(hFind, &EnumCtx->findData));
264 FindClose(hFind);
265
266 return bFound;
267}
268
269static BOOL
271 _In_ PCWSTR pszPath,
272 _In_ PCWSTR pszFile,
273 _In_ DWORD fFlags,
274 _In_ PATTRIBS_MASKS AttribsMasks)
275{
276 ENUMFILES_CTX EnumContext = {0};
277 size_t offFilePart;
278 HRESULT hRes;
279
280 EnumContext.FileName = pszFile;
281 EnumContext.Flags = fFlags;
282 EnumContext.Callback = (AttribsMasks->dwMask == 0 ? PrintAttributes : ChangeAttributes);
283 EnumContext.Context = (AttribsMasks->dwMask == 0 ? NULL : AttribsMasks);
284
285 /* Prepare the full file path buffer */
286 EnumContext.cchBuffer = _countof(EnumContext.FullPathBuffer);
287 hRes = StringCchCopyExW(EnumContext.FullPathBuffer,
288 EnumContext.cchBuffer,
289 pszPath,
290 NULL,
291 &offFilePart,
292 0);
293 if (hRes != S_OK)
294 return FALSE;
295
296 /* Offset to the file name part */
297 offFilePart = EnumContext.cchBuffer - offFilePart;
298 if (EnumContext.FullPathBuffer[offFilePart - 1] != L'\\')
299 {
300 EnumContext.FullPathBuffer[offFilePart] = L'\\';
301 EnumContext.FullPathBuffer[offFilePart + 1] = UNICODE_NULL;
302 offFilePart++;
303 }
304
305 return EnumFilesWorker(&EnumContext, offFilePart);
306}
307
308int wmain(int argc, WCHAR *argv[])
309{
310 INT i;
311 DWORD dwEnumFlags = 0;
312 ATTRIBS_MASKS AttribsMasks = {0};
313 BOOL bFound = FALSE;
315 WCHAR szFilePath[MAX_PATH + 2] = L""; // + 2 to reserve an extra path separator and a NULL-terminator.
316
317 /* Initialize the Console Standard Streams */
319
320 /* Check for options and file specifications */
321 for (i = 1; i < argc; i++)
322 {
323 if (*argv[i] == L'/')
324 {
325 /* Print help and bail out if needed */
326 if (wcscmp(argv[i], L"/?") == 0)
327 {
329 return 0;
330 }
331 else
332 /* Retrieve the enumeration modes */
333 if (_wcsicmp(argv[i], L"/s") == 0)
334 dwEnumFlags |= ENUM_RECURSE;
335 else if (_wcsicmp(argv[i], L"/d") == 0)
336 dwEnumFlags |= ENUM_DIRECTORIES;
337 else
338 {
339 /* Unknown option */
341 return -1;
342 }
343 }
344 else
345 /* Build attributes and mask */
346 if ((*argv[i] == L'+') || (*argv[i] == L'-'))
347 {
348 BOOL bAdd = (*argv[i] == L'+');
349
350 if (wcslen(argv[i]) != 2)
351 {
353 return -1;
354 }
355
356 switch (towupper(argv[i][1]))
357 {
358 case L'A':
359 AttribsMasks.dwMask |= FILE_ATTRIBUTE_ARCHIVE;
360 if (bAdd)
361 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
362 else
363 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
364 break;
365
366 case L'S':
367 AttribsMasks.dwMask |= FILE_ATTRIBUTE_SYSTEM;
368 if (bAdd)
369 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
370 else
371 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
372 break;
373
374 case L'H':
375 AttribsMasks.dwMask |= FILE_ATTRIBUTE_HIDDEN;
376 if (bAdd)
377 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
378 else
379 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
380 break;
381
382 case L'R':
383 AttribsMasks.dwMask |= FILE_ATTRIBUTE_READONLY;
384 if (bAdd)
385 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_READONLY;
386 else
387 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
388 break;
389
390#ifdef EXTENDED_ATTRIBUTES
391 case L'I':
393 if (bAdd)
395 else
396 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
397 break;
398#endif
399
400 default:
402 return -1;
403 }
404 }
405 else
406 {
407 /* At least one file specification found */
408 bFound = TRUE;
409 }
410 }
411
412 /* If no file specification was found, operate on all files of the current directory */
413 if (!bFound)
414 {
417
418 bFound = AttribEnumFiles(szFilePath, pszFileName, dwEnumFlags, &AttribsMasks);
419 if (!bFound)
421
422 return 0;
423 }
424
425 /* Operate on each file specification */
426 for (i = 1; i < argc; i++)
427 {
428 /* Skip options */
429 if (*argv[i] == L'/' || *argv[i] == L'+' || *argv[i] == L'-')
430 continue;
431
433 if (pszFileName)
434 {
435 /* Move the file part so as to separate and NULL-terminate the directory */
437 sizeof(szFilePath) - (pszFileName -szFilePath + 1) * sizeof(*szFilePath));
439 }
440 else
441 {
442 pszFileName = L"";
443 }
444
445 bFound = AttribEnumFiles(szFilePath, pszFileName, dwEnumFlags, &AttribsMasks);
446 if (!bFound)
448 }
449
450 return 0;
451}
static int argc
Definition: ServiceArgs.c:12
char * va_list
Definition: acmsvcex.h:78
#define va_end(ap)
Definition: acmsvcex.h:90
#define va_start(ap, A)
Definition: acmsvcex.h:91
struct _ENUMFILES_CTX ENUMFILES_CTX
#define ENUM_DIRECTORIES
Definition: attrib.c:120
static BOOL PrintAttributes(_In_ PWIN32_FIND_DATAW pFindData, _In_ PCWSTR pszFullName, _Inout_opt_ PVOID Context)
Displays attributes for the given file.
Definition: attrib.c:68
struct _ATTRIBS_MASKS ATTRIBS_MASKS
struct _ATTRIBS_MASKS * PATTRIBS_MASKS
static BOOL EnumFilesWorker(_Inout_ PENUMFILES_CTX EnumCtx, _Inout_ _off_t offFilePart)
Definition: attrib.c:151
BOOL(* PENUMFILES_CALLBACK)(_In_ PWIN32_FIND_DATAW pFindData, _In_ PCWSTR pszFullName, _Inout_opt_ PVOID Context)
Definition: attrib.c:123
static VOID ErrorMessage(_In_ DWORD dwErrorCode, _In_opt_ PCWSTR pszMsg,...)
Definition: attrib.c:33
static BOOL ChangeAttributes(_In_ PWIN32_FIND_DATAW pFindData, _In_ PCWSTR pszFullName, _Inout_opt_ PVOID Context)
Changes attributes for the given file.
Definition: attrib.c:106
static BOOL AttribEnumFiles(_In_ PCWSTR pszPath, _In_ PCWSTR pszFile, _In_ DWORD fFlags, _In_ PATTRIBS_MASKS AttribsMasks)
Definition: attrib.c:270
CON_SCREEN StdOutScreen
Definition: attrib.c:30
struct _ENUMFILES_CTX * PENUMFILES_CTX
#define ENUM_RECURSE
Definition: attrib.c:119
#define ALL_FILES_PATTERN
Definition: attrib.c:28
#define STRING_ATTRIB_HELP
Definition: resource.h:7
#define STRING_ERROR_INVALID_PARAM_FORMAT
Definition: resource.h:5
#define STRING_CONSOLE_ERROR
Definition: resource.h:6
#define STRING_FILE_NOT_FOUND
Definition: resource.h:8
#define ConInitStdStreams()
Definition: fc.c:13
void ConPrintf(FILE *fp, LPCWSTR psz,...)
Definition: fc.c:20
#define StdOut
Definition: fc.c:14
void ConResPrintf(FILE *fp, UINT nID,...)
Definition: fc.c:33
#define StdErr
Definition: fc.c:15
void ConResPuts(FILE *fp, UINT nID)
Definition: fc.c:27
BOOL Error
Definition: chkdsk.c:66
#define Len
Definition: deflate.h:82
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define GetCurrentDirectoryW(x, y)
Definition: compat.h:756
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define MAX_PATH
Definition: compat.h:34
BOOL WINAPI SetFileAttributesW(LPCWSTR lpFileName, DWORD dwFileAttributes)
Definition: fileinfo.c:794
HANDLE WINAPI FindFirstFileW(IN LPCWSTR lpFileName, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:320
BOOL WINAPI FindClose(HANDLE hFindFile)
Definition: find.c:502
BOOL WINAPI FindNextFileW(IN HANDLE hFindFile, OUT LPWIN32_FIND_DATAW lpFindFileData)
Definition: find.c:382
DWORD WINAPI GetFullPathNameW(IN LPCWSTR lpFileName, IN DWORD nBufferLength, OUT LPWSTR lpBuffer, OUT LPWSTR *lpFilePart)
Definition: path.c:1106
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
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
long _off_t
Definition: stdio.h:73
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define S_OK
Definition: intsafe.h:52
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define argv
Definition: mplay32.c:18
#define _Inout_
Definition: ms_sal.h:378
#define _Inout_opt_
Definition: ms_sal.h:379
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define BOOL
Definition: nt_native.h:43
#define FILE_ATTRIBUTE_READONLY
Definition: nt_native.h:702
#define FILE_ATTRIBUTE_HIDDEN
Definition: nt_native.h:703
#define FILE_ATTRIBUTE_SYSTEM
Definition: nt_native.h:704
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FILE_ATTRIBUTE_DIRECTORY
Definition: nt_native.h:705
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
Definition: ntifs_ex.h:384
#define L(x)
Definition: ntvdm.h:50
INT ConMsgPrintfV(IN PCON_STREAM Stream, IN DWORD dwFlags, IN LPCVOID lpSource OPTIONAL, IN DWORD dwMessageId, IN DWORD dwLanguageId, IN va_list *Arguments OPTIONAL)
Definition: outstream.c:1030
static WCHAR szFilePath[]
Definition: qotd.c:14
int wmain()
#define INIT_CON_SCREEN(pStream)
Definition: screen.h:49
_Check_return_ _CRTIMP int __cdecl _wcsicmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
#define _countof(array)
Definition: sndvol32.h:70
STRSAFEAPI StringCchCopyExW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags)
Definition: strsafe.h:184
STRSAFEAPI StringCchPrintfExW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPWSTR *ppszDestEnd, size_t *pcchRemaining, STRSAFE_DWORD dwFlags, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:585
STRSAFEAPI StringCchCopyW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszSrc)
Definition: strsafe.h:149
#define STRSAFE_E_INSUFFICIENT_BUFFER
Definition: strsafe.h:103
DWORD dwMask
Definition: attrib.c:97
DWORD dwAttrib
Definition: attrib.c:98
size_t cchBuffer
Definition: attrib.c:144
_In_ DWORD Flags
Definition: attrib.c:132
WIN32_FIND_DATAW findData
Definition: attrib.c:139
_In_ PCWSTR FileName
Definition: attrib.c:131
WCHAR FullPathBuffer[MAX_PATH+_countof("\\" ALL_FILES_PATTERN)]
Definition: attrib.c:145
_In_ PENUMFILES_CALLBACK Callback
Definition: attrib.c:135
ULONG uReparseLevel
Definition: attrib.c:140
_In_ PVOID Context
Definition: attrib.c:136
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
#define towupper(c)
Definition: wctype.h:99
uint16_t * PWSTR
Definition: typedefs.h:56
const uint16_t * PCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
DWORD dwAttributes
Definition: vdmdbg.h:34
WORD WORD PSZ PSZ pszFileName
Definition: vdmdbg.h:44
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
#define MoveMemory
Definition: winbase.h:1733
#define FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:448
#define ERROR_SHARING_VIOLATION
Definition: winerror.h:135
#define ERROR_DIRECTORY
Definition: winerror.h:295
__wchar_t WCHAR
Definition: xmlstorage.h:180