/* 03.13.96 Joe Holman (joehol) Ported from Win95 to NT. 09.23.96 Joe Holman (joehol) Added the code to check for new version message and old version message. 12.05.96 Joe Holman (joehol) Added code to have only one copy running at time. Win95 and NT now calls winnt32.exe. 08.20.97 Joe Holman (joehol) Backport the Japanese code for NEC's PC-98 machine so that we launch autorun from i386, but then turn around and launch winnt32.exe from NEC98. Issues: - for Win95, we want to show: - WINNT32 Setup - Explore the CD - for WinNT, we want to show: - WINNT32.EXE Setup - Explore the CD - Add Remove Programs - The following value is used in WinMain to help not display the applet when some NT Setup thing is asking for the OS CD. Currently, we do not have any windows with this object for NT. Perhaps maybe we will for 5.0. static const char c_szAutoRunPrevention[] = "__WinNTSetupDiskQuery"; */ /* 10.05.96 Shunichi Kajisa (shunk) Support NEC PC-98 1. Determine if autorun is running on PC-98 or regular PC/AT by: bNEC98 = (HIBYTE(LOWORD(GetKeyboardType(1))) == 0x0D)? TRUE : FALSE; Following description is from KB Q130054, and this can be applied on NT and Win95: If an application uses the GetKeyboardType API, it can get OEM ID by specifying "1" (keyboard subtype) as argument of the function. Each OEM ID is listed here: OEM Windows OEM ID ------------------------------ Microsoft 00H (DOS/V) .... NEC 0DH 2. If autorun is running on PC-98, replace every "I386" resource with "PC98" at runtime, regardless that autorun is running on NT or Win95. Notes: - NEC PC-98 is available only in Japan. - NEC PC-98 uses x86 processor, but the underlaying hardware architecture is different. The PC98 files is stored under CD:\pc98 directory instead of CD:\i386. - There was an idea that we should detect PC-98 in SHELL32.DLL, and treat PC98 as a different platform, like having [AutoRun.Pc98] section in NT CD's autorun.inf. We don't do this, since Win95 doesn't support this, and we don't want to introduce the apps incompatibility. In any case, if app has any dependency on the hardware and needs to do any special things, the app should detect the hardware and OS. This is separate issue from Autorun.exe. */ //--------------------------------------------------------------------------- // AutoRun applet. //--------------------------------------------------------------------------- #include "autorun.h" #include "resource.h" #include #include #include #include #define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) //--------------------------------------------------------------------------- // define this to force 4bit mode in debug builds //#define FORCE_4BIT //--------------------------------------------------------------------------- // appwide globals HINSTANCE g_hinst = NULL; BOOL g_f4BitForColor = FALSE; BOOL g_fNeedPalette = FALSE; BOOL g_fMouseAvailable = FALSE; //--------------------------------------------------------------------------- // file globals BOOL g_fAppDisabled = TRUE; HHOOK g_hMouseHook = NULL; HWND g_hMainWindow = NULL; // less of a pain for our mouse hook to see int g_iActiveButton = -2; // less of a pain for our mouse hook to see const RGBQUAD g_rgbBlack = {0}; const RGBQUAD g_rgbWhite = {0xFF, 0xFF, 0xFF, 0}; #pragma data_seg(".text") static const char c_szAutoRunPrevention[] = "__WinNTSetupDiskQuery"; static const char c_szAutoRunClass[] = "AutoRunMain"; static const char c_szNULL[] = ""; static const char c_szArial[] = "Arial"; static const char c_szButtonClass[] = "Button"; static const char c_szSetupKey[] = REGSTR_PATH_SETUP "\\SETUP"; static const char c_szExpoSwitch[] = "Expostrt"; #pragma data_seg() char szAppTitle[MAX_PATH]; CHAR dbgStr[2*MAX_PATH]; BOOL bDebug = FALSE; //--------------------------------------------------------------------------- // private messages #define ARM_MOUSEOVER (WM_APP) //--------------------------------------------------------------------------- // states for tracking mouse over buttons #define BTNST_DEAD (0) #define BTNST_UP (1) #define BTNST_DOWN (2) #define BTNST_UNDOWN (3) //--------------------------------------------------------------------------- // how to root a relative path (if at all) #define NOROOT (0x00000000) #define ONACD (0x00000001) #define INWIN (0x00000002) #define INSYS (0x00000003) #define ALLROOTS (0x00000003) #define ROOTED(app,parms,dir) \ ((((DWORD)app)<<6)|(((DWORD)parms)<<3)|(DWORD)dir) #define CMD_ROOT(item) ((((DWORD)item)>>6)&ALLROOTS) #define PARAMS_ROOT(item) ((((DWORD)item)>>3)&ALLROOTS) #define DEFDIR_ROOT(item) (((DWORD)item)&ALLROOTS) #define BUTTON_IMAGE_X_SIZE (59) #define BUTTON_IMAGE_Y_SIZE (59) #define NORMAL_IMAGE_X_OFFSET (0) #define FOCUS_IMAGE_X_OFFSET (BUTTON_IMAGE_X_SIZE) #define SELECTED_IMAGE_X_OFFSET (2 * BUTTON_IMAGE_X_SIZE) #define DISABLED_IMAGE_X_OFFSET (3 * BUTTON_IMAGE_X_SIZE) #define BUTTON_DEFAULT_CX (BUTTON_IMAGE_X_SIZE) #define BUTTON_DEFAULT_CY (BUTTON_IMAGE_Y_SIZE) #define BUTTON_LABEL_RECT { -160, 17, -20, 66 } #define DEF_BUTTON_LABEL_HEIGHT (19) #define AUTORUN_DESCRIPTION_LEFT (36) #define AUTORUN_DESCRIPTION_TOP (313) #define AUTORUN_DESCRIPTION_RIGHT (360) #define AUTORUN_4BIT_TEXTCOLOR RGB(192,192,192) #define AUTORUN_4BIT_HIGHLIGHT RGB(255,255,255) #define AUTORUN_4BIT_DISABLED RGB(127,127,127) #define AUTORUN_4BIT_DESCRIPTION RGB(192,192,192) //#define AUTORUN_8BIT_TEXTCOLOR PALETTERGB( 75, 90,129) //#define AUTORUN_8BIT_HIGHLIGHT RGB(000,000,000) //#define AUTORUN_8BIT_DISABLED PALETTERGB(107,136,185) //#define AUTORUN_8BIT_DESCRIPTION RGB(000,000,000) #define AUTORUN_8BIT_TEXTCOLOR PALETTERGB(125,125,125) #define AUTORUN_8BIT_HIGHLIGHT RGB(175,175,175) #define AUTORUN_8BIT_DISABLED PALETTERGB(107,136,185) #define AUTORUN_8BIT_DESCRIPTION RGB(220,220,220) #define BUTTON_X_PLACEMENT (519) #define BUTTON_Y_MARGIN (9) #define SHADOW_FACTOR (930) #define LABEL_VERIFY_TIMER (0) //--------------------------------------------------------------------------- typedef struct { int res; // base for all resources this button owns DWORD rooting; // packed info on how to root paths for the command int xpos, ypos; // location of button in window RECT face; // client coordinates of actual button image on video RECT textrect; // parent coordinates of accompanying label text BOOL abdicated; // did we just release the capture? int state; // what are we doing? HWND window; // handle of button control WNDPROC oldproc; // original window procedure BOOL isdorky; // is this a strange icon button? char text[64]; // the label for the button char description[256]; // the description of the button's function } AUTORUNBTN; //--------------------------------------------------------------------------- AUTORUNBTN g_ButtonInfo[] = { // { WINTOUR, ROOTED(ONACD, NOROOT, ONACD), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, // { MSEXPO, ROOTED(ONACD, NOROOT, ONACD), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, // { HOVER, ROOTED(ONACD, NOROOT, ONACD), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, // { VIDEOS, ROOTED(NOROOT, ONACD, ONACD), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, { NTSETUP, ROOTED(NOROOT, NOROOT, ONACD), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, { EXPLORECD, ROOTED(NOROOT, ONACD, ONACD), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, { OCSETUP, ROOTED(NOROOT, NOROOT, INSYS), 0, 0, 0, 0, 49, 49, 0, 0, 0, 0, FALSE, 0, NULL, NULL, FALSE, 0 }, }; //#define IDAB_WINTOUR 0 //#define IDAB_MSEXPO 1 //#define IDAB_HOVER 2 //#define IDAB_VIDEOS 3 //#define IDAB_EXPLORECD 4 //#define IDAB_OCSETUP 5 #define IDAB_NTSETUP 0 #define IDAB_EXLPORECD 1 #define IDAB_OCSETUP 2 #define AUTORUN_NUM_BUTTONS (sizeof(g_ButtonInfo)/sizeof(g_ButtonInfo[0])) //--------------------------------------------------------------------------- typedef struct { HWND window; // main app window HDC image; // source dc with our cool backdrop HBITMAP oldbmp; // the default bitmap from the dc above HDC btnimage; // source dc with our cool buttons HBITMAP oldbtnbmp; // the default bitmap from the dc above HPALETTE palette; // our app's palette (if any) HFONT textfont; // font for labels RECT descrect; // client coordinates of description text int wndheight; // height of client area COLORREF clrnormal; // normal text color COLORREF clrhigh; // highlighted text color COLORREF clrdisable; // disabled text color COLORREF clrdescription; // disabled text color BOOL keyboard; // whether the app is under keyboard control } AUTORUNDATA; BOOL bNEC98 = FALSE; BOOL PathAppend( char * prefix, const char * spec) { //wsprintf ( dbgStr, "myPathAppend: prefix = %s, spec = %s", prefix, spec ); //MessageBox ( NULL, dbgStr, "", MB_ICONASTERISK ); strcat ( prefix, spec ); return TRUE; } BOOL PathFileExists ( LPCSTR FileName ) { /*++ Routine Description: Determine if a file exists and is accessible. Errormode is set (and then restored) so the user will not see any pop-ups. Arguments: FileName - supplies full path of file to check for existance. Return Value: TRUE if the file exists and is accessible. FALSE if not. GetLastError() returns extended error info. --*/ WIN32_FIND_DATA FindData; HANDLE FindHandle; BOOL b; UINT OldMode; OldMode = SetErrorMode(SEM_FAILCRITICALERRORS); FindHandle = FindFirstFile(FileName,&FindData); if(FindHandle == INVALID_HANDLE_VALUE) { b = FALSE; } else { FindClose(FindHandle); b = TRUE; } SetErrorMode(OldMode); return(b); } ///////////////////////////////////////////////////////////////////////////// // randomness ///////////////////////////////////////////////////////////////////////////// LONG WINAPI AnotherStrToLong(LPCSTR sz) { long l=0; BOOL fNeg = (*sz == '-'); if (fNeg) sz++; while (*sz >= '0' && *sz <= '9') l = l*10 + (*sz++ - '0'); if (fNeg) l *= -1L; return l; } ///////////////////////////////////////////////////////////////////////////// // ///////////////////////////////////////////////////////////////////////////// /*** this stuff uses the bitmap array - we won't use it. BOOL AssembleButtonImagesReal(AUTORUNDATA *data, HDC cellimage, HDC srcimage, SIZE size) { RGBQUAD rgbSrc[256], rgbCell[256], rgbMask[256] = {0}; HBITMAP dstbmp = CreateCompatibleBitmap(data->image, size.cx, size.cy); UINT uColors, uSrcColors, u; int iButton; // // set up the destination dc // if (!dstbmp) return FALSE; if ((data->btnimage = CreateCompatibleDC(data->image)) == NULL) { DeleteBitmap(dstbmp); return FALSE; } data->oldbtnbmp = SelectBitmap(data->btnimage, dstbmp); // // build a tile of the cell backgrounds based on button positions // for (iButton = 0; iButton < AUTORUN_NUM_BUTTONS; iButton++) { AUTORUNBTN *pButton = g_ButtonInfo + iButton; if (pButton->res != -1) { BOOL b; int xsrc = pButton->xpos; int ysrc = pButton->ypos; int xdst, ydst = iButton * BUTTON_IMAGE_Y_SIZE; for (xdst = 0; xdst < size.cx; xdst += BUTTON_IMAGE_X_SIZE) { b = BitBlt(cellimage, xdst, ydst, BUTTON_IMAGE_X_SIZE, BUTTON_IMAGE_Y_SIZE, data->image, xsrc, ysrc, SRCCOPY); } } } // // copy the entire cell backgrounds to the destination image // BitBlt(data->btnimage, 0, 0, size.cx, size.cy, cellimage, 0, 0, SRCCOPY); // // save the color table of the source image for posterity // uSrcColors = GetDIBColorTable(srcimage, 0, 256, rgbSrc); // // mask out holes on the destination for the buttons and shadows // rgbMask[0] = g_rgbWhite; SetDIBColorTable(srcimage, 0, uSrcColors, rgbMask); BitBlt(data->btnimage, 0, 0, size.cx, size.cy, srcimage, 0, 0, SRCAND); // // dim the background cells to produce the shadow image // u = uColors = GetDIBColorTable(cellimage, 0, 256, rgbCell); while (u--) { rgbCell[u].rgbBlue = (BYTE)(SHADOW_FACTOR * (UINT)rgbCell[u].rgbBlue / 1000); rgbCell[u].rgbGreen = (BYTE)(SHADOW_FACTOR * (UINT)rgbCell[u].rgbGreen / 1000); rgbCell[u].rgbRed = (BYTE)(SHADOW_FACTOR * (UINT)rgbCell[u].rgbRed / 1000); } SetDIBColorTable(cellimage, 0, uColors, rgbCell); // // mask out the shadows and add them to the destination image // rgbMask[0] = g_rgbBlack; rgbMask[1] = g_rgbWhite; SetDIBColorTable(srcimage, 0, uSrcColors, rgbMask); BitBlt(cellimage, 0, 0, size.cx, size.cy, srcimage, 0, 0, SRCAND); BitBlt(data->btnimage, 0, 0, size.cx, size.cy, cellimage, 0, 0, SRCPAINT); // // mask out the button faces and add them to the destination image // rgbSrc[0] = rgbSrc[1] = g_rgbBlack; SetDIBColorTable(srcimage, 0, uSrcColors, rgbSrc); BitBlt(data->btnimage, 0, 0, size.cx, size.cy, srcimage, 0, 0, SRCPAINT); // all done return TRUE; } //--------------------------------------------------------------------------- BOOL AssembleButtonImages(AUTORUNDATA *data) { BOOL result = FALSE; HBITMAP hbmSrc = LoadImage(HINST_THISAPP, MAKEINTRESOURCE(IDB_8BPP_BUTTONS), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); if (hbmSrc) { HDC hdcSrc = CreateCompatibleDC(data->image); BITMAP bm; GetObject(hbmSrc, sizeof(bm), &bm); if (hdcSrc) { HBITMAP hbmSrcOld = SelectBitmap(hdcSrc, hbmSrc); SIZE size = {bm.bmWidth, bm.bmHeight}; HBITMAP hbmTmp = CreateCompatibleBitmap(data->image, size.cx, size.cy); if (hbmTmp) { HDC hdcTmp = CreateCompatibleDC(data->image); if (hdcTmp) { HBITMAP hbmTmpOld = SelectBitmap(hdcTmp, hbmTmp); result = AssembleButtonImagesReal(data, hdcTmp, hdcSrc, size); SelectBitmap(hdcTmp, hbmTmpOld); DeleteDC(hdcTmp); } DeleteBitmap(hbmTmp); } SelectBitmap(hdcSrc, hbmSrcOld); DeleteDC(hdcSrc); } DeleteBitmap(hbmSrc); } return result; } */ //--------------------------------------------------------------------------- LRESULT CALLBACK AutoRunButtonSubclassProc(HWND window, UINT msg, WPARAM wp, LPARAM lp) { int index = (int)GetWindowLong(window, GWL_ID); if ((index >= 0) && (index < AUTORUN_NUM_BUTTONS)) { if (msg == WM_KEYDOWN) PostMessage(GetParent(window), msg, wp, lp); return CallWindowProc((g_ButtonInfo + index)->oldproc, window, msg, wp, lp); } return 0L; } //--------------------------------------------------------------------------- #define DORKYBUTTONSTYLE \ (WS_CHILD | WS_VISIBLE | BS_ICON | BS_CENTER | BS_VCENTER) HWND AutoRunCreateDorkyButton(AUTORUNDATA *data, AUTORUNBTN *button) { HICON icon = LoadIcon(HINST_THISAPP, IDI_ICON(button->res)); HWND child = NULL; if (icon) { child = CreateWindow(c_szButtonClass, c_szNULL, DORKYBUTTONSTYLE, 0, 0, 0, 0, data->window, NULL, HINST_THISAPP, 0); if (child) { button->isdorky = TRUE; SendMessage(child, BM_SETIMAGE, MAKEWPARAM(IMAGE_ICON,0),(LPARAM)icon); } // remove this debugging later else { //wsprintf ( dbgStr, "CreateWindow FAILed. gle = %ld, res = %ld", GetLastError(), button->res ); //MessageBox ( NULL, dbgStr, szAppName, MB_ICONASTERISK ); } } // remove this debugging later else { //wsprintf ( dbgStr, "LoadIcon FAILed. gle = %ld, res = %ld", GetLastError(), button->res ); //MessageBox ( NULL, dbgStr, szAppName, MB_ICONASTERISK ); } return child; } //--------------------------------------------------------------------------- #define COOLBUTTONSTYLE \ (WS_CHILD | WS_VISIBLE | BS_OWNERDRAW) HWND AutoRunCreateCoolButton(AUTORUNDATA *data, AUTORUNBTN *button) { HWND h; h = CreateWindow(c_szButtonClass, c_szNULL, COOLBUTTONSTYLE, 0, 0, 0, 0, data->window, NULL, HINST_THISAPP, 0); return ( h ); } //--------------------------------------------------------------------------- void AutoRunCreateButtons(AUTORUNDATA *data) { RECT labelbase = BUTTON_LABEL_RECT; int i; for (i = 0; i < AUTORUN_NUM_BUTTONS; i++) { AUTORUNBTN *button = g_ButtonInfo + i; HWND child = NULL; if (button->res != -1) { child = AutoRunCreateDorkyButton(data, button); /*** Don't call this code because we don't use the bitmap array. if (!g_f4BitForColor) { child = AutoRunCreateCoolButton(data, button); } if (!child) { child = AutoRunCreateDorkyButton(data, button); } ***/ } if (child) { BOOL b; int cx = BUTTON_DEFAULT_CX; int cy = BUTTON_DEFAULT_CY; button->window = child; SetWindowLong(child, GWL_ID, i); button->oldproc = SubclassWindow(child, (WNDPROC)AutoRunButtonSubclassProc); if (button->isdorky) { cx = button->face.right - button->face.left; cy = button->face.bottom - button->face.top; } b = SetWindowPos(child, NULL, button->xpos, button->ypos, cx, cy, SWP_NOZORDER | SWP_NOACTIVATE); LoadString(HINST_THISAPP, IDS_TITLE(button->res), button->text, ARRAYSIZE(button->text)); LoadString(HINST_THISAPP, IDS_INFO(button->res), button->description, ARRAYSIZE(button->description)); button->textrect = labelbase; b = OffsetRect(&button->textrect, button->xpos, button->ypos); b = InvalidateRect(data->window, &button->textrect, FALSE); } } } //--------------------------------------------------------------------------- void CleanupAutoRunWindow(AUTORUNDATA *data) { // // Deactivate any button so its timer will get killed // if (g_iActiveButton >= 0) { data->keyboard = FALSE; SendMessage(data->window, ARM_MOUSEOVER, TRUE, (LPARAM)-1L); } if (data->image) { if (data->oldbmp) { SelectBitmap(data->image, data->oldbmp); // real backdrop image is deleted in WinMain data->oldbmp = NULL; } DeleteDC(data->image); data->image = NULL; } if (data->btnimage) { if (data->oldbtnbmp) { DeleteBitmap(SelectBitmap(data->btnimage, data->oldbtnbmp)); data->oldbtnbmp = NULL; } DeleteDC(data->btnimage); data->btnimage = NULL; } if (data->palette) { DeleteObject(data->palette); data->palette = NULL; } if (data->textfont) { DeleteObject(data->textfont); data->textfont = NULL; } } //--------------------------------------------------------------------------- BOOL AutoRunBuildPath(char *spec, int resid, DWORD rooting) { char prefix[MAX_PATH]; // // get the relative path of the spec // if (resid == -1) { // // empty string hack for callers // *spec = 0; } else { char * p; // // Normal case, where we load the resource from the block of resource ids. // if (!LoadString(HINST_THISAPP, resid, spec, MAX_PATH)) { return FALSE; } // Since we will be initiating setup from one of the platforms, // we need to specify the correct platform directory. // Do the following: // - see if we are going to attempt to run setup, ie. winnt32.exe. // - if so, figure out from which platform // - and, load the appropriate string. if ( strstr ( spec, "winnt32" ) != NULL ) { char launchLocation[MAX_PATH]; // Get complete path of where autorun.exe is running from. // It will contain the platform because autorun.inf specified it. // GetModuleFileName(HINST_THISAPP, launchLocation, ARRAYSIZE(prefix)); _strupr ( launchLocation ); // At this point, should be, for example: C:\I386\AUTORUN.EXE // if ( bNEC98 ) { // On a Nec98 machine, the autorun will be launched from // the i386 directory. So, we can be smart at what we are // looking for and launch the appropriate winnt32.exe. p = strstr ( launchLocation, "I386" ); strcpy ( p, "NEC98\\winnt32.exe" ); } else { p = strstr ( launchLocation, "AUTORUN.EXE" ); strcpy ( p, "winnt32.exe" ); } strcpy ( spec, launchLocation ); } } // // our "empty" strings contain a single space so we know they succeeded // if ((*spec == ' ') && !spec[1]) *spec = 0; // // figure out what the prefix should be // *prefix = 0; switch (rooting) { case ONACD: // // assume the cd is the root of wherever we were launched from // GetModuleFileName(HINST_THISAPP, prefix, ARRAYSIZE(prefix)); _PathStripToRoot(prefix); break; case INWIN: GetRealWindowsDirectory(prefix, ARRAYSIZE(prefix)); break; case INSYS: GetSystemDirectory(prefix, ARRAYSIZE(prefix)); break; } // // if we have a prefix then prepend it // if (*prefix) { if (*spec) { PathAppend(prefix, spec); } // // copy the whole mess out to the original buffer // lstrcpy(spec, prefix); } return TRUE; } BOOL IsNec98( VOID ) { static BOOL Checked = FALSE; static BOOL Is98; if(!Checked) { Is98 = ((GetKeyboardType(0) == 7) && ((GetKeyboardType(1) & 0xff00) == 0x0d00)); Checked = TRUE; } return(Is98); } //--------------------------------------------------------------------------- BOOL InitAutoRunWindow(HWND window, AUTORUNDATA *data, LPCREATESTRUCT cs) { //char command[MAX_PATH]; AUTORUNBTN *button; OSVERSIONINFO osVersionInfo; BOOL b; data->window = window; if ((data->image = CreateCompatibleDC(NULL)) == NULL) goto im_doug; if ((data->oldbmp = SelectBitmap(data->image, (HBITMAP)cs->lpCreateParams)) == NULL) { goto im_doug; } if (g_fNeedPalette) { if ((data->palette = PaletteFromDS(data->image)) == NULL) goto im_doug; } /*** NT doesn't do the Expo Button. // should we show the expo button? button = g_ButtonInfo + IDAB_MSEXPO; if (!AutoRunBuildPath(command, IDS_CMD(button->res), CMD_ROOT(button->rooting)) || !PathFileExists(command)) { button->res = -1; } ***/ // Should we show the Add/Remove program button ? // Yes, if running on NT. // No, if running on anything else. button = g_ButtonInfo + IDAB_OCSETUP; osVersionInfo.dwOSVersionInfoSize = sizeof ( OSVERSIONINFO ); b = GetVersionEx ( &osVersionInfo ); if ( !b || !(osVersionInfo.dwPlatformId & VER_PLATFORM_WIN32_NT) ) { button->res = -1; } // artifical scoping oh boy! { BITMAP bm; int i, ivis = 0; int range = 0; int origin, extent; for (i = 0; i < AUTORUN_NUM_BUTTONS; i++) { button = g_ButtonInfo + i; if (button->res != -1) range++; } #if defined(_X86_) bNEC98 = IsNec98(); #endif GetObject((HBITMAP)cs->lpCreateParams, sizeof(bm), &bm); origin = BUTTON_Y_MARGIN * ((1 + AUTORUN_NUM_BUTTONS) - range); extent = bm.bmHeight - ((2 * origin) + BUTTON_IMAGE_Y_SIZE); if (--range < 1) range = 1; for (i = 0; i < AUTORUN_NUM_BUTTONS; i++) { button = g_ButtonInfo + i; if (button->res != -1) { button->xpos = BUTTON_X_PLACEMENT; button->ypos = ivis * extent / range + origin; ivis++; } } } // more artifical scoping! { HDC screen = GetDC(NULL); LOGFONT lf = { DEF_BUTTON_LABEL_HEIGHT, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE, (screen? GetTextCharset(screen) : DEFAULT_CHARSET), OUT_STROKE_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY | NONANTIALIASED_QUALITY, VARIABLE_PITCH | FF_DONTCARE, 0 }; char buf[32]; if (screen) ReleaseDC(NULL, screen); if (!LoadString(HINST_THISAPP, IDS_LABELFONT, lf.lfFaceName, ARRAYSIZE(lf.lfFaceName))) { lstrcpy(lf.lfFaceName, c_szArial); } if (LoadString(HINST_THISAPP, IDS_LABELHEIGHT, buf, ARRAYSIZE(buf))) lf.lfHeight = AnotherStrToLong(buf); if ((data->textfont = CreateFontIndirect(&lf)) == NULL) goto im_doug; } // // see if we need to do 8bit+ work... // if (g_f4BitForColor) { data->clrnormal = AUTORUN_4BIT_TEXTCOLOR; data->clrhigh = AUTORUN_4BIT_HIGHLIGHT; data->clrdisable = AUTORUN_4BIT_DISABLED; data->clrdescription = AUTORUN_4BIT_DESCRIPTION; } else { data->clrnormal = AUTORUN_8BIT_TEXTCOLOR; data->clrhigh = AUTORUN_8BIT_HIGHLIGHT; data->clrdisable = AUTORUN_8BIT_DISABLED; data->clrdescription = AUTORUN_8BIT_DESCRIPTION; /*** if (!AssembleButtonImages(data)) goto im_doug; ***/ } PostMessage(g_hMainWindow, ARM_MOUSEOVER, TRUE, (LPARAM)-1L); return TRUE; im_doug: CleanupAutoRunWindow(data); return FALSE; } //--------------------------------------------------------------------------- void AutoRunSized(AUTORUNDATA *data) { GetClientRect(data->window, &data->descrect); data->wndheight = data->descrect.bottom - data->descrect.top; data->descrect.left = AUTORUN_DESCRIPTION_LEFT; data->descrect.top = AUTORUN_DESCRIPTION_TOP; data->descrect.right = AUTORUN_DESCRIPTION_RIGHT; } //--------------------------------------------------------------------------- void AutoRunRealize(HWND window, AUTORUNDATA *data, HDC theirdc) { if (data->palette) { HDC dc = theirdc? theirdc : GetDC(window); if (dc) { BOOL repaint = FALSE; SelectPalette(dc, data->palette, FALSE); repaint = (RealizePalette(dc) > 0); if (!theirdc) ReleaseDC(window, dc); if (repaint) { RedrawWindow(window, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_ALLCHILDREN); } } } } //--------------------------------------------------------------------------- void AutoRunErase(AUTORUNDATA *data, HDC dc) { RECT rc; GetClientRect(data->window, &rc); AutoRunRealize(data->window, data, dc); BitBlt(dc, 0, 0, rc.right, rc.bottom, data->image, 0, 0, SRCCOPY); } //--------------------------------------------------------------------------- void AutoRunPaint(AUTORUNDATA *data) { PAINTSTRUCT ps; HDC dc = BeginPaint(data->window, &ps); AUTORUNBTN *button; COLORREF curtextcolor = GetTextColor(dc); COLORREF color; HFONT hfold = NULL; int i; AutoRunRealize(data->window, data, dc); SetBkMode(dc, TRANSPARENT); // // paint all the button labels // if (data->textfont) hfold = SelectFont(dc, data->textfont); for (i = 0; i < AUTORUN_NUM_BUTTONS; i++) { button = g_ButtonInfo + i; if (button->window) { color = (i == g_iActiveButton)? data->clrhigh : (IsWindowEnabled(button->window)? data->clrnormal : data->clrdisable); if (color != curtextcolor) { SetTextColor(dc, color); curtextcolor = color; } DrawText(dc, button->text, -1, &button->textrect, DT_WORDBREAK | DT_RIGHT | DT_TOP); } } // // paint the description for the current button // if (g_iActiveButton >= 0) { button = g_ButtonInfo + g_iActiveButton; color = data->clrdescription; if (color != curtextcolor) { SetTextColor(dc, color); curtextcolor = color; } DrawText(dc, button->description, -1, &data->descrect, DT_WORDBREAK | DT_LEFT | DT_TOP); } if (hfold) SelectFont(dc, hfold); EndPaint(data->window, &ps); } //--------------------------------------------------------------------------- void AutoRunDrawItem(AUTORUNDATA *data, DRAWITEMSTRUCT *dis) { POINT loc = { dis->rcItem.left, dis->rcItem.top }; SIZE size = { dis->rcItem.right - loc.x, dis->rcItem.bottom - loc.y }; loc.y += dis->CtlID * BUTTON_IMAGE_Y_SIZE; if (dis->itemState & ODS_DISABLED) { loc.x += DISABLED_IMAGE_X_OFFSET; } else if (dis->itemState & ODS_SELECTED) { loc.x += SELECTED_IMAGE_X_OFFSET; } else if (dis->itemState & ODS_FOCUS) { loc.x += FOCUS_IMAGE_X_OFFSET; } AutoRunRealize(dis->hwndItem, data, dis->hDC); BitBlt(dis->hDC, dis->rcItem.left, dis->rcItem.top, size.cx, size.cy, data->btnimage, loc.x, loc.y, SRCCOPY); } //--------------------------------------------------------------------------- void AutoRunActivateItem(AUTORUNDATA *data, int index) { if (index >= 0) { // // prevent disabled buttons from getting focus... // AUTORUNBTN *button = g_ButtonInfo + index; if (!button->window || !IsWindowEnabled(button->window)) index = -1; } if (g_iActiveButton != index) { AUTORUNBTN *newbtn = (index >= 0)? (g_ButtonInfo + index) : NULL; AUTORUNBTN *oldbtn = (g_iActiveButton >= 0)? (g_ButtonInfo + g_iActiveButton) : NULL; // // if there was an previous button, repaint its label highlight // if (oldbtn) InvalidateRect(data->window, &oldbtn->textrect, FALSE); g_iActiveButton = index; if (newbtn) { InvalidateRect(data->window, &newbtn->textrect, FALSE); SetFocus(newbtn->window); // // if activating via mouse, track it (trust me...) // if (g_fMouseAvailable && !data->keyboard) SetTimer(data->window, LABEL_VERIFY_TIMER, 333, NULL); } else { SetFocus(data->window); if (g_fMouseAvailable) KillTimer(data->window, LABEL_VERIFY_TIMER); } // // go ahead and paint any label changes now before we erase // UpdateWindow(data->window); InvalidateRect(data->window, &data->descrect, TRUE); } } //--------------------------------------------------------------------------- void AutoRunMouseOver(AUTORUNDATA *data, int index, BOOL fForce) { if ((index >= 0) || !data->keyboard || fForce) { data->keyboard = !g_fMouseAvailable; AutoRunActivateItem(data, index); } } //--------------------------------------------------------------------------- int AutoRunProcessPotentialHit(HWND candidate, const POINT *loc) { if (GetAsyncKeyState(VK_LBUTTON) < 0) return g_iActiveButton; if (candidate && IsWindowEnabled(candidate) && (GetParent(candidate) == g_hMainWindow)) { int index; index = (int)GetWindowLong(candidate, GWL_ID); if ((index >= 0) && (index < AUTORUN_NUM_BUTTONS)) { AUTORUNBTN *button = g_ButtonInfo + index; POINT cli = *loc; ScreenToClient(candidate, &cli); if (PtInRect(&button->face, cli)) return index; } } return -1; } //--------------------------------------------------------------------------- void AutoRunVerifyActiveItem(AUTORUNDATA *data) { if (!data->keyboard) { int index = -1; if (!g_fAppDisabled) { POINT loc; HWND candidate; GetCursorPos(&loc); if ((candidate = WindowFromPoint(loc)) != NULL) index = AutoRunProcessPotentialHit(candidate, &loc); } if (index != g_iActiveButton) AutoRunMouseOver(data, index, FALSE); } } //--------------------------------------------------------------------------- void AutorunEnableButton(AUTORUNDATA *data, int id, BOOL f) { if ((id >= 0) && (id < AUTORUN_NUM_BUTTONS)) { AUTORUNBTN *button = g_ButtonInfo + id; HWND window = button->window; if (button->window && IsWindow(button->window)) { EnableWindow(button->window, f); InvalidateRect(data->window, &button->textrect, FALSE); AutoRunVerifyActiveItem(data); } } } //--------------------------------------------------------------------------- BOOL AutoRunCDIsInDrive(HWND hwndOwner) { char me[MAX_PATH]; GetModuleFileName(HINST_THISAPP, me, ARRAYSIZE(me)); //MessageBox ( NULL, "Entering AutoRunCDIsInDrive...", "", MB_ICONASTERISK ); while (!PathFileExists(me)) { char szNeed[MAX_PATH]; char szName[MAX_PATH]; LoadString(HINST_THISAPP, IDS_NEEDCDROM, szNeed, MAX_PATH); LoadString(HINST_THISAPP, IDS_APPTITLE, szName, MAX_PATH); //////if (ShellMessageBox(HINST_THISAPP, hwndOwner, if ( MessageBox ( NULL, szNeed, szName, MB_OKCANCEL | MB_ICONSTOP) == IDCANCEL ) { //MessageBox ( NULL, "AutoRunCDIsInDrive FALSE", "", MB_ICONASTERISK ); return FALSE; } } //MessageBox ( NULL, "AutoRunCDIsInDrive TRUE", "", MB_ICONASTERISK ); return TRUE; } //--------------------------------------------------------------------------- void AutoRunClick(AUTORUNDATA *data, int nCmd) { char command[MAX_PATH], dir[MAX_PATH], params[MAX_PATH]; AUTORUNBTN *button; ULONG_PTR uRC; if ((nCmd < 0) || (nCmd >= AUTORUN_NUM_BUTTONS)) return; button = g_ButtonInfo + nCmd; // // meep at the user (meep meep!) so they know something is happening... // PlaySound(MAKEINTRESOURCE(IDW_BLIP), HINST_THISAPP, SND_RESOURCE | SND_ASYNC | SND_NODEFAULT); // // verify that the app disk is still visible and prompt if not... // if (!AutoRunCDIsInDrive(data->window)) { return; } // // calculate the paths for the command // if (!AutoRunBuildPath(command, IDS_CMD(button->res), CMD_ROOT(button->rooting)) || !AutoRunBuildPath(params, IDS_PARAMS(button->res), PARAMS_ROOT(button->rooting)) || !AutoRunBuildPath(dir, IDS_DIR(button->res), DEFDIR_ROOT(button->rooting))) { // BUGBUG an error message would be nice } //wsprintf ( dbgStr, "ShellExecute : command = %s, params = %s, dir = %s", command, params, dir ); //MessageBox ( NULL, dbgStr, "", MB_ICONASTERISK ); uRC = (ULONG_PTR) ShellExecute(data->window, NULL, command, params, dir, SW_SHOWNORMAL); if ( uRC >= 0 && uRC <= 32 ) { char cmdString[MAX_PATH]; LoadString(HINST_THISAPP, IDS_SHELLEXECUTE_ERROR, cmdString, MAX_PATH); wsprintf ( dbgStr, "%s lpFiles = %s, lpParameters = %s, lpDirectory = %s", cmdString, command, params, dir ); MessageBox ( NULL, dbgStr, szAppTitle, MB_ICONASTERISK ); } } //--------------------------------------------------------------------------- void AutoRunHandleKeystroke(AUTORUNDATA *data, TCHAR key, LPARAM lp) { int move = 0; int where = g_iActiveButton; // // see if we care about this keystroke // switch (key) { case VK_RETURN: if (where >= 0) AutoRunClick(data, where); //fallthru case VK_ESCAPE: where = -1; break; case VK_TAB: move = (GetKeyState(VK_SHIFT) < 0)? -1 : 1; break; case VK_END: where = AUTORUN_NUM_BUTTONS; //fallthru case VK_UP: case VK_LEFT: move = -1; break; case VK_HOME: where = -1; //fallthru case VK_DOWN: case VK_RIGHT: move = 1; break; default: return; } // // we should only get down here if the active button is going to change // if (move) { int scanned; for (scanned = 0; scanned <= AUTORUN_NUM_BUTTONS; scanned++) { where += move; if (where >= (int)AUTORUN_NUM_BUTTONS) { where = -1; } else if (where < 0) { where = AUTORUN_NUM_BUTTONS; } else { HWND child = (g_ButtonInfo + where)->window; if (child && IsWindowEnabled(child)) break; } } } if (where >= 0) { SetCursor(NULL); data->keyboard = TRUE; } else data->keyboard = !g_fMouseAvailable; AutoRunActivateItem(data, where); } //--------------------------------------------------------------------------- void LaunchSetup(HWND window) { LONG_PTR uRC; char command[MAX_PATH], params[MAX_PATH], dir[MAX_PATH]; // // calculate the paths for the command // if (!AutoRunBuildPath(command, IDS_CMD(NTSETUP), NOROOT) || !AutoRunBuildPath(params, IDS_PARAMS(NTSETUP),NOROOT) || !AutoRunBuildPath(dir, IDS_DIR(NTSETUP), ONACD)) { MessageBox ( NULL, "Could not build launch path.", szAppTitle, MB_ICONASTERISK ); } uRC = (LONG_PTR) ShellExecute(window, NULL, command, params, dir, SW_SHOWNORMAL); if ( uRC >= 0 && uRC <= 32 ) { char cmdString[MAX_PATH]; LoadString(HINST_THISAPP, IDS_SHELLEXECUTE_ERROR, cmdString, MAX_PATH); wsprintf ( dbgStr, "%s lpFiles = %s, lpParameters = %s, lpDirectory = %s", cmdString, command, params, dir ); MessageBox ( NULL, dbgStr, szAppTitle, MB_ICONASTERISK ); } } //--------------------------------------------------------------------------- #define CD_PLATFORM_ID (VER_PLATFORM_WIN32_WINDOWS) #define CD_MAJOR_VERSION (5) // hardcoded unfortunately #define CD_MINOR_VERSION (1) // hardcoded unfortunately #define CD_BUILD_NUMBER (VER_PRODUCTBUILD) // Return of FALSE, means quit the applet. // Return of TRUE, means continue. // BOOL CheckVersionConsistency(AUTORUNDATA *data) { OSVERSIONINFO ovi = { sizeof(ovi), 0, 0, 0, 0, 0 }; UINT msgtype = 0; BOOL result = FALSE; BOOL fDisableSetupStuff = FALSE; CHAR szMessage[MAX_PATH]; if (!GetVersionEx(&ovi)) { LoadString(HINST_THISAPP, IDS_CANTGETVERSION, szMessage, MAX_PATH); msgtype = MB_OK | MB_ICONSTOP; goto deal; } if ( bDebug ) { wsprintf ( dbgStr, "ovi.dwMajorVersion = %ld, ovi.dwMinorVersion = %ld, ovi.dwBuildNumber = %ld, CD_MAJOR_VERSION = %ld, CD_MINOR_VERSION = %ld, CD_BUILD_NUMBER = %ld", ovi.dwMajorVersion, ovi.dwMinorVersion, ovi.dwBuildNumber, CD_MAJOR_VERSION, CD_MINOR_VERSION, CD_BUILD_NUMBER ); MessageBox ( NULL, dbgStr, szAppTitle, MB_ICONASTERISK ); } // // Is this CD a version of the same os platform? // ie. we don't run on Win32s, but we do run on Win95 (VER_PLATFORM_WIN32_WINDOWS) // and NT (VER_PLATFORM_WIN32_NT). // if (ovi.dwPlatformId == VER_PLATFORM_WIN32s ) { // The system running is Win32s on Windows. // In this case, we won't offer setup. // fDisableSetupStuff = TRUE; } else if ( ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS ) { // The system running is Win95. // In this case, we always offer to upgrade the system. // LoadString(HINST_THISAPP, IDS_CRUSTYINSTALLATION, szMessage, MAX_PATH); msgtype = MB_YESNO | MB_ICONQUESTION; } else { // The system is running NT. // In this case, let's see if the build running is older(offer upgrade) or // newer(don't offer upgrade). // BOOL offersetup = FALSE; // // Find out if this this CD is an older build on the same major release // than that is running; // if so, tell the user to get a newer CD. // if ((ovi.dwMajorVersion == CD_MAJOR_VERSION) && (ovi.dwMinorVersion == CD_MINOR_VERSION) && (ovi.dwBuildNumber > CD_BUILD_NUMBER) ) { // // Tell them to go find a newer CD. // LoadString(HINST_THISAPP, IDS_CRUSTYCDROM, szMessage, MAX_PATH); msgtype = MB_OK | MB_ICONEXCLAMATION; fDisableSetupStuff = TRUE; result = TRUE; goto deal; } // Find out if the major version of the os is greater than of the CD. // If so, tell user to get newer CD. // if ((ovi.dwMajorVersion > CD_MAJOR_VERSION) ) { // // Tell them to go find a newer CD. // LoadString(HINST_THISAPP, IDS_CRUSTYCDROM, szMessage, MAX_PATH); msgtype = MB_OK | MB_ICONEXCLAMATION; fDisableSetupStuff = TRUE; result = TRUE; goto deal; } // Check if the versions are way different, or not. // if (ovi.dwMajorVersion < CD_MAJOR_VERSION) { // The CD is much newer than the os running, ie. new version release. // offersetup = TRUE; } else if (ovi.dwMajorVersion == CD_MAJOR_VERSION) { // Deal with same major release. // if (ovi.dwMinorVersion < CD_MINOR_VERSION) { // Same major release and CD is newer minor release. // offersetup = TRUE; } else if ((ovi.dwMinorVersion <= CD_MINOR_VERSION) && (ovi.dwBuildNumber < CD_BUILD_NUMBER ) ) { // Same major release, same minor release, running build is less than CD, // so setup. // offersetup = TRUE; } } // // look at the result of that hulking mess above // if (offersetup) { // // offer to upgrade them to this version // LoadString(HINST_THISAPP, IDS_CRUSTYINSTALLATION, szMessage, MAX_PATH); msgtype = MB_YESNO | MB_ICONQUESTION; goto deal; } } deal: if (fDisableSetupStuff) { AutorunEnableButton ( data, IDAB_NTSETUP, FALSE ); AutorunEnableButton ( data, IDAB_OCSETUP, FALSE ); } if (msgtype) { int imbResult; ShowWindow(data->window, SW_SHOWNORMAL); imbResult = MessageBox(data->window, szMessage, szAppTitle, msgtype); if ( imbResult == IDYES ) { LaunchSetup(data->window); } else if ( imbResult == IDNO ) { // User choose NO, but we will leave the applet around for them to play. // result = TRUE; } // We will end the applet shortly here since the launched setup is threaded out, // and result remains FALSE. } else { result = TRUE; } return result; } //--------------------------------------------------------------------------- LRESULT CALLBACK AutoRunMouseHook(int code, WPARAM wp, LPARAM lp) { if (code >= 0) { #define hook ((MOUSEHOOKSTRUCT *)lp) int id = g_fAppDisabled? -1 : AutoRunProcessPotentialHit(hook->hwnd, &hook->pt); if (id != g_iActiveButton) PostMessage(g_hMainWindow, ARM_MOUSEOVER, FALSE, (LPARAM)id); #undef hook } return CallNextHookEx(g_hMouseHook, code, wp, lp); } //--------------------------------------------------------------------------- LRESULT CALLBACK AutoRunWndProc(HWND window, UINT msg, WPARAM wp, LPARAM lp) { AUTORUNDATA *data = (AUTORUNDATA *)GetWindowLongPtr(window, GWLP_USERDATA); switch (msg) { case WM_NCCREATE: data = (AUTORUNDATA *)LocalAlloc(LPTR, sizeof(AUTORUNDATA)); if (data && !InitAutoRunWindow(window, data, (LPCREATESTRUCT)lp)) { LocalFree((HANDLE)data); data = NULL; } SetWindowLongPtr(window, GWLP_USERDATA, (LONG_PTR)data); if (!data) return FALSE; g_hMainWindow = window; goto DoDefault; case WM_CREATE: PlaySound(MAKEINTRESOURCE(IDW_STARTAPP), HINST_THISAPP, SND_RESOURCE | SND_ASYNC | SND_NODEFAULT); AutoRunCreateButtons(data); ShowWindow(window, SW_SHOWNORMAL); if (!CheckVersionConsistency(data)) { PostQuitMessage(0); break; //return -1; } break; case WM_DESTROY: PostQuitMessage(0); break; case WM_NCDESTROY: if (data) { CleanupAutoRunWindow(data); LocalFree((HANDLE)data); } g_hMainWindow = NULL; goto DoDefault; case WM_SIZE: AutoRunSized(data); break; case WM_DRAWITEM: AutoRunDrawItem(data, (DRAWITEMSTRUCT *)lp); break; case ARM_MOUSEOVER: AutoRunMouseOver(data, (int)lp, (BOOL)wp); break; case WM_ACTIVATE: g_fAppDisabled = ((LOWORD(wp) == WA_INACTIVE) || HIWORD(wp)); AutoRunVerifyActiveItem(data); goto DoDefault; case WM_TIMER: AutoRunVerifyActiveItem(data); break; case WM_KEYDOWN: AutoRunHandleKeystroke(data, (TCHAR)wp, lp); break; case WM_COMMAND: if (GET_WM_COMMAND_CMD(wp, lp) == BN_CLICKED) AutoRunClick(data, GET_WM_COMMAND_ID(wp, lp)); break; case WM_PALETTECHANGED: if ((HWND)wp == window) break; //fallthru case WM_QUERYNEWPALETTE: AutoRunRealize(window, data, NULL); break; case WM_ERASEBKGND: AutoRunErase(data, (HDC)wp); break; case WM_PAINT: AutoRunPaint(data); break; default: DoDefault: return DefWindowProc(window, msg, wp, lp); } return 1; } //--------------------------------------------------------------------------- int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { WNDCLASS wc; HBITMAP hbm = NULL; BITMAP bm; DWORD style; HWND window; RECT r; HDC screen; int retval = -1; HANDLE mutex = NULL; g_hinst = hInstance; if ( strstr ( lpCmdLine, "testit" ) ) { bDebug = TRUE; } // Only run one copy of NT's autorun.exe program at a time. // mutex = CreateMutex ( NULL, FALSE, "NT AutoRun Is Running" ); if ( mutex == NULL ) { // An error occurred, like running out of memory, bail now... // ExitProcess ( 0 ); } // Make sure we are the only process with our named mutex. // if ( GetLastError() == ERROR_ALREADY_EXISTS ) { CloseHandle (mutex); ExitProcess ( 0 ); } // // The below code is here in order to prevent this application from // displaying any windows, etc., in the case where NT Setup is asking the user to // insert the system CD, for example, when the user is installing a new driver. // Otherwise, we'll get this app each time the CD is put in the drive for NT 4.0 and // beyond. // window = FindWindow(c_szAutoRunPrevention, c_szAutoRunPrevention); if (window) { // do nothing // setup is probably trying to copy a driver or something... retval = 0; goto im_doug; } // // Stop if we can't load the app title in for this application. // if (!LoadString(HINST_THISAPP, IDS_APPTITLE, szAppTitle, sizeof(szAppTitle))) { goto im_doug; } // // Stop if we can't find our window ? // window = FindWindow(c_szAutoRunClass, szAppTitle); if (window) { retval = 0; SetForegroundWindow(window); goto im_doug; } // // yet more mundane platform-centric details // if (!GetClassInfo(HINST_THISAPP, c_szAutoRunClass, &wc)) { wc.style = 0; wc.lpfnWndProc = AutoRunWndProc; wc.cbClsExtra = wc.cbWndExtra = 0; wc.hInstance = hInstance; wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hIcon = NULL; wc.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wc.lpszMenuName = NULL; wc.lpszClassName = c_szAutoRunClass; if (!RegisterClass(&wc)) goto im_doug; } // // get a few tidbits about the display we're running on // screen = GetDC(NULL); #if defined (DEBUG) && defined (FORCE_4BIT) g_f4BitForColor = TRUE; #else g_f4BitForColor = (GetDeviceCaps(screen, PLANES) * GetDeviceCaps(screen, BITSPIXEL)) < 8; //g_f4BitForColor = TRUE; // testing... #endif g_fNeedPalette = (!g_f4BitForColor && (GetDeviceCaps(screen, RASTERCAPS) & RC_PALETTE)); ReleaseDC(NULL, screen); // // load the window backdrop image // hbm = LoadImage(HINST_THISAPP, MAKEINTRESOURCE(g_f4BitForColor? IDB_4BPP_BACKDROP : IDB_8BPP_BACKDROP), IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); if (!hbm) goto im_doug; // // // See if there is a mouse on the system. // if ((g_fMouseAvailable = (GetSystemMetrics(SM_MOUSEPRESENT) != 0)) != 0) { // // Set-up a mouse hook for our thread, but // don't worry if it fails, the app will still work. // g_hMouseHook = SetWindowsHookEx(WH_MOUSE, AutoRunMouseHook, HINST_THISAPP, GetCurrentThreadId()); } // // create the window based on the backdrop image // GetObject(hbm, sizeof(bm), &bm); r.left = (GetSystemMetrics(SM_CXSCREEN) - bm.bmWidth) / 2; r.top = (GetSystemMetrics(SM_CYSCREEN) - bm.bmHeight) / 3; // intended r.right = r.left + bm.bmWidth; r.bottom = r.top + bm.bmHeight; style = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; AdjustWindowRect(&r, style, FALSE); g_hMainWindow = CreateWindow(c_szAutoRunClass, szAppTitle, style, r.left, r.top, r.right - r.left, r.bottom - r.top, NULL, NULL, HINST_THISAPP, hbm); // // if we got here it's probably safe to show ourselves and pump messages // if (g_hMainWindow) { MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } retval = (int)msg.wParam; } im_doug: // // random cleanup // if (g_hMouseHook) { UnhookWindowsHookEx(g_hMouseHook); g_hMouseHook = NULL; } if (hbm) DeleteObject(hbm); CloseHandle ( mutex ); return retval; } //--------------------------------------------------------------------------- /**** NT doesn't use this, currently. int _stdcall ModuleEntry(void) { int i; STARTUPINFO si; LPSTR pszCmdLine = GetCommandLine(); if ( *pszCmdLine == '\"' ) { // Scan, and skip over, subsequent characters until // another double-quote or a null is encountered. // while ( *++pszCmdLine && (*pszCmdLine != '\"') ); // If we stopped on a double-quote (usual case), skip // over it. if ( *pszCmdLine == '\"' ) pszCmdLine++; } else { while (*pszCmdLine > ' ') pszCmdLine++; } //Skip past any white space preceeding the second token. // while (*pszCmdLine && (*pszCmdLine <= ' ')) { pszCmdLine++; } si.dwFlags = 0; GetStartupInfoA(&si); i = WinMain(GetModuleHandle(NULL), NULL, pszCmdLine, si.dwFlags & STARTF_USESHOWWINDOW ? si.wShowWindow : SW_SHOWDEFAULT); ExitProcess(i); return i; // We never comes here. } ****/