summaryrefslogtreecommitdiff
path: root/plugins/AVS/src/utils.cpp
diff options
context:
space:
mode:
authorGeorge Hazan <george.hazan@gmail.com>2013-08-10 21:34:29 +0000
committerGeorge Hazan <george.hazan@gmail.com>2013-08-10 21:34:29 +0000
commit960336573d3420785094dd46fe4a3edb4cb152a8 (patch)
treef4e581537a72dad2e1fb07ab0cc8eef91bd56e3f /plugins/AVS/src/utils.cpp
parent84bb8836befd3d31b22562bb02f4ecf22e92c4a9 (diff)
divide et impera
git-svn-id: http://svn.miranda-ng.org/main/trunk@5639 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/AVS/src/utils.cpp')
-rw-r--r--plugins/AVS/src/utils.cpp634
1 files changed, 634 insertions, 0 deletions
diff --git a/plugins/AVS/src/utils.cpp b/plugins/AVS/src/utils.cpp
new file mode 100644
index 0000000000..1d0494e258
--- /dev/null
+++ b/plugins/AVS/src/utils.cpp
@@ -0,0 +1,634 @@
+/*
+Copyright (C) 2006 Ricardo Pescuma Domenecci, Nightwish
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "commonheaders.h"
+
+#ifdef _DEBUG
+
+int _DebugTrace(const char *fmt, ...)
+{
+ char debug[2048];
+ int ibsize = 2047;
+ va_list va;
+ va_start(va, fmt);
+
+ mir_snprintf(debug, SIZEOF(debug) - 10, " ***** AVS [%08d] [ID:%04x]: ", GetTickCount(), GetCurrentThreadId());
+ OutputDebugStringA(debug);
+ mir_vsnprintf(debug, ibsize, fmt, va);
+ OutputDebugStringA(debug);
+ OutputDebugStringA(" ***** \n");
+
+ return 0;
+}
+
+int _DebugTrace(HANDLE hContact, const char *fmt, ...)
+{
+ char text[1024];
+ size_t len;
+ va_list va;
+
+ char *name = NULL;
+ char *proto = NULL;
+ if (hContact != NULL)
+ {
+ name = (char*)CallService(MS_CLIST_GETCONTACTDISPLAYNAME, (WPARAM)hContact, 0);
+ proto = GetContactProto(hContact);
+ }
+
+ mir_snprintf(text, SIZEOF(text) - 10, " ***** AVS [%08d] [ID:%04x]: [%08d - %s - %s] ",
+ GetTickCount(), GetCurrentThreadId(), hContact, proto == NULL ? "" : proto, name == NULL ? "" : name);
+ len = strlen(text);
+
+ va_start(va, fmt);
+ mir_vsnprintf(&text[len], SIZEOF(text) - len, fmt, va);
+ va_end(va);
+
+ OutputDebugStringA(text);
+ OutputDebugStringA(" ***** \n");
+
+ return 0;
+}
+
+#endif
+
+void mir_sleep(int time)
+{
+ if (!g_shutDown)
+ WaitForSingleObject(hShutdownEvent, time);
+}
+
+/*
+ * path utilities (make avatar paths relative to *PROFILE* directory, not miranda directory.
+ * taken and modified from core services
+ */
+
+int AVS_pathIsAbsolute(const TCHAR *path)
+{
+ if (!path || !(lstrlen(path) > 2))
+ return 0;
+ if ((path[1]==':'&&path[2]=='\\')||(path[0]=='\\'&&path[1]=='\\')) return 1;
+ return 0;
+}
+
+size_t AVS_pathToRelative(const TCHAR *pSrc, TCHAR *pOut)
+{
+ if (!pSrc || !*pSrc || _tcslen(pSrc) > MAX_PATH) return 0;
+ if (!AVS_pathIsAbsolute( pSrc ))
+ lstrcpyn(pOut, pSrc, MAX_PATH);
+ else {
+ TCHAR szTmp[MAX_PATH];
+ mir_sntprintf(szTmp, SIZEOF(szTmp), _T("%s"), pSrc);
+ _tcslwr(szTmp);
+ if (_tcsstr(szTmp, g_szDataPath))
+ lstrcpyn(pOut, pSrc + _tcslen(g_szDataPath) + 1, MAX_PATH);
+ else
+ lstrcpyn(pOut, pSrc, MAX_PATH);
+ }
+ return _tcslen(pOut);
+}
+
+size_t AVS_pathToAbsolute(const TCHAR *pSrc, TCHAR *pOut)
+{
+ if (!pSrc || !lstrlen(pSrc) || lstrlen(pSrc) > MAX_PATH)
+ return 0;
+
+ if (AVS_pathIsAbsolute(pSrc) || !_istalnum(pSrc[0]))
+ lstrcpyn(pOut, pSrc, MAX_PATH);
+ else
+ mir_sntprintf(pOut, MAX_PATH, _T("%s\\%s"), g_szDataPath, pSrc, MAX_PATH);
+ return lstrlen(pOut);
+}
+
+/*
+ * convert the avatar image path to a relative one...
+ * given: contact handle, path to image
+ */
+void MakePathRelative(HANDLE hContact, TCHAR *path)
+{
+ TCHAR szFinalPath[MAX_PATH];
+ szFinalPath[0] = '\0';
+
+ size_t result = AVS_pathToRelative(path, szFinalPath);
+ if (result && lstrlen(szFinalPath) > 0) {
+ db_set_ts(hContact, "ContactPhoto", "RFile", szFinalPath);
+ if (!db_get_b(hContact, "ContactPhoto", "Locked", 0))
+ db_set_ts(hContact, "ContactPhoto", "Backup", szFinalPath);
+ }
+}
+
+/*
+ * convert the avatar image path to a relative one...
+ * given: contact handle
+ */
+
+void MakePathRelative(HANDLE hContact)
+{
+ DBVARIANT dbv;
+ if ( !db_get_ts(hContact, "ContactPhoto", "File", &dbv)) {
+ MakePathRelative(hContact, dbv.ptszVal);
+ db_free(&dbv);
+ }
+}
+
+// create the avatar in cache
+// returns 0 if not created (no avatar), iIndex otherwise, -2 if has to request avatar, -3 if avatar too big
+int CreateAvatarInCache(HANDLE hContact, avatarCacheEntry *ace, char *szProto)
+{
+ DBVARIANT dbv = {0};
+ char *szExt = NULL;
+ TCHAR tszFilename[MAX_PATH];
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ DWORD dwFileSizeHigh = 0, dwFileSize = 0, sizeLimit = 0;
+
+ tszFilename[0] = 0;
+
+ ace->hbmPic = 0;
+ ace->dwFlags = 0;
+ ace->bmHeight = 0;
+ ace->bmWidth = 0;
+ ace->lpDIBSection = NULL;
+ ace->szFilename[0] = 0;
+
+ if (szProto == NULL) {
+ char *proto = GetContactProto(hContact);
+ if (proto == NULL || !db_get_b(NULL, AVS_MODULE, proto, 1))
+ return -1;
+
+ if (db_get_b(hContact, "ContactPhoto", "Locked", 0)
+ && !db_get_ts(hContact, "ContactPhoto", "Backup", &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ else if ( !db_get_ts(hContact, "ContactPhoto", "RFile", &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ else if ( !db_get_ts(hContact, "ContactPhoto", "File", &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ else return -2;
+ }
+ else {
+ if (hContact == 0) { // create a protocol picture in the proto picture cache
+ if ( !db_get_ts(NULL, PPICT_MODULE, szProto, &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ else {
+ if (lstrcmpA(szProto, AVS_DEFAULT)) {
+ if ( !db_get_ts(NULL, PPICT_MODULE, AVS_DEFAULT, &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+
+ if (!strstr(szProto, "Global avatar for")) {
+ PROTOACCOUNT* pdescr = (PROTOACCOUNT*)CallService(MS_PROTO_GETACCOUNT, 0, (LPARAM)szProto);
+ if (pdescr == NULL)
+ return -1;
+ char key[MAX_PATH];
+ mir_snprintf(key, SIZEOF(key), "Global avatar for %s accounts", pdescr->szProtoName);
+ if ( !db_get_ts(NULL, PPICT_MODULE, key, &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ }
+ }
+ }
+ }
+ else if (hContact == (HANDLE)-1) { // create own picture - note, own avatars are not on demand, they are loaded once at
+ // startup and everytime they are changed.
+ if (szProto[0] == '\0') {
+ // Global avatar
+ if ( db_get_ts(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv))
+ return -10;
+
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ else if ( ProtoServiceExists(szProto, PS_GETMYAVATART)) {
+ if (CallProtoService(szProto, PS_GETMYAVATART, (WPARAM)tszFilename, (LPARAM)MAX_PATH))
+ tszFilename[0] = '\0';
+ }
+ else if ( ProtoServiceExists(szProto, PS_GETMYAVATAR)) {
+ char szFileName[ MAX_PATH ];
+ if (CallProtoService(szProto, PS_GETMYAVATAR, (WPARAM)szFileName, (LPARAM)MAX_PATH))
+ tszFilename[0] = '\0';
+ else
+ MultiByteToWideChar( CP_ACP, 0, szFileName, -1, tszFilename, SIZEOF(tszFilename));
+ }
+ else if ( !db_get_ts(NULL, szProto, "AvatarFile", &dbv)) {
+ AVS_pathToAbsolute(dbv.ptszVal, tszFilename);
+ db_free(&dbv);
+ }
+ else return -1;
+ }
+ }
+
+ if ( lstrlen(tszFilename) < 4)
+ return -1;
+
+ _tcsncpy_s(tszFilename, SIZEOF(tszFilename), VARST(tszFilename), _TRUNCATE);
+ if ((hFile = CreateFile(tszFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE)
+ return -2;
+
+ CloseHandle(hFile);
+ WPARAM isTransparentImage = 0;
+
+ ace->hbmPic = (HBITMAP) BmpFilterLoadBitmap32((WPARAM)&isTransparentImage, (LPARAM)tszFilename);
+ ace->dwFlags = 0;
+ ace->bmHeight = 0;
+ ace->bmWidth = 0;
+ ace->lpDIBSection = NULL;
+ _tcsncpy(ace->szFilename, tszFilename, MAX_PATH);
+ ace->szFilename[MAX_PATH - 1] = 0;
+ if (ace->hbmPic != 0) {
+ BITMAP bminfo;
+
+ GetObject(ace->hbmPic, sizeof(bminfo), &bminfo);
+
+ ace->cbSize = sizeof(avatarCacheEntry);
+ ace->dwFlags = AVS_BITMAP_VALID;
+ if (hContact != NULL && db_get_b(hContact, "ContactPhoto", "Hidden", 0))
+ ace->dwFlags |= AVS_HIDEONCLIST;
+ ace->hContact = hContact;
+ ace->bmHeight = bminfo.bmHeight;
+ ace->bmWidth = bminfo.bmWidth;
+
+ BOOL noTransparency = db_get_b(0, AVS_MODULE, "RemoveAllTransparency", 0);
+
+ // Calc image hash
+ if (hContact != 0 && hContact != (HANDLE)-1) {
+ // Have to reset settings? -> do it if image changed
+ DWORD imgHash = GetImgHash(ace->hbmPic);
+ if (imgHash != db_get_dw(hContact, "ContactPhoto", "ImageHash", 0)) {
+ db_unset(hContact, "ContactPhoto", "MakeTransparentBkg");
+ db_unset(hContact, "ContactPhoto", "TranspBkgNumPoints");
+ db_unset(hContact, "ContactPhoto", "TranspBkgColorDiff");
+
+ db_set_dw(hContact, "ContactPhoto", "ImageHash", imgHash);
+ }
+
+ // Make transparent?
+ if (!noTransparency && !isTransparentImage
+ && db_get_b(hContact, "ContactPhoto", "MakeTransparentBkg",
+ db_get_b(0, AVS_MODULE, "MakeTransparentBkg", 0)))
+ {
+ if (MakeTransparentBkg(hContact, &ace->hbmPic)) {
+ ace->dwFlags |= AVS_CUSTOMTRANSPBKG | AVS_HASTRANSPARENCY;
+ GetObject(ace->hbmPic, sizeof(bminfo), &bminfo);
+ isTransparentImage = TRUE;
+ }
+ }
+ }
+ else if (hContact == (HANDLE)-1) { // My avatars
+ if (!noTransparency && !isTransparentImage
+ && db_get_b(0, AVS_MODULE, "MakeTransparentBkg", 0)
+ && db_get_b(0, AVS_MODULE, "MakeMyAvatarsTransparent", 0))
+ {
+ if (MakeTransparentBkg(0, &ace->hbmPic)) {
+ ace->dwFlags |= AVS_CUSTOMTRANSPBKG | AVS_HASTRANSPARENCY;
+ GetObject(ace->hbmPic, sizeof(bminfo), &bminfo);
+ isTransparentImage = TRUE;
+ }
+ }
+ }
+
+ if (db_get_b(0, AVS_MODULE, "MakeGrayscale", 0))
+ ace->hbmPic = MakeGrayscale(hContact, ace->hbmPic);
+
+ if (noTransparency) {
+ fei->FI_CorrectBitmap32Alpha(ace->hbmPic, TRUE);
+ isTransparentImage = FALSE;
+ }
+
+ if (bminfo.bmBitsPixel == 32 && isTransparentImage) {
+ if (fei->FI_Premultiply(ace->hbmPic))
+ ace->dwFlags |= AVS_HASTRANSPARENCY;
+
+ ace->dwFlags |= AVS_PREMULTIPLIED;
+ }
+
+ if (szProto) {
+ protoPicCacheEntry *pAce = (protoPicCacheEntry *)ace;
+ if (hContact == 0)
+ pAce->dwFlags |= AVS_PROTOPIC;
+ else if (hContact == (HANDLE)-1)
+ pAce->dwFlags |= AVS_OWNAVATAR;
+ }
+
+ return 1;
+ }
+ return -1;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#define POLYNOMIAL (0x488781ED) /* This is the CRC Poly */
+#define TOPBIT (1 << (WIDTH - 1)) /* MSB */
+#define WIDTH 32
+
+int GetFileHash(TCHAR* filename)
+{
+ HANDLE hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return 0;
+
+ int remainder = 0;
+ char data[1024];
+ DWORD dwRead;
+ do
+ {
+ // Read file chunk
+ dwRead = 0;
+ ReadFile(hFile, data, 1024, &dwRead, NULL);
+
+ /* loop through each byte of data */
+ for (int byte = 0; byte < (int) dwRead; ++byte) {
+ /* store the next byte into the remainder */
+ remainder ^= (data[byte] << (WIDTH - 8));
+ /* calculate for all 8 bits in the byte */
+ for (int bit = 8; bit > 0; --bit) {
+ /* check if MSB of remainder is a one */
+ if (remainder & TOPBIT)
+ remainder = (remainder << 1) ^ POLYNOMIAL;
+ else
+ remainder = (remainder << 1);
+ }
+ }
+ }
+ while(dwRead == 1024);
+
+ CloseHandle(hFile);
+
+ return remainder;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+protoPicCacheEntry::~protoPicCacheEntry()
+{
+ if (hbmPic != 0)
+ DeleteObject(hbmPic);
+ mir_free(szProtoname);
+ mir_free(tszAccName);
+}
+
+void protoPicCacheEntry::clear()
+{
+ if (hbmPic != 0)
+ DeleteObject(hbmPic);
+
+ memset(this, 0, sizeof(avatarCacheEntry));
+}
+
+BOOL Proto_IsAvatarsEnabled(const char *proto)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS))
+ return CallProtoService(proto, PS_GETAVATARCAPS, AF_ENABLED, 0);
+
+ return TRUE;
+}
+
+BOOL Proto_IsAvatarFormatSupported(const char *proto, int format)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS))
+ return CallProtoService(proto, PS_GETAVATARCAPS, AF_FORMATSUPPORTED, format);
+
+ if (format >= PA_FORMAT_SWF)
+ return FALSE;
+
+ return TRUE;
+}
+
+int Proto_AvatarImageProportion(const char *proto)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS))
+ return CallProtoService(proto, PS_GETAVATARCAPS, AF_PROPORTION, 0);
+
+ return 0;
+}
+
+void Proto_GetAvatarMaxSize(const char *proto, int *width, int *height)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS)) {
+ POINT maxSize;
+ CallProtoService(proto, PS_GETAVATARCAPS, AF_MAXSIZE, (LPARAM) &maxSize);
+ *width = maxSize.y;
+ *height = maxSize.x;
+ }
+ else {
+ *width = 300;
+ *height = 300;
+ }
+
+ if (*width < 0)
+ *width = 0;
+ else if (*width > 300)
+ *width = 300;
+
+ if (*height < 0)
+ *height = 0;
+ else if (*height > 300)
+ *height = 300;
+}
+
+BOOL Proto_NeedDelaysForAvatars(const char *proto)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS)) {
+ int ret = CallProtoService(proto, PS_GETAVATARCAPS, AF_DONTNEEDDELAYS, 0);
+ if (ret > 0)
+ return FALSE;
+ else
+ return TRUE;
+ }
+
+ return TRUE;
+}
+
+int Proto_GetAvatarMaxFileSize(const char *proto)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS))
+ return CallProtoService(proto, PS_GETAVATARCAPS, AF_MAXFILESIZE, 0);
+
+ return 0;
+}
+
+int Proto_GetDelayAfterFail(const char *proto)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS))
+ return CallProtoService(proto, PS_GETAVATARCAPS, AF_DELAYAFTERFAIL, 0);
+
+ return 0;
+}
+
+BOOL Proto_IsFetchingAlwaysAllowed(const char *proto)
+{
+ if ( ProtoServiceExists(proto, PS_GETAVATARCAPS))
+ return CallProtoService(proto, PS_GETAVATARCAPS, AF_FETCHALWAYS, 0);
+
+ return FALSE;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+protoPicCacheEntry *GetProtoDefaultAvatar(HANDLE hContact)
+{
+ char *szProto = GetContactProto(hContact);
+ if (szProto) {
+ for(int i = 0; i < g_ProtoPictures.getCount(); i++) {
+ protoPicCacheEntry& p = g_ProtoPictures[i];
+ if ( !lstrcmpA(p.szProtoname, szProto) && p.hbmPic != NULL)
+ return &g_ProtoPictures[i];
+ }
+ }
+ return NULL;
+}
+
+HANDLE GetContactThatHaveTheAvatar(HANDLE hContact, int locked)
+{
+ if (g_MetaAvail && db_get_b(NULL, g_szMetaName, "Enabled", 0)) {
+ if (db_get_dw(hContact, g_szMetaName, "NumContacts", 0) >= 1) {
+ if (locked == -1)
+ locked = db_get_b(hContact, "ContactPhoto", "Locked", 0);
+
+ if (!locked)
+ hContact = (HANDLE)CallService(MS_MC_GETMOSTONLINECONTACT, (WPARAM)hContact, 0);
+ }
+ }
+ return hContact;
+}
+
+int ChangeAvatar(HANDLE hContact, BOOL fLoad, BOOL fNotifyHist, int pa_format)
+{
+ if (g_shutDown)
+ return 0;
+
+ hContact = GetContactThatHaveTheAvatar(hContact);
+
+ // Get the node
+ CacheNode *node = FindAvatarInCache(hContact, g_AvatarHistoryAvail && fNotifyHist, TRUE);
+ if (node == NULL)
+ return 0;
+
+ if (fNotifyHist)
+ node->dwFlags |= AVH_MUSTNOTIFY;
+
+ node->mustLoad = fLoad ? 1 : -1;
+ node->pa_format = pa_format;
+ SetEvent(hLoaderEvent);
+ return 0;
+}
+
+void DeleteGlobalUserAvatar()
+{
+ DBVARIANT dbv = {0};
+ if (db_get_ts(NULL, AVS_MODULE, "GlobalUserAvatarFile", &dbv))
+ return;
+
+ TCHAR szFilename[MAX_PATH];
+ AVS_pathToAbsolute(dbv.ptszVal, szFilename);
+ db_free(&dbv);
+
+ DeleteFile(szFilename);
+ db_unset(NULL, AVS_MODULE, "GlobalUserAvatarFile");
+}
+
+void SetIgnoreNotify(char *protocol, BOOL ignore)
+{
+ for(int i = 0; i < g_MyAvatars.getCount(); i++) {
+ if (protocol == NULL || !lstrcmpA(g_MyAvatars[i].szProtoname, protocol)) {
+ if (ignore)
+ g_MyAvatars[i].dwFlags |= AVS_IGNORENOTIFY;
+ else
+ g_MyAvatars[i].dwFlags &= ~AVS_IGNORENOTIFY;
+ }
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+const TCHAR *GetFormatExtension(int format)
+{
+ if (format == PA_FORMAT_PNG)
+ return _T(".png");
+ if (format == PA_FORMAT_JPEG)
+ return _T(".jpg");
+ if (format == PA_FORMAT_ICON)
+ return _T(".ico");
+ if (format == PA_FORMAT_BMP)
+ return _T(".bmp");
+ if (format == PA_FORMAT_GIF)
+ return _T(".gif");
+ if (format == PA_FORMAT_SWF)
+ return _T(".swf");
+ if (format == PA_FORMAT_XML)
+ return _T(".xml");
+
+ return NULL;
+}
+
+int GetImageFormat(TCHAR *filename)
+{
+ size_t len = lstrlen(filename);
+
+ if (len < 5)
+ return PA_FORMAT_UNKNOWN;
+
+ if (_tcsicmp(_T(".png"), &filename[len-4]) == 0)
+ return PA_FORMAT_PNG;
+
+ if (_tcsicmp(_T(".jpg"), &filename[len-4]) == 0 || _tcsicmp(_T(".jpeg"), &filename[len-4]) == 0)
+ return PA_FORMAT_JPEG;
+
+ if (_tcsicmp(_T(".ico"), &filename[len-4]) == 0)
+ return PA_FORMAT_ICON;
+
+ if (_tcsicmp(_T(".bmp"), &filename[len-4]) == 0 || _tcsicmp(_T(".rle"), &filename[len-4]) == 0)
+ return PA_FORMAT_BMP;
+
+ if (_tcsicmp(_T(".gif"), &filename[len-4]) == 0)
+ return PA_FORMAT_GIF;
+
+ if (_tcsicmp(_T(".swf"), &filename[len-4]) == 0)
+ return PA_FORMAT_SWF;
+
+ if (_tcsicmp(_T(".xml"), &filename[len-4]) == 0)
+ return PA_FORMAT_XML;
+
+ return PA_FORMAT_UNKNOWN;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////
+
+DWORD GetFileSize(TCHAR *szFilename)
+{
+ HANDLE hFile = CreateFile(szFilename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return 0;
+
+ DWORD low = GetFileSize(hFile, NULL);
+
+ CloseHandle(hFile);
+
+ if (low == INVALID_FILE_SIZE)
+ return 0;
+
+ return low;
+}