#include <iostream>
using namespace std;
typedef unsigned char u_char;
typedef char CCHAR;
typedef int16_t WCHAR;
typedef uint32_t ULONG;
typedef uint32_t DWORD;
typedef uint64_t LARGE_INTEGER;
#pragma pack(1)
typedef struct smb2_FileBothDirectoryInformation {
ULONG NextEntryOffset;
ULONG FileIndex;
LARGE_INTEGER CreationTime;
LARGE_INTEGER LastAccessTime;
LARGE_INTEGER LastWriteTime;
LARGE_INTEGER ChangeTime;
LARGE_INTEGER EndOfFile;
LARGE_INTEGER AllocationSize;
ULONG FileAttributes;
ULONG FileNameLength;
ULONG EaSize;
CCHAR ShortNameLength;
CCHAR Reserved;
WCHAR ShortName[12];
LARGE_INTEGER FileId; // Missing in [MS-FSCC]: File System Control Codes - 2.4.8 FileBothDirectoryInformation
u_char Reserved2[2]; // Missing in [MS-FSCC]: File System Control Codes - 2.4.8 FileBothDirectoryInformation
WCHAR FileName[1];
} smb2_FileBothDirectoryInformation_t;
typedef struct {
uint16_t StructureSize;
uint16_t OutputBufferOffset;
uint32_t OutputBufferLength;
u_char Buffer[1];
} smb2_query_directory_response_t;
#pragma pack()
//https://stackoverflow.com/questions/15934111/portable-and-safe-way-to-add-byte-offset-to-any-pointer
template <typename T> inline void addOffset(std::ptrdiff_t offset, T *&ptr) {
if (!ptr) return;
ptr = (T*)((const unsigned char*)ptr + offset);
}
template <typename T> inline T* offset(std::ptrdiff_t offset, T *ptr) {
return (T*)((const unsigned char*)ptr + offset);
}
//SomeType* ptr; int offset = 12345; offset_ptr(offset, ptr);
template <typename T> inline void offset_ptr(std::ptrdiff_t byte_offset, const T* &ref_ptr) {
ref_ptr = (T*)((const unsigned char*)ref_ptr + byte_offset);
}
//If you use this marco like `typedef struct {} SomeType; SomeType* ptr; OFFSET_PTR(16, ptr);`
//IDE error: expression must be a modifiable value. Compile: error C2106: '=': left operand must be l-value.
#define OFFSET_PTR(byte_offset, ref_ptr) ((const unsigned char*)ref_ptr = (const unsigned char*)ref_ptr + byte_offset)
char packet_bytes[9] = {0};
int main() {
printf("(int)sizeof(smb2_query_directory_response_t) = %d\n", (int)sizeof(smb2_query_directory_response_t));
printf("(int)sizeof(smb2_FileBothDirectoryInformation_t) = %d\n", (int)sizeof(smb2_FileBothDirectoryInformation_t));
const smb2_query_directory_response_t* pQueryDirInfoRsp = (smb2_query_directory_response_t*)packet_bytes;
const smb2_FileBothDirectoryInformation_t *pFileBothDirInfo = pQueryDirInfoRsp->OutputBufferLength ? reinterpret_cast<const smb2_FileBothDirectoryInformation_t*>(pQueryDirInfoRsp->Buffer) : NULL;
while (pFileBothDirInfo)
{
// ideone runs on linux with a compiler who consider wchar_t 4 bytes?
// https://stackoverflow.com/questions/16944750/c-unicode-characters-printing
//wprintf(L"%.*s|%.*s\n", pFileBothDirInfo->FileNameLength/2, pFileBothDirInfo->FileName, pFileBothDirInfo->ShortNameLength/2, pFileBothDirInfo->ShortName);
if (pFileBothDirInfo->NextEntryOffset)
{
offset_ptr(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
const unsigned char *ptrTemp;
ptrTemp = ((const unsigned char*)pFileBothDirInfo + 10);
//be equivalent to
//((const unsigned char*)pFileBothDirInfo) = ( (const unsigned char*)pFileBothDirInfo + 10 );
OFFSET_PTR(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
printf("ptrTemp = %p", ptrTemp);
}
else
{
break;
}
}
return 0;
}