In many applications we would like to have same functionalities of C++ vectors with all their rich set of methods to handle dynamic arrays of data structures or pointers.
It would be very nice to have possibility to add, remove and insert items at random positions, expand and squeeze your array as needed ::)
If you don't want to spend time to write your personal library for that you can use the DPA (Dynamic Pointers Array) and DSA (Dynamic Structure Array) already coded and, presumably >:(, tested for you in the ComCtl32.dll library.
Below an example of the possibilities:
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
HDSA hDsa = DSA_Create(sizeof(char[32]), 2);
printf("------ Writing the array ------\n");
for (int i=0; i<20; i++)
{
char str[32];
sprintf(str, "Test%2d", i+1);
printf (" - Appending string \"%s\".\n", str);
//DSA_GetSize present in COMCTL32.DLL V.6.00.00
//printf (" - Appending string \"%s\". Actual array size = %llu\n", str, DSA_GetSize(hDsa));
DSA_AppendItem(hDsa, str);
}
printf("------ Reading the array ------\n");
int cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems; i++)
{
char str[32];
DSA_GetItem(hDsa, i, str);
printf (" - Read string \"%s\".\n", str);
}
printf("------ Invert the array ------\n");
//DSA_Sort(hDsa, fn_compare, 0); //DSA_Sort present in COMCTL32.DLL V.6.00.00
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems/2; i++)
{
char str[32];
memcpy(str, DSA_GetItemPtr(hDsa, i), sizeof(str));
memcpy(DSA_GetItemPtr(hDsa, i), DSA_GetItemPtr(hDsa, cItems - i - 1), sizeof(str));
memcpy(DSA_GetItemPtr(hDsa, cItems - i - 1), str, sizeof(str));
}
printf("------ Reading the array ------\n");
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems; i++)
{
char *str = DSA_GetItemPtr(hDsa, i);
printf (" - Read string \"%s\".\n", str);
}
printf("------ Invert again the array ------\n");
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems/2; i++)
{
char str[32];
memcpy(str, DSA_GetItemPtr(hDsa, i), sizeof(str));
memcpy(DSA_GetItemPtr(hDsa, i), DSA_GetItemPtr(hDsa, cItems - i - 1), sizeof(str));
memcpy(DSA_GetItemPtr(hDsa, cItems - i - 1), str, sizeof(str));
}
printf("------ Remove odd items from the array ------\n");
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems/2; i++)
DSA_DeleteItem(hDsa, i);
printf("------ Reading the array ------\n");
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems; i++)
{
char *str = DSA_GetItemPtr(hDsa, i);
printf (" - Read string \"%s\".\n", str);
}
printf("------ Add odd items after even items in the array ------\n");
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems*2; i+=2)
{
char str[32];
sprintf(str, "Test%2d", i+1);
printf (" - Adding string \"%s\".\n", str);
DSA_InsertItem(hDsa, i+1, str);
}
printf("------ Reading the array ------\n");
cItems = DSA_GetItemCount(hDsa);
for (int i=0; i<cItems; i++)
{
char *str = DSA_GetItemPtr(hDsa, i);
printf (" - Read string \"%s\".\n", str);
}
printf("------ Reading directly the array ------\n");
cItems = DSA_GetItemCount(hDsa);
char (*first)[32] = DSA_GetItemPtr(hDsa, 0);
for (int i=0; i<cItems; i++)
{
printf (" - Read string \"%s\".\n", first[i]);
}
printf("------ Destroy the array ------\n");
DSA_Destroy(hDsa);
return 0;
}
EDIT: I forget to say that the array can be accessed as a standard array using the pointer to the first element as array address. See last part of the example above updated with the feature.
Hi Frankie,
That's a nice one, thanks :)
I checked with Masm32 and found out that the declarations are all there, but we never used DSA_*, except for one post by Donkey (https://www.masmforum.com/board/index.php?msg=135185) 12 years ago. Astonishing 8)
Nice :)
This usually helps these examples
#define WIN32_LEAN_AND_MEAN
...
#pragma comment(lib, "comctl32.lib")
...
Hi Frankie,
Thanks. Here is my report of Windows 7 SP1 64-bit, the list of exported functions with the leading symbol DSA_ :
E:\PellesC\Bin>podump.exe /EXPORTS C:\Windows\System32\comctl32.dll | findstr "DSA_"
140 1E 000007FF75870770 DSA_Create
147 1F 000007FF75870B58 DSA_DeleteAllItems
146 20 000007FF75870AA0 DSA_DeleteItem
141 21 000007FF758707B8 DSA_Destroy
184 22 000007FF75870878 DSA_DestroyCallback
183 23 000007FF7587080C DSA_EnumCallback
142 24 000007FF7587089C DSA_GetItem
143 25 000007FF758708D8 DSA_GetItemPtr
144 26 000007FF758709C8 DSA_InsertItem
145 27 000007FF758708F4 DSA_SetItem
There should be some more, e.g. DSA_Sort (https://learn.microsoft.com/en-us/windows/win32/api/dpa_dsa/nf-dpa_dsa-dsa_sort)
DSA_AppendItem macro
DSA_Clone function
DSA_Create function
DSA_DeleteAllItems function
DSA_DeleteItem function
DSA_Destroy function
DSA_DestroyCallback function
DSA_EnumCallback function
DSA_GetItem function
DSA_GetItemCount macro
DSA_GetItemPtr function
DSA_GetSize function
DSA_InsertItem function
DSA_SetItem function
DSA_Sort function
COMCTL32 Functions (https://www.geoffchappell.com/studies/windows/shell/comctl32/api/index.htm)
QuoteDSA_Sort 6.10 and higher documented
In my Windows 7 it is 5.82.7601.18837
But in C:\Windows\winsxs 6.10.7601
so have to use manifest for that
perhaps:
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
MS documentation says:
QuoteDSA_GetItem is not exported by name. To use it, you must use GetProcAddress and request ordinal 322 from ComCtl32.dll to obtain a function pointer.
QuoteDSA_SetItem is not exported by name. To use it, you must use GetProcAddress and request ordinal 325 from ComCtl32.dll to obtain a function pointer.
QuoteDSA_DeleteItem is not exported by name. To use it, you must use GetProcAddress and request ordinal 326 from ComCtl32.dll to obtain a function pointer.
But in WIN10 all the three are available and exported by name.
The functions DSA_GetSize() and DSA_Sort() instead have been completely removed, they are no more available by name not by ordinal.
This means that in different OS versions there are different functions available.In the case as documented you can workaround changing only a the
DSA_Create() functions defining a new function
DSA_New() as in the following snippet:
#include <windows.h>
#define DSA_DeleteItem DSA_DeleteItem_org
#define DSA_GetItem DSA_GetItem_org
#define DSA_SetItem DSA_SetItem_org
#include <commctrl.h>
#undef DSA_DeleteItem
#undef DSA_GetItem
#undef DSA_SetItem
#include <stdio.h>
#define DSA_GETITEM_ORDINAL 322
#define DSA_SETITEM_ORDINAL 325
#define DSA_DELETEITEM_ORDINAL 326
extern BOOL WINAPI (*DSA_GetItem)(HDSA hdsa, int i, void *pitem) = NULL;
extern BOOL WINAPI (*DSA_SetItem)(HDSA hdsa, int i, const void *pitem) = NULL;
extern BOOL WINAPI (*DSA_DeleteItem)(HDSA hdsa, int i) = NULL;
HDSA DSA_New(int cbItem, int cItemGrow)
{
if (!DSA_GetItem)
{
/*
* Initialize function addresses for unexported functions
*/
DSA_GetItem = GetProcAddress(GetModuleHandle("ComCtl32.dll"), MAKEINTRESOURCE(DSA_GETITEM_ORDINAL));
DSA_SetItem = GetProcAddress(GetModuleHandle("ComCtl32.dll"), MAKEINTRESOURCE(DSA_SETITEM_ORDINAL));
DSA_DeleteItem = GetProcAddress(GetModuleHandle("ComCtl32.dll"), MAKEINTRESOURCE(DSA_DELETEITEM_ORDINAL));
}
/*
* Create the Dynamic structure array.
*/
return DSA_Create(cbItem, cItemGrow);
}
The missing functions DSA_GetSize() and DSA_Sort() are not a problem, the first have no practical use, the second could be easily implemented.
QuoteThe functions DSA_GetSize() and DSA_Sort() instead have been completely removed, they are no more available by name not by ordinal.
It seems not all of Microsoft have realised that change 8)
https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/UI/Controls/fn.DSA_Sort.html
QuoteFunction windows::Win32::UI::Controls::DSA_Sort
pub unsafe fn DSA_Sort<P0, P1>(
pdsa: P0,
pfncompare: PFNDACOMPARE,
lparam: P1
) -> BOOL
Are you sure it's no longer there?
DSA_Sort (https://learn.microsoft.com/en-us/windows/win32/api/dpa_dsa/nf-dpa_dsa-dsa_sort-r1)
Sorts the items in a dynamic structure array (DSA).
Minimum supported client Windows 10 Build 20348
Quote from: jj2007 on January 31, 2024, 10:49:50 AM
Are you sure it's no longer there?
DSA_Sort (https://learn.microsoft.com/en-us/windows/win32/api/dpa_dsa/nf-dpa_dsa-dsa_sort-r1)
Sorts the items in a dynamic structure array (DSA).
Minimum supported client Windows 10 Build 20348
In my win10 system are missing. See picture.
The function
DSA_GetSize() has ordinal
348, and the function
DSA_Sort() has ordinal
346, they are missing from DLL exports with name and ordinal.
I will test agains win10SDK libraries to see if the ordinal change.... :o not very likely anyway ::)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <commctrl.h>
#include <stdio.h>
#pragma comment(linker,"\"/manifestdependency:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
int __cdecl main(void)
{
char szFile[MAX_PATH];
HMODULE hMod = LoadLibrary("comctl32.dll");
GetModuleFileName(hMod, szFile, sizeof(szFile));
printf("%s\n", szFile);
FARPROC pFunc = GetProcAddress(hMod, MAKEINTRESOURCE(346));
printf("%ph\n", pFunc);
return 0;
}
C:\WINDOWS\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.3636_none_a863d714867441db\comctl32.dll
742dbe90h
C:\WINDOWS\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.19041.3636_none_60b6a03d71f818d5\comctl32.dll
00007ffe45ed7c40h
Thanks Timo, I just made the same test adding a manifest.
The functions exists indeed in ComCtl32.dll V6.00