DLL Skeleton
A minimal C DLL with a set of exported system and string functions, plus a console test driver that calls every export.
This is the classic shape of a Win32 C DLL project: one source file full of __declspec(dllexport) functions, built into an import library, and a small console app that links against it to prove each export works. It makes a good skeleton when you are starting your own DLL - note how each function that returns a string uses a static buffer ring (64 slots) so repeated calls from multiple callers do not clobber each other's results.
The export list below covers the usual suspects: time and date formatting, machine/user names, OS version detection, directory paths, case conversion, number-to-string and string-to-number, substring extraction, uptime, memory statistics, and CPU information via GetSystemInfo.
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetTime(void)
{
static SYSTEMTIME st;
static char t [257];
GetLocalTime(&st);
GetTimeFormat(LOCALE_USER_DEFAULT,TIME_NOSECONDS,&st,NULL,t,64);
return (t);
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetLongDate(void)
{
static SYSTEMTIME st;
static char d [257];
GetLocalTime(&st);
GetDateFormat(LOCALE_USER_DEFAULT,DATE_LONGDATE,&st,NULL,d,64);
return (d);
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetShortDate(void)
{
static SYSTEMTIME st;
static char s [257];
GetLocalTime(&st);
GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,&st,NULL,s,64);
return (s);
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetMachineName(void)
{
static char StrFunction [64][257];
static int StrCnt;
static char A[257];
static DWORD b;
if (++StrCnt==64) StrCnt = 0;
b=256;
GetComputerName(A,&b);
sprintf(StrFunction[StrCnt],"%s",A);
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetLogonName(void)
{
static char StrFunction [64][257];
static int StrCnt;
static char A[257];
static DWORD b;
if (++StrCnt==64) StrCnt = 0;
b=256;
GetUserName(A,&b);
sprintf(StrFunction[StrCnt],"%s",A);
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetOsVersion(void)
{
DWORD dwVersion;
char szBuf[80];
char *WinVer_Number;
static OSVERSIONINFO os;
os.dwOSVersionInfoSize=sizeof(os);
dwVersion = GetVersion();
WinVer_Number = calloc(100, sizeof(char));
if(GetVersionEx(&os))
{
for(;;)
{
if(os.dwPlatformId==1)
{
if(os.dwMinorVersion==0)
{
sprintf(szBuf, "Windows 95 %d.%d",LOBYTE(LOWORD(dwVersion)),HIBYTE(LOWORD(dwVersion)));
strcat(WinVer_Number, szBuf);
}
if(os.dwMinorVersion==10)
{
sprintf(szBuf, "Windows 98 %d.%d",LOBYTE(LOWORD(dwVersion)),HIBYTE(LOWORD(dwVersion)));
strcat(WinVer_Number, szBuf);
}
break;
}
if(os.dwPlatformId==2)
{
if(os.dwMajorVersion==3)
{
sprintf(szBuf, "Windows NT %d.%d",LOBYTE(LOWORD(dwVersion)),HIBYTE(LOWORD(dwVersion)));
strcat(WinVer_Number, szBuf);
}
if(os.dwMajorVersion==4)
{
sprintf(szBuf, "Windows NT %d.%d",LOBYTE(LOWORD(dwVersion)),HIBYTE(LOWORD(dwVersion)));
strcat(WinVer_Number, szBuf);
}
if(os.dwMajorVersion==5)
{
sprintf(szBuf, "Windows 2000 %d.%d",LOBYTE(LOWORD(dwVersion)),HIBYTE(LOWORD(dwVersion)));
strcat(WinVer_Number, szBuf);
}
}
break;
}
}
return WinVer_Number;
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetWorkingDirectory(void)
{
static char StrFunction [64][257];
static int StrCnt;
static char T [257];
GetCurrentDirectory(256,T);
if (++StrCnt==64) StrCnt = 0;
sprintf(StrFunction[StrCnt],"%s",T);
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetTempDirectory(void)
{
static char StrFunction [64][257];
static int StrCnt;
static char T [257];
GetTempPath (256,T);
if (++StrCnt==64) StrCnt = 0;
sprintf(StrFunction[StrCnt],"%s",T);
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetSysDirectory(void)
{
static char StrFunction [64][257];
static int StrCnt;
static char T [257];
GetSystemDirectory (T,256);
if (++StrCnt==64) StrCnt = 0;
sprintf(StrFunction[StrCnt],"%s",T);
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *UCase (char *S)
{
static char StrFunction [64][257];
static int StrCnt;
static char Tmp [257];
if(++StrCnt==64) StrCnt = 0;
sprintf(Tmp,"%s",S);
{
sprintf (StrFunction[StrCnt],"%s",strupr(Tmp));
}
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *LCase(char *S)
{
static char StrFunction [64][257];
static int StrCnt;
static char Tmp [257];
if(++StrCnt==64) StrCnt = 0;
sprintf(Tmp,"%s",S);
{
sprintf (StrFunction[StrCnt],"%s",strlwr(Tmp));
}
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *IntChar(double d)
{
static int StrCnt;
LPSTR StrFunc [16];
if (++StrCnt==16) StrCnt = 0;
if (StrFunc[StrCnt]) free (StrFunc[StrCnt]);
StrFunc[StrCnt] = (char*) malloc (2048);
memset (StrFunc[StrCnt],0,2048);
sprintf(StrFunc[StrCnt],"% .16g",d);
return StrFunc[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) int CharInt(char *string2convert)
{
int i, lenght_string;
int power;
int tmp_number;
char tmp_char;
if (!string2convert)
{
return 0;
}
lenght_string = strlen(string2convert);
for(i = 0; i < (lenght_string / 2); i++)
{
tmp_char = string2convert[i];
string2convert[i] = string2convert[lenght_string - 1 - i];
string2convert[lenght_string - 1 - i] = tmp_char;
}
power = 1;
i = 0;
tmp_number = 0;
while (string2convert[i] != '\0')
{
tmp_number += (string2convert[i] - '0') * power;
power *= 10;
i++;
}
return tmp_number;
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *StringScan(char *S, int length1, int length2)
{
static char StrFunction [64][257];
static int StrCnt;
if(++StrCnt==64) StrCnt = 0;
strncpy (StrFunction[StrCnt], &S[length1], length2);
return StrFunction[StrCnt];
}
/////////////////////////////////////////////////////////////////////
__declspec(dllexport) char *GetUpTime(void)
{
long int Mins = 0;
long int Secs = 0;
long int Hous = 0;
long int Days = 0;
static char UpTimeReturn[256];
int Temp_Time = GetTickCount()/1000;
while(Temp_Time >= 60)
{
if(Temp_Time >= 60)
{
Mins++;
Temp_Time = Temp_Time-60;
}
}
while(Mins >= 60)
{
if(Mins >= 60)
{
Hous++;
Mins = Mins-60;
}
}
while(Hous >= 24)
{
if(Hous >= 24)
{
Days++;
Hous = Hous-24;
}
}
Secs = Temp_Time;
sprintf(UpTimeReturn,"%d Days, %d Hours, %d Minutes, %d Seconds",Days,Hous,Mins,Secs);
return (UpTimeReturn);
}
//////////////////////////////////////////////////////////////////////
__declspec(dllexport) long int TotalMemory(void)
{
static SYSTEM_INFO si;
static MEMORYSTATUS ms;
ms.dwLength=sizeof(&ms);
GlobalMemoryStatus(&ms);
GetSystemInfo(&si);
return ms.dwTotalPhys;
}
//////////////////////////////////////////////////////////////////////
__declspec(dllexport) long int UsedMemory(void)
{
static SYSTEM_INFO si;
static MEMORYSTATUS ms;
ms.dwLength=sizeof(&ms);
GlobalMemoryStatus(&ms);
GetSystemInfo(&si);
return ms.dwTotalPhys - ms.dmAvailPhys;
}
...and so on for FreeMemory, NumberOfProcessors, ProcessorType, ProcessorLevel, ProcessorRevision, ProcessorModel and ProcessorStepping - all thin wrappers over GlobalMemoryStatus and GetSystemInfo in the same style.
And the console test driver that links against the import library:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
extern char *GetTime(void);
extern char *GetLongDate(void);
extern char *GetShortDate(void);
extern char *GetMachineName(void);
extern char *GetLogonName(void);
extern char *GetOsVersion(void);
extern char *GetWorkingDirectory(void);
extern char *GetTempDirectory(void);
extern char *GetSysDirectory(void);
extern char *UCase (char *);
extern char *LCase(char *);
extern char *IntChar(double);
extern char *GetUpTime(void);
extern char *StringScan(char *, int , int);
extern int CharInt(char *);
extern long int TotalMemory(void);
extern long int UsedMemory(void);
extern long int FreeMemory(void);
extern int NumberOfProcessors(void);
extern int ProcessorType(void);
extern int ProcessorLevel(void);
extern int ProcessorRevision(void);
extern int ProcessorModel(void);
extern int ProcessorStepping(void);
int main()
{
printf("GetTime %s\n",GetTime());
printf("GetLongDate %s\n",GetLongDate());
printf("GetShortDate %s\n",GetShortDate());
printf("GetMachineName %s\n",GetMachineName());
printf("GetLogonName %s\n",GetLogonName());
printf("GetOsVersion %s\n",GetOsVersion());
printf("GetWorkingDirectory %s\n",GetWorkingDirectory());
printf("GetTempDirectory %s\n",GetTempDirectory());
printf("GetSysDirectory %s\n",GetSysDirectory());
printf("UCase %s\n",UCase("my string"));
printf("LCase %s\n",LCase("MY OTHER STRING"));
printf("IntChar %s\n",IntChar(123456));
printf("CharInt %d\n",CharInt("123456"));
printf("StringScan %s\n",StringScan("Hello Cruel World",6,5));
printf("TotalMemory %d\n",TotalMemory());
printf("UsedMemory %d\n",UsedMemory());
printf("FreeMemory %d\n",FreeMemory());
printf("NumberOfProcessors %d\n",NumberOfProcessors());
printf("ProcessorType %d\n",ProcessorType());
printf("ProcessorLevel %d\n",ProcessorLevel());
printf("ProcessorRevision %d\n",ProcessorRevision());
printf("ProcessorModel %d\n",ProcessorModel());
printf("ProcessorStepping %d\n",ProcessorStepping());
return 0;
}