You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1625 lines
38 KiB
1625 lines
38 KiB
//
|
|
// candutil.cpp
|
|
//
|
|
|
|
#include "private.h"
|
|
#include "candutil.h"
|
|
#include "globals.h"
|
|
#include "cuilib.h"
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/* F I S W I N D O W S N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
BOOL FIsWindowsNT( void )
|
|
{
|
|
static BOOL fInitialized = FALSE;
|
|
static BOOL fWindowsNT = FALSE;
|
|
|
|
if (!fInitialized) {
|
|
OSVERSIONINFO OSVerInfo = {0};
|
|
|
|
OSVerInfo.dwOSVersionInfoSize = sizeof(OSVerInfo);
|
|
if (GetVersionEx( &OSVerInfo )) {
|
|
fWindowsNT = (OSVerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
|
}
|
|
|
|
fInitialized = TRUE;
|
|
}
|
|
|
|
return fWindowsNT;
|
|
}
|
|
|
|
|
|
/* C P G F R O M C H S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
UINT CpgFromChs( BYTE chs )
|
|
{
|
|
DWORD dwChs = chs;
|
|
CHARSETINFO ChsInfo = {0};
|
|
|
|
if (chs != SYMBOL_CHARSET && TranslateCharsetInfo( &dwChs, &ChsInfo, TCI_SRCCHARSET )) {
|
|
return ChsInfo.ciACP;
|
|
}
|
|
|
|
return GetACP();
|
|
}
|
|
|
|
|
|
/* C O N V E R T L O G F O N T W T O A */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Convert LOGFONTW to LOGFONTA
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void ConvertLogFontWtoA( CONST LOGFONTW *plfW, LOGFONTA *plfA )
|
|
{
|
|
UINT cpg;
|
|
|
|
plfA->lfHeight = plfW->lfHeight;
|
|
plfA->lfWidth = plfW->lfWidth;
|
|
plfA->lfEscapement = plfW->lfEscapement;
|
|
plfA->lfOrientation = plfW->lfOrientation;
|
|
plfA->lfWeight = plfW->lfWeight;
|
|
plfA->lfItalic = plfW->lfItalic;
|
|
plfA->lfUnderline = plfW->lfUnderline;
|
|
plfA->lfStrikeOut = plfW->lfStrikeOut;
|
|
plfA->lfCharSet = plfW->lfCharSet;
|
|
plfA->lfOutPrecision = plfW->lfOutPrecision;
|
|
plfA->lfClipPrecision = plfW->lfClipPrecision;
|
|
plfA->lfQuality = plfW->lfQuality;
|
|
plfA->lfPitchAndFamily = plfW->lfPitchAndFamily;
|
|
|
|
cpg = CpgFromChs( plfW->lfCharSet );
|
|
WideCharToMultiByte( cpg, 0, plfW->lfFaceName, -1, plfA->lfFaceName, ARRAYSIZE(plfA->lfFaceName), NULL, NULL );
|
|
}
|
|
|
|
|
|
/* C O N V E R T L O G F O N T A T O W */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Convert LOGFONTA to LOGFONTW
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void ConvertLogFontAtoW( CONST LOGFONTA *plfA, LOGFONTW *plfW )
|
|
{
|
|
UINT cpg;
|
|
|
|
plfW->lfHeight = plfA->lfHeight;
|
|
plfW->lfWidth = plfA->lfWidth;
|
|
plfW->lfEscapement = plfA->lfEscapement;
|
|
plfW->lfOrientation = plfA->lfOrientation;
|
|
plfW->lfWeight = plfA->lfWeight;
|
|
plfW->lfItalic = plfA->lfItalic;
|
|
plfW->lfUnderline = plfA->lfUnderline;
|
|
plfW->lfStrikeOut = plfA->lfStrikeOut;
|
|
plfW->lfCharSet = plfA->lfCharSet;
|
|
plfW->lfOutPrecision = plfA->lfOutPrecision;
|
|
plfW->lfClipPrecision = plfA->lfClipPrecision;
|
|
plfW->lfQuality = plfA->lfQuality;
|
|
plfW->lfPitchAndFamily = plfA->lfPitchAndFamily;
|
|
|
|
cpg = CpgFromChs( plfA->lfCharSet );
|
|
MultiByteToWideChar( cpg, 0, plfA->lfFaceName, -1, plfW->lfFaceName, ARRAYSIZE(plfW->lfFaceName) );
|
|
}
|
|
|
|
|
|
/* O U R C R E A T E F O N T I N D I R E C T W */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create font from LOGFONTW
|
|
|
|
------------------------------------------------------------------------------*/
|
|
HFONT OurCreateFontIndirectW( CONST LOGFONTW *plfW )
|
|
{
|
|
if (!FIsWindowsNT()) {
|
|
LOGFONTA lfA;
|
|
|
|
ConvertLogFontWtoA( plfW, &lfA );
|
|
return CreateFontIndirectA( &lfA );
|
|
}
|
|
|
|
return CreateFontIndirectW( plfW );
|
|
}
|
|
|
|
|
|
/* G E T F O N T H E I G H T O F F O N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Get font height of the font
|
|
|
|
------------------------------------------------------------------------------*/
|
|
int GetFontHeightOfFont( HDC hDC, HFONT hFont )
|
|
{
|
|
HFONT hFontOld;
|
|
TEXTMETRIC tm;
|
|
BOOL fReleaseDC = FALSE;
|
|
|
|
if (hDC == NULL)
|
|
{
|
|
hDC = GetDC( NULL );
|
|
fReleaseDC = TRUE;
|
|
}
|
|
|
|
hFontOld = (HFONT)SelectObject( hDC, hFont );
|
|
GetTextMetrics( hDC, &tm );
|
|
SelectObject( hDC, hFontOld );
|
|
|
|
if (fReleaseDC)
|
|
{
|
|
ReleaseDC( NULL, hDC );
|
|
}
|
|
|
|
return tm.tmHeight + tm.tmExternalLeading;
|
|
}
|
|
|
|
|
|
/* C O M P A R E S T R I N G */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
int CompareString( LPCWSTR pchStr1, LPCWSTR pchStr2, int cch )
|
|
{
|
|
int cchStr1 = wcslen( pchStr1 ) + 1;
|
|
int cchStr2 = wcslen( pchStr2 ) + 1;
|
|
|
|
__try {
|
|
LPWSTR pchBuf1 = (LPWSTR)alloca( cchStr1*sizeof(WCHAR) );
|
|
LPWSTR pchBuf2 = (LPWSTR)alloca( cchStr2*sizeof(WCHAR) );
|
|
LPWSTR pch;
|
|
|
|
memcpy( pchBuf1, pchStr1, cchStr1*sizeof(WCHAR) );
|
|
for (pch = pchBuf1; *pch != L'\0'; pch++) {
|
|
if (L'A' <= *pch && *pch <= L'Z') {
|
|
*pch = *pch - L'A' + L'a';
|
|
}
|
|
}
|
|
|
|
memcpy( pchBuf2, pchStr2, cchStr2*sizeof(WCHAR) );
|
|
for (pch = pchBuf2; *pch != L'\0'; pch++) {
|
|
if (L'A' <= *pch && *pch <= L'Z') {
|
|
*pch = *pch - L'A' + L'a';
|
|
}
|
|
}
|
|
|
|
return wcsncmp( pchBuf1, pchBuf2, cch );
|
|
}
|
|
__except(GetExceptionCode() == STATUS_STACK_OVERFLOW) {
|
|
_resetstkoflw();
|
|
return -1; // treat different
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//
|
|
|
|
/* C B D I B C O L O R T A B L E */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Calc the size of color table of bitmap
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static int CbDIBColorTable( BITMAPINFOHEADER *pbmih )
|
|
{
|
|
WORD nColor;
|
|
|
|
Assert( pbmih->biSize == sizeof(BITMAPINFOHEADER) );
|
|
if (pbmih->biPlanes != 1) {
|
|
Assert( FALSE );
|
|
return 0;
|
|
}
|
|
|
|
if (pbmih->biClrUsed == 0) {
|
|
if (pbmih->biBitCount == 1 || pbmih->biBitCount == 4 || pbmih->biBitCount == 8) {
|
|
nColor = (WORD) (1 << pbmih->biBitCount);
|
|
}
|
|
else {
|
|
nColor = 0;
|
|
}
|
|
}
|
|
else if (pbmih->biBitCount != 24) {
|
|
nColor = (WORD)pbmih->biClrUsed;
|
|
}
|
|
else {
|
|
nColor = 0;
|
|
}
|
|
|
|
return (nColor * sizeof(RGBQUAD));
|
|
}
|
|
|
|
|
|
/* P D I B I T S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Returns pointer of DIBits from DIB data
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static LPVOID PDIBits( LPVOID pDIB )
|
|
{
|
|
return ((BYTE*)pDIB + (sizeof(BITMAPINFOHEADER) + CbDIBColorTable( (BITMAPINFOHEADER *)pDIB )));
|
|
}
|
|
|
|
|
|
/* C R E A T E D I B F R O M B M P */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create DIB from Bitmap
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static HANDLE CreateDIBFromBmp( HDC hDC, HBITMAP hBmp, HPALETTE hPalette )
|
|
{
|
|
HDC hDCMem;
|
|
BITMAP bmp;
|
|
BITMAPINFOHEADER bmih = {0};
|
|
LPBITMAPINFOHEADER pbmih;
|
|
HANDLE hDIB;
|
|
void *pDIB;
|
|
void *pDIBits;
|
|
HPALETTE hPaletteOld = NULL;
|
|
DWORD cbImage;
|
|
DWORD cbColorTable;
|
|
DWORD cbBits;
|
|
|
|
if (hBmp == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
|
|
hDCMem = CreateCompatibleDC( hDC );
|
|
|
|
// initialize bmi
|
|
|
|
GetObject( hBmp, sizeof(bmp), &bmp );
|
|
|
|
bmih.biSize = sizeof(BITMAPINFOHEADER);
|
|
bmih.biWidth = bmp.bmWidth;
|
|
bmih.biHeight = bmp.bmHeight;
|
|
bmih.biPlanes = 1;
|
|
bmih.biBitCount = bmp.bmPlanes * bmp.bmBitsPixel;
|
|
bmih.biCompression = BI_RGB;
|
|
bmih.biSizeImage = 0;
|
|
bmih.biXPelsPerMeter = 0;
|
|
bmih.biYPelsPerMeter = 0;
|
|
bmih.biClrUsed = 0;
|
|
bmih.biClrImportant = 0;
|
|
|
|
if (hPalette) {
|
|
hPaletteOld = SelectPalette( hDCMem, hPalette, FALSE );
|
|
RealizePalette( hDCMem );
|
|
}
|
|
|
|
//
|
|
|
|
cbColorTable = CbDIBColorTable( &bmih );
|
|
|
|
cbBits = bmih.biWidth * (DWORD)bmih.biBitCount;
|
|
cbImage = (((cbBits + 31) >> 5) << 2) * bmih.biHeight;
|
|
hDIB = GlobalAlloc( GMEM_ZEROINIT, sizeof(bmih) + cbColorTable + cbImage );
|
|
|
|
if (hDIB)
|
|
{
|
|
|
|
// get dibits
|
|
|
|
pDIB = GlobalLock( hDIB );
|
|
pbmih = (BITMAPINFOHEADER *)pDIB;
|
|
*pbmih = bmih;
|
|
pDIBits = PDIBits( pDIB );
|
|
|
|
if (GetDIBits( hDCMem, hBmp, 0, bmp.bmHeight, pDIBits, (BITMAPINFO *)pbmih, DIB_RGB_COLORS )) {
|
|
GlobalUnlock( hDIB );
|
|
}
|
|
else {
|
|
GlobalUnlock( hDIB );
|
|
GlobalFree( hDIB );
|
|
hDIB = NULL;
|
|
}
|
|
|
|
if (hPaletteOld != NULL) {
|
|
SelectPalette( hDCMem, hPaletteOld, FALSE );
|
|
}
|
|
}
|
|
DeleteDC( hDCMem );
|
|
return hDIB;
|
|
}
|
|
|
|
|
|
/* C R E A T E B M P F R O M D I B */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create Bitmap from DIB
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static HBITMAP CreateBmpFromDIB( HDC hDC, HANDLE hDIB, HPALETTE hPalette )
|
|
{
|
|
void *pDIB;
|
|
void *pDIBits;
|
|
HDC hDCMem;
|
|
BITMAPINFOHEADER *pbmih;
|
|
HPALETTE hPaletteOld = NULL;
|
|
HBITMAP hBmp;
|
|
HBITMAP hBmpOld;
|
|
|
|
if (hDIB == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
|
|
pDIB = GlobalLock( hDIB );
|
|
pbmih = (BITMAPINFOHEADER *)pDIB;
|
|
pDIBits = PDIBits( pDIB );
|
|
|
|
//
|
|
|
|
hBmp = CreateBitmap( pbmih->biWidth, pbmih->biHeight, pbmih->biPlanes, pbmih->biBitCount, NULL );
|
|
if (hBmp == NULL) {
|
|
GlobalUnlock( hDIB );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
|
|
hDCMem = CreateCompatibleDC( hDC );
|
|
if (hDCMem)
|
|
{
|
|
if (hPalette != NULL) {
|
|
hPaletteOld = SelectPalette( hDCMem, hPalette, FALSE );
|
|
RealizePalette( hDCMem );
|
|
}
|
|
|
|
hBmpOld = (HBITMAP)SelectObject( hDCMem, hBmp );
|
|
StretchDIBits( hDCMem, 0, 0, pbmih->biWidth, pbmih->biHeight, 0, 0, pbmih->biWidth, pbmih->biHeight, pDIBits, (BITMAPINFO *)pbmih, DIB_RGB_COLORS, SRCCOPY );
|
|
SelectObject( hDCMem, hBmpOld );
|
|
|
|
GlobalUnlock( hDIB );
|
|
DeleteDC( hDCMem );
|
|
}
|
|
return hBmp;
|
|
}
|
|
|
|
|
|
/* C R E A T E D I B 8 F R O M D I B 1 */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create DIB-8bpp from DIB-1bpp
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static HANDLE CreateDIB8FromDIB1( BITMAPINFOHEADER *pbmihSrc, void *pDIBitsSrc )
|
|
{
|
|
HANDLE hDIBDst;
|
|
void *pDIBDst;
|
|
BITMAPINFOHEADER *pbmihDst;
|
|
BYTE *pbPixelsSrc;
|
|
BYTE *pbPixelsDst;
|
|
WORD cbits;
|
|
int cbLnSrc;
|
|
int cbLnDst;
|
|
int cx;
|
|
int cy;
|
|
int x;
|
|
int y;
|
|
int i;
|
|
|
|
Assert( pbmihSrc->biBitCount == 1 );
|
|
|
|
cx = pbmihSrc->biHeight;
|
|
cy = pbmihSrc->biWidth;
|
|
cbits = pbmihSrc->biBitCount;
|
|
|
|
// count of bytes of line (DWORD aligned)
|
|
|
|
cbLnSrc = ((cx + 31) / 32) * 4;
|
|
cbLnDst = (((cx<<3) + 31) / 32) * 4;
|
|
|
|
//
|
|
|
|
hDIBDst = GlobalAlloc( GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD) + ((DWORD)cbLnDst * cy) );
|
|
if (hDIBDst)
|
|
{
|
|
pDIBDst = GlobalLock( hDIBDst );
|
|
|
|
// store bitmap info header
|
|
|
|
pbmihDst = (BITMAPINFOHEADER *)pDIBDst;
|
|
*pbmihDst = *pbmihSrc;
|
|
pbmihDst->biBitCount = 8;
|
|
pbmihDst->biSizeImage = 0;
|
|
pbmihDst->biClrUsed = 0;
|
|
pbmihDst->biClrImportant = 0;
|
|
|
|
// copy palette
|
|
|
|
for (i = 0; i < (1 << cbits); i++) {
|
|
((BITMAPINFO *)pbmihDst)->bmiColors[i] = ((BITMAPINFO *)pbmihSrc)->bmiColors[i];
|
|
}
|
|
|
|
//
|
|
|
|
pbPixelsSrc = (BYTE *)pDIBitsSrc;
|
|
pbPixelsDst = (BYTE *)PDIBits( pDIBDst );
|
|
for (y = 0; y < cy; y++) {
|
|
BYTE *pbSrc = pbPixelsSrc + ((DWORD)cbLnSrc) * y;
|
|
BYTE *pbDst = pbPixelsDst + ((DWORD)cbLnDst) * y;
|
|
BYTE bMask;
|
|
|
|
for (x = 0, bMask = (BYTE)0x80; x < cx; x++) {
|
|
if (*pbSrc & bMask) {
|
|
*pbDst = 1;
|
|
}
|
|
|
|
pbDst++;
|
|
bMask = bMask >> 1;
|
|
|
|
if (bMask < 1) {
|
|
pbSrc++;
|
|
bMask = (BYTE)0x80;
|
|
}
|
|
}
|
|
}
|
|
|
|
GlobalUnlock( hDIBDst );
|
|
}
|
|
return hDIBDst;
|
|
}
|
|
|
|
|
|
/* C R E A T E D I B 8 F R O M D I B 4 */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create DIB-8bpp from DIB-4bpp
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static HANDLE CreateDIB8FromDIB4( BITMAPINFOHEADER *pbmihSrc, void *pDIBitsSrc )
|
|
{
|
|
HANDLE hDIBDst;
|
|
void *pDIBDst;
|
|
BITMAPINFOHEADER *pbmihDst;
|
|
BYTE *pbPixelsSrc;
|
|
BYTE *pbPixelsDst;
|
|
WORD cbits;
|
|
int cbLnSrc;
|
|
int cbLnDst;
|
|
int cx;
|
|
int cy;
|
|
int x;
|
|
int y;
|
|
int i;
|
|
|
|
Assert( pbmihSrc->biBitCount == 4 );
|
|
|
|
cx = pbmihSrc->biHeight;
|
|
cy = pbmihSrc->biWidth;
|
|
cbits = pbmihSrc->biBitCount;
|
|
|
|
// count of bytes of line (DWORD aligned)
|
|
|
|
cbLnSrc = (((cx<<2) + 31) / 32) * 4;
|
|
cbLnDst = (((cx<<3) + 31) / 32) * 4;
|
|
|
|
//
|
|
|
|
hDIBDst = GlobalAlloc( GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD) + ((DWORD)cbLnDst * cy) );
|
|
if (hDIBDst)
|
|
{
|
|
pDIBDst = GlobalLock( hDIBDst );
|
|
|
|
// store bitmap info header
|
|
|
|
pbmihDst = (BITMAPINFOHEADER *)pDIBDst;
|
|
*pbmihDst = *pbmihSrc;
|
|
pbmihDst->biBitCount = 8;
|
|
pbmihDst->biSizeImage = 0;
|
|
pbmihDst->biClrUsed = 0;
|
|
pbmihDst->biClrImportant = 0;
|
|
|
|
// copy palette
|
|
|
|
for (i = 0; i < (1 << cbits); i++) {
|
|
((BITMAPINFO *)pbmihDst)->bmiColors[i] = ((BITMAPINFO *)pbmihSrc)->bmiColors[i];
|
|
}
|
|
|
|
//
|
|
|
|
pbPixelsSrc = (BYTE *)pDIBitsSrc;
|
|
pbPixelsDst = (BYTE *)PDIBits( pDIBDst );
|
|
for (y = 0; y < cy; y++) {
|
|
BYTE *pbSrc = pbPixelsSrc + ((DWORD)cbLnSrc) * y;
|
|
BYTE *pbDst = pbPixelsDst + ((DWORD)cbLnDst) * y;
|
|
|
|
for (x = 0; x < cx; x+=2 ) {
|
|
*(pbDst++) = ((*pbSrc & 0xf0) >> 4);
|
|
*(pbDst++) = (*(pbSrc++) & 0x0f);
|
|
}
|
|
}
|
|
|
|
GlobalUnlock( hDIBDst );
|
|
}
|
|
return hDIBDst;
|
|
}
|
|
|
|
|
|
/* C R E A T E R O T A T E D I B */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create a rotated DIB from DIB
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static HANDLE CreateRotateDIB( HANDLE hDIBSrc, CANDANGLE angle )
|
|
{
|
|
HANDLE hDIB8 = NULL;
|
|
void *pDIBSrc;
|
|
BITMAPINFOHEADER bmihSrc;
|
|
void *pDIBitsSrc;
|
|
int cxSrc;
|
|
int cySrc;
|
|
long cbLnSrc;
|
|
|
|
HANDLE hDIBDst;
|
|
void *pDIBDst;
|
|
BITMAPINFOHEADER *pbmihDst;
|
|
void *pDIBitsDst;
|
|
int cxDst;
|
|
int cyDst;
|
|
long cbLnDst;
|
|
|
|
int cBitsPixel; /* number of bits per pixel */
|
|
int cbPixel; /* number of bytes per pixel */
|
|
BYTE *pbPixelSrc;
|
|
BYTE *pbPixelDst;
|
|
int cbNextPixel;
|
|
int cbNextLine;
|
|
int x;
|
|
int y;
|
|
|
|
// sanity check
|
|
|
|
if (hDIBSrc == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// prepare source DIB
|
|
//
|
|
|
|
pDIBSrc = GlobalLock( hDIBSrc );
|
|
bmihSrc = *((BITMAPINFOHEADER *)pDIBSrc);
|
|
pDIBitsSrc = PDIBits( pDIBSrc );
|
|
|
|
// if bit depth is less than eight convert to an 8bpp image so that we can rotate.
|
|
|
|
if (bmihSrc.biBitCount < 8) {
|
|
hDIB8 = (bmihSrc.biBitCount == 4) ? CreateDIB8FromDIB4( &bmihSrc, PDIBits(pDIBSrc) )
|
|
: CreateDIB8FromDIB1( &bmihSrc, PDIBits(pDIBSrc) );
|
|
|
|
GlobalUnlock( hDIBSrc );
|
|
|
|
// satori81#312 / prefix#179976
|
|
if (hDIB8 == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
hDIBSrc = hDIB8;
|
|
pDIBSrc = GlobalLock( hDIB8 );
|
|
bmihSrc = *((BITMAPINFOHEADER *)pDIBSrc);
|
|
pDIBitsSrc = PDIBits( pDIBSrc );
|
|
}
|
|
|
|
cxSrc = bmihSrc.biWidth;
|
|
cySrc = bmihSrc.biHeight;
|
|
|
|
//
|
|
// create rotated DIB
|
|
//
|
|
|
|
// calc DIBits size
|
|
|
|
cBitsPixel = bmihSrc.biBitCount;
|
|
cbPixel = cBitsPixel/8;
|
|
|
|
switch (angle) {
|
|
default:
|
|
case CANGLE0:
|
|
case CANGLE180: {
|
|
cxDst = cxSrc;
|
|
cyDst = cySrc;
|
|
break;
|
|
}
|
|
|
|
case CANGLE90:
|
|
case CANGLE270: {
|
|
cxDst = cySrc;
|
|
cyDst = cxSrc;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// count of bytes of line (DWORD aligned)
|
|
|
|
cbLnSrc = (((cxSrc * bmihSrc.biBitCount) + 31) / 32) * 4;
|
|
cbLnDst = (((cxDst * bmihSrc.biBitCount) + 31) / 32) * 4;
|
|
|
|
// allocate memory for new dib bits
|
|
|
|
hDIBDst = GlobalAlloc( GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER) + CbDIBColorTable( &bmihSrc ) + ((DWORD)cbLnDst * cyDst) );
|
|
if (!hDIBDst) {
|
|
//satori81#258 / prefix#179977
|
|
GlobalUnlock( hDIBSrc );
|
|
if (hDIB8 != NULL) {
|
|
GlobalFree( hDIB8 );
|
|
}
|
|
return NULL;
|
|
}
|
|
pDIBDst = GlobalLock( hDIBDst );
|
|
pbmihDst = (BITMAPINFOHEADER *)pDIBDst;
|
|
|
|
// store bitmap infoheader (including color table)
|
|
|
|
memcpy( pDIBDst, pDIBSrc, sizeof(BITMAPINFOHEADER) + CbDIBColorTable( &bmihSrc ) );
|
|
pbmihDst->biHeight = cyDst;
|
|
pbmihDst->biWidth = cxDst;
|
|
pbmihDst->biSizeImage = 0;
|
|
|
|
pDIBitsDst = PDIBits( pDIBDst );
|
|
|
|
//
|
|
// create rotated DIBits
|
|
//
|
|
|
|
pbPixelSrc = (BYTE *)pDIBitsSrc;
|
|
switch (angle) {
|
|
default:
|
|
case CANGLE0: {
|
|
cbNextPixel = cbPixel;
|
|
cbNextLine = cbLnDst;
|
|
|
|
pbPixelDst = (BYTE*)pDIBitsDst;
|
|
break;
|
|
}
|
|
|
|
case CANGLE90: {
|
|
cbNextPixel = cbLnDst;
|
|
cbNextLine = -cbPixel;
|
|
|
|
pbPixelDst = (BYTE*)pDIBitsDst + ((DWORD)cbPixel*(cxDst - 1));
|
|
break;
|
|
}
|
|
|
|
case CANGLE180: {
|
|
cbNextPixel = -cbPixel;
|
|
cbNextLine = -cbLnDst;
|
|
|
|
pbPixelDst = (BYTE*)pDIBitsDst + ((DWORD)cbPixel*(cxDst - 1) + (DWORD)cbLnDst*(cyDst - 1));
|
|
break;
|
|
}
|
|
|
|
case CANGLE270: {
|
|
cbNextPixel = -cbLnDst;
|
|
cbNextLine = cbPixel;
|
|
|
|
pbPixelDst = (BYTE*)pDIBitsDst + ((DWORD)cbLnDst*(cyDst - 1));
|
|
}
|
|
}
|
|
|
|
// copy bits
|
|
|
|
for (y = 0; y < cySrc; y++) {
|
|
BYTE *pbPixelSrcLine = pbPixelSrc;
|
|
BYTE *pbPixelDstLine = pbPixelDst;
|
|
|
|
for (x = 0; x < cxSrc; x++) {
|
|
memcpy( pbPixelDst, pbPixelSrc, cbPixel );
|
|
|
|
pbPixelSrc += cbPixel;
|
|
pbPixelDst += cbNextPixel;
|
|
}
|
|
|
|
pbPixelSrc = pbPixelSrcLine + cbLnSrc;
|
|
pbPixelDst = pbPixelDstLine + cbNextLine;
|
|
}
|
|
|
|
//
|
|
// finish creating new DIB
|
|
//
|
|
|
|
GlobalUnlock( hDIBDst );
|
|
GlobalUnlock( hDIBSrc );
|
|
|
|
// dispose temporary DIB
|
|
|
|
if (hDIB8 != NULL) {
|
|
GlobalFree( hDIB8 );
|
|
}
|
|
|
|
return hDIBDst;
|
|
}
|
|
|
|
|
|
/* C R E A T E R O T A T E B I T M A P */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Create a rotated bitmap from bitmap
|
|
|
|
------------------------------------------------------------------------------*/
|
|
HBITMAP CreateRotateBitmap( HBITMAP hBmpSrc, HPALETTE hPalette, CANDANGLE angle )
|
|
{
|
|
HDC hDC;
|
|
HBITMAP hBmpDst;
|
|
HANDLE hDIBSrc;
|
|
HANDLE hDIBDst;
|
|
|
|
hDC = CreateDC( "DISPLAY", NULL, NULL, NULL );
|
|
// satori81#256 / prefix#110692
|
|
if (hDC == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
// create dib from bitmap
|
|
|
|
if ((hDIBSrc = CreateDIBFromBmp( hDC, hBmpSrc, hPalette )) == NULL) {
|
|
DeleteDC( hDC );
|
|
return NULL;
|
|
}
|
|
|
|
// rotate bitmap
|
|
|
|
hDIBDst = CreateRotateDIB( hDIBSrc, angle );
|
|
|
|
// create bitmap from dib
|
|
|
|
hBmpDst = CreateBmpFromDIB( hDC, hDIBDst, hPalette );
|
|
|
|
// dispose temp objects
|
|
|
|
GlobalFree( hDIBSrc );
|
|
GlobalFree( hDIBDst );
|
|
|
|
if (hDC)
|
|
DeleteDC( hDC );
|
|
|
|
return hBmpDst;
|
|
}
|
|
|
|
|
|
/* G E T T E X T E X T E N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Get text extent of the given wide string with specified font
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void GetTextExtent( HFONT hFont, LPCWSTR pwchText, int cch, SIZE *psize, BOOL fHorizontal )
|
|
{
|
|
HDC hDC;
|
|
HFONT hFontOld;
|
|
const int nOffOneBugShield = 1;
|
|
|
|
psize->cx = 0;
|
|
psize->cy = 0;
|
|
|
|
if (pwchText != NULL) {
|
|
hDC = GetDC(NULL);
|
|
hFontOld = (HFONT)SelectObject(hDC, hFont);
|
|
|
|
FLGetTextExtentPoint32(hDC, pwchText, cch, psize);
|
|
|
|
SelectObject(hDC, hFontOld);
|
|
ReleaseDC(NULL, hDC);
|
|
|
|
// HACK
|
|
// FLGetTextExtentPoint32() is suspected have off-one bug in calculation with "vertical" font.
|
|
if ( !fHorizontal ) {
|
|
psize->cx += nOffOneBugShield;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/* G E T W O R K A R E A F R O M W I N D O W */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void GetWorkAreaFromWindow( HWND hWindow, RECT *prc )
|
|
{
|
|
HMONITOR hMonitor = NULL;
|
|
|
|
SystemParametersInfo( SPI_GETWORKAREA, 0, prc, 0 );
|
|
hMonitor = CUIMonitorFromWindow( hWindow, MONITOR_DEFAULTTONEAREST );
|
|
if (hMonitor != NULL) {
|
|
MONITORINFO MonitorInfo = {0};
|
|
|
|
MonitorInfo.cbSize = sizeof(MONITORINFO);
|
|
if (CUIGetMonitorInfo( hMonitor, &MonitorInfo )) {
|
|
*prc = MonitorInfo.rcWork;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* G E T W O R K A R E A F R O M P O I N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void GetWorkAreaFromPoint( POINT pt, RECT *prc )
|
|
{
|
|
HMONITOR hMonitor = NULL;
|
|
|
|
// We want the screen size - not the working area as we can and do want to overlap toolbars etc.
|
|
// We use the basic function first as a fail-safe.
|
|
prc->left = prc->top = 0;
|
|
prc->right = GetSystemMetrics(SM_CXSCREEN);
|
|
prc->bottom = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
// Now we use the more intelligent function to deal with multiple monitors properly.
|
|
hMonitor = CUIMonitorFromPoint( pt, MONITOR_DEFAULTTONEAREST );
|
|
if (hMonitor != NULL)
|
|
{
|
|
MONITORINFO MonitorInfo = {0};
|
|
|
|
MonitorInfo.cbSize = sizeof(MONITORINFO);
|
|
if (CUIGetMonitorInfo( hMonitor, &MonitorInfo ))
|
|
{
|
|
*prc = MonitorInfo.rcMonitor;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* A D J U S T W I N D O W R E C T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void AdjustWindowRect( HWND hWindow, RECT *prc, POINT *pptRef, BOOL fResize )
|
|
{
|
|
RECT rcWorkArea;
|
|
int cxWindow;
|
|
int cyWindow;
|
|
|
|
cxWindow = prc->right - prc->left;
|
|
cyWindow = prc->bottom - prc->top;
|
|
|
|
// get work area
|
|
|
|
if (pptRef == NULL) {
|
|
GetWorkAreaFromWindow( hWindow, &rcWorkArea );
|
|
}
|
|
else {
|
|
GetWorkAreaFromPoint( *pptRef, &rcWorkArea );
|
|
}
|
|
|
|
// check vertical pos
|
|
|
|
if (rcWorkArea.bottom < prc->bottom) {
|
|
if (!fResize) {
|
|
prc->top = rcWorkArea.bottom - cyWindow;
|
|
}
|
|
prc->bottom = rcWorkArea.bottom;
|
|
}
|
|
if (prc->top < rcWorkArea.top) {
|
|
prc->top = rcWorkArea.top;
|
|
if (!fResize) {
|
|
prc->bottom = rcWorkArea.top + cyWindow;
|
|
}
|
|
}
|
|
|
|
// check horizontal pos
|
|
|
|
if (rcWorkArea.right < prc->right) {
|
|
if (!fResize) {
|
|
prc->left = rcWorkArea.right - cxWindow;
|
|
}
|
|
prc->right = rcWorkArea.right;
|
|
}
|
|
if (prc->left < rcWorkArea.left) {
|
|
prc->left = rcWorkArea.left;
|
|
if (!fResize) {
|
|
prc->right = rcWorkArea.left + cxWindow;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* C A L C W I N D O W R E C T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Calculate window rect to fit in the screen
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void CalcWindowRect( RECT *prcDst, const RECT *prcSrc, int cxWindow, int cyWindow, int cxOffset, int cyOffset, WNDALIGNH HAlign, WNDALIGNV VAlign )
|
|
{
|
|
RECT rcNew;
|
|
RECT rcWorkArea;
|
|
POINT ptRef;
|
|
|
|
Assert( prcDst != NULL );
|
|
Assert( prcSrc != NULL );
|
|
|
|
// calc rect and reference point
|
|
|
|
switch (HAlign) {
|
|
default:
|
|
case ALIGN_LEFT: {
|
|
rcNew.left = prcSrc->left + cxOffset;
|
|
rcNew.right = prcSrc->left + cxOffset + cxWindow;
|
|
|
|
ptRef.x = prcSrc->left;
|
|
break;
|
|
}
|
|
|
|
case ALIGN_RIGHT: {
|
|
rcNew.left = prcSrc->right + cxOffset - cxWindow;
|
|
rcNew.right = prcSrc->right + cxOffset;
|
|
|
|
ptRef.x = prcSrc->right;
|
|
break;
|
|
}
|
|
|
|
case LOCATE_LEFT: {
|
|
rcNew.left = prcSrc->left + cxOffset - cxWindow;
|
|
rcNew.right = prcSrc->left + cxOffset;
|
|
|
|
ptRef.x = prcSrc->right;
|
|
break;
|
|
}
|
|
|
|
case LOCATE_RIGHT: {
|
|
rcNew.left = prcSrc->right + cxOffset;
|
|
rcNew.right = prcSrc->right + cxOffset + cxWindow;
|
|
|
|
ptRef.x = prcSrc->left;
|
|
break;
|
|
}
|
|
}
|
|
|
|
switch (VAlign) {
|
|
default:
|
|
case ALIGN_TOP: {
|
|
rcNew.top = prcSrc->top + cyOffset;
|
|
rcNew.bottom = prcSrc->top + cyOffset + cyWindow;
|
|
|
|
ptRef.y = prcSrc->top;
|
|
break;
|
|
}
|
|
|
|
case ALIGN_BOTTOM: {
|
|
rcNew.top = prcSrc->bottom + cyOffset - cyWindow;
|
|
rcNew.bottom = prcSrc->bottom + cyOffset;
|
|
|
|
ptRef.y = prcSrc->bottom;
|
|
break;
|
|
}
|
|
|
|
case LOCATE_ABOVE: {
|
|
rcNew.top = prcSrc->top + cyOffset - cyWindow;
|
|
rcNew.bottom = prcSrc->top + cyOffset;
|
|
|
|
ptRef.y = prcSrc->bottom;
|
|
break;
|
|
}
|
|
|
|
case LOCATE_BELLOW: {
|
|
rcNew.top = prcSrc->bottom + cyOffset;
|
|
rcNew.bottom = prcSrc->bottom + cyOffset + cyWindow;
|
|
|
|
ptRef.y = prcSrc->top;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// get work area
|
|
|
|
GetWorkAreaFromPoint( ptRef, &rcWorkArea );
|
|
|
|
// check vertical pos
|
|
|
|
if (rcWorkArea.bottom < rcNew.bottom) {
|
|
if ((VAlign == LOCATE_BELLOW) && (rcWorkArea.top <= prcSrc->top - cyWindow)) {
|
|
rcNew.top = min( prcSrc->top, rcWorkArea.bottom ) - cyWindow;
|
|
rcNew.bottom = rcNew.top + cyWindow;
|
|
}
|
|
else {
|
|
rcNew.top = rcWorkArea.bottom - cyWindow;
|
|
rcNew.bottom = rcNew.top + cyWindow;
|
|
}
|
|
}
|
|
if (rcNew.top < rcWorkArea.top) {
|
|
if ((VAlign == LOCATE_ABOVE) && (prcSrc->bottom + cyWindow <= rcWorkArea.bottom)) {
|
|
rcNew.top = max( prcSrc->bottom, rcWorkArea.top );
|
|
rcNew.bottom = rcNew.top + cyWindow;
|
|
}
|
|
else {
|
|
rcNew.top = rcWorkArea.top;
|
|
rcNew.bottom = rcNew.top + cyWindow;
|
|
}
|
|
}
|
|
|
|
// check horizontal pos
|
|
|
|
if (rcWorkArea.right < rcNew.right) {
|
|
if ((HAlign == LOCATE_RIGHT) && (rcWorkArea.left <= prcSrc->left - cxWindow)) {
|
|
rcNew.left = min( prcSrc->left, rcWorkArea.right ) - cxWindow;
|
|
rcNew.right = rcNew.left + cxWindow;
|
|
}
|
|
else {
|
|
rcNew.left = rcWorkArea.right - cxWindow;
|
|
rcNew.right = rcNew.left + cxWindow;
|
|
}
|
|
}
|
|
if (rcNew.left < rcWorkArea.left) {
|
|
if ((HAlign == LOCATE_LEFT) && (prcSrc->right + cxWindow <= rcWorkArea.right)) {
|
|
rcNew.left = max( prcSrc->right, rcWorkArea.left );
|
|
rcNew.right = rcNew.left + cxWindow;
|
|
}
|
|
else {
|
|
rcNew.left = rcWorkArea.left;
|
|
rcNew.right = rcNew.left + cxWindow;
|
|
}
|
|
}
|
|
|
|
*prcDst = rcNew;
|
|
}
|
|
|
|
|
|
/* G E T L O G F O N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Get logfont of font
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void GetLogFont( HFONT hFont, LOGFONTW *plf )
|
|
{
|
|
if (!FIsWindowsNT()) {
|
|
LOGFONTA lfA;
|
|
|
|
GetObjectA( hFont, sizeof(LOGFONTA), &lfA );
|
|
ConvertLogFontAtoW( &lfA, plf );
|
|
return;
|
|
}
|
|
|
|
GetObjectW( hFont, sizeof(LOGFONTW), plf );
|
|
}
|
|
|
|
|
|
/* G E T N O N C L I E N T L O G F O N T */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
Get logfont of non-client font
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void GetNonClientLogFont( NONCLIENTFONT ncfont, LOGFONTW *plf )
|
|
{
|
|
if (!FIsWindowsNT()) {
|
|
NONCLIENTMETRICSA ncmA = {0};
|
|
LOGFONTA lf;
|
|
|
|
ncmA.cbSize = sizeof(ncmA);
|
|
SystemParametersInfoA( SPI_GETNONCLIENTMETRICS, sizeof(ncmA), &ncmA, 0 );
|
|
|
|
switch (ncfont) {
|
|
default:
|
|
case NCFONT_CAPTION: {
|
|
lf = ncmA.lfCaptionFont;
|
|
break;
|
|
}
|
|
case NCFONT_SMCAPTION: {
|
|
lf = ncmA.lfSmCaptionFont;
|
|
break;
|
|
}
|
|
case NCFONT_MENU: {
|
|
lf = ncmA.lfMenuFont;
|
|
break;
|
|
}
|
|
case NCFONT_STATUS: {
|
|
lf = ncmA.lfStatusFont;
|
|
break;
|
|
}
|
|
case NCFONT_MESSAGE: {
|
|
lf = ncmA.lfMessageFont;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ConvertLogFontAtoW( &lf, plf );
|
|
}
|
|
else {
|
|
NONCLIENTMETRICSW ncmW = {0};
|
|
LOGFONTW lf;
|
|
|
|
ncmW.cbSize = sizeof(ncmW);
|
|
SystemParametersInfoW( SPI_GETNONCLIENTMETRICS, sizeof(ncmW), &ncmW, 0 );
|
|
|
|
switch (ncfont) {
|
|
default:
|
|
case NCFONT_CAPTION: {
|
|
lf = ncmW.lfCaptionFont;
|
|
break;
|
|
}
|
|
case NCFONT_SMCAPTION: {
|
|
lf = ncmW.lfSmCaptionFont;
|
|
break;
|
|
}
|
|
case NCFONT_MENU: {
|
|
lf = ncmW.lfMenuFont;
|
|
break;
|
|
}
|
|
case NCFONT_STATUS: {
|
|
lf = ncmW.lfStatusFont;
|
|
break;
|
|
}
|
|
case NCFONT_MESSAGE: {
|
|
lf = ncmW.lfMessageFont;
|
|
break;
|
|
}
|
|
}
|
|
|
|
*plf = lf;
|
|
}
|
|
}
|
|
|
|
|
|
void DrawTriangle( HDC hDC, const RECT *prc, COLORREF col, DWORD dwFlag )
|
|
{
|
|
HPEN hPen;
|
|
HPEN hPenOld;
|
|
POINT ptTriOrg;
|
|
int nTriHeight;
|
|
int nTriWidth;
|
|
SIZE size;
|
|
int i;
|
|
|
|
size.cx = prc->right - prc->left;
|
|
size.cy = prc->bottom - prc->top;
|
|
|
|
switch ( dwFlag ) {
|
|
|
|
case UIFDCTF_RIGHTTOLEFT:
|
|
case UIFDCTF_LEFTTORIGHT:
|
|
nTriHeight = min ( size.cx, size.cy ) / 3;
|
|
nTriHeight = nTriHeight - ( nTriHeight % 2 ) + 1; // Make an odd number
|
|
nTriWidth = nTriHeight / 2 + 1;
|
|
break;
|
|
|
|
case UIFDCTF_BOTTOMTOTOP:
|
|
case UIFDCTF_TOPTOBOTTOM:
|
|
nTriWidth = min ( size.cx, size.cy ) / 3;
|
|
nTriWidth = nTriWidth - ( nTriWidth % 2 ) + 1;
|
|
nTriHeight = nTriWidth / 2 + 1;
|
|
break;
|
|
|
|
case UIFDCTF_MENUDROP:
|
|
nTriWidth = 5;
|
|
nTriHeight = 3;
|
|
break;
|
|
}
|
|
|
|
ptTriOrg.x = prc->left + (size.cx - nTriWidth) / 2;
|
|
ptTriOrg.y = prc->top + (size.cy - nTriHeight) / 2;
|
|
|
|
hPen = CreatePen( PS_SOLID, 0, col );
|
|
hPenOld = (HPEN)SelectObject(hDC, hPen);
|
|
|
|
switch ( dwFlag & UIFDCTF_DIRMASK ) {
|
|
|
|
case UIFDCTF_RIGHTTOLEFT:
|
|
for (i = 0; i < nTriWidth; i++) {
|
|
MoveToEx( hDC, ptTriOrg.x + nTriWidth - i, ptTriOrg.y + i, NULL );
|
|
LineTo( hDC, ptTriOrg.x + nTriWidth - i, ptTriOrg.y + nTriHeight - i );
|
|
}
|
|
break;
|
|
|
|
case UIFDCTF_BOTTOMTOTOP:
|
|
for (i = 0; i < nTriHeight; i++) {
|
|
MoveToEx( hDC, ptTriOrg.x + i, ptTriOrg.y + nTriHeight - i, NULL );
|
|
LineTo( hDC, ptTriOrg.x + nTriWidth - i, ptTriOrg.y + nTriHeight - i );
|
|
}
|
|
break;
|
|
|
|
case UIFDCTF_LEFTTORIGHT:
|
|
for (i = 0; i < nTriWidth; i++) {
|
|
MoveToEx( hDC, ptTriOrg.x + i, ptTriOrg.y + i, NULL );
|
|
LineTo( hDC, ptTriOrg.x + i, ptTriOrg.y + nTriHeight - i );
|
|
}
|
|
break;
|
|
|
|
case UIFDCTF_TOPTOBOTTOM:
|
|
for (i = 0; i < nTriHeight; i++) {
|
|
MoveToEx( hDC, ptTriOrg.x + i, ptTriOrg.y + i, NULL );
|
|
LineTo( hDC, ptTriOrg.x + nTriWidth - i, ptTriOrg.y + i );
|
|
}
|
|
break;
|
|
}
|
|
|
|
SelectObject( hDC, hPenOld );
|
|
DeleteObject( hPen );
|
|
}
|
|
|
|
|
|
/* O U R C R E A T E S I D */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
static PSID OurCreateSid( DWORD dwSubAuthority )
|
|
{
|
|
PSID psid;
|
|
BOOL fResult;
|
|
SID_IDENTIFIER_AUTHORITY SidAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
//
|
|
// allocate and initialize an SID
|
|
//
|
|
fResult = AllocateAndInitializeSid( &SidAuthority,
|
|
1,
|
|
dwSubAuthority,
|
|
0,0,0,0,0,0,0,
|
|
&psid );
|
|
if ( ! fResult ) {
|
|
return NULL;
|
|
}
|
|
|
|
if ( ! IsValidSid( psid ) ) {
|
|
FreeSid( psid );
|
|
return NULL;
|
|
}
|
|
|
|
return psid;
|
|
}
|
|
|
|
|
|
/* C R E A T E S E C U R I T Y A T T R I B U T E S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
//
|
|
// CreateSecurityAttributes()
|
|
//
|
|
// The purpose of this function:
|
|
//
|
|
// Allocate and set the security attributes that is
|
|
// appropriate for named objects created by an IME.
|
|
// The security attributes will give GENERIC_ALL
|
|
// access to the following users:
|
|
//
|
|
// o Users who log on for interactive operation
|
|
// o The user account used by the operating system
|
|
//
|
|
// Return value:
|
|
//
|
|
// If the function succeeds, the return value is a
|
|
// pointer to SECURITY_ATTRIBUTES. If the function fails,
|
|
// the return value is NULL. To get extended error
|
|
// information, call GetLastError().
|
|
//
|
|
// Remarks:
|
|
//
|
|
// FreeSecurityAttributes() should be called to free up the
|
|
// SECURITY_ATTRIBUTES allocated by this function.
|
|
//
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
#if 0
|
|
|
|
static PSECURITY_ATTRIBUTES CreateSecurityAttributes()
|
|
{
|
|
PSECURITY_ATTRIBUTES psa;
|
|
PSECURITY_DESCRIPTOR psd;
|
|
PACL pacl;
|
|
DWORD cbacl;
|
|
|
|
PSID psid1, psid2, psid3, psid4;
|
|
BOOL fResult;
|
|
|
|
psid1 = OurCreateSid( SECURITY_INTERACTIVE_RID );
|
|
if ( psid1 == NULL ) {
|
|
return NULL;
|
|
}
|
|
|
|
psid2 = OurCreateSid( SECURITY_LOCAL_SYSTEM_RID );
|
|
if ( psid2 == NULL ) {
|
|
FreeSid ( psid1 );
|
|
return NULL;
|
|
}
|
|
|
|
psid3 = OurCreateSid( SECURITY_SERVICE_RID );
|
|
if ( psid3 == NULL ) {
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
return NULL;
|
|
}
|
|
|
|
psid4 = OurCreateSid( SECURITY_NETWORK_RID );
|
|
if ( psid4 == NULL ) {
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
return NULL;
|
|
}
|
|
//
|
|
// allocate and initialize an access control list (ACL) that will
|
|
// contain the SIDs we've just created.
|
|
//
|
|
cbacl = sizeof(ACL) +
|
|
(sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD)) * 4 +
|
|
GetLengthSid(psid1) + GetLengthSid(psid2) + GetLengthSid(psid3) + GetLengthSid(psid4);
|
|
|
|
pacl = (PACL)LocalAlloc( LMEM_FIXED, cbacl );
|
|
if ( pacl == NULL ) {
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
return NULL;
|
|
}
|
|
|
|
fResult = InitializeAcl( pacl, cbacl, ACL_REVISION );
|
|
if ( ! fResult ) {
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
LocalFree( pacl );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for interactive users to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce( pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid1 );
|
|
|
|
if ( !fResult ) {
|
|
LocalFree( pacl );
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce( pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid2 );
|
|
|
|
if ( !fResult ) {
|
|
LocalFree( pacl );
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce( pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid3 );
|
|
|
|
if ( !fResult ) {
|
|
LocalFree( pacl );
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// adds an access-allowed ACE for operating system to the ACL
|
|
//
|
|
fResult = AddAccessAllowedAce( pacl,
|
|
ACL_REVISION,
|
|
GENERIC_ALL,
|
|
psid4 );
|
|
|
|
if ( !fResult ) {
|
|
LocalFree( pacl );
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// Those SIDs have been copied into the ACL. We don't need'em any more.
|
|
//
|
|
FreeSid ( psid1 );
|
|
FreeSid ( psid2 );
|
|
FreeSid ( psid3 );
|
|
FreeSid ( psid4 );
|
|
|
|
//
|
|
// Let's make sure that our ACL is valid.
|
|
//
|
|
if (!IsValidAcl(pacl)) {
|
|
LocalFree( pacl );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// allocate security attribute
|
|
//
|
|
psa = (PSECURITY_ATTRIBUTES)LocalAlloc( LMEM_FIXED, sizeof( SECURITY_ATTRIBUTES ) );
|
|
if ( psa == NULL ) {
|
|
LocalFree( pacl );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// allocate and initialize a new security descriptor
|
|
//
|
|
psd = LocalAlloc( LMEM_FIXED, SECURITY_DESCRIPTOR_MIN_LENGTH );
|
|
if ( psd == NULL ) {
|
|
LocalFree( pacl );
|
|
LocalFree( psa );
|
|
return NULL;
|
|
}
|
|
|
|
if ( ! InitializeSecurityDescriptor( psd, SECURITY_DESCRIPTOR_REVISION ) ) {
|
|
LocalFree( pacl );
|
|
LocalFree( psa );
|
|
LocalFree( psd );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
fResult = SetSecurityDescriptorDacl( psd,
|
|
TRUE,
|
|
pacl,
|
|
FALSE );
|
|
|
|
// The discretionary ACL is referenced by, not copied
|
|
// into, the security descriptor. We shouldn't free up ACL
|
|
// after the SetSecurityDescriptorDacl call.
|
|
|
|
if ( ! fResult ) {
|
|
LocalFree( pacl );
|
|
LocalFree( psa );
|
|
LocalFree( psd );
|
|
return NULL;
|
|
}
|
|
|
|
if (!IsValidSecurityDescriptor(psd)) {
|
|
LocalFree( pacl );
|
|
LocalFree( psa );
|
|
LocalFree( psd );
|
|
return NULL;
|
|
}
|
|
|
|
//
|
|
// everything is done
|
|
//
|
|
psa->nLength = sizeof( SECURITY_ATTRIBUTES );
|
|
psa->lpSecurityDescriptor = (PVOID)psd;
|
|
psa->bInheritHandle = TRUE;
|
|
|
|
return psa;
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
/* F R E E S E C U R I T Y A T T R I B U T E S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
//
|
|
// FreeSecurityAttributes()
|
|
//
|
|
// The purpose of this function:
|
|
//
|
|
// Frees the memory objects allocated by previous
|
|
// CreateSecurityAttributes() call.
|
|
//
|
|
|
|
------------------------------------------------------------------------------*/
|
|
|
|
#if 0
|
|
|
|
static void FreeSecurityAttributes( PSECURITY_ATTRIBUTES psa )
|
|
{
|
|
BOOL fResult;
|
|
BOOL fDaclPresent;
|
|
BOOL fDaclDefaulted;
|
|
PACL pacl;
|
|
|
|
fResult = GetSecurityDescriptorDacl( psa->lpSecurityDescriptor,
|
|
&fDaclPresent,
|
|
&pacl,
|
|
&fDaclDefaulted );
|
|
if ( fResult ) {
|
|
if ( pacl != NULL )
|
|
LocalFree( pacl );
|
|
}
|
|
|
|
LocalFree( psa->lpSecurityDescriptor );
|
|
LocalFree( psa );
|
|
}
|
|
|
|
#endif // 0
|
|
|
|
/* I N I T C A N D U I S E C U R I T Y A T T R I B U T E S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void InitCandUISecurityAttributes( void )
|
|
{
|
|
g_psa = NULL;
|
|
|
|
// disabled for whistler bug 305970
|
|
// CreateSecurityAttributes creates a sid with SECURITY_INTERACTIVE_RID, which
|
|
// allows any user access to the mutex. But g_psa is only used to guard
|
|
// some shared memory and a mutex that are used on a single desktop (the
|
|
// objects have names that are unique to their desktops). So we can just
|
|
// leave g_psa NULL so long as it is only used for objects on a single
|
|
// desktop.
|
|
#if 0
|
|
if (FIsWindowsNT()) {
|
|
g_psa = CreateSecurityAttributes();
|
|
}
|
|
#endif // 0
|
|
}
|
|
|
|
|
|
/* D O N E C A N D U I S E C U R I T Y A T T R I B U T E S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
void DoneCandUISecurityAttributes( void )
|
|
{
|
|
#if 0
|
|
if (g_psa != NULL) {
|
|
FreeSecurityAttributes( g_psa );
|
|
g_psa = NULL;
|
|
}
|
|
#endif // 0
|
|
}
|
|
|
|
|
|
/* G E T C A N D U I S E C U R I T Y A T T R I B U T E S */
|
|
/*------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------*/
|
|
PSECURITY_ATTRIBUTES GetCandUISecurityAttributes( void )
|
|
{
|
|
return g_psa;
|
|
}
|
|
|
|
|