extract contacts and distribution lists (groups) from wab (mapi) - c++

I'm looking a way to extract all contacts and distribution list (with related contacts) from a WAB (Windows Address Book).
I need to do this because I need to import address books, with distribution lists/groups, in roundcube.
After some research, I've founded a C++ project on Code Project ( http://www.codeproject.com/Articles/3407/Accessing-the-Windows-Address-Book ), but this support only contacts.
Looking around on MSDN I've founded that the OpenEntry method of iAddrBook should support in the third parameter the interface to open, iDistList in my case, but I can't find anywhere the interface id.
I searched some documentation abount WAB file structure, but nothing.
Any suggestions?

Here is a path I used to acomplish this:
I use WABOpen method from wab32 dll to get LPADRBOOK lpAddr;
I set PAB folder lpAddr: call lpAddr->GetPAB(), OpenEntry to get container, then GetContentsTable on container to get LPMAPITABLE lpTable.
To get table element count use GetRowCount on lpTable
To verify if given table row is a distribution list, use QueryRows, this should return MAPI_DISTLIST or MAPI_MAILUSER.
If this is a MAPI_DISTLIST row then use its PR_ENTRYID to call lpAdrBook->OpenEntry(), this should return IABContainer container on which you call GetContentsTable to get table with contents of this distribution list.
the last OpenEntry looks as follows, I do not set third parameter anywhere:
// Now emails will be loaded.
ULONG ulObjType;
IUnknown* lpUnk;
hr = lpAdrBook->OpenEntry(DistEntryId.size, (LPENTRYID)DistEntryId.ab, NULL, 0, &ulObjType, &lpUnk );
if (FAILED(hr)) {
assert(false); return hr;
}

Related

How to call Win32_NetworkAdapterConfiguration::EnableDHCP() for a specific adapter in C++?

One of my tasks it to configure network adapters for DHCP/static IP, and the only way I found to do this is using Win32_NetworkAdapterConfiguration class.
WMI is new to me, and it seems to use it in C++ (Qt/MinGW) is not that easy, and most things I found in the WWW deal with .NET, PowerShell or VBScript. However, I already succeeded in querying information, for example the MAC address for a specific adapter.
I already read the MSDN: Calling a Provider method on MSDN, but in looking forware to WIn32_NetworkAdapterConfiguration there is one thing I don't unstand.
My IEnumWbemClassObject is the result of a SELECT * FROM Win32_NetworkAdapterConfiguration WHERE InterfaceIndex=n (n is a number, of course), and returns IWbemClassObject for the specific adapter.
How to I tell ExecMethod which instance of Win32_NetworkAdapterConiguration to use when calling the EnableDHCP()/EnableStatic() methods (in meaning of the IWbemClassObject I will recieve when i enumerate the result of my query)?
While looking for a example for passing string arrays to ExecMethod() if found this thread at CodeProject which execatly fit to my tasks. As stated in the comments above, the path of the object instance (not the class path!) must be passed to the "strObjectPath" parameter of ExecMethod.

Persistent and ephemeral nodes in ZooKeeper

I want to know how to create persistent nodes in ZooKeeper, using C++ client. I know from documentation, that there is a method zoo_acreate. And documentation says about this method that:
This method will create a node in ZooKeeper. A node can only be created if it does not already exists. The Create Flags affect the creation of nodes. If ZOO_EPHEMERAL flag is set, the node will automatically get removed if the client session goes away. If the ZOO_SEQUENCE flag is set, a unique monotonically increasing sequence number is appended to the path name.
But, unfortunatelly, almost as always with C++ libraries, this library completely lacks reasonable teeny-weeny examples demonstarting the usage of the library methods. As for example in this case where documentation page is about zoo_acreate method, but some terribly looking example is totally about something else (it does not even mention zoo_acreate method).
So, my question is how to set these flags ZOO_EPHEMERAL and ZOO_SEQUENCE. It would be great to see this in the context of some tiny examples. Thanks!
Googling for "zoo_acreate ZOO_EPHEMERAL" gave this as the seventh result:
string path = "/nodes/";
string value = "data";
int rc = zoo_acreate(zh, path.c_str(), value.c_str(), value.length(),
&ZOO_OPEN_ACL_UNSAFE, ZOO_EPHEMERAL | ZOO_SEQUENCE, &czoo_created, &where);
Source: https://issues.apache.org/jira/browse/ZOOKEEPER-348

C++/Qt: Get files in directory ordered according to sorting currently applied in Windows Explorer

I would like to know if there is a way in Qt to obtain the filenames of files in a folder ordered according to the current Windows Explorer Settings for this folder. In Windows Explorer the user can sort files by many different criteria (e.g. name, capture date etc.) and I would like to be able to maintain maintain that order in my application.
UPDATE:
Perfect would be a cross-platform solution which also works in Finder on Macintosh and in Nautilus on Ubuntu.
This answer suggests to use the IFolderView interface.
UPDATE:
Sorry, you might be looking for the IFolderView2 interface, especially the GetSortColumns method:
HRESULT GetSortColumns(
[out] const SORTCOLUMN *rgSortColumns,
[in] int cColumns
);
The returned SORTCOLUMN structure seems to have the information you need:
typedef struct SORTCOLUMN {
PROPERTYKEY propkey;
SORTDIRECTION direction;
} SORTCOLUMN;

OpenLDAP API Search

I'm attempting to do an LDAP search using the OpenLDAP API. I've already successfully connected and bound to the server. I've done the search with ldap_search_ext_s() and parsed the result with ldap_parse_result(). However, I can't seem to figure out how to get the actual results of the search. Unfortunately, the OpenLDAP C API has changed recently and many of the existing examples on the Internet do not use the current API.
I've already attempted to use ldap_first_attribute(), ldap_next_attribute(), and ldap_get_values() as shown on http://www-archive.mozilla.org/directory/csdk-docs/search.htm (Example 6-13). However, it appears that ldap_get_values() is now deprecated and that ldap_get_values_len() is the closest replacement. Instead of returning a char**, the new function returns a berval**. I've attempted to tweak this example code by creating a berval* with the value of barval**[i]. This results in a successful compile, but a core dump at ber_scanf().
Does anyone know how to get the results of an LDAP search with the OpenLDAP C API?
UPDATE:
In particular, I'm asking how to get the attributes requested from the search message.
The result of a search request always contains a series of SearchResultEntry or SeachResultReference messages, this series terminated by a SearchResultDone message. Calling getNextAttribute (in any language and in any API) makes no sense whatever because the search results are a list of messages. An API should package the array of entries or references in such a way wherein the caller can simply retrieve the list of entries or references. Look for a method that does that.
After taking a look at the OpenLDAP API source code and seeing how the berval value was used, I eventually stumbled upon how to get it's value.
First, you have to get the first entry with ldap_first_entry(). Then, you need to get the first attribute in that entry with ldap_first_attribute(). Then, put the values in a berval** array with ldap_get_values_len(). The returned attribute values can then be access with berval[i]->bv_val.
You can get the next entries and attributes with ldap_next_entry() and ldap_next_attribute(), respectively.
I hope this helps anyone who has a similar issue.
hope the bellow function may help you,
int ldap_search_result(LDAP *ld, char *search_filter, char *search_base)
{
LDAPMessage *result;
BerElement *ber;
char *attr;
char **val;
if(ldap_search_ext_s(ld, search_base, LDAP_SCOPE_CHILDREN,
search_filter, NULL, 0, NULL, NULL, NULL, -1, &result) != LDAP_SUCCESS) {
return -1;
}
if(ldap_count_entries(ld,result) != 1) { // assuming search_filter is unique,
// matches only one entry, and so
// search routine returns only one entry
return -1;
}
if((attr = ldap_first_attribute(ldp, result, &ber)) == NULL) {
return -1;
}
do {
if((val = ldap_get_values(ldp,result,attr)) == NULL) {
return -1;
}
printf(" %s : %s \n", attr, val[0]); // assuming all attributes are single -
//valued.
ldap_memfree(attr);
ldap_value_free(val);
while((attr = ldap_next_attribute(ld,result,ber)) != NULL);
return 0;
}

Use a MSHFlexGrid with non-database data and still define the shape

I am trying to use the Microsoft Hierarchical FlexGrid (MSHFlexGrid) in a Visual C++ (VS 2005). I have the grid shown, and I can manually add data to the individual cells. However, according to online documentation I've read, I should be able to show the hierarchical nature of the data (hence MSHFlexGrid instead of MSFlexGrid) by defining the SHAPE as the RecordSource. I can do that fine (by using the put_RecordSource method of the grid object), however I'm at a loss as to how to add the actual data.
I've read that the best way to do this is to use an ADO Data Control (ie ADODC) component and bind it as the DataSource for the Grid. You can then specify "provider=msdatashape;data provider=none;" as the provider of the DataControl and fill it with data. If I were doing SQL, I'd specify my SELECT query as the RecordSource, then call Refresh() and let the control load the data.
However, my data is in custom objects. I know what needs to be displayed, I'm just at a loss as to the best way to insert the data into the FlexGrid and still use the built in features of the control. I'm open to any suggestions, but I need to keep the data local (ie no JET, Access, etc).
Here's some code:
In header:
....
// Variable to control the Flex Grid component
CMshflexgrid1 m_grid; //generated by wizard from the MSHFlexGrid component
// to control the data source hierarchical information
CAdodc1 m_adodc1;
....
In cpp:
....
BOOL MyDialogClass::OnInitDialog()
{
CDialog::OnInitDialog();
m_grid.Clear();
CString strCn = "provider=msdatashape;data provider=none;";
m_adodc1.put_ConnectionString(strCn);
CString BackupOfRecordSource = "";
BackupOfRecordSource = m_adodc1.get_RecordSource();
//CString strShape = "SHAPE APPEND new adInteger As PID, New adVarChar(10) As StudentName, ((SHAPE APPEND new adInteger As ChID, New adVarChar(10) As Course, ((SHAPE APPEND new adInteger As GrndChID, New adBSTR As Description) RELATE ChID TO GrndChID) As GrandChild) RELATE PID TO ChID) AS Child";
CString strShape = "SHAPE APPEND new adInteger As PID, New adVarChar(10) As StudentName";
m_adodc1.put_RecordSource(strShape);
m_adodc1.Refresh();
m_grid.Refresh();
BackupOfRecordSource = m_adodc1.get_RecordSource(); //returns the strShape that I just put in
//ADD RECORDS HERE! HOW?
return TRUE;
}
The sample talked about building an ADODB.Recordset and use it as the data source of ADODC. The code you give is building a SQL and use it as the data source of ADODC. I don't think you can replace an ADODB.Recordset with a string.