/* Win32-like Services for Windows CE 5.0 and above win32 applications, such as stunnel. */ #include "common.h" #include "prototypes.h" #include #include "mywcedefs.h" LPSTR wstr2str(LPCWSTR in) { /* code identical to W part of tstr2str function in file.c */ int len; LPSTR out; len=WideCharToMultiByte(CP_ACP, 0, in, -1, NULL, 0, NULL, NULL); if(!len) return NULL; out=str_alloc(len+1); len=WideCharToMultiByte(CP_ACP, 0, in, -1, out, len, NULL, NULL); if(!len) return NULL; return out; } errno_t _tputenv_s( const TCHAR *name, const TCHAR *value ) { TCHAR envcmd_l[MAX_PATH]; int cr_l; _tcscpy(envcmd_l, name); _tcscat(envcmd_l,TEXT("=")); _tcscat(envcmd_l,value); cr_l = _tputenv(envcmd_l); if (cr_l < 0) return EINVAL; return 0; } HICON wceLoadIconFromFile(TCHAR *filename) /* Loads only BMP (NOT .ico !) files as HICON, 16x16 and 16 colors */ { char *pANDMASK_l; int width_l, height_l; HBITMAP HBMICON_l;/* Icon image Hbitmap */ HBITMAP HBMAND_l; /* AND-Mask, to "AND" with background, before xor-ing the bg with the image, all at 0 */ ICONINFO iconinfo_l; HICON hicon_l; DWORD errcode_l; /* Load the file in a bitmap (file MUST BE a bmp file, not a ".ico" one) */ HBMICON_l = SHLoadDIBitmap(filename); errcode_l=GetLastError(); if (!HBMICON_l) s_log(LOG_DEBUG, "MYWCEDEFS[%d] : wceLoadIconFromFile HBMICON_l is %x error is %d", __LINE__, HBMICON_l, errcode_l); /* Create Masks as MONOCHROME bitmaps (1 plane, 1 bit/pixel), based on SXCM metrics */ width_l = GetSystemMetrics(SM_CXSMICON); /* should be...is...multiple of 2 (word aligned see CreateBitmap doc...or 4 ?) */ height_l = GetSystemMetrics(SM_CYSMICON); pANDMASK_l = (char *) malloc(width_l * height_l / 8);/* monochrome masks are 1 bit/pixel images */ memset(pANDMASK_l, 0x00, width_l * height_l / 8 ); /* the Color Bitmap (from the file) will Overwrite the background */ HBMAND_l = CreateBitmap(width_l, height_l, 1, 1, pANDMASK_l); /* dixit MSDN "for performance reasons applications should use CreateBitmap to create monochrome bitmaps" */ errcode_l=GetLastError(); if (!HBMAND_l) s_log(LOG_DEBUG, "MYWCEDEFS[%d] : HBMAND_l is %x error is %d", __LINE__, HBMAND_l, errcode_l); /* Create an icon from the bitmap and MASKS */ iconinfo_l.fIcon = TRUE; iconinfo_l.xHotspot = 0; /* ignored */ iconinfo_l.yHotspot = 0; /* ignored */ iconinfo_l.hbmMask = HBMAND_l;/* AND Mask for a Color Icon; AND+XOR mask for a BW icon */ iconinfo_l.hbmColor = HBMICON_l;/* NULL for a BW icon */ hicon_l = CreateIconIndirect(&iconinfo_l); errcode_l=GetLastError(); if(!hicon_l) s_log(LOG_DEBUG, "MYWCEDEFS[%d] : hicon_l is %x error is %d", __LINE__, hicon_l, errcode_l); DeleteObject(HBMICON_l); DeleteObject(HBMAND_l); /* pANDMASK_l freed because memory area not anymore used by GUI (?) */ free(pANDMASK_l); return(hicon_l); } HICON wceDuplicateIcon( HINSTANCE hInst, /* not used (as in MSDN) */ HICON hIcon /* handle to icon */ ) { HDC hdc, /* Full Screen DC */ hdcsrc, /* Color memory DC, based on Screen, to internally store the original Icon with its original colors AND transparency zones */ hdcmask;/* B&W memory DC, for AND-mask management */ int width_l, height_l; HBITMAP HBMICON_l;/* Color bitmap for original Icon -transparent- drawing */ HBITMAP HBMMASK_l; /* NEW Icon AND-Mask, basically at 1 on the background (ie icon transparent pixels), 1 under the Icon "sprite" */ ICONINFO iconinfo_l; HICON hNewIcon_l = (HICON) NULL; COLORREF bgColor;/* conventional BackGround Color for original Icon : MUST be an "improbable" color */ HBRUSH bgBrush= (HBRUSH) NULL;/* to draw the background of the original Icon bitmap */ BOOL cr_l = FALSE; DWORD errcode_l; width_l = GetSystemMetrics(SM_CXSMICON); /* should be...is...multiple of 2 (word aligned see CreateBitmap doc...or 4 ?) */ height_l = GetSystemMetrics(SM_CYSMICON); /* STEP 1 : we just need to draw the original Icon into a bitmap, with an easily removable coloured background ----------------------------------------------------------------------------------------------------------- To do this we paint the background of a coloured hdc with some rarely used color (ideally a "never-used" color. Then we draw, with original transparency support, the original Icon to that painting surface. NOW we have a typical coloroured background, and our Icon projected on it. The background will be made transparent later... */ /* Draw the original Icon in a "screen-like" hdc (to get highest possible color fidelity) */ hdc = GetDC(NULL); hdcsrc = CreateCompatibleDC(hdc); HBMICON_l = CreateCompatibleBitmap(hdc, width_l, height_l);/* Note: hdc, NOT hdcsrc, just to HAVE A FULL COLOR bitmap, as close as possible to the screen colors */ SelectObject(hdcsrc, HBMICON_l); /* For future computation of BGMASK (white outside Icon, black under the icon), we need to decide of a transparent Background Color This MUST be an "improbable" color, ie that is probably NOT used in the original Icon, this color will be transparent in next steps. NB : be careful that on poor color display, this color will be interpolated to something else "as close as possible": but we do NOT want something being interpolated to black nor white (because those colors are USED in icons)... and we DO want something that is "probably" supported by ANY device WITHOUT interpolation (just to have a predictive effect on masking computation) This is OK but sometimes used : bgColor = (COLORREF) RGB(127,127,127); This is NOT ok because interpolated to black : bgColor = (COLORREF) RGB(1,1,1); */ bgColor = (COLORREF) RGB(15,15,15);/* This is Ok on WCE5/WM6 HTC smartphones */ SetBkColor(hdcsrc, bgColor);/* THIS is ABSOLUTELY necessary to get some B&W mask FROM this coloured icon, in second step */ /* Fill the background of our Icon hdc with our BgColor: necessary for when we will make this background transparent */ bgBrush = CreateSolidBrush(bgColor); SelectObject(hdcsrc, bgBrush); PatBlt(hdcsrc,0,0,width_l, height_l, PATCOPY); /* Draw the Icon (remember : our hdcsrc is AS CLOSE AS POSSIBLE to the Screen DC in color support) */ DrawIcon(hdcsrc, 0, 0, hIcon); /* STEP2 : Generate a "transparency" AND-mask for the icon : --------------------------------------------------------- This mask will be anded to the screen background, to DELETE the area where the future NEW-Icon will be drawn by XOR (0 XOR Y = Y) This is done by a typical MSDN trick, using Monochrome Bitmaps and COLOR conversion rules between COLOR HDC and B&W hdc : Color hdc => B&W hdc : BkColor will become White, OTHER colors will become BLACK B&W hdc => Color hdc : B&W 0 becomes DST TextColor, B&W 1 becomes DST BkColor (as set by SetBkColor) */ hdcmask = CreateCompatibleDC(hdc); HBMMASK_l = CreateBitmap(width_l, height_l, 1, 1, NULL);/* Mandatory B&W bitmap here */ SelectObject(hdcmask, HBMMASK_l); /* Optional : Just in case anything goes wrong, the mask "could be at least" completely black PatBlt(hdcmask,0,0,width_l, height_l, BLACKNESS); */ BitBlt(hdcmask, 0,0,width_l, height_l, hdcsrc, 0, 0, SRCCOPY);/* This is the graal of Win32 transparent bitmap copy */ /* now we have a mask WHERE each original bg pixel (from the original color Icon bitmap), in NOW a "white pixel", and anything else, ie the Icon itself, is just a black surface, similar to the shadow of the original Icon. */ /* STEP 3 : DELETE -ONLY- BACKGROUND pixels from the Original Color Icon Bitmap This is necessary because we will use that bitmap as the future DUPLICATE of the original Icon, and, by using CreateIconIndirect to create the icon, we need to be sure that the background will be transparent: This is not only obtained by having an and-mask for the background, BUT ALSO by BEING sure that, in the colored icon bitmap, the bg pixels will be at 0 : because the colored icon bitmap will be XOR'ed to the screen background, and 0 XOR Y = Y... Ideally, to do that we do : Icon = Icon AND (NOT(MASK)) (ie ternary ROP code "DSna" : 0x00220326, dixit MSDN) BUT...as this ROP operation will mix a B&W hdc and a Color HDC we need to be sure that the B&W 0 will translate to RGB(0,0,0) (BLACK) and that the B&W 1 will translate to RGB(255,255,255) (WHITE), BEFORE than the logical ROP operation occurs. Because this is how it will happen : before a ROP occurs between a B&W hdc and a coloured hdc, 1st/ the B&W hdc is converted to coloured one (0= DST TextColr / 1 : DST BkColor) and 2nd/ the logical ROP operation occurs. So, before ROP bitblt, we DO : Orig Icon TextColor = black, Orig Icon BkColor = White. */ SetTextColor(hdcsrc, RGB( 0, 0, 0));/* to translate 0 from the mask */ SetBkColor( hdcsrc, RGB(255,255,255));/* to translate 1 from the mask */ BitBlt(hdcsrc, 0, 0, width_l, height_l, hdcmask, 0, 0, 0x00220326);/* NOTSRC_AND ternary ROP code ("DSna" in MSDN) */ /* Create an icon from the bitmap and MASKS */ iconinfo_l.fIcon = TRUE; iconinfo_l.xHotspot = 0; /* ignored */ iconinfo_l.yHotspot = 0; /* ignored */ iconinfo_l.hbmMask = HBMMASK_l;/* AND Mask for a Color Icon; AND+XOR mask for a BW icon */ iconinfo_l.hbmColor = HBMICON_l;/* NULL for a BW icon */ hNewIcon_l = CreateIconIndirect(&iconinfo_l); errcode_l = GetLastError(); if(!hNewIcon_l) s_log(LOG_DEBUG, "MYWCEDEFS[%d] : wceDuplicateIcon hNewIcon_l is %x error is %d",__LINE__, hNewIcon_l, errcode_l); /* Free resources */ DeleteObject(HBMMASK_l); DeleteObject(HBMICON_l); DeleteDC(hdcmask); DeleteDC(hdcsrc); ReleaseDC(NULL, hdc); return(hNewIcon_l); } HINSTANCE wceShellExecute( HWND hwnd, LPCTSTR lpVerb, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd ) { SHELLEXECUTEINFO execinfo_l; BOOL cr_l; execinfo_l.cbSize = sizeof(SHELLEXECUTEINFO); execinfo_l.fMask = 0; execinfo_l.hwnd = hwnd; execinfo_l.lpVerb = lpVerb; /* must be COMPLETE PATH in WCE, because there is NO "current dir" in WCE */ execinfo_l.lpFile = lpFile; execinfo_l.lpParameters = lpParameters; execinfo_l.lpDirectory = lpDirectory; execinfo_l.nShow = nShowCmd; /* output parameter : execinfo_l.hInstApp; */ /* ignored on WCE : execinfo_l.lpIDList; execinfo_l.lpClass; execinfo_l.hkeyClass; execinfo_l.dwHotKey; execinfo_l.hIcon; */ /* output parameter : execinfo_l.hProcess; */ cr_l = ShellExecuteEx(&execinfo_l); return(execinfo_l.hInstApp); /* on Win32, hInstApp documented to return EITHER success > 32 or error <= 32, not so clear in WCE. If fails, see BELOW... */ /* DWORD errcode_l; errcode_l = GetLastError(); if (!cr_l) return(errcode_l); return(64); */ /* pdelaage 20140610 : as WCE doc says, returns value > 32 if successful*/ } DWORD wceGetCurrentDirectory( DWORD nBufferLength, /* size of directory buffer */ LPTSTR lpBuffer /* directory buffer */ ) { DWORD cr_l; TCHAR car_l; TCHAR *ch_l = NULL; cr_l = GetModuleFileName((HMODULE) NULL, lpBuffer, nBufferLength); if (cr_l == 0) return 0; /* conversion from filename to pathname */ car_l = TEXT('\\'); #ifdef UNICODE ch_l = _tcsrchr(lpBuffer, car_l); /* in UNICODE, wcsrchr takes car_l as a wchar */ #else ch_l = _tcsrchr(lpBuffer, (int) car_l); /* in ANSI, strrchr takes car_l as an int ! */ #endif if (!ch_l) return(0); *ch_l = TEXT('\0'); return(_tcslen(lpBuffer)); }