// __________________________________________________________ // // W32Start.h // Startup Code for Win32 Applications V1.02 // 08-23-2000 Sven B. Schreiber // sbs@orgon.com // __________________________________________________________ #ifndef _W32START_H_ #define _W32START_H_ #include // ================================================================= // DISCLAIMER // ================================================================= /* This software is provided "as is" and any express or implied warranties, including, but not limited to, the implied warranties of merchantibility and fitness for a particular purpose are disclaimed. In no event shall the author Sven B. Schreiber be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage. */ // ================================================================= // REVISION HISTORY // ================================================================= /* 06-25-1999 V1.00 Original version (SBS). This is a replacement for ConStart.h and GuiStart.h, containing common startup and library code for both Win32 console and GUI applications. Differences are accounted for by checking the existence of the _CONSOLE symbol in conditional compilation blocks. New enhanced printf(), fprintf(), vfprintf(), sprintf(), and vsprintf() implementations for Unicode and ANSI. mprintf() and vmprintf() are derivatives of fprintf() and vfprintf(), displaying the data in a MessageBox() instead of writing it to a stream. All *printf() functions impose no restrictions on the size of the data and have various new formatting features. If sprintf() and vsprintf() receive a buffer pointer of NULL, the required buffer size is computed only. GUI applications are allowed to call printf(), which will automatically create a console window on first invocation. The console status can also be controlled explicitly using the ConsoleCreate() and ConsoleDestroy() run-time functions. The console line length computation has moved from Main() to the startup code. New command line parser, featuring an argp[] array of pointers to the arguments in the raw command line. Main() and WinMain() prototypes slightly revised for the new parser. 07-17-1999 V1.01 Upgrade (SBS). Added vprintfA(), vprintfW(), and the corresponding ANSI/Unicode macro vprintf. Changed printf() to use vprintf() now instead of vfprintf(). 08-23-2000 V1.02 Upgrade (SBS). Moved the WriteFile() calls into a loop that outputs the data in 16-KB blocks. Moved the ConsoleCreate() call inside printf() to vprintf(). Added eprintf() and veprintf(), which write to STDERR instead of STDOUT. Added ConsoleTest() and redesigned ConsoleCreate() and ConsoleDestroy(). Renamed ConsoleCreate() to ConsoleOpen() and ConsoleDestroy() to ConsoleClose(). */ //////////////////////////////////////////////////////////////////// #ifndef _RC_PASS_ //////////////////////////////////////////////////////////////////// // ================================================================= // MACROS // ================================================================= #define ALLOC_ANSI(_n) \ ((PBYTE) LocalAlloc (LMEM_FIXED, (_n))) #define ALLOC_UNICODE(_n) \ ((PWORD) LocalAlloc (LMEM_FIXED, (_n) * sizeof (WORD))) // ================================================================= // CONSTANTS // ================================================================= #define UNICODE_UNMAPPED 0x7F #define WRITE_FILE_BLOCK 0x4000 #define CONSOLE_TITLE 0x1000 // ================================================================= // STRUCTURES // ================================================================= typedef struct _WIN_CMD { DWORD argc; PTBYTE *argv; PTBYTE *argp; PTBYTE ptRaw; PTBYTE ptCooked; PTBYTE ptTail; BYTE abData []; } WIN_CMD, *PWIN_CMD, **PPWIN_CMD; #define WIN_CMD_ sizeof (WIN_CMD) // ================================================================= // GLOBAL VARIABLES // ================================================================= HANDLE ghStdInput = INVALID_HANDLE_VALUE; HANDLE ghStdOutput = INVALID_HANDLE_VALUE; HANDLE ghStdError = INVALID_HANDLE_VALUE; BOOL gfStdHandles = FALSE; BOOL gfStdFailure = FALSE; BOOL gfStdTransient = FALSE; DWORD gdLine = 80; INT giNetwork = 0; INT giDebug = 0; WORD gwFill = ' '; // ================================================================= // GLOBAL STRINGS // ================================================================= TBYTE atUsage [] = T("\r\n") T("Usage: ") S(MAIN_MODULE) T(" %s\r\n"); TBYTE atAbout [] = T("\r\n") T("// ") S(ABOUT_TEXT1) T("\r\n") T("// ") S(ABOUT_TEXT2) T("\r\n") T("// ") S(ABOUT_TEXT3) T("\r\n") T("// ") S(ABOUT_TEXT4) T("\r\n"); // ================================================================= // CONDITIONAL ANSI/UNICODE NAMES // ================================================================= #ifdef UNICODE #define ConsoleTest ConsoleTestW #define vsprintf vsprintfW #define vmprintf vmprintfW #define vfprintf vfprintfW #define veprintf veprintfW #define vprintf vprintfW #define sprintf sprintfW #define mprintf mprintfW #define fprintf fprintfW #define eprintf eprintfW #define printf printfW #else #define ConsoleTest ConsoleTestA #define vsprintf vsprintfA #define vmprintf vmprintfA #define vfprintf vfprintfA #define veprintf veprintfA #define vprintf vprintfA #define sprintf sprintfA #define mprintf mprintfA #define fprintf fprintfA #define eprintf eprintfA #define printf printfA #endif // ================================================================= // CONSOLE MANAGEMENT // ================================================================= BOOL WINAPI ConsoleTestA (void) { BYTE abTitle [CONSOLE_TITLE]; return GetConsoleTitleA (abTitle, CONSOLE_TITLE) != 0; } // ----------------------------------------------------------------- BOOL WINAPI ConsoleTestW (void) { WORD awTitle [CONSOLE_TITLE]; return GetConsoleTitleW (awTitle, CONSOLE_TITLE) != 0; } // ----------------------------------------------------------------- BOOL WINAPI ConsoleOpen (void) { if ((!gfStdHandles) && (!gfStdFailure)) { gfStdTransient = (!ConsoleTest ()) && AllocConsole (); if (ConsoleTest ()) { ghStdInput = GetStdHandle (STD_INPUT_HANDLE); ghStdOutput = GetStdHandle (STD_OUTPUT_HANDLE); ghStdError = GetStdHandle (STD_ERROR_HANDLE); if ((ghStdInput != INVALID_HANDLE_VALUE) && (ghStdOutput != INVALID_HANDLE_VALUE) && (ghStdError != INVALID_HANDLE_VALUE)) { gfStdHandles = TRUE; } else { ghStdInput = INVALID_HANDLE_VALUE; ghStdOutput = INVALID_HANDLE_VALUE; ghStdError = INVALID_HANDLE_VALUE; } } if ((gfStdFailure = !gfStdHandles) && gfStdTransient) { FreeConsole (); gfStdTransient = FALSE; } } return gfStdHandles; } // ----------------------------------------------------------------- BOOL WINAPI ConsoleClose (void) { BOOL fOk = FALSE; if (gfStdHandles) { ghStdInput = INVALID_HANDLE_VALUE; ghStdOutput = INVALID_HANDLE_VALUE; ghStdError = INVALID_HANDLE_VALUE; gfStdHandles = FALSE; fOk = TRUE; } if (gfStdTransient) { if (ConsoleTest ()) FreeConsole (); gfStdTransient = FALSE; } gfStdFailure = FALSE; return fOk; } // ================================================================= // TEXT CONVERSION ROUTINES // ================================================================= PWORD WINAPI ConvertAnsiToUnicode (PBYTE pbData, PWORD pwData) { DWORD n; PWORD pwData1 = NULL; if (pbData != NULL) { for (n = 0; pbData [n]; n++); if ((pwData1 = (pwData != NULL ? pwData : ALLOC_UNICODE (n+1))) != NULL) { do { pwData1 [n] = pbData [n]; } while (n--); } } return pwData1; } // ----------------------------------------------------------------- PBYTE WINAPI ConvertUnicodeToAnsi (PWORD pwData, PBYTE pbData) { DWORD n; PBYTE pbData1 = NULL; if (pwData != NULL) { for (n = 0; pwData [n]; n++); if ((pbData1 = (pbData != NULL ? pbData : ALLOC_ANSI (n+1))) != NULL) { if (!WideCharToMultiByte (CP_ACP, WC_COMPOSITECHECK | WC_DISCARDNS, pwData, -1, pbData1, n+1, NULL, NULL)) { do { pbData1 [n] = (pwData [n] < 0x0100 ? (BYTE) pwData [n] : UNICODE_UNMAPPED); } while (n--); } } } return pbData1; } // ================================================================= // printf() PRIMITIVES // ================================================================= DWORD WINAPI FormatAnsiW (PWORD pwBuffer, DWORD dOffset, PBYTE pbData, DWORD dData, DWORD dWidth, DWORD dPrecision, WORD wFill, BOOL fRight, BOOL fZero) { PWORD pwBuffer1; WORD wData; DWORD i, j, k; DWORD n = 0; if (pbData != NULL) { if (dData != -1) { i = dData; } else { for (i = 0; pbData [i]; i++); } } j = (dPrecision == -1 ? i : max (i, dPrecision)); n = max (i, dWidth); if (pwBuffer != NULL) { pwBuffer1 = pwBuffer + dOffset; wData = (fZero ? '0' : wFill); if (fRight) { k = n; while (k > j) pwBuffer1 [--k] = wData; while (k > i) pwBuffer1 [--k] = ' '; k = 0; } else { k = 0; while (k < n - j) pwBuffer1 [k++] = wData; while (k < n - i) pwBuffer1 [k++] = ' '; } while (i--) { pwBuffer1 [k+i] = pbData [i]; } } if (pwBuffer != NULL) pwBuffer [dOffset+n] = 0; return n; } // ----------------------------------------------------------------- DWORD WINAPI FormatUnicodeW (PWORD pwBuffer, DWORD dOffset, PWORD pwData, DWORD dData, DWORD dWidth, DWORD dPrecision, WORD wFill, BOOL fRight, BOOL fZero) { PWORD pwBuffer1; WORD wData; DWORD i, j, k; DWORD n = 0; if (pwData != NULL) { if (dData != -1) { i = dData; } else { for (i = 0; pwData [i]; i++); } } j = (dPrecision == -1 ? i : max (i, dPrecision)); n = max (i, dWidth); if (pwBuffer != NULL) { pwBuffer1 = pwBuffer + dOffset; wData = (fZero ? '0' : wFill); if (fRight) { k = n; while (k > j) pwBuffer1 [--k] = wData; while (k > i) pwBuffer1 [--k] = ' '; k = 0; } else { k = 0; while (k < n - j) pwBuffer1 [k++] = wData; while (k < n - i) pwBuffer1 [k++] = ' '; } while (i--) { pwBuffer1 [k+i] = pwData [i]; } } if (pwBuffer != NULL) pwBuffer [dOffset+n] = 0; return n; } // ----------------------------------------------------------------- DWORD WINAPI FormatDecimalW (PWORD pwBuffer, DWORD dOffset, DWORD dData, DWORD dWidth, DWORD dPrecision, WORD wFill, BOOL fRight, BOOL fZero, BOOL fPrefix, BOOL fSigned) { BOOL fMinus; PWORD pwBuffer1; WORD wPrefix, wData; DWORD dData1, i, j, k; DWORD n = 0; fMinus = (fSigned && ((LONG) dData < 0)); dData1 = (fMinus ? 0 - dData : dData); for (i = dData1, j = 1; i >= 10; i /= 10, j++); if (dPrecision != -1) j = max (j, dPrecision); k = (fPrefix || fMinus ? j+1 : j); n = max (k, dWidth); wPrefix = (k == j ? 0 : (fMinus ? '-' : (dData1 ? '+' : ' '))); if (pwBuffer != NULL) { pwBuffer1 = pwBuffer + dOffset; wData = (fZero ? '0' : wFill); if (fRight) { for (i = n; i > k; i--) pwBuffer1 [i-1] = wData; k = 0; } else { for (i = 0; i < n - j; i++) pwBuffer1 [i] = wData; i = n; k = (fZero ? 0 : n - k); } while (j--) { pwBuffer1 [--i] = (WORD) (dData1 % 10) + '0'; dData1 /= 10; } if (wPrefix) { pwBuffer1 [k] = wPrefix; } } if (pwBuffer != NULL) pwBuffer [dOffset+n] = 0; return n; } // ----------------------------------------------------------------- DWORD WINAPI FormatHexW (PWORD pwBuffer, DWORD dOffset, DWORD dData, DWORD dWidth, DWORD dPrecision, WORD wFill, BOOL fRight, BOOL fZero, BOOL fPrefix, BOOL fLower) { PWORD pwBuffer1; WORD wData; DWORD dData1, i, j, k; DWORD n = 0; dData1 = dData; for (i = dData1, j = 1; i >= 0x10; i >>= 4, j++); if (dPrecision != -1) j = max (j, dPrecision); k = (fPrefix ? j+2 : j); n = max (k, (fPrefix ? dWidth+2 : dWidth)); if (pwBuffer != NULL) { pwBuffer1 = pwBuffer + dOffset; wData = (fZero ? '0' : wFill); if (fRight) { for (i = n; i > k; i--) pwBuffer1 [i-1] = wData; k = 0; } else { for (i = 0; i < n - j; i++) pwBuffer1 [i] = wData; i = n; k = (fZero ? 0 : n - k); } wData = (fLower ? 'a' : 'A'); while (j--) { if ((pwBuffer1 [--i] = (WORD) (dData1 & 0xF)) < 10) { pwBuffer1 [i] += '0'; } else { pwBuffer1 [i] -= 10; pwBuffer1 [i] += wData; } dData1 >>= 4; } if (fPrefix) { pwBuffer1 [k ] = '0'; pwBuffer1 [k+1] = (fLower ? 'x' : 'X'); } } if (pwBuffer != NULL) pwBuffer [dOffset+n] = 0; return n; } // ----------------------------------------------------------------- DWORD WINAPI FormatSingleW (PWORD pwBuffer, DWORD dOffset, PWORD pwFormat, PDWORD pdFormat, PVOID *ppData, WORD wFill, BOOL fUnicode) { PVOID pData, pText; WORD wData, wFill1; BOOL fAnsi, fShort, fSigned, fLower, fRight, fZero, fPrefix; BOOL fPrecision, fDone, fSkip; DWORD dPrecision, dWidth, dData, dFormat, dNumber; DWORD n = 0; pData = (ppData != NULL ? *ppData : NULL); dFormat = (pdFormat != NULL ? *pdFormat : 0); if (pwFormat != NULL) { fAnsi = !fUnicode; fShort = FALSE; fSigned = FALSE; fLower = FALSE; fRight = FALSE; fZero = FALSE; fPrefix = FALSE; wData = '%'; wFill1 = wFill; dWidth = 0; dPrecision = -1; fPrecision = FALSE; fDone = FALSE; while ((!fDone) && pwFormat [dFormat]) { fSkip = TRUE; switch (pwFormat [dFormat]) { // operand size case 'l': { fShort = fAnsi = FALSE; break; } case 'h': { fShort = fAnsi = TRUE; break; } // strings case 'S': { fAnsi = fUnicode; } case 's': { pText = (pData != NULL ? *(PVOID *) pData : NULL); if (fAnsi) { n = FormatAnsiW (pwBuffer, dOffset, pText, -1, dWidth, dPrecision, wFill1, fRight, fZero); } else { n = FormatUnicodeW (pwBuffer, dOffset, pText, -1, dWidth, dPrecision, wFill1, fRight, fZero); } if (pData != NULL) { pData = (PBYTE) pData + sizeof (PVOID); } fDone = TRUE; break; } // characters case 'C': { fAnsi = fUnicode; } case 'c': { wData = (pData != NULL ? (fAnsi ? *(PBYTE) pData : *(PWORD) pData) : ' '); if (pData != NULL) { pData = (PBYTE) pData + sizeof (DWORD); } } case '%': { n = FormatUnicodeW (pwBuffer, dOffset, &wData, 1, dWidth, dPrecision, wFill1, fRight, fZero); fDone = TRUE; break; } // decimal numbers case 'd': case 'i': { fSigned = TRUE; } case 'u': { dData = (pData != NULL ? (fSigned ? (fShort ? *(PSHORT) pData : *(PLONG ) pData) : (fShort ? *(PWORD ) pData : *(PDWORD) pData)) : 0); n = FormatDecimalW (pwBuffer, dOffset, dData, dWidth, dPrecision, wFill1, fRight, fZero, fPrefix, fSigned); if (pData != NULL) { pData = (PBYTE) pData + sizeof (DWORD); } fDone = TRUE; break; } // hex numbers case 'x': { fLower = TRUE; } case 'X': { dData = (pData != NULL ? (fShort ? *(PWORD ) pData : *(PDWORD) pData) : 0); n = FormatHexW (pwBuffer, dOffset, dData, dWidth, dPrecision, wFill1, fRight, fZero, fPrefix, fLower); if (pData != NULL) { pData = (PBYTE) pData + sizeof (DWORD); } fDone = TRUE; break; } // output styles case '+': { if (pwFormat [dFormat+1]) { wFill1 = pwFormat [++dFormat]; } break; } case '-': { fRight = TRUE; break; } case '0': { fZero = TRUE; break; } case '#': { fPrefix = TRUE; break; } // output width default: { if (fPrecision = (pwFormat [dFormat] == '.')) { dFormat++; dPrecision = 0; fSkip = FALSE; } if ((pwFormat [dFormat] >= '0') && (pwFormat [dFormat] <= '9')) { dNumber = 0; while ((pwFormat [dFormat] >= '0') && (pwFormat [dFormat] <= '9')) { dNumber *= 10; dNumber += (pwFormat [dFormat++] - '0'); } if (fPrecision) { dPrecision = dNumber; } else { dWidth = dNumber; } fSkip = FALSE; } break; } } if (fSkip) dFormat++; } } if (pwBuffer != NULL) pwBuffer [dOffset+n] = 0; if (pdFormat != NULL) *pdFormat = dFormat; if (ppData != NULL) *ppData = pData; return n; } // ----------------------------------------------------------------- DWORD WINAPI FormatMultiW (PWORD pwBuffer, DWORD dOffset, PWORD pwFormat, PVOID pArguments, WORD wFill, BOOL fUnicode) { PVOID pData; DWORD i, j; DWORD n = 0; if (pwFormat != NULL) { if ((pData = pArguments) != NULL) { for (i = 0; pwFormat [i]; i = j) { for (j = i; pwFormat [j] && (pwFormat [j] != '%'); j++); n += FormatUnicodeW (pwBuffer, dOffset+n, pwFormat+i, j-i, 0, -1, wFill, TRUE, FALSE); if (pwFormat [j] == '%') { j++; n += FormatSingleW (pwBuffer, dOffset+n, pwFormat, &j, &pData, wFill, fUnicode); } } } else { n = FormatUnicodeW (pwBuffer, dOffset, pwFormat, -1, 0, -1, wFill, TRUE, FALSE); } } if (pwBuffer != NULL) pwBuffer [dOffset+n] = 0; return n; } // ================================================================= // vprintf() ROUTINES (UNICODE) // ================================================================= DWORD WINAPI vsprintfW (PWORD pwBuffer, PWORD pwFormat, PVOID pArguments) { return FormatMultiW (pwBuffer, 0, pwFormat, pArguments, gwFill, TRUE); } // ----------------------------------------------------------------- INT WINAPI vmprintfW (HWND hWnd, UINT uiType, PWORD pwCaption, PWORD pwFormat, PVOID pArguments) { PWORD pwBuffer; DWORD dBuffer; INT iId = IDABORT; dBuffer = vsprintfW (NULL, pwFormat, pArguments); if ((pwBuffer = ALLOC_UNICODE (dBuffer+1)) != NULL) { vsprintfW (pwBuffer, pwFormat, pArguments); iId = MessageBoxW (hWnd, pwBuffer, (pwCaption != NULL ? pwCaption : SW(MAIN_CAPTION)), uiType); LocalFree (pwBuffer); } return iId; } // ----------------------------------------------------------------- DWORD WINAPI vfprintfW (HANDLE hFile, PWORD pwFormat, PVOID pArguments) { PWORD pwBuffer; PBYTE pbBuffer; DWORD dBuffer, n1, n2; DWORD n = 0; dBuffer = vsprintfW (NULL, pwFormat, pArguments); if ((pwBuffer = ALLOC_UNICODE (dBuffer+1)) != NULL) { vsprintfW (pwBuffer, pwFormat, pArguments); if ((pbBuffer = ConvertUnicodeToAnsi (pwBuffer, NULL)) != NULL) { while (dBuffer > n) { n1 = min (dBuffer-n, WRITE_FILE_BLOCK); n2 = 0; if (WriteFile (hFile, pbBuffer+n, n1, &n2, NULL) && n2) { n += n2; } else break; } LocalFree (pbBuffer); } LocalFree (pwBuffer); } return n; } // ----------------------------------------------------------------- DWORD WINAPI veprintfW (PWORD pwFormat, PVOID pArguments) { ConsoleOpen (); return vfprintfW (ghStdError, pwFormat, pArguments); } // ----------------------------------------------------------------- DWORD WINAPI vprintfW (PWORD pwFormat, PVOID pArguments) { ConsoleOpen (); return vfprintfW (ghStdOutput, pwFormat, pArguments); } // ================================================================= // printf() ROUTINES (UNICODE) // ================================================================= DWORD WINAPI sprintfW (PWORD pwBuffer, PWORD pwFormat, ...) { return vsprintfW (pwBuffer, pwFormat, (&pwFormat)+1); } // ----------------------------------------------------------------- INT WINAPI mprintfW (HWND hWnd, UINT uiType, PWORD pwCaption, PWORD pwFormat, ...) { return vmprintfW (hWnd, uiType, pwCaption, pwFormat, (&pwFormat)+1); } // ----------------------------------------------------------------- DWORD WINAPI fprintfW (HANDLE hFile, PWORD pwFormat, ...) { return vfprintfW (hFile, pwFormat, (&pwFormat)+1); } // ----------------------------------------------------------------- DWORD WINAPI eprintfW (PWORD pwFormat, ...) { return veprintfW (pwFormat, (&pwFormat)+1); } // ----------------------------------------------------------------- DWORD WINAPI printfW (PWORD pwFormat, ...) { return vprintfW (pwFormat, (&pwFormat)+1); } // ================================================================= // vprintf() ROUTINES (ANSI) // ================================================================= DWORD WINAPI vsprintfA (PBYTE pbBuffer, PBYTE pbFormat, PVOID pArguments) { PWORD pwBuffer, pwFormat; DWORD n = 0; if ((pwFormat = ConvertAnsiToUnicode (pbFormat, NULL)) != NULL) { n = FormatMultiW (NULL, 0, pwFormat, pArguments, gwFill, FALSE); if (pbBuffer != NULL) { if ((pwBuffer = ALLOC_UNICODE (n+1)) != NULL) { FormatMultiW (pwBuffer, 0, pwFormat, pArguments, gwFill, FALSE); ConvertUnicodeToAnsi (pwBuffer, pbBuffer); LocalFree (pwBuffer); } else { pbBuffer [n = 0] = 0; } } LocalFree (pwFormat); } return n; } // ----------------------------------------------------------------- INT WINAPI vmprintfA (HWND hWnd, UINT uiType, PBYTE pbCaption, PBYTE pbFormat, PVOID pArguments) { PWORD pwFormat; PWORD pwBuffer; PBYTE pbBuffer; DWORD dBuffer; INT iId = IDABORT; if ((pwFormat = ConvertAnsiToUnicode (pbFormat, NULL)) != NULL) { dBuffer = FormatMultiW (NULL, 0, pwFormat, pArguments, gwFill, FALSE); if ((pwBuffer = ALLOC_UNICODE (dBuffer+1)) != NULL) { FormatMultiW (pwBuffer, 0, pwFormat, pArguments, gwFill, FALSE); if ((pbBuffer = ConvertUnicodeToAnsi (pwBuffer, NULL)) != NULL) { iId = MessageBoxA (hWnd, pbBuffer, (pbCaption != NULL ? pbCaption : SA(MAIN_CAPTION)), uiType); LocalFree (pbBuffer); } LocalFree (pwBuffer); } LocalFree (pwFormat); } return iId; } // ----------------------------------------------------------------- DWORD WINAPI vfprintfA (HANDLE hFile, PBYTE pbFormat, PVOID pArguments) { PWORD pwFormat; PWORD pwBuffer; PBYTE pbBuffer; DWORD dBuffer, n1, n2; DWORD n = 0; if ((pwFormat = ConvertAnsiToUnicode (pbFormat, NULL)) != NULL) { dBuffer = FormatMultiW (NULL, 0, pwFormat, pArguments, gwFill, FALSE); if ((pwBuffer = ALLOC_UNICODE (dBuffer+1)) != NULL) { FormatMultiW (pwBuffer, 0, pwFormat, pArguments, gwFill, FALSE); if ((pbBuffer = ConvertUnicodeToAnsi (pwBuffer, NULL)) != NULL) { while (dBuffer > n) { n1 = min (dBuffer-n, WRITE_FILE_BLOCK); n2 = 0; if (WriteFile (hFile, pbBuffer+n, n1, &n2, NULL) && n2) { n += n2; } else break; } LocalFree (pbBuffer); } LocalFree (pwBuffer); } LocalFree (pwFormat); } return n; } // ----------------------------------------------------------------- DWORD WINAPI veprintfA (PBYTE pbFormat, PVOID pArguments) { ConsoleOpen (); return vfprintfA (ghStdError, pbFormat, pArguments); } // ----------------------------------------------------------------- DWORD WINAPI vprintfA (PBYTE pbFormat, PVOID pArguments) { ConsoleOpen (); return vfprintfA (ghStdOutput, pbFormat, pArguments); } // ================================================================= // printf() ROUTINES (ANSI) // ================================================================= DWORD WINAPI sprintfA (PBYTE pbBuffer, PBYTE pbFormat, ...) { return vsprintfA (pbBuffer, pbFormat, (&pbFormat)+1); } // ----------------------------------------------------------------- INT WINAPI mprintfA (HWND hWnd, UINT uiType, PBYTE pbCaption, PBYTE pbFormat, ...) { return vmprintfA (hWnd, uiType, pbCaption, pbFormat, (&pbFormat)+1); } // ----------------------------------------------------------------- DWORD WINAPI fprintfA (HANDLE hFile, PBYTE pbFormat, ...) { return vfprintfA (hFile, pbFormat, (&pbFormat)+1); } // ----------------------------------------------------------------- DWORD WINAPI eprintfA (PBYTE pbFormat, ...) { return veprintfA (pbFormat, (&pbFormat)+1); } // ----------------------------------------------------------------- DWORD WINAPI printfA (PBYTE pbFormat, ...) { return vprintfA (pbFormat, (&pbFormat)+1); } // ================================================================= // PROTOTYPES // ================================================================= #ifdef _CONSOLE DWORD Main (DWORD argc, PTBYTE *argv, PTBYTE *argp); #else #pragma warning (disable: 4028) int WINAPI WinMain (HINSTANCE hInstance, PWIN_CMD pwc, PTBYTE ptCmdLine, int iShowCmd); #pragma warning (default: 4028) #endif // ================================================================= // COMMAND PARSER // ================================================================= PWIN_CMD W32Command (void) { PTBYTE ptRaw; DWORD dCount, dRaw, dCooked; PWIN_CMD pwc = NULL; if ((ptRaw = GetCommandLine ()) != NULL) { for (dCount = dRaw = dCooked = 0; ptRaw [dRaw]; dCount++) { while (ptRaw [dRaw] == ' ') dRaw++; if (!ptRaw [dRaw]) break; while ( ptRaw [dRaw] && (ptRaw [dRaw] != ' ')) { if (ptRaw [dRaw++] != '"') { dCooked++; } else { while ( ptRaw [dRaw ] && (ptRaw [dRaw++] != '"')) { dCooked++; } } } dCooked++; } dRaw++; if ((pwc = LocalAlloc (LMEM_FIXED, WIN_CMD_ + (dCount * 2 * sizeof (PTBYTE)) + (dRaw * sizeof ( TBYTE)) + (dCooked * sizeof ( TBYTE)))) != NULL) { pwc->argc = dCount; pwc->argv = (PTBYTE *) pwc->abData; pwc->argp = pwc->argv + dCount; pwc->ptRaw = (PTBYTE ) (pwc->argp + dCount); pwc->ptCooked = pwc->ptRaw + dRaw; pwc->ptTail = NULL; CopyMemory (pwc->ptRaw, ptRaw, dRaw * sizeof ( TBYTE)); for (dCount = dRaw = dCooked = 0; pwc->ptRaw [dRaw]; dCount++) { while (pwc->ptRaw [dRaw] == ' ') dRaw++; if (!pwc->ptRaw [dRaw]) break; pwc->argp [dCount] = pwc->ptRaw + dRaw; pwc->argv [dCount] = pwc->ptCooked + dCooked; while ( pwc->ptRaw [dRaw] && (pwc->ptRaw [dRaw] != ' ')) { if (pwc->ptRaw [dRaw++] != '"') { pwc->ptCooked [dCooked++] = pwc->ptRaw [dRaw-1]; } else { while ( pwc->ptRaw [dRaw ] && (pwc->ptRaw [dRaw++] != '"')) { pwc->ptCooked [dCooked++] = pwc->ptRaw [dRaw-1]; } } } pwc->ptCooked [dCooked++] = 0; } pwc->ptTail = (pwc->argc > 1 ? pwc->argp [1] : pwc->ptRaw + dRaw); } } return pwc; } // ================================================================= // STARTUP CODE // ================================================================= void W32Start (void) { #ifdef _CONSOLE CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dCodePage; #else STARTUPINFO si; INT iShowCmd; #endif PWIN_CMD pwc; DWORD dStatus = 0; if ((pwc = W32Command ()) != NULL) { giNetwork = GetSystemMetrics (SM_NETWORK); giDebug = GetSystemMetrics (SM_DEBUG ); #ifdef _CONSOLE // ----------------------------------------------------------------- if (ConsoleOpen ()) { dCodePage = GetConsoleOutputCP (); SetConsoleOutputCP (GetACP ()); GetConsoleScreenBufferInfo (ghStdOutput, &csbi); gdLine = csbi.dwSize.X; dStatus = Main (pwc->argc, pwc->argv, pwc->argp); SetConsoleOutputCP (dCodePage); } #else // ----------------------------------------------------------------- GetStartupInfo (&si); iShowCmd = (si.dwFlags & STARTF_USESHOWWINDOW ? (INT) si.wShowWindow : SW_SHOWDEFAULT); dStatus = WinMain (GetModuleHandle (NULL), pwc, pwc->ptTail, iShowCmd); #endif // ----------------------------------------------------------------- ConsoleClose (); LocalFree (pwc); } ExitProcess (dStatus); return; } // ================================================================= // LINKER CONTROL // ================================================================= #pragma comment (linker, "/entry:\"W32Start\"") //////////////////////////////////////////////////////////////////// #endif // #ifndef _RC_PASS_ //////////////////////////////////////////////////////////////////// #endif // #ifndef _W32START_H_ // ================================================================= // END OF FILE // =================================================================