#pragma pack and struct offsets/sizes

Talk about things C/C++, some related to AutoHotkey
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

#pragma pack and struct offsets/sizes

Post by jeeswg » 12 Nov 2019, 16:41

- In general:
- The basic rules are the same for both 64-bit and 32-bit processes.
- An n-byte parameter must start at an n-byte offset.
- The overall size of the struct must be divisible by the size of the biggest parameter.

- However, I came across around 9-11 structs where this is not the case, they are marked '[CHECK]', in this link:
list of structs with parameters (sizes and types) - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=74&t=30497

- Here I came across #pragma as a possible explanation:
c - Structure padding and packing - Stack Overflow
https://stackoverflow.com/questions/4306186/structure-padding-and-packing

- Does MSDN indicate how structs are packed, can I retrieve this information programmatically via C++, by specifying a struct's name?

- Here is some test code:

Code: Select all

// ConsoleApplicationTestStructs.cpp : Defines the entry point for the console application.
//

//checking 11 structs marked '[CHECK]', listed here:
//list of structs with parameters (sizes and types) - AutoHotkey Community
//https://autohotkey.com/boards/viewtopic.php?f=74&t=30497
//would using '#pragma pack' give the expected item offsets/struct sizes

#include "stdafx.h"

#include <iostream>
#include "Windows.h"

#include "WinUser.h" //DLGTEMPLATE //(NMHDR)
#include "CommCtrl.h" //NMLVKEYDOWN
#include "Richedit.h" //GETTEXTEX
#include "commdlg.h" //(OPENFILENAMEA) //PRINTDLG
#include "shellapi.h" //SHFILEOPSTRUCT //SHQUERYRBINFO
#include "shtypes.h" //SHITEMID
#include "mmreg.h" //WAVEFORMAT //WAVEFORMATEX

//C:\Program Files (x86)\Windows Kits\8.1\Include\um\Richedit.h
//#pragma pack(4)
//#pragma pack()

//C:\Program Files (x86)\Windows Kits\8.1\Include\shared\mmreg.h
//#pragma pack(1)
//#pragma pack(1)
//#pragma pack(push, 1)
//#pragma pack(pop)  /* Assume byte packing throughout */

int _tmain(int argc, _TCHAR* argv[])
{
	//DLGTEMPLATE ;WinUser.h
	//GETTEXTEX ;Richedit.h
	//(NMHDR) ;WinUser.h
	//NMLVKEYDOWN ;CommCtrl.h
	//(OPENFILENAMEA) ;commdlg.h
	//PRINTDLG ;commdlg.h
	//SHFILEOPSTRUCT ;shellapi.h
	//SHITEMID ;shtypes.h
	//SHQUERYRBINFO ;shellapi.h
	//WAVEFORMAT ;mmreg.h
	//WAVEFORMATEX ;mmreg.h

	//std::cout << "abc" << std::endl;
	
	//std::cout << "MYSTRUCT=" << sizeof(MYSTRUCT) << std::endl;

	//==================================================

	//DLGTEMPLATE ;WinUser.h
	typedef struct {
		DWORD style;
		DWORD dwExtendedStyle;
		WORD  cdit;
		short x;
		short y;
		short cx;
		short cy;
	} MyDLGTEMPLATE;

#pragma pack(4)
	//GETTEXTEX ;Richedit.h
	typedef struct My_gettextex {
		DWORD  cb;
		DWORD  flags;
		UINT   codepage;
		LPCSTR lpDefaultChar;
		LPBOOL lpUsedDefChar;
	} MyGETTEXTEX;
#pragma pack()

	//(NMHDR) ;WinUser.h [MSDN: richedit.h (include Winuser.h)]
	typedef struct My_nmhdr {
		HWND hwndFrom;
		UINT idFrom;
		UINT code;
	} MyNMHDR;
	//(NMHDR) ;WinUser.h [MSDN: richedit.h (include Winuser.h)]
	typedef struct My2_nmhdr {
		HWND hwndFrom;
		UINT_PTR idFrom;
		UINT code;
	} My2NMHDR;

	//NMLVKEYDOWN ;CommCtrl.h
	typedef struct MytagLVKEYDOWN {
		NMHDR hdr;
		WORD  wVKey;
		UINT  flags;
	} MyNMLVKEYDOWN, *MyLPNMLVKEYDOWN;

	//(OPENFILENAMEA) ;commdlg.h
	typedef struct MytagOFNA {
		DWORD         lStructSize;
		HWND          hwndOwner;
		HINSTANCE     hInstance;
		LPCSTR        lpstrFilter;
		LPSTR         lpstrCustomFilter;
		DWORD         nMaxCustFilter;
		DWORD         nFilterIndex;
		LPSTR         lpstrFile;
		DWORD         nMaxFile;
		LPSTR         lpstrFileTitle;
		DWORD         nMaxFileTitle;
		LPCSTR        lpstrInitialDir;
		LPCSTR        lpstrTitle;
		DWORD         Flags;
		WORD          nFileOffset;
		WORD          nFileExtension;
		LPCSTR        lpstrDefExt;
		LPARAM        lCustData;
		LPOFNHOOKPROC lpfnHook;
		LPCSTR        lpTemplateName;
		//LPEDITMENU    lpEditInfo; //not found, so using LPVOID instead (see line below)
		LPVOID        lpEditInfo;
		LPCSTR        lpstrPrompt;
		void          *pvReserved;
		DWORD         dwReserved;
		DWORD         FlagsEx;
	} MyOPENFILENAMEA, *MyLPOPENFILENAMEA;

	//PRINTDLG ;commdlg.h
	typedef struct MytagPDA {
		DWORD           lStructSize;
		HWND            hwndOwner;
		HGLOBAL         hDevMode;
		HGLOBAL         hDevNames;
		HDC             hDC;
		DWORD           Flags;
		WORD            nFromPage;
		WORD            nToPage;
		WORD            nMinPage;
		WORD            nMaxPage;
		WORD            nCopies;
		HINSTANCE       hInstance;
		LPARAM          lCustData;
		LPPRINTHOOKPROC lpfnPrintHook;
		LPSETUPHOOKPROC lpfnSetupHook;
		LPCSTR          lpPrintTemplateName;
		LPCSTR          lpSetupTemplateName;
		HGLOBAL         hPrintTemplate;
		HGLOBAL         hSetupTemplate;
	} MyPRINTDLGA, *MyLPPRINTDLGA;
	typedef MyPRINTDLGA MyPRINTDLG;

	//SHFILEOPSTRUCT ;shellapi.h
	typedef struct My_SHFILEOPSTRUCTA {
		HWND         hwnd;
		UINT         wFunc;
		PCZZSTR      pFrom;
		PCZZSTR      pTo;
		FILEOP_FLAGS fFlags;
		BOOL         fAnyOperationsAborted;
		LPVOID       hNameMappings;
		PCSTR        lpszProgressTitle;
	} MySHFILEOPSTRUCTA, *MyLPSHFILEOPSTRUCTA;
	typedef MySHFILEOPSTRUCTA MySHFILEOPSTRUCT;
	//typedef OLDNAME NEWNAME;

	//SHITEMID ;shtypes.h
	typedef struct My_SHITEMID {
		USHORT cb;
		BYTE   abID[1];
	} MySHITEMID;

	//SHQUERYRBINFO ;shellapi.h
	//source: shellapi.h
	typedef struct My_SHQUERYRBINFO {
		DWORD   cbSize;
	#if !defined(_MAC) || defined(_MAC_INT_64)
		__int64 i64Size;
		__int64 i64NumItems;
	#else
		DWORDLONG i64Size;
		DWORDLONG i64NumItems;
	#endif
	} MySHQUERYRBINFO, *MyLPSHQUERYRBINFO;

#pragma pack(1)
	//WAVEFORMAT ;mmreg.h
	typedef struct Mywaveformat_tag {
		WORD  wFormatTag;
		WORD  nChannels;
		DWORD nSamplesPerSec;
		DWORD nAvgBytesPerSec;
		WORD  nBlockAlign;
	} MyWAVEFORMAT;

	//WAVEFORMATEX ;mmreg.h
	typedef struct {
		WORD  wFormatTag;
		WORD  nChannels;
		DWORD nSamplesPerSec;
		DWORD nAvgBytesPerSec;
		WORD  nBlockAlign;
		WORD  wBitsPerSample;
		WORD  cbSize;
	} MyWAVEFORMATEX;
#pragma pack()

	//==================================================

	std::cout << "DLGTEMPLATE=" << sizeof(DLGTEMPLATE) << std::endl;
	std::cout << "GETTEXTEX=" << sizeof(GETTEXTEX) << std::endl;
	std::cout << "NMHDR=" << sizeof(NMHDR) << std::endl;
	std::cout << "NMLVKEYDOWN=" << sizeof(NMLVKEYDOWN) << std::endl;
	std::cout << "OPENFILENAMEA=" << sizeof(OPENFILENAMEA) << std::endl;
	std::cout << "PRINTDLG=" << sizeof(PRINTDLG) << std::endl;
	std::cout << "SHFILEOPSTRUCT=" << sizeof(SHFILEOPSTRUCT) << std::endl;
	std::cout << "SHITEMID=" << sizeof(SHITEMID) << std::endl;
	std::cout << "SHQUERYRBINFO=" << sizeof(SHQUERYRBINFO) << std::endl;
	std::cout << "WAVEFORMAT=" << sizeof(WAVEFORMAT) << std::endl;
	std::cout << "WAVEFORMATEX=" << sizeof(WAVEFORMATEX) << std::endl;

	std::cout << "" << std::endl;

	std::cout << "MyDLGTEMPLATE=" << sizeof(MyDLGTEMPLATE) << std::endl;
	std::cout << "MyGETTEXTEX=" << sizeof(MyGETTEXTEX) << std::endl;
	std::cout << "MyNMHDR=" << sizeof(MyNMHDR) << std::endl;
	std::cout << "MyNMLVKEYDOWN=" << sizeof(MyNMLVKEYDOWN) << std::endl;
	std::cout << "MyOPENFILENAMEA=" << sizeof(MyOPENFILENAMEA) << std::endl;
	std::cout << "MyPRINTDLG=" << sizeof(MyPRINTDLG) << std::endl;
	std::cout << "MySHFILEOPSTRUCT=" << sizeof(MySHFILEOPSTRUCT) << std::endl;
	std::cout << "MySHITEMID=" << sizeof(MySHITEMID) << std::endl;
	std::cout << "MySHQUERYRBINFO=" << sizeof(MySHQUERYRBINFO) << std::endl;
	std::cout << "MyWAVEFORMAT=" << sizeof(MyWAVEFORMAT) << std::endl;
	std::cout << "MyWAVEFORMATEX=" << sizeof(MyWAVEFORMATEX) << std::endl;

	std::cout << "" << std::endl;

	std::cout << "My2NMHDR=" << sizeof(My2NMHDR) << std::endl;

	std::getchar();
	return 0;
}
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA

Return to “C/C++”