From b1bd9208185813b3291e64032e8f5e23d8541566 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Thu, 23 Aug 2007 14:42:27 -0700 Subject: [PATCH] cabinet: Append new file nodes to the front of the file list. --- dlls/cabinet/cabinet_main.c | 34 +++++--- dlls/cabinet/tests/extract.c | 186 +++++++++++++++++++------------------------ 2 files changed, 106 insertions(+), 114 deletions(-) diff --git a/dlls/cabinet/cabinet_main.c b/dlls/cabinet/cabinet_main.c index aa46cf040aa..24be376cbe3 100644 --- a/dlls/cabinet/cabinet_main.c +++ b/dlls/cabinet/cabinet_main.c @@ -163,12 +163,18 @@ static void fill_file_node(struct FILELIST *pNode, LPCSTR szFilename) lstrcpyA(pNode->FileName, szFilename); } -static BOOL file_in_list(const struct FILELIST *pNode, LPCSTR szFilename) +static BOOL file_in_list(struct FILELIST *pNode, LPCSTR szFilename, + struct FILELIST **pOut) { while (pNode) { if (!lstrcmpiA(pNode->FileName, szFilename)) + { + if (pOut) + *pOut = pNode; + return TRUE; + } pNode = pNode->next; } @@ -182,7 +188,7 @@ static INT_PTR fdi_notify_extract(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pf { case fdintCOPY_FILE: { - struct FILELIST **fileList; + struct FILELIST *fileList, *node; SESSION *pDestination = pfdin->pv; LPSTR szFullPath, szDirectory; HANDLE hFile = 0; @@ -201,26 +207,26 @@ static INT_PTR fdi_notify_extract(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pf szDirectory = HeapAlloc(GetProcessHeap(), 0, dwSize); lstrcpynA(szDirectory, szFullPath, dwSize); + pDestination->FileSize += pfdin->cb; + if (pDestination->Operation & EXTRACT_FILLFILELIST) { - fileList = &pDestination->FileList; + fileList = HeapAlloc(GetProcessHeap(), 0, + sizeof(struct FILELIST)); - while (*fileList) - fileList = &((*fileList)->next); - - *fileList = HeapAlloc(GetProcessHeap(), 0, - sizeof(struct FILELIST)); - - fill_file_node(*fileList, pfdin->psz1); + fill_file_node(fileList, pfdin->psz1); + fileList->Extracted = TRUE; + fileList->next = pDestination->FileList; + pDestination->FileList = fileList; lstrcpyA(pDestination->CurrentFile, szFullPath); pDestination->FileCount++; } if ((pDestination->Operation & EXTRACT_EXTRACTFILES) || - file_in_list(pDestination->FilterList, pfdin->psz1)) + file_in_list(pDestination->FilterList, pfdin->psz1, NULL)) { /* skip this file if it is not in the file list */ - if (!file_in_list(pDestination->FileList, pfdin->psz1)) + if (!file_in_list(pDestination->FileList, pfdin->psz1, &node)) return 0; /* create the destination directory if it doesn't exist */ @@ -232,6 +238,8 @@ static INT_PTR fdi_notify_extract(FDINOTIFICATIONTYPE fdint, PFDINOTIFICATION pf if (hFile == INVALID_HANDLE_VALUE) hFile = 0; + else + node->Extracted = FALSE; } HeapFree(GetProcessHeap(), 0, szFullPath); @@ -345,6 +353,8 @@ HRESULT WINAPI Extract(SESSION *dest, LPCSTR szCabName) path = NULL; } + dest->FileSize = 0; + if (!FDICopy(hfdi, name, path, 0, fdi_notify_extract, NULL, dest)) res = E_FAIL; diff --git a/dlls/cabinet/tests/extract.c b/dlls/cabinet/tests/extract.c index b9df804d304..6fb5ad5900c 100644 --- a/dlls/cabinet/tests/extract.c +++ b/dlls/cabinet/tests/extract.c @@ -314,21 +314,26 @@ static void create_cab_file(void) ok(res, "Failed to destroy the cabinet\n"); } -static BOOL check_list(struct FILELIST *filelist, const char *filename, BOOL extracted) +static BOOL check_list(struct FILELIST **node, const char *filename, BOOL extracted) { - struct FILELIST *fl; + if (!*node) + return FALSE; - for (fl = filelist; fl; fl = fl->next) - if (!lstrcmp(filename, fl->FileName)) - return (extracted == fl->Extracted); + if (lstrcmpA((*node)->FileName, filename)) + return FALSE; - return FALSE; + if ((*node)->Extracted != extracted) + return FALSE; + + *node = (*node)->next; + return TRUE; } static void test_Extract(void) { SESSION session; HRESULT res; + struct FILELIST *node; /* native windows crashes if * - invalid parameters are sent in @@ -341,11 +346,9 @@ static void test_Extract(void) lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -363,21 +366,19 @@ static void test_Extract(void) ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n"); - ok(check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); /* try fill file list operation */ ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST; res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -392,22 +393,17 @@ static void test_Extract(void) ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); - todo_wine - { - ok(check_list(session.FileList, "testdir\\d.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", TRUE), "list entry wrong\n"); - } + ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n"); /* try extract files operation once file list is filled */ session.Operation = EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -426,18 +422,16 @@ static void test_Extract(void) ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); ok(RemoveDirectoryA("dest\\testdir"), "Expected dest\\testdir to exist\n"); ok(RemoveDirectoryA("dest"), "Expected dest to exist\n"); - ok(check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); /* Extract does not extract files if the dest dir does not exist */ res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -452,10 +446,10 @@ static void test_Extract(void) ok(!session.FilterList, "Expected empty filter list\n"); ok(!DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); - ok(check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); /* remove two of the files in the list */ session.FileList->next = session.FileList->next->next; @@ -463,11 +457,9 @@ static void test_Extract(void) session.FilterList = NULL; CreateDirectoryA("dest", NULL); res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -480,26 +472,24 @@ static void test_Extract(void) "Expected dest\\testdir\\d.txt, got %s\n", session.CurrentFile); ok(!*session.Reserved, "Expected empty string, got %s\n", session.Reserved); ok(!session.FilterList, "Expected empty filter list\n"); - ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); - ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); - ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); - ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); - - todo_wine { - ok(check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry wrong\n"); - ok(!check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", FALSE), "list entry wrong\n"); - ok(!check_list(session.FileList, "a.txt", FALSE), "list entry wrong\n"); + todo_wine + { + ok(DeleteFileA("dest\\a.txt"), "Expected dest\\a.txt to exist\n"); + ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); + ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); + ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); } + ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); + ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n"); session.Operation = EXTRACT_FILLFILELIST; session.FileList = NULL; res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -516,21 +506,16 @@ static void test_Extract(void) ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); - - todo_wine { - ok(check_list(session.FileList, "testdir\\d.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", TRUE), "list entry wrong\n"); - } + ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n"); + ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(!check_list(&node, "a.txt", FALSE), "list entry wrong\n"); session.Operation = 0; res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -546,22 +531,17 @@ static void test_Extract(void) ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); - - todo_wine { - ok(check_list(session.FileList, "testdir\\d.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", TRUE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", TRUE), "list entry wrong\n"); - } + ok(check_list(&node, "testdir\\d.txt", TRUE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", TRUE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", TRUE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n"); session.Operation = 0; session.FilterList = session.FileList; res = pExtract(&session, "extract.cab"); + node = session.FileList; ok(res == S_OK, "Expected S_OK, got %d\n", res); - todo_wine - { - ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); - } + ok(session.FileSize == 40, "Expected 40, got %d\n", session.FileSize); ok(session.Error.erfOper == FDIERROR_NONE, "Expected FDIERROR_NONE, got %d\n", session.Error.erfOper); ok(session.Error.erfType == 0, "Expected 0, got %d\n", session.Error.erfType); @@ -576,21 +556,22 @@ static void test_Extract(void) ok(DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to exist\n"); ok(DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to exist\n"); ok(DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to exist\n"); - - ok(check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "b.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FilterList, "testdir\\d.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FilterList, "testdir\\c.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FilterList, "b.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FilterList, "a.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); + node = session.FilterList; + ok(check_list(&node, "testdir\\d.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", FALSE), "list entry wrong\n"); /* cabinet does not exist */ ZeroMemory(&session, sizeof(SESSION)); lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "nonexistent.cab"); + node = session.FileList; todo_wine { ok(res == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), @@ -612,10 +593,10 @@ static void test_Extract(void) ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); - ok(!check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry should not exist\n"); - ok(!check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry should not exist\n"); - ok(!check_list(session.FileList, "b.txt", FALSE), "list entry should not exist\n"); - ok(!check_list(session.FileList, "a.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n"); /* first file exists */ createTestFile("dest\\a.txt"); @@ -624,6 +605,7 @@ static void test_Extract(void) lstrcpyA(session.Destination, "dest"); session.Operation = EXTRACT_FILLFILELIST | EXTRACT_EXTRACTFILES; res = pExtract(&session, "extract.cab"); + node = session.FileList; todo_wine { ok(res == HRESULT_FROM_WIN32(ERROR_ACCESS_DENIED), @@ -648,11 +630,11 @@ static void test_Extract(void) ok(!DeleteFileA("dest\\b.txt"), "Expected dest\\b.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\c.txt"), "Expected dest\\testdir\\c.txt to not exist\n"); ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); - ok(!check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry should not exist\n"); - ok(!check_list(session.FileList, "testdir\\c.txt", FALSE), "list entry should not exist\n"); - ok(!check_list(session.FileList, "b.txt", FALSE), "list entry should not exist\n"); - ok(!check_list(session.FileList, "a.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "b.txt", FALSE), "list entry should not exist\n"); } + ok(!check_list(&node, "a.txt", FALSE), "list entry should not exist\n"); SetFileAttributesA("dest\\a.txt", FILE_ATTRIBUTE_NORMAL); DeleteFileA("dest\\a.txt"); @@ -688,11 +670,11 @@ static void test_Extract(void) todo_wine { ok(!DeleteFileA("dest\\testdir\\d.txt"), "Expected dest\\testdir\\d.txt to not exist\n"); - ok(!check_list(session.FileList, "testdir\\d.txt", FALSE), "list entry should not exist\n"); - ok(check_list(session.FileList, "testdir\\c.txt", TRUE), "list entry wrong\n"); } - ok(check_list(session.FileList, "b.txt", FALSE), "list entry wrong\n"); - ok(check_list(session.FileList, "a.txt", FALSE), "list entry wrong\n"); + ok(!check_list(&node, "testdir\\d.txt", FALSE), "list entry should not exist\n"); + ok(!check_list(&node, "testdir\\c.txt", FALSE), "list entry wrong\n"); + ok(!check_list(&node, "b.txt", FALSE), "list entry wrong\n"); + ok(check_list(&node, "a.txt", TRUE), "list entry wrong\n"); SetFileAttributesA("dest\\testdir\\c.txt", FILE_ATTRIBUTE_NORMAL); DeleteFileA("dest\\testdir\\c.txt"); -- 2.11.4.GIT