I’m examining the source code (written in C) of bkhive — a utility for dumping the SysKey bootkey from a Windows NT/2K/XP system hive — and would like to know if there is any rationale for something the original author did: passing a pointer to a struct into a function and then returning the same pointer. Here is the relevant source code:
In main() there is a call that looks like this:
struct hive h;
char *root_key;
// Do some stuff to init
_RegGetRootKey(&h, &root_key)
Which calls:
int _RegGetRootKey(struct hive *h, char **root_key)
{
nk_hdr *n;
n = (nk_hdr*) malloc(sizeof(nk_hdr));
/* ************************************************
* RELEVANT FUNCTION CALL
* Why pass n as a parameter and use return value?
* ************************************************/
n = read_nk(n, h, 0x1020);
if (n->id == NK_ID && n->type == NK_ROOT)
{
*root_key = (char *) malloc(n->name_len + 1);
strncpy(*root_key, n->key_name, n->name_len);
(*root_key)[n->name_len] = 0;
free(n);
return 0;
}
free(n);
return -1;
}
Which calls:
nk_hdr* read_nk(nk_hdr *nk, struct hive *h, int offset)
{
memcpy(nk, h->base + offset + 4, sizeof(nk_hdr));
nk->key_name = (h->base + offset + 4 + 76);
return nk;
}
So, what is the purpose of passing the struct pointer and then returning it? Couldn’t the function return nothing and use n after the function call?
The main benefit of this convention is to allow for simpler concatenation of function calls. If you want to use the return of one function as a parameter to another function, having it return the pointer can enable you to write the statement in a single line. Thus, instead of writing something like this:
You can do this:
The specific code you show doesn’t use this, but this is a convention used in many C functions, and I guess the author of the code is used to this by now.