summary refs log tree commit diff stats
path: root/plugins/xtray/utility.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/xtray/utility.cpp')
-rw-r--r--plugins/xtray/utility.cpp563
1 files changed, 563 insertions, 0 deletions
diff --git a/plugins/xtray/utility.cpp b/plugins/xtray/utility.cpp
new file mode 100644
index 00000000..60f3f2f0
--- /dev/null
+++ b/plugins/xtray/utility.cpp
@@ -0,0 +1,563 @@
+/* X-Tray

+ * Copyright (C) 2005 Michael Hotaling <Mike.Hotaling@SinisterDevelopments.com>

+ *

+ * X-Tray is free software; you can redistribute it and/or modify

+ * it under the terms of the GNU General Public License as published by

+ * the Free Software Foundation; either version 2 of the License, or

+ * (at your option) any later version.

+ * 

+ * X-Tray is distributed in the hope that it will be useful,

+ * but WITHOUT ANY WARRANTY; without even the implied warranty of

+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the

+ * GNU General Public License for more details.

+ * 

+ * You should have received a copy of the GNU General Public License

+ * along with X-Tray; if not, write to the Free Software

+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

+ */

+

+#include <windows.h>

+#include <stdio.h>

+#include <commctrl.h>

+#include <tchar.h>

+#include "utility.h"

+#include "plugin.h"

+#include "xtray.h"

+#include "callbacks.h"

+#include "resource.h"

+

+TCHAR BACKUP_INI_FILE[] = _T(".\\plugins\\config\\xtray.conf");

+struct HOTKEY g_hHotKey;

+

+void SavePrefs(int iDlg)

+{

+	/**************************************************************************************************/

+	/********** allocate space for our string, and then set it to the currently logged on user ********/

+	/**************************************************************************************************/

+	DWORD dBuff = 257;

+	TCHAR szUser[257];

+

+	GetUserName(szUser, &dBuff);

+

+	/**************************************************************************************************/

+	/*********************** Test if the file exists, If it doesn't, Create It ************************/

+	/**************************************************************************************************/

+	TCHAR XTRAY_INI_FILE[1024];

+	

+#ifdef UNICODE

+	char temp[1024];

+    TCHAR TEMP_INI_FILE[1024];

+	

+	_snprintf(temp, 1024, "%s\\xtray.conf", xchat_get_info(ph, "xchatdir"));

+	ConvertString(temp, TEMP_INI_FILE, 1024);

+

+	// ok this one is really ugly

+	// it checks to see if the file exists in two locations

+	// X-Chat default config dir, if that fails it trys xchat\plugins\config

+	// if neither one exists it tries to create it in

+	// X-Chat default config dir, if that fails it trys xchat\plugins\config

+	// In either case it writes \xFF\xFE to the file ( on creation )

+	// so that we can save unicode away messages WritePrivateProfile doesn't 

+	// do this for us, though I think it really should

+

+	if(FileExists(TEMP_INI_FILE))

+	{

+		_tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE);

+	}

+	else

+	{

+		if(FileExists(BACKUP_INI_FILE))

+		{

+			_tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE);

+		}

+		else

+		{

+			HANDLE xTemp;

+			DWORD dwBytesTemp;

+

+			if(xTemp = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL))

+			{

+				if(GetLastError() != ERROR_ALREADY_EXISTS)

+				{

+					WriteFile(xTemp, _T("\xFF\xFE"), 4, &dwBytesTemp, NULL);

+				}

+				CloseHandle(xTemp);

+			}

+

+			if(FileExists(TEMP_INI_FILE))

+			{

+				_tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE);

+			}

+			else

+			{

+				HANDLE xBackup;

+				DWORD dwBytesBackup;

+

+				if(xBackup = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL))

+				{

+					if(GetLastError() != ERROR_ALREADY_EXISTS)

+					{

+						WriteFile(xBackup, _T("\xFF\xFE"), 4, &dwBytesBackup, NULL);

+					}

+

+					CloseHandle(xBackup);

+				}

+

+				if(FileExists(BACKUP_INI_FILE))

+				{

+					_tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE);

+				}

+			}

+		}

+	}

+

+#else

+	_tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE);

+#endif

+

+	WritePrivateProfileInt(szUser, _T("SETTINGS"),		g_dwPrefs,		XTRAY_INI_FILE);

+	WritePrivateProfileInt(szUser, _T("AOT"),			g_iTime,		XTRAY_INI_FILE);

+	WritePrivateProfileInt(szUser, _T("KEY"),			g_hHotKey.key,	XTRAY_INI_FILE);

+	WritePrivateProfileInt(szUser, _T("MOD"),			g_hHotKey.mod,	XTRAY_INI_FILE);

+	WritePrivateProfileString(szUser, _T("AWAY"),		g_szAway,		XTRAY_INI_FILE);

+}

+

+void LoadPrefs()

+{

+	/**************************************************************************************************/

+	/*********************** Our Settings Section *****************************************************/

+	/**************************************************************************************************/

+	DWORD dBuff = 257;

+	TCHAR szUser[257];

+

+	GetUserName(szUser, &dBuff);

+

+	/**************************************************************************************************/

+	/*********************** Test if the file exists, If it doesn't, Create It ************************/

+	/**************************************************************************************************/

+	TCHAR XTRAY_INI_FILE[1024];

+

+#ifdef UNICODE

+	char temp[1024];

+	TCHAR TEMP_INI_FILE[1024];

+

+	_snprintf(temp, 1024, "%s\\xtray.conf", xchat_get_info(ph, "xchatdir"));

+	ConvertString(temp, TEMP_INI_FILE, 1024);

+

+	if(FileExists(TEMP_INI_FILE))

+	{

+		_tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE);

+	}

+	else

+	{

+		if(FileExists(BACKUP_INI_FILE))

+		{

+			_tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE);

+		}

+		else

+		{

+			HANDLE xTemp;

+			DWORD dwBytesTemp;

+

+			if(xTemp = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL))

+			{

+				if(GetLastError() != ERROR_ALREADY_EXISTS)

+				{

+					WriteFile(xTemp, _T("\xFF\xFE"), 4, &dwBytesTemp, NULL);

+				}

+

+				CloseHandle(xTemp);

+			}

+

+			if(FileExists(TEMP_INI_FILE))

+			{

+				_tcscpy(XTRAY_INI_FILE, TEMP_INI_FILE);

+			}

+			else

+			{

+				HANDLE xBackup;

+				DWORD dwBytesBackup;

+

+				if(xBackup = CreateFile(TEMP_INI_FILE, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL))

+				{

+					if(GetLastError() != ERROR_ALREADY_EXISTS)

+					{

+						WriteFile(xBackup, _T("\xFF\xFE"), 4, &dwBytesBackup, NULL);

+					}

+

+					CloseHandle(xBackup);

+				}

+

+				if(FileExists(BACKUP_INI_FILE))

+				{

+					_tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE);

+				}

+			}

+		}

+	}

+

+#else

+	_tcscpy(XTRAY_INI_FILE, BACKUP_INI_FILE);

+#endif

+

+	/**************************************************************************************************/

+	/*************************** Get the value for each of our preferances ****************************/

+	/**************************************************************************************************/

+	g_dwPrefs = GetPrivateProfileInt(szUser, _T("SETTINGS"),	0,  XTRAY_INI_FILE);

+

+	// backwards compatability

+	// also allows us to set defaults if its a new installation

+	// disable topic change, channel message and server notice by default

+	if(g_dwPrefs == 0)

+	{

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("HILIGHT"),		1,  XTRAY_INI_FILE)<<1);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("INVITE"),		1,  XTRAY_INI_FILE)<<2);

+		/* g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("TOPIC"),		1,  XTRAY_INI_FILE)<<3); */

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("BANNED"),		1,  XTRAY_INI_FILE)<<4);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("KICKED"),		1,  XTRAY_INI_FILE)<<5);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("CTCP"),		1,  XTRAY_INI_FILE)<<6);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("PMSG"),		1,  XTRAY_INI_FILE)<<7);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("KILLED"),		1,  XTRAY_INI_FILE)<<8);

+		/* g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("NOTICE"),		1,  XTRAY_INI_FILE)<<9); */

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("DISCONNECT"),	1,  XTRAY_INI_FILE)<<10);

+

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("AOM"),			0,  XTRAY_INI_FILE)<<11);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("TOT"),			1,  XTRAY_INI_FILE)<<12);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("AMAE"),		1,  XTRAY_INI_FILE)<<13);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("OSBWM"),		0,  XTRAY_INI_FILE)<<14);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("UWIOB"),		0,  XTRAY_INI_FILE)<<15);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("KAOI"),		0,  XTRAY_INI_FILE)<<16);

+		g_dwPrefs	|= (GetPrivateProfileInt(szUser, _T("MIOC"),		0,  XTRAY_INI_FILE)<<17);

+	}

+	

+	g_hHotKey.key	= GetPrivateProfileInt(szUser, _T("KEY"),	84, XTRAY_INI_FILE);

+	g_hHotKey.mod	= GetPrivateProfileInt(szUser, _T("MOD"),	(MOD_CONTROL | MOD_SHIFT),  XTRAY_INI_FILE);

+	g_iTime			= GetPrivateProfileInt(szUser, _T("AOT"),	5,  XTRAY_INI_FILE);

+

+	GetPrivateProfileString(szUser, _T("AWAY"), _T(""),	g_szAway, 1024, XTRAY_INI_FILE);

+	

+	/**************************************************************************************************/

+	/******************************** Register our hotkey with windows ********************************/

+	/**************************************************************************************************/

+	if(g_dwPrefs & (1<<PREF_UWIOB))

+	{

+		RegisterHotKey(g_hHotkeyWnd, 1, g_hHotKey.mod, g_hHotKey.key);

+	}

+}

+

+void CheckPrefs(HWND hwnd, int iDlg)

+{

+	/**************************************************************************************************/

+	/**************** save the preferances based on the checkmarks/options ****************************/

+	/**************************************************************************************************/

+	switch(iDlg)

+	{

+	case IDD_EVENTS:

+		{

+			SetOption(hwnd, CHAN_HILIGHT,		CHAN_HILIGHT);

+			SetOption(hwnd, CHAN_INVITE,		CHAN_INVITE);

+			SetOption(hwnd, CHAN_TOPIC_CHANGE,	CHAN_TOPIC_CHANGE);

+			SetOption(hwnd, CHAN_BANNED,		CHAN_BANNED);

+			SetOption(hwnd, CHAN_KICKED,		CHAN_KICKED);

+			SetOption(hwnd, CTCP_GENERIC,		CTCP_GENERIC);

+			SetOption(hwnd, PMSG_RECEIVE,		PMSG_RECEIVE);

+			SetOption(hwnd, SERV_KILLED,		SERV_KILLED);

+			SetOption(hwnd, SERV_NOTICE,		SERV_NOTICE);

+			SetOption(hwnd, SERV_DISCONNECT,	SERV_DISCONNECT);

+			SetOption(hwnd, CHAN_MESSAGE,		CHAN_MESSAGE);

+		}

+		break;

+	case IDD_ALERTS:

+		{

+			SetOption(hwnd, PREF_AMAE,	PREF_AMAE);

+			SetOption(hwnd, PREF_OSBWM,	PREF_OSBWM);

+			SetOption(hwnd, PREF_UWIOB,	PREF_UWIOB);

+			SetOption(hwnd, PREF_KAOI,	PREF_KAOI);

+			SetOption(hwnd, PREF_BLINK,	PREF_BLINK);

+

+			/**************************************************************************/

+			/**************************************************************************/

+			/**************************************************************************/

+			TCHAR tTime[512];

+

+			GetWindowText(GetDlgItem(hwnd, IDC_ALERT_TIME), tTime, 511);

+			

+			g_iTime = _tstoi(tTime);

+			

+			/**************************************************************************/

+			/**************** Get our Hotkey and save it                     **********/

+			/**************** then remove the old hotkey and add the new one **********/

+			/**************************************************************************/

+			DWORD hHotkey;

+			hHotkey = SendDlgItemMessage(hwnd, IDC_ALERT_HOTKEY, HKM_GETHOTKEY, 0, 0);

+			

+			g_hHotKey.key = LOBYTE(hHotkey);

+			g_hHotKey.mod = HIBYTE(hHotkey);

+			

+			if(IsDlgButtonChecked(hwnd, PREF_UWIOB) == BST_CHECKED)

+			{

+				UnregisterHotKey(g_hHotkeyWnd, 1);

+				RegisterHotKey(g_hHotkeyWnd, 1, g_hHotKey.mod, g_hHotKey.key);

+			}

+			else

+			{

+				UnregisterHotKey(g_hHotkeyWnd, 1);

+			}

+

+			/*************************************************************************/

+			/*********** Get and save the away msg and alert time ********************/

+			/*************************************************************************/

+		}

+		break;

+	case IDD_SETTINGS:

+		{

+			SetOption(hwnd, PREF_AOM, PREF_AOM);

+			SetOption(hwnd, PREF_TOT, PREF_TOT);

+			SetOption(hwnd, PREF_MIOC, PREF_MIOC);

+			SetOption(hwnd, PREF_DNSIT, PREF_DNSIT);

+

+			GetDlgItemText(hwnd, IDC_AWAY_MSG, g_szAway, 511);

+

+			if(g_dwPrefs & (1<<PREF_DNSIT))

+			{

+				DWORD dwStyle;

+				dwStyle = GetWindowLong(g_hXchatWnd, GWL_STYLE);

+				dwStyle |= (1<<WS_CHILD);

+				SetWindowLongPtr(g_hXchatWnd, GWL_STYLE, (LONG_PTR)dwStyle);

+				SetWindowLongPtr(g_hXchatWnd, GWL_HWNDPARENT, (LONG_PTR)g_hHotkeyWnd);

+			}

+			else

+			{

+				DWORD dwStyle;

+				dwStyle = GetWindowLong(g_hXchatWnd, GWL_STYLE);

+				dwStyle &= ~(1<<WS_CHILD);

+				SetWindowLongPtr(g_hXchatWnd, GWL_STYLE, (LONG_PTR)dwStyle);

+				SetWindowLongPtr(g_hXchatWnd, GWL_HWNDPARENT, NULL);

+			}

+		}

+		break;

+	} 

+}

+

+void SetDialog(HWND hwnd, int iDlg)

+{

+	switch(iDlg)

+	{

+	case IDD_EVENTS:

+		{

+			SetCheck(hwnd, CHAN_HILIGHT,		CHAN_HILIGHT);

+			SetCheck(hwnd, CHAN_INVITE,			CHAN_INVITE);

+			SetCheck(hwnd, CHAN_TOPIC_CHANGE,	CHAN_TOPIC_CHANGE);

+			SetCheck(hwnd, CHAN_BANNED,			CHAN_BANNED);

+			SetCheck(hwnd, CHAN_KICKED,			CHAN_KICKED);

+			SetCheck(hwnd, CTCP_GENERIC,		CTCP_GENERIC);

+			SetCheck(hwnd, PMSG_RECEIVE,		PMSG_RECEIVE);

+			SetCheck(hwnd, SERV_KILLED,			SERV_KILLED);

+			SetCheck(hwnd, SERV_NOTICE,			SERV_NOTICE);

+			SetCheck(hwnd, SERV_DISCONNECT,		SERV_DISCONNECT);

+			SetCheck(hwnd, CHAN_MESSAGE,		CHAN_MESSAGE);

+		}

+		break;

+	case IDD_SETTINGS:

+		{

+			SetCheck(hwnd, PREF_TOT,	PREF_TOT);

+			SetCheck(hwnd, PREF_MIOC,	PREF_MIOC);

+			SetCheck(hwnd, PREF_AOM,	PREF_AOM);

+			SetCheck(hwnd, PREF_DNSIT,	PREF_DNSIT);

+

+			SetDlgItemText(hwnd, IDC_AWAY_MSG, g_szAway);

+		}

+		break;

+	case IDD_ALERTS:

+		{

+			

+			SetCheck(hwnd, PREF_BLINK,	PREF_BLINK);

+			SetCheck(hwnd, PREF_OSBWM,	PREF_OSBWM);

+			SetCheck(hwnd, PREF_UWIOB,	PREF_UWIOB);

+			SetCheck(hwnd, PREF_KAOI,	PREF_KAOI);

+

+			/**********************************************************/

+			/**********************************************************/

+			/**********************************************************/

+			if(SetCheck(hwnd, PREF_AMAE, PREF_AMAE) == false)

+			{

+				SetToggle(hwnd, PREF_OSBWM,				PREF_AMAE, TRUE);

+				SetToggle(hwnd, PREF_UWIOB,				PREF_AMAE, TRUE);

+				SetToggle(hwnd, PREF_KAOI,				PREF_AMAE, TRUE);

+				SetToggle(hwnd, IDC_ALERT_TIME,			PREF_AMAE, TRUE);

+				SetToggle(hwnd, IDC_ALERT_TIME_TEXT,	PREF_AMAE, TRUE);

+				SetToggle(hwnd, IDC_ALERT_HOTKEY,		PREF_AMAE, TRUE);

+				SetToggle(hwnd, IDC_ALERT_HOTKEY_TEXT,	PREF_AMAE, TRUE);

+			}

+			else

+			{

+

+				SetToggle(hwnd, IDC_ALERT_HOTKEY,		PREF_UWIOB, TRUE);

+				SetToggle(hwnd, IDC_ALERT_HOTKEY_TEXT,	PREF_UWIOB, TRUE);

+				SetToggle(hwnd, IDC_ALERT_TIME,			PREF_KAOI, FALSE);

+				SetToggle(hwnd, IDC_ALERT_TIME_TEXT,	PREF_KAOI, FALSE);

+			}

+

+			/**********************************************************/

+			/**********************************************************/

+			/**********************************************************/

+			TCHAR tTime[255];

+			SendDlgItemMessage(hwnd, IDC_ALERT_TIME,	WM_SETTEXT, 0, (LPARAM)_itot(g_iTime, tTime, 10));

+			SendDlgItemMessage(hwnd, IDC_ALERT_HOTKEY,	HKM_SETHOTKEY, MAKEWORD(g_hHotKey.key, g_hHotKey.mod), 0);

+		}

+		break;

+	}

+}

+

+int SetCheck(HWND hDialog, unsigned int uiCheckBox, unsigned int uiPref)

+{

+	if((g_dwPrefs & (1<<uiPref)))

+	{

+		CheckDlgButton(hDialog, uiCheckBox, BST_CHECKED);

+		return 1;

+	}

+	else

+	{

+		CheckDlgButton(hDialog, uiCheckBox, BST_UNCHECKED);

+		return 0;

+	}

+

+	return 0;

+}

+

+int SetToggle(HWND hDialog, unsigned int uiCheckBox, unsigned int uiTestbox, bool offeqoff)

+{

+	/**************************************************************************************************/

+	/*********************** if(true) then if option is off turn toggle off ***************************/

+	/*********************** if(false) then if option is off turn toggle on ***************************/

+	/**************************************************************************************************/

+	if(offeqoff)

+	{

+		if(IsDlgButtonChecked(hDialog, uiTestbox) == BST_CHECKED)

+		{

+			EnableWindow(GetDlgItem(hDialog, uiCheckBox), TRUE);

+			return 1;

+		}

+		else

+		{

+			EnableWindow(GetDlgItem(hDialog, uiCheckBox), FALSE);

+			return 0;

+		}

+	}

+	else

+	{

+		if(IsDlgButtonChecked(hDialog, uiTestbox) == BST_CHECKED)

+		{

+			EnableWindow(GetDlgItem(hDialog, uiCheckBox), FALSE);

+			return 1;

+		}

+		else

+		{

+			EnableWindow(GetDlgItem(hDialog, uiCheckBox), TRUE);

+			return 0;

+		}

+	}

+

+	return 0;

+}

+

+int SetOption(HWND hDialog, unsigned int uiCheckBox, unsigned int uiPref)

+{

+	if(IsDlgButtonChecked(hDialog, uiCheckBox) == BST_CHECKED)

+	{

+		g_dwPrefs |= (1<<uiPref);

+	}

+	else

+	{

+		g_dwPrefs &= ~(1<<uiPref);

+	}

+

+	return (g_dwPrefs & (1<<uiPref));

+}

+

+int WritePrivateProfileIntA(char *szSection, char *szItem, int iData, char *szPath)

+{

+	char szData[33];

+	itoa(iData, szData, 10);

+	return WritePrivateProfileStringA(szSection, szItem, szData, szPath);

+}

+

+int WritePrivateProfileIntW(wchar_t *wszSection, wchar_t *wszItem, int iData, wchar_t *wszPath)

+{

+	wchar_t wszData[33];

+	_itow(iData, wszData, 10);

+	return WritePrivateProfileStringW(wszSection, wszItem, wszData, wszPath);

+}

+

+// For cleanup ( Closing windows and the such )

+void HoldClose()

+{

+	HANDLE hcThread;

+	DWORD dwThreadID;

+	hcThread = CreateThread(NULL, 0, HoldCloseThread, 0, 0, &dwThreadID);

+}

+

+DWORD WINAPI HoldCloseThread(LPVOID lpParam)

+{

+	Sleep(1000);

+	PostMessage(g_hXchatWnd, WM_CLOSE, 0, 0);

+	return 0;

+}

+

+bool FileExists(TCHAR *file)

+{

+	HANDLE hTemp = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

+	int nRet = GetLastError();

+	CloseHandle(hTemp);

+

+	if(nRet == 0)

+	{

+		return true;

+	}

+	else

+	{

+		return false;

+	}

+

+	return false;

+}

+

+void ConvertString(const char *in, wchar_t *out, int size)

+{

+	MultiByteToWideChar(CP_UTF8, 0, in,  -1, out, size);

+}

+

+void ConvertString(const wchar_t *in, char *out, int size)

+{

+	WideCharToMultiByte(CP_UTF8, 0, in, (size - 1), out, size, NULL, NULL);

+}

+

+void ConvertString(const char *in, char *out, int size)

+{

+	strncpy(out, in, size);

+}

+

+void ErrorDebug(LPTSTR lpszFunction)

+{ 

+    TCHAR szBuf[80]; 

+    LPVOID lpMsgBuf;

+    DWORD dw = GetLastError(); 

+

+    FormatMessage(

+        FORMAT_MESSAGE_ALLOCATE_BUFFER | 

+        FORMAT_MESSAGE_FROM_SYSTEM,

+        NULL,

+        dw,

+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),

+        (LPTSTR) &lpMsgBuf,

+        0, NULL );

+

+    _stprintf(szBuf, 

+        _T("%s failed with error %d: %s"), 

+        lpszFunction, dw, lpMsgBuf); 

+ 

+    MessageBox(NULL, szBuf, _T("Error"), MB_OK); 

+

+    LocalFree(lpMsgBuf);

+}

+