ReactOS 0.4.16-dev-2613-g9533ad7
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 <strsafe.h>
17
18#include <conutils.h>
19
20#include "resource.h"
21
22/* Enable to support extended attributes.
23 * See https://ss64.com/nt/attrib.html for an exhaustive list. */
24// TODO: If you enable this, translations need to be updated as well!
25//#define EXTENDED_ATTRIBUTES
26
27#define ALL_FILES_PATTERN L"*.*" // It may also be possible to use L"*" (shorter)
28
30
31static VOID
33 _In_ DWORD dwErrorCode,
34 _In_opt_ PCWSTR pszMsg,
35 ...)
36{
37 INT Len;
38 va_list arg_ptr;
39
40 if (dwErrorCode == ERROR_SUCCESS)
41 return;
42
43 va_start(arg_ptr, pszMsg);
46 NULL,
47 dwErrorCode,
49 &arg_ptr);
50 va_end(arg_ptr);
51
52 /* Fall back just in case the error is not defined */
53 if (Len <= 0)
55
56 /* Display the extra optional message if necessary */
57 if (pszMsg)
58 ConPrintf(StdErr, L" %s\n", pszMsg);
59}
60
61
66static BOOL
68 _In_ PWIN32_FIND_DATAW pFindData,
69 _In_ PCWSTR pszFullName,
71{
72 DWORD dwAttributes = pFindData->dwFileAttributes;
73
75
77#ifdef EXTENDED_ATTRIBUTES
78 L"%c %c%c%c %c %s\n",
79#else
80 L"%c %c%c%c %s\n",
81#endif
86#ifdef EXTENDED_ATTRIBUTES
88#endif
89 pszFullName);
90
91 return TRUE;
92}
93
94typedef struct _ATTRIBS_MASKS
95{
99
104static BOOL
106 _In_ PWIN32_FIND_DATAW pFindData,
107 _In_ PCWSTR pszFullName,
109{
110 PATTRIBS_MASKS AttribsMasks = (PATTRIBS_MASKS)Context;
112
113 dwAttributes = ((pFindData->dwFileAttributes & ~AttribsMasks->dwMask) | AttribsMasks->dwAttrib);
114 return SetFileAttributesW(pszFullName, dwAttributes);
115}
116
117
118#define ENUM_RECURSE 0x01
119#define ENUM_DIRECTORIES 0x02
120
121typedef BOOL
123 _In_ PWIN32_FIND_DATAW pFindData,
124 _In_ PCWSTR pszFullName,
126
127typedef struct _ENUMFILES_CTX
128{
129 /* Fixed data */
132
133 /* Callback invoked on each enumerated file/directory */
136
137 /* Dynamic data */
140
141 /* The full path buffer the function will act recursively */
142 // PWSTR FullPath; // Use a relocated buffer once long paths become supported!
143 size_t cchBuffer; // Buffer size
145
147
148/* Returns TRUE if anything is done, FALSE otherwise */
149static BOOL
151 _Inout_ PENUMFILES_CTX EnumCtx,
152 _Inout_ size_t offFilePart) // Offset to the file name inside FullPathBuffer
153{
154 BOOL bFound = FALSE;
155 HRESULT hRes;
156 HANDLE hFind;
157 PWSTR findFileName = EnumCtx->findData.cFileName;
158 PWSTR pFilePart = EnumCtx->FullPathBuffer + offFilePart;
159 size_t cchRemaining = EnumCtx->cchBuffer - offFilePart;
160
161 /* Recurse over all subdirectories */
162 if (EnumCtx->Flags & ENUM_RECURSE)
163 {
164 /* Append '*.*' */
165 hRes = StringCchCopyW(pFilePart, cchRemaining, ALL_FILES_PATTERN);
166 if (hRes != S_OK)
167 {
169 {
170 // TODO: If this fails, try to reallocate EnumCtx->FullPathBuffer by
171 // increasing its size by _countof(EnumCtx->findData.cFileName) + 1
172 // to satisfy this copy, as well as the one made in the loop below.
173 }
174 // else
175 ConPrintf(StdErr, L"Directory level too deep: %s\n", EnumCtx->FullPathBuffer);
176 return FALSE;
177 }
178
179 hFind = FindFirstFileW(EnumCtx->FullPathBuffer, &EnumCtx->findData);
180 if (hFind == INVALID_HANDLE_VALUE)
181 {
183 if ((Error != ERROR_DIRECTORY) &&
186 {
187 ErrorMessage(Error, EnumCtx->FullPathBuffer);
188 }
189 return FALSE;
190 }
191
192 do
193 {
194 BOOL bIsReparse;
195 size_t offNewFilePart;
196
197 if (!(EnumCtx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
198 continue;
199
200 if (!wcscmp(findFileName, L".") || !wcscmp(findFileName, L".."))
201 continue;
202
203 /* Allow at most 2 levels of reparse points / symbolic links */
204 bIsReparse = !!(EnumCtx->findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT);
205 if (bIsReparse)
206 {
207 if (EnumCtx->uReparseLevel < 2)
208 EnumCtx->uReparseLevel++;
209 else
210 continue;
211 }
212
213 hRes = StringCchPrintfExW(pFilePart, cchRemaining,
214 NULL, &offNewFilePart, 0,
215 L"%s\\", findFileName);
216 /* Offset to the new file name part */
217 offNewFilePart = EnumCtx->cchBuffer - offNewFilePart;
218
219 bFound |= EnumFilesWorker(EnumCtx, offNewFilePart);
220
221 /* Recalculate the file part pointer and the number of characters
222 * remaining: the buffer may have been enlarged and relocated. */
223 pFilePart = EnumCtx->FullPathBuffer + offFilePart;
224 cchRemaining = EnumCtx->cchBuffer - offFilePart;
225
226 /* If we went through a reparse point / symbolic link, decrease level */
227 if (bIsReparse)
228 EnumCtx->uReparseLevel--;
229 }
230 while (FindNextFileW(hFind, &EnumCtx->findData));
231 FindClose(hFind);
232 }
233
234 /* Append the file name pattern to search for */
235 hRes = StringCchCopyW(pFilePart, cchRemaining, EnumCtx->FileName);
236
237 /* Search in the current directory */
238 hFind = FindFirstFileW(EnumCtx->FullPathBuffer, &EnumCtx->findData);
239 if (hFind == INVALID_HANDLE_VALUE)
240 return bFound;
241
242 do
243 {
244 BOOL bIsDir = !!(EnumCtx->findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
245 BOOL bExactMatch = (_wcsicmp(findFileName, EnumCtx->FileName) == 0);
246
247 if (bIsDir && !(EnumCtx->Flags & ENUM_DIRECTORIES) && !bExactMatch)
248 continue;
249
250 if (!wcscmp(findFileName, L".") || !wcscmp(findFileName, L".."))
251 continue;
252
253 /* If we recursively enumerate files excluding directories,
254 * exclude any directory from the enumeration. */
255 if (bIsDir && !(EnumCtx->Flags & ENUM_DIRECTORIES) && (EnumCtx->Flags & ENUM_RECURSE))
256 continue;
257
258 StringCchCopyW(pFilePart, cchRemaining, findFileName);
259 /* bFound = */ EnumCtx->Callback(&EnumCtx->findData, EnumCtx->FullPathBuffer, EnumCtx->Context);
260 bFound = TRUE;
261 }
262 while (FindNextFileW(hFind, &EnumCtx->findData));
263 FindClose(hFind);
264
265 return bFound;
266}
267
268static BOOL
270 _In_ PCWSTR pszPath,
271 _In_ PCWSTR pszFile,
272 _In_ DWORD fFlags,
273 _In_ PATTRIBS_MASKS AttribsMasks)
274{
275 ENUMFILES_CTX EnumContext = {0};
276 size_t offFilePart;
277 HRESULT hRes;
278
279 EnumContext.FileName = pszFile;
280 EnumContext.Flags = fFlags;
281 EnumContext.Callback = (AttribsMasks->dwMask == 0 ? PrintAttributes : ChangeAttributes);
282 EnumContext.Context = (AttribsMasks->dwMask == 0 ? NULL : AttribsMasks);
283
284 /* Prepare the full file path buffer */
285 EnumContext.cchBuffer = _countof(EnumContext.FullPathBuffer);
286 hRes = StringCchCopyExW(EnumContext.FullPathBuffer,
287 EnumContext.cchBuffer,
288 pszPath,
289 NULL,
290 &offFilePart,
291 0);
292 if (hRes != S_OK)
293 return FALSE;
294
295 /* Offset to the file name part */
296 offFilePart = EnumContext.cchBuffer - offFilePart;
297 if (EnumContext.FullPathBuffer[offFilePart - 1] != L'\\')
298 {
299 EnumContext.FullPathBuffer[offFilePart] = L'\\';
300 EnumContext.FullPathBuffer[offFilePart + 1] = UNICODE_NULL;
301 offFilePart++;
302 }
303
304 return EnumFilesWorker(&EnumContext, offFilePart);
305}
306
307int wmain(int argc, WCHAR *argv[])
308{
309 INT i;
310 DWORD dwEnumFlags = 0;
311 ATTRIBS_MASKS AttribsMasks = {0};
312 BOOL bFound = FALSE;
314 WCHAR szFilePath[MAX_PATH + 2] = L""; // + 2 to reserve an extra path separator and a NULL-terminator.
315
316 /* Initialize the Console Standard Streams */
318
319 /* Check for options and file specifications */
320 for (i = 1; i < argc; i++)
321 {
322 if (*argv[i] == L'/')
323 {
324 /* Print help and bail out if needed */
325 if (wcscmp(argv[i], L"/?") == 0)
326 {
328 return 0;
329 }
330 else
331 /* Retrieve the enumeration modes */
332 if (_wcsicmp(argv[i], L"/s") == 0)
333 dwEnumFlags |= ENUM_RECURSE;
334 else if (_wcsicmp(argv[i], L"/d") == 0)
335 dwEnumFlags |= ENUM_DIRECTORIES;
336 else
337 {
338 /* Unknown option */
340 return -1;
341 }
342 }
343 else
344 /* Build attributes and mask */
345 if ((*argv[i] == L'+') || (*argv[i] == L'-'))
346 {
347 BOOL bAdd = (*argv[i] == L'+');
348
349 if (wcslen(argv[i]) != 2)
350 {
352 return -1;
353 }
354
355 switch (towupper(argv[i][1]))
356 {
357 case L'A':
358 AttribsMasks.dwMask |= FILE_ATTRIBUTE_ARCHIVE;
359 if (bAdd)
360 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_ARCHIVE;
361 else
362 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_ARCHIVE;
363 break;
364
365 case L'S':
366 AttribsMasks.dwMask |= FILE_ATTRIBUTE_SYSTEM;
367 if (bAdd)
368 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_SYSTEM;
369 else
370 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_SYSTEM;
371 break;
372
373 case L'H':
374 AttribsMasks.dwMask |= FILE_ATTRIBUTE_HIDDEN;
375 if (bAdd)
376 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_HIDDEN;
377 else
378 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_HIDDEN;
379 break;
380
381 case L'R':
382 AttribsMasks.dwMask |= FILE_ATTRIBUTE_READONLY;
383 if (bAdd)
384 AttribsMasks.dwAttrib |= FILE_ATTRIBUTE_READONLY;
385 else
386 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_READONLY;
387 break;
388
389#ifdef EXTENDED_ATTRIBUTES
390 case L'I':
392 if (bAdd)
394 else
395 AttribsMasks.dwAttrib &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
396 break;
397#endif
398
399 default:
401 return -1;
402 }
403 }
404 else
405 {
406 /* At least one file specification found */
407 bFound = TRUE;
408 }
409 }
410
411 /* If no file specification was found, operate on all files of the current directory */
412 if (!bFound)
413 {
416
417 bFound = AttribEnumFiles(szFilePath, pszFileName, dwEnumFlags, &AttribsMasks);
418 if (!bFound)
420
421 return 0;
422 }
423
424 /* Operate on each file specification */
425 for (i = 1; i < argc; i++)
426 {
427 /* Skip options */
428 if (*argv[i] == L'/' || *argv[i] == L'+' || *argv[i] == L'-')
429 continue;
430
432 if (pszFileName)
433 {
434 /* Move the file part so as to separate and NULL-terminate the directory */
436 sizeof(szFilePath) - (pszFileName -szFilePath + 1) * sizeof(*szFilePath));
438 }
439 else
440 {
441 pszFileName = L"";
442 }
443
444 bFound = AttribEnumFiles(szFilePath, pszFileName, dwEnumFlags, &AttribsMasks);
445 if (!bFound)
447 }
448
449 return 0;
450}
struct _ENUMFILES_CTX ENUMFILES_CTX
#define ENUM_DIRECTORIES
Definition: attrib.c:119
static BOOL PrintAttributes(_In_ PWIN32_FIND_DATAW pFindData, _In_ PCWSTR pszFullName, _Inout_opt_ PVOID Context)
Displays attributes for the given file.
Definition: attrib.c:67
struct _ATTRIBS_MASKS ATTRIBS_MASKS
struct _ATTRIBS_MASKS * PATTRIBS_MASKS
BOOL(* PENUMFILES_CALLBACK)(_In_ PWIN32_FIND_DATAW pFindData, _In_ PCWSTR pszFullName, _Inout_opt_ PVOID Context)
Definition: attrib.c:122
static VOID ErrorMessage(_In_ DWORD dwErrorCode, _In_opt_ PCWSTR pszMsg,...)
Definition: attrib.c:32
static BOOL ChangeAttributes(_In_ PWIN32_FIND_DATAW pFindData, _In_ PCWSTR pszFullName, _Inout_opt_ PVOID Context)
Changes attributes for the given file.
Definition: attrib.c:105
static BOOL AttribEnumFiles(_In_ PCWSTR pszPath, _In_ PCWSTR pszFile, _In_ DWORD fFlags, _In_ PATTRIBS_MASKS AttribsMasks)
Definition: attrib.c:269
CON_SCREEN StdOutScreen
Definition: attrib.c:29
struct _ENUMFILES_CTX * PENUMFILES_CTX
#define ENUM_RECURSE
Definition: attrib.c:118
#define ALL_FILES_PATTERN
Definition: attrib.c:27
static BOOL EnumFilesWorker(_Inout_ PENUMFILES_CTX EnumCtx, _Inout_ size_t offFilePart)
Definition: attrib.c:150
#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
BOOL Error
Definition: chkdsk.c:66
#define ConInitStdStreams()
Definition: conutils_noros.h:5
void ConPrintf(FILE *fp, LPCWSTR psz,...)
#define StdOut
Definition: conutils_noros.h:6
void ConResPrintf(FILE *fp, UINT nID,...)
#define StdErr
Definition: conutils_noros.h:7
void ConResPuts(FILE *fp, UINT nID)
#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:778
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
MonoAssembly int argc
Definition: metahost.c:107
_ACRTIMP int __cdecl _wcsicmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:159
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
char * va_list
Definition: vadefs.h:50
#define L(x)
Definition: resources.c:13
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
#define S_OK
Definition: intsafe.h:52
#define MoveMemory
Definition: minwinbase.h:28
#define ERROR_FILE_NOT_FOUND
Definition: disk.h:79
#define argv
Definition: mplay32.c:18
#define _Inout_
Definition: no_sal2.h:162
#define _Inout_opt_
Definition: no_sal2.h:216
#define _In_
Definition: no_sal2.h:158
#define _In_opt_
Definition: no_sal2.h:212
#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 BOOL
Definition: nt_native.h:43
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
#define FILE_ATTRIBUTE_REPARSE_POINT
Definition: ntifs_ex.h:381
#define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED
Definition: ntifs_ex.h:384
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:1028
short WCHAR
Definition: pedump.c:58
static WCHAR szFilePath[]
Definition: qotd.c:14
int wmain()
#define INIT_CON_SCREEN(pStream)
Definition: screen.h:49
#define towupper(c)
Definition: wctype.h:99
#define _countof(array)
Definition: sndvol32.h:70
_In_ PVOID Context
Definition: storport.h:2269
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:96
DWORD dwAttrib
Definition: attrib.c:97
size_t cchBuffer
Definition: attrib.c:143
_In_ DWORD Flags
Definition: attrib.c:131
WIN32_FIND_DATAW findData
Definition: attrib.c:138
_In_ PCWSTR FileName
Definition: attrib.c:130
WCHAR FullPathBuffer[MAX_PATH+_countof("\\" ALL_FILES_PATTERN)]
Definition: attrib.c:144
_In_ PENUMFILES_CALLBACK Callback
Definition: attrib.c:134
ULONG uReparseLevel
Definition: attrib.c:139
_In_ PVOID Context
Definition: attrib.c:135
#define LANG_USER_DEFAULT
Definition: tnerror.cpp:50
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 FORMAT_MESSAGE_FROM_SYSTEM
Definition: winbase.h:400
#define ERROR_SHARING_VIOLATION
Definition: winerror.h:257
#define ERROR_DIRECTORY
Definition: winerror.h:416