diff --git a/mozilla/tools/preloader/check.ico b/mozilla/tools/preloader/check.ico new file mode 100644 index 00000000000..f3f7ae27c63 Binary files /dev/null and b/mozilla/tools/preloader/check.ico differ diff --git a/mozilla/tools/preloader/check1.ico b/mozilla/tools/preloader/check1.ico new file mode 100644 index 00000000000..7a90ab4f10a Binary files /dev/null and b/mozilla/tools/preloader/check1.ico differ diff --git a/mozilla/tools/preloader/icon1.ico b/mozilla/tools/preloader/icon1.ico new file mode 100644 index 00000000000..438fed86a98 Binary files /dev/null and b/mozilla/tools/preloader/icon1.ico differ diff --git a/mozilla/tools/preloader/makefile.win b/mozilla/tools/preloader/makefile.win new file mode 100644 index 00000000000..6d40644752f --- /dev/null +++ b/mozilla/tools/preloader/makefile.win @@ -0,0 +1,56 @@ +#!nmake +# +# The contents of this file are subject to the Netscape Public +# License Version 1.1 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.mozilla.org/NPL/ +# +# Software distributed under the License is distributed on an "AS +# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or +# implied. See the License for the specific language governing +# rights and limitations under the License. +# +# The Original Code is mozilla.org code. +# +# The Initial Developer of the Original Code is Netscape +# Communications Corporation. Portions created by Netscape are +# Copyright (C) 1998 Netscape Communications Corporation. All +# Rights Reserved. +# +# Contributor(s): + +DEPTH = ..\.. + +WIN_LIBS = \ + shell32.lib \ + $(NULL) + +LFLAGS = -Wl,--subsystem,windows +CFLAGS = -x c++ -fno-exceptions -O -c +RESFILE = preloader.res + +CPP_OBJS = \ + .\$(OBJDIR)\preloader.obj \ + $(NULL) + +CPPSRCS = \ + preloader.cpp \ + $(NULL) + +MAKE_OBJ_TYPE = exe + +PROGRAM = .\$(OBJDIR)\preloader.exe + +MOZ_NO_COVERAGE = 1 + +include <$(DEPTH)\config\rules.mak> + +preloader.res: preloader.rc resource.h + +install:: $(PROGRAM) + $(MAKE_INSTALL) $(PROGRAM) $(DIST)\bin + +clobber:: + rm -rf $(DIST)\bin\$(PROGRAM) + + diff --git a/mozilla/tools/preloader/preloader.cpp b/mozilla/tools/preloader/preloader.cpp new file mode 100644 index 00000000000..517ae393859 --- /dev/null +++ b/mozilla/tools/preloader/preloader.cpp @@ -0,0 +1,1222 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + */ + +/**************************************************************************** + + Module Notes: + ============= + + Overview: + This little win32 application knows how to load the modules for + intalled version netscape and mozilla browsers. It preloads these + modules in order to make overall startup time seem faster to our + end users. + + Notes: + We assume that this preloader is stored with the mozilla/netscape + install somewhere, and that a link to that file is stored in either + the CURRENT_USER startup folder or the ALL_USERS startup folder. + If it's get's put somewhere else (like DEFAULT_USERS) then the + code we use to remove ourselves from the startup folder needs to + be adjusted accordingly. + + + Who When What Changed + ================================================================== + rickg 03.15.01 Version 1.0 of the preloader; proof of concept. + + rickg 04.16.01 changed code to use system-tray API's directly + rickg 04.17.01 added menu code to system tray to allow user to disable us + rickg 04.18.01 added code to auto-remove the preloader from startup folder + rickg 04.18.01 switched strings to resource files for easier localization. + rickg 04.23.01 added code to prevent multiple instances + rickg 04.23.01 added code to prevent preloader operation if browser is already running + rickg 04.23.01 added code to display unique icon (ugly yellow) if browser is already running. + rickg 04.23.01 added code to get/set "tuning" config settings from config dialog + rickg 04.24.01 added code to get/set "tuning" settings from registry + rickg 04.24.01 added accelerators to menu, and changed tooltip + rickg 04.24.01 moved more strings to resource file + rickg 04.24.01 hooked up "tuning" config settings for modulepercent and gFrequencyPercent + + NOTE: I've not hooked up the gEntryPercent setting. + + ****************************************************************************/ + + +//additional includes +#include "resrc1.h" +#include +#include +#include +#include + +//trayicon notification message +#define WM_TRAY WM_USER+0x100+5 + +static NOTIFYICONDATA gTrayData = {0,0,0,0,0,0,0}; +static HWND gMainWindow=0; +static HICON gCheckIcons[2] = {0,0}; +static HICON gBrowserRunningIcon = {0}; + +static const int kLoadTimerID = 2; +static const int kPingModuleTimerID = 3; + +static char gExePath[1024]={0}; //used to keep a path to our executable... +static const char* thePathSep="\\"; +static const char* gBrowserWindowName=0; +static const char *gRegKey=0; +static const char *gRegSubKey=0; + +static HINSTANCE gMainInst=0; //application main instance handle +static int gModulePercent = 100; //This tells us the percent of modules to load (default value) +static int gEntryPercent = 50; //Tells us the % of entry points per module (default value) +static int gFrequencyPercent = 50; //Tells us relative frequency to call entry points (default value) + +/*********************************************************** + call this to change the icon shown for our tray app + ***********************************************************/ +void SetTrayIcon(const HICON hIcon){ + gTrayData.hIcon=hIcon; + Shell_NotifyIcon(NIM_MODIFY, &gTrayData); +} + +/*********************************************************** + call this to change the tooltip shown for our tray app + ***********************************************************/ +void SetTrayToolTip(const char *aTip){ + if(aTip) { + if(!gTrayData.szTip[0]) //if previously no tooltip + gTrayData.uFlags=gTrayData.uFlags | NIF_TIP; + strcpy(gTrayData.szTip, aTip); + } + else gTrayData.uFlags=NIF_ICON | NIF_MESSAGE; + Shell_NotifyIcon(NIM_MODIFY, &gTrayData); +} + +/*********************************************************** + call this to init and display the tray app. + ***********************************************************/ +void ShowTrayApp(bool aVisible) { + + if(aVisible) { + gTrayData.cbSize=sizeof(NOTIFYICONDATA); + gTrayData.hWnd=gMainWindow; + gTrayData.uID=IDI_CHECK; //our tray ID + gTrayData.uFlags= NIF_ICON | NIF_MESSAGE | NIF_TIP; + gTrayData.uCallbackMessage=WM_TRAY; //send a WM_TRAY message when users clicks in our tray window + gTrayData.hIcon=gCheckIcons[0]; //init our default icon + + Shell_NotifyIcon(NIM_ADD, &gTrayData); //now show our tray icon + + char theTip[256]; + if(LoadString(gMainInst,IDS_TOOLTIP,theTip,sizeof(theTip))){ + SetTrayToolTip(theTip); + } + else SetTrayToolTip("Click to configure moz-preloader"); + SetTrayIcon(gCheckIcons[0]); + } + else { + Shell_NotifyIcon(NIM_DELETE, &gTrayData); + } +} + +//******************************************************************** + + +static bool gUseFullModuleList = false; + + +//this enum distinguishes version of netscape (and mozilla). +enum eAppVersion {eNetscape65, eNetscape60, eMozilla, eNetscapePre60, eUserPath,eUnknown}; + + +//Constants for my DLL loader to use... +static char gMozPath[2048]= {0}; +static char gUserPath[2048]= {0}; + +static char gMozModuleList[4096] = {0}; +static char* gModuleCP = gMozModuleList; +static int gModuleCount=0; +static int gMozPathLen=0; +static int gUserPathLen=0; + +static const char *theMozPath=0; +static int gDLLIndex=0; + + +/********************************************************* + This counts the number of unique modules in the given + list of modules, by counting semicolons. + *********************************************************/ +int CountModules(char*&aModuleList) { + char *cp=aModuleList; + + int count=0; + + while(*cp) { + if(*cp) { + count++; + } + char *theSemi=strchr(cp,';'); + if(theSemi) { + cp=theSemi+1; //skip the semi + } + } + return count; +} + + +/********************************************************* + This list describes the set of modules for NS6.0 + XXX This data should really live in a string table too. + *********************************************************/ +int Get60ModuleList(char*&aModuleList) { + + static char* theModuleList = + + "nspr4;plds4;plc4;mozreg;xpcom;img3250;zlib;" \ + + "gkgfxwin;gkwidget;" \ + + "components\\gkparser;" \ + "jpeg3250;" \ + "js3250;" \ + "jsj3250;" \ + "jsdom;" \ + "components\\jsloader;" \ + + "components\\activation;" \ + "components\\appcomps;" \ + "components\\addrbook;" \ + "components\\appshell;" \ + "components\\caps;" \ + "components\\chardet;" \ + "components\\chrome;" \ + "components\\cookie;" \ + "components\\docshell;" \ + "components\\editor;" \ + "components\\gkhtml;" \ + "components\\gkplugin;" \ + "components\\gkview;" \ + "gkwidget;" \ + "components\\jar50;" \ + "components\\lwbrk;" \ + "mozreg;" \ + "components\\necko;" \ + "components\\nsgif;" \ + "components\\nslocale;" \ + "components\\nsprefm;" \ + "components\\profile;" \ + "components\\psmglue;" \ + "components\\rdf;" \ + "components\\shistory;" \ + "components\\strres;" \ + "components\\txmgr;" \ + "components\\txtsvc;" \ + "components\\ucharuti;" \ + "components\\uconv;" \ + "components\\ucvlatin;" \ + "components\\ucvcn;" \ + "components\\ucvja;" \ + "components\\urildr;" \ + "components\\wallet;" \ + "components\\xpc3250;" \ + "components\\xpinstal;" \ + "components\\xppref32;" \ + "components\\mozbrwsr;" \ + "components\\nsjpg;" \ + "components\\oji;" \ + + "msgbsutl;" \ + "components\\mork;" \ + "components\\msglocal;" \ + + "xprt;" \ + "xptl;" \ + "xpcs;"; + + strcpy(aModuleList,theModuleList); + return CountModules(theModuleList); +} + +/********************************************************* + This list describes the set of modules for NS6.5 + XXX This data should really live in a string table too. + *********************************************************/ +int Get65ModuleList(char *&aModuleList) { + static char* theModuleList = + + "nspr4;plds4;plc4;mozreg;xpcom;img3250;zlib;" \ + + "gkgfxwin;gkwidget;" \ + + "components\\gkparser;" \ + "jpeg3250;" \ + "js3250;" \ + "jsj3250;" \ + "jsdom;" \ + "components\\jsloader;" \ + + "components\\activation;" \ + "components\\addrbook;" \ + "components\\appcomps;" \ + "components\\appshell;" \ + "components\\embedcomponents;" + "components\\caps;" \ + "components\\chardet;" \ + "components\\chrome;" \ + "components\\cookie;" \ + "components\\docshell;" \ + "components\\editor;" \ + "components\\gkplugin;" \ + "components\\gkview;" \ + "gkwidget;" \ + "components\\jar50;" \ + "components\\lwbrk;" \ + "components\\necko;" \ + "components\\nsgif;" \ + "components\\nslocale;" \ + "components\\nsprefm;" \ + "components\\profile;" \ + "components\\psmglue;" \ + "components\\rdf;" \ + "components\\shistory;" \ + "components\\strres;" \ + "components\\txmgr;" \ + "components\\txtsvc;" \ + "components\\ucharuti;" \ + "components\\uconv;" \ + "components\\ucvlatin;" \ + "components\\ucvcn;" \ + "components\\ucvja;" \ + "components\\urildr;" \ + "components\\wallet;" \ + "components\\xpc3250;" \ + "components\\xpinstal;" \ + "components\\xppref32;" \ + "components\\xmlextras;" \ + + "components\\gklayout;" \ + "components\\gkcontent;" \ + "components\\mozbrwsr;" \ + "components\\nsjpg;" \ + "components\\oji;" \ + + "msgbsutl;" \ + "components\\mork;" \ + "components\\msglocal;" \ + + "xprt;" \ + "xptl;" \ + "xpcs;"; + + strcpy(aModuleList,theModuleList); + return CountModules(theModuleList); +} + + +/********************************************************* + ... + *********************************************************/ +static char gKeyBuffer[512]={0}; +static char gSubKeyBuffer[128]={0}; +static char gWinNameBuffer[128]={0}; //this is the expected browser name. + +void GetPathFromRegistry(eAppVersion aVersion, const char *&aKey, const char *&aSubkey, char *&aModuleList, int &aSize) { + + switch(aVersion) { + + case eMozilla: + + aKey=(LoadString(gMainInst,IDS_MOZ_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Mozilla.org\\Mozilla\\0.8 (en)\\Main"; + + aSubkey = (LoadString(gMainInst,IDS_SUBKEY_INSTALL,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Install Directory"; + + gBrowserWindowName = (LoadString(gMainInst,IDS_MOZ_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Mozilla"; + + aSize=Get65ModuleList(aModuleList); + + break; + + case eNetscape65: + + aKey=(LoadString(gMainInst,IDS_NS65_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Netscape\\Netscape 6\\6.5 (en)\\Main"; + + aSubkey = (LoadString(gMainInst,IDS_SUBKEY_INSTALL,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Install Directory"; + + gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6"; + + aSize=Get65ModuleList(aModuleList); + + break; + + case eNetscape60: + + aKey=(LoadString(gMainInst,IDS_NS60_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Netscape\\Netscape 6\\6.0 (en)\\Main"; + + aSubkey = (LoadString(gMainInst,IDS_SUBKEY_PATH,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Path"; + + gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6"; + + aSize=Get60ModuleList(aModuleList); + + break; + + case eNetscapePre60: + + aKey=(LoadString(gMainInst,IDS_PRE60_KEY,gKeyBuffer,sizeof(gKeyBuffer))) ? gKeyBuffer : "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\netscp6.exe"; + + aSubkey = (LoadString(gMainInst,IDS_SUBKEY_PATH,gSubKeyBuffer,sizeof(gSubKeyBuffer))) ? gSubKeyBuffer : "Path"; + + gBrowserWindowName = (LoadString(gMainInst,IDS_NS_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Netstacpe 6"; + + aSize=Get60ModuleList(aModuleList); + + break; + + case eUserPath: + aKey = 0; + aSubkey= 0; + strcpy(gMozPath,gUserPath); + + aSize=Get65ModuleList(aModuleList); + + gBrowserWindowName = (LoadString(gMainInst,IDS_MOZ_WINDOWNAME,gWinNameBuffer,sizeof(gWinNameBuffer))) ? gWinNameBuffer: "- Mozilla"; + + break; + + case eUnknown: + break; + } +} + +/********************************************************* + Get the path to the netscape6 browser via the registry... + *********************************************************/ +void GetMozillaRegistryInfo(eAppVersion aVersion) { + + //first we try to get the registry info based on the command line settings. + //if that fails, we try others. + + LONG theOpenResult = 1; //any non-zero will do to initialize this... + + while(ERROR_SUCCESS!=theOpenResult) { + + GetPathFromRegistry(aVersion,gRegKey,gRegSubKey,gModuleCP,gModuleCount); + theOpenResult=ERROR_SUCCESS; + + CRegKey theRegKey; + + if(eUserPath!=aVersion) { + theOpenResult=theRegKey.Open(HKEY_LOCAL_MACHINE,gRegKey,KEY_QUERY_VALUE); + + if(ERROR_SUCCESS==theOpenResult) { + DWORD theSize=1024; + + theRegKey.QueryValue(gMozPath,gRegSubKey,&theSize); + + if((ERROR_SUCCESS==theOpenResult) && (aVersion!=eUserPath)) { + + theSize=1024; + char theCachedModuleList[1024] = {0}; + + theRegKey.QueryValue(theCachedModuleList,"Modules",&theSize); + + if(theCachedModuleList[0]) { + strcpy(gMozModuleList,theCachedModuleList); + } + else { + theRegKey.Create(HKEY_LOCAL_MACHINE,gRegKey); + theRegKey.SetValue( HKEY_LOCAL_MACHINE, gRegKey, gMozModuleList, "Modules"); + } + } + + break; + } + } + aVersion=eAppVersion(int(aVersion)+1); + + } //while + + gMozPathLen=strlen(gMozPath); + gModuleCP = gMozModuleList; + +} + + +/********************************************************* + Extract the "next" module name from our module name list. + XXX The module names should come from string resources. + *********************************************************/ +void GetNextModuleName(char* aName) { + //scan ahead to find the next ';' or the end of the string... + bool done=false; + char theChar=0; + + aName[0]=0; + + char *theCP=gModuleCP; + + while(*theCP) { + theChar=*theCP; + if(';'==theChar) + break; + else theCP++; + } + + if(theCP!=gModuleCP) { + size_t theSize=theCP-gModuleCP; + strncpy(aName,gModuleCP,theSize); + aName[theSize]=0; + gModuleCP=theCP; + while(';'==*gModuleCP) + gModuleCP++; + } + +} + +/**************************************************************** + The following types are fraudulent. They're just here so + we can write up calls entry points in each module. + ****************************************************************/ + +const int gMaxProcIndex=256; +static HINSTANCE gInstances[256]; +static long* gFuncTable[256][gMaxProcIndex]; +static int gDLLCount=0; + +struct nsIID; +typedef const nsIID& (*GetIIDFunc)(void); + + +/**************************************************************** + Call this once for each module you want to preload. + ****************************************************************/ +HINSTANCE LoadModule(const char* aName) { + + //gModulePercent + + //we operate on gMozPath directly to avoid an unnecessary string copy. + //when we're done with this method, we reset gMozpath to it's original value for reuse. + + strcat(gMozPath,aName); + strcat(gMozPath,".dll"); + + gFuncTable[gDLLCount][0]=0; //make sure the table looks empty by default. + + HINSTANCE theInstance=gInstances[gDLLCount++]=LoadLibrary(gMozPath); + + int theEntryCount=0; + + if(theInstance) { + //let's get addresses throughout the module, skipping over every 20. + for(int theEntryPoint=0;theEntryPoint<64;theEntryPoint++){ + long *entry=(long*)::GetProcAddress(theInstance,MAKEINTRESOURCE(1+(20*theEntryPoint))); + if(entry) { + gFuncTable[gDLLCount-1][theEntryCount++]=entry; + gFuncTable[gDLLCount][theEntryCount]=0; //always add a null to the end + } + } + } + + gMozPath[gMozPathLen]=0; + return theInstance; +} + + +BOOL CALLBACK EnumWindowsProc(HWND hwnd,LPARAM lParam ) { + + char buf[256]={0}; + if(GetWindowText(hwnd,buf,sizeof(buf))){ + if(strstr(buf,gBrowserWindowName)) { + return FALSE; //stop iterating now... + } + } + return TRUE; +} + +/**************************************************************** + Call this to detect whether the browser is running. + ****************************************************************/ +bool BrowserIsRunning() { + if(!EnumWindows(EnumWindowsProc,0)) { + return true; + } + return false; +} + +/**************************************************************** + This function get's called repeatedly to call on a timer, + and it calls GetProcAddr() to keep modules from paging. + ****************************************************************/ +VOID CALLBACK KeepAliveTimerProc(HWND hwnd, UINT uMsg, UINT idEvent, DWORD dwTime ) { + + //let's go see if mozilla is running. + //if so, then bail out without pinging modules... + + if(BrowserIsRunning()) { + return; + } + + static bool theTimerIsRunning=false; + static int theCurrentModule=0; + static int theCurrentProc=0; + + if(!theTimerIsRunning) { //ignore other timer calls till we're done. + theTimerIsRunning=true; + + const int modulesPerStep=40; //how many modules to "touch" each time... + + int theCount=0; + + for(int theSteps=0;theSteps=gDLLCount) { + theCurrentModule=0; //loop back around to top of module list... + theCurrentProc++; + if(theCurrentProc>=gMaxProcIndex){ + theCurrentProc=0; //reset this too! + } + } + + } + + theTimerIsRunning=false; + } +} + + +/**************************************************************** + This gets called repeatedly by a windows timer, and loads + the modules that it gets from the modulelist (see top of this file). + + This routine has been updated to account for the gModulesPercent + setting (1-100). We'll load modules until we cross over this + percentage. + ****************************************************************/ +VOID CALLBACK LoadModuleTimerProc(HWND hwnd, UINT uMsg, UINT idEvent,DWORD dwTime) { + + static bool theTimerIsRunning=false; + static int gTrayIconIndex = 0; + + if(!theTimerIsRunning) { + theTimerIsRunning=true; + + //gDLLCount is the number of modules loaded so far + //gModuleCount is the total number of modules we know about + //gModulePercent is the total % of modules we're being asked to load (config setting) + + if(gDLLCount/gModuleCount + + +//menu messages + + + diff --git a/mozilla/tools/preloader/resrc1.h b/mozilla/tools/preloader/resrc1.h new file mode 100644 index 00000000000..e8e3aab0738 --- /dev/null +++ b/mozilla/tools/preloader/resrc1.h @@ -0,0 +1,49 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by main.rc +// +#define IDS_MOZ_KEY 1 +#define IDS_NS65_KEY 2 +#define IDS_NS60_KEY 3 +#define IDS_PRE60_KEY 4 +#define IDS_STARTUP_FOLDER_PREFIX 5 +#define IDS_STARTUP_FOLDER_SUFFIX 6 +#define IDS_STARTUP_FOLDER_KEY 7 +#define IDS_STARTUP_FOLDER_SUBKEY1 8 +#define IDS_STARTUP_FOLDER_SUBKEY2 9 +#define IDS_CLASSNAME 10 +#define IDS_TOOLTIP 11 +#define IDS_SUBKEY_INSTALL 12 +#define IDS_SUBKEY_PATH 13 +#define IDS_NS_WINDOWNAME 14 +#define IDS_MOZ_WINDOWNAME 15 +#define DISABLE 101 +#define TRYMERICK 101 +#define IDD_DIALOG1 102 +#define IDR_MENU1 106 +#define IDI_CHECK 108 +#define IDD_PERFORMANCE 108 +#define IDI_CHECK1 109 +#define IDI_BROWSERRUNNING 110 +#define IDC_SLIDER1 1000 +#define IDC_MODULES 1000 +#define IDC_SLIDER2 1001 +#define IDC_ENTRIES 1001 +#define IDC_SLIDER3 1002 +#define IDC_FREQUENCY 1002 +#define IDM_CONFIGURE 40007 +#define IDM_EXIT 40011 +#define IDM_CHANGE 40012 +#define IDM_REMOVE 40013 +#define IDC_STATIC -1 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 111 +#define _APS_NEXT_COMMAND_VALUE 40008 +#define _APS_NEXT_CONTROL_VALUE 1003 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif