Fossil SCM
merge ticket-c8c0b78c84 convert winhttp.c to unicode
Commit
f342247c50eb13aa3b3e1b5328b95c63307f61d1
Parent
0387251bd3521cd…
5 files changed
+34
-16
+34
-16
+3
-8
+45
-43
+45
-43
+34
-16
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -24,11 +24,13 @@ | ||
| 24 | 24 | #include <time.h> |
| 25 | 25 | #include <fcntl.h> |
| 26 | 26 | #include <sys/types.h> |
| 27 | 27 | #include <sys/stat.h> |
| 28 | 28 | #include <stdlib.h> /* atexit() */ |
| 29 | -#if !defined(_WIN32) | |
| 29 | +#if defined(_WIN32) | |
| 30 | +# include <windows.h> | |
| 31 | +#else | |
| 30 | 32 | # include <errno.h> /* errno global */ |
| 31 | 33 | #endif |
| 32 | 34 | #if INTERFACE |
| 33 | 35 | #ifdef FOSSIL_ENABLE_JSON |
| 34 | 36 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| @@ -36,16 +38,10 @@ | ||
| 36 | 38 | #endif |
| 37 | 39 | #ifdef FOSSIL_ENABLE_TCL |
| 38 | 40 | #include "tcl.h" |
| 39 | 41 | #endif |
| 40 | 42 | |
| 41 | -#if !defined(_WIN32) || !defined(UNICODE) | |
| 42 | -# define fossil_unicode_to_utf8 fossil_mbcs_to_utf8 | |
| 43 | -# define wchar_t char | |
| 44 | -# define wmain main | |
| 45 | -#endif | |
| 46 | - | |
| 47 | 43 | /* |
| 48 | 44 | ** Number of elements in an array |
| 49 | 45 | */ |
| 50 | 46 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 51 | 47 | |
| @@ -355,14 +351,26 @@ | ||
| 355 | 351 | int n; /* Number of bytes in one line */ |
| 356 | 352 | char *z; /* General use string pointer */ |
| 357 | 353 | char **newArgv; /* New expanded g.argv under construction */ |
| 358 | 354 | char const * zFileName; /* input file name */ |
| 359 | 355 | FILE * zInFile; /* input FILE */ |
| 356 | + int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */ | |
| 357 | +#ifdef _WIN32 | |
| 358 | + wchar_t buf[PATH_MAX]; | |
| 359 | +#endif | |
| 360 | 360 | |
| 361 | 361 | g.argc = argc; |
| 362 | 362 | g.argv = argv; |
| 363 | - for(i=0; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); | |
| 363 | +#ifdef _WIN32 | |
| 364 | + GetModuleFileNameW(NULL, buf, PATH_MAX); | |
| 365 | + g.argv[0] = fossil_unicode_to_utf8(buf); | |
| 366 | +#ifdef UNICODE | |
| 367 | + for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); | |
| 368 | +#else | |
| 369 | + for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]); | |
| 370 | +#endif | |
| 371 | +#endif | |
| 364 | 372 | for(i=1; i<g.argc-1; i++){ |
| 365 | 373 | z = g.argv[i]; |
| 366 | 374 | if( z[0]!='-' ) continue; |
| 367 | 375 | z++; |
| 368 | 376 | if( z[0]=='-' ) z++; |
| @@ -392,15 +400,25 @@ | ||
| 392 | 400 | blob_rewind(&file); |
| 393 | 401 | while( (n = blob_line(&file, &line))>0 ){ |
| 394 | 402 | if( n<=1 ) continue; |
| 395 | 403 | z = blob_buffer(&line); |
| 396 | 404 | z[n-1] = 0; |
| 405 | + if (foundBom == -1) { | |
| 406 | + static const char bom[] = { 0xEF, 0xBB, 0xBF }; | |
| 407 | + foundBom = memcmp(z, bom, 3)==0; | |
| 408 | + if( foundBom ) { | |
| 409 | + z += 3; n -= 3; | |
| 410 | + } | |
| 411 | + } | |
| 397 | 412 | if((n>1) && ('\r'==z[n-2])){ |
| 398 | 413 | if(n==2) continue /*empty line*/; |
| 399 | 414 | z[n-2] = 0; |
| 400 | 415 | } |
| 401 | - newArgv[j++] = z = fossil_mbcs_to_utf8(z); | |
| 416 | + if (!foundBom) { | |
| 417 | + z = fossil_mbcs_to_utf8(z); | |
| 418 | + } | |
| 419 | + newArgv[j++] = z; | |
| 402 | 420 | if( z[0]=='-' ){ |
| 403 | 421 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 404 | 422 | if( z[k] ){ |
| 405 | 423 | z[k] = 0; |
| 406 | 424 | k++; |
| @@ -416,11 +434,15 @@ | ||
| 416 | 434 | } |
| 417 | 435 | |
| 418 | 436 | /* |
| 419 | 437 | ** This procedure runs first. |
| 420 | 438 | */ |
| 439 | +#if defined(_WIN32) && defined(UNICODE) | |
| 421 | 440 | int wmain(int argc, wchar_t **argv) |
| 441 | +#else | |
| 442 | +int main(int argc, char **argv) | |
| 443 | +#endif | |
| 422 | 444 | { |
| 423 | 445 | const char *zCmdName = "unknown"; |
| 424 | 446 | int idx; |
| 425 | 447 | int rc; |
| 426 | 448 | |
| @@ -522,15 +544,11 @@ | ||
| 522 | 544 | |
| 523 | 545 | /* |
| 524 | 546 | ** Return the name of the current executable. |
| 525 | 547 | */ |
| 526 | 548 | const char *fossil_nameofexe(void){ |
| 527 | -#ifdef _WIN32 | |
| 528 | - return _pgmptr; | |
| 529 | -#else | |
| 530 | 549 | return g.argv[0]; |
| 531 | -#endif | |
| 532 | 550 | } |
| 533 | 551 | |
| 534 | 552 | /* |
| 535 | 553 | ** Exit. Take care to close the database first. |
| 536 | 554 | */ |
| @@ -699,13 +717,13 @@ | ||
| 699 | 717 | #if defined(_WIN32) |
| 700 | 718 | /* On windows, we have to put double-quotes around the entire command. |
| 701 | 719 | ** Who knows why - this is just the way windows works. |
| 702 | 720 | */ |
| 703 | 721 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 704 | - char *zMbcs = fossil_utf8_to_mbcs(zNewCmd); | |
| 705 | - if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zMbcs); | |
| 706 | - rc = system(zMbcs); | |
| 722 | + wchar_t *zMbcs = fossil_utf8_to_unicode(zNewCmd); | |
| 723 | + if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zNewCmd); | |
| 724 | + rc = _wsystem(zMbcs); | |
| 707 | 725 | fossil_mbcs_free(zMbcs); |
| 708 | 726 | free(zNewCmd); |
| 709 | 727 | #else |
| 710 | 728 | /* On unix, evaluate the command directly. |
| 711 | 729 | */ |
| 712 | 730 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -24,11 +24,13 @@ | |
| 24 | #include <time.h> |
| 25 | #include <fcntl.h> |
| 26 | #include <sys/types.h> |
| 27 | #include <sys/stat.h> |
| 28 | #include <stdlib.h> /* atexit() */ |
| 29 | #if !defined(_WIN32) |
| 30 | # include <errno.h> /* errno global */ |
| 31 | #endif |
| 32 | #if INTERFACE |
| 33 | #ifdef FOSSIL_ENABLE_JSON |
| 34 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| @@ -36,16 +38,10 @@ | |
| 36 | #endif |
| 37 | #ifdef FOSSIL_ENABLE_TCL |
| 38 | #include "tcl.h" |
| 39 | #endif |
| 40 | |
| 41 | #if !defined(_WIN32) || !defined(UNICODE) |
| 42 | # define fossil_unicode_to_utf8 fossil_mbcs_to_utf8 |
| 43 | # define wchar_t char |
| 44 | # define wmain main |
| 45 | #endif |
| 46 | |
| 47 | /* |
| 48 | ** Number of elements in an array |
| 49 | */ |
| 50 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 51 | |
| @@ -355,14 +351,26 @@ | |
| 355 | int n; /* Number of bytes in one line */ |
| 356 | char *z; /* General use string pointer */ |
| 357 | char **newArgv; /* New expanded g.argv under construction */ |
| 358 | char const * zFileName; /* input file name */ |
| 359 | FILE * zInFile; /* input FILE */ |
| 360 | |
| 361 | g.argc = argc; |
| 362 | g.argv = argv; |
| 363 | for(i=0; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); |
| 364 | for(i=1; i<g.argc-1; i++){ |
| 365 | z = g.argv[i]; |
| 366 | if( z[0]!='-' ) continue; |
| 367 | z++; |
| 368 | if( z[0]=='-' ) z++; |
| @@ -392,15 +400,25 @@ | |
| 392 | blob_rewind(&file); |
| 393 | while( (n = blob_line(&file, &line))>0 ){ |
| 394 | if( n<=1 ) continue; |
| 395 | z = blob_buffer(&line); |
| 396 | z[n-1] = 0; |
| 397 | if((n>1) && ('\r'==z[n-2])){ |
| 398 | if(n==2) continue /*empty line*/; |
| 399 | z[n-2] = 0; |
| 400 | } |
| 401 | newArgv[j++] = z = fossil_mbcs_to_utf8(z); |
| 402 | if( z[0]=='-' ){ |
| 403 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 404 | if( z[k] ){ |
| 405 | z[k] = 0; |
| 406 | k++; |
| @@ -416,11 +434,15 @@ | |
| 416 | } |
| 417 | |
| 418 | /* |
| 419 | ** This procedure runs first. |
| 420 | */ |
| 421 | int wmain(int argc, wchar_t **argv) |
| 422 | { |
| 423 | const char *zCmdName = "unknown"; |
| 424 | int idx; |
| 425 | int rc; |
| 426 | |
| @@ -522,15 +544,11 @@ | |
| 522 | |
| 523 | /* |
| 524 | ** Return the name of the current executable. |
| 525 | */ |
| 526 | const char *fossil_nameofexe(void){ |
| 527 | #ifdef _WIN32 |
| 528 | return _pgmptr; |
| 529 | #else |
| 530 | return g.argv[0]; |
| 531 | #endif |
| 532 | } |
| 533 | |
| 534 | /* |
| 535 | ** Exit. Take care to close the database first. |
| 536 | */ |
| @@ -699,13 +717,13 @@ | |
| 699 | #if defined(_WIN32) |
| 700 | /* On windows, we have to put double-quotes around the entire command. |
| 701 | ** Who knows why - this is just the way windows works. |
| 702 | */ |
| 703 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 704 | char *zMbcs = fossil_utf8_to_mbcs(zNewCmd); |
| 705 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zMbcs); |
| 706 | rc = system(zMbcs); |
| 707 | fossil_mbcs_free(zMbcs); |
| 708 | free(zNewCmd); |
| 709 | #else |
| 710 | /* On unix, evaluate the command directly. |
| 711 | */ |
| 712 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -24,11 +24,13 @@ | |
| 24 | #include <time.h> |
| 25 | #include <fcntl.h> |
| 26 | #include <sys/types.h> |
| 27 | #include <sys/stat.h> |
| 28 | #include <stdlib.h> /* atexit() */ |
| 29 | #if defined(_WIN32) |
| 30 | # include <windows.h> |
| 31 | #else |
| 32 | # include <errno.h> /* errno global */ |
| 33 | #endif |
| 34 | #if INTERFACE |
| 35 | #ifdef FOSSIL_ENABLE_JSON |
| 36 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| @@ -36,16 +38,10 @@ | |
| 38 | #endif |
| 39 | #ifdef FOSSIL_ENABLE_TCL |
| 40 | #include "tcl.h" |
| 41 | #endif |
| 42 | |
| 43 | /* |
| 44 | ** Number of elements in an array |
| 45 | */ |
| 46 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 47 | |
| @@ -355,14 +351,26 @@ | |
| 351 | int n; /* Number of bytes in one line */ |
| 352 | char *z; /* General use string pointer */ |
| 353 | char **newArgv; /* New expanded g.argv under construction */ |
| 354 | char const * zFileName; /* input file name */ |
| 355 | FILE * zInFile; /* input FILE */ |
| 356 | int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */ |
| 357 | #ifdef _WIN32 |
| 358 | wchar_t buf[PATH_MAX]; |
| 359 | #endif |
| 360 | |
| 361 | g.argc = argc; |
| 362 | g.argv = argv; |
| 363 | #ifdef _WIN32 |
| 364 | GetModuleFileNameW(NULL, buf, PATH_MAX); |
| 365 | g.argv[0] = fossil_unicode_to_utf8(buf); |
| 366 | #ifdef UNICODE |
| 367 | for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); |
| 368 | #else |
| 369 | for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]); |
| 370 | #endif |
| 371 | #endif |
| 372 | for(i=1; i<g.argc-1; i++){ |
| 373 | z = g.argv[i]; |
| 374 | if( z[0]!='-' ) continue; |
| 375 | z++; |
| 376 | if( z[0]=='-' ) z++; |
| @@ -392,15 +400,25 @@ | |
| 400 | blob_rewind(&file); |
| 401 | while( (n = blob_line(&file, &line))>0 ){ |
| 402 | if( n<=1 ) continue; |
| 403 | z = blob_buffer(&line); |
| 404 | z[n-1] = 0; |
| 405 | if (foundBom == -1) { |
| 406 | static const char bom[] = { 0xEF, 0xBB, 0xBF }; |
| 407 | foundBom = memcmp(z, bom, 3)==0; |
| 408 | if( foundBom ) { |
| 409 | z += 3; n -= 3; |
| 410 | } |
| 411 | } |
| 412 | if((n>1) && ('\r'==z[n-2])){ |
| 413 | if(n==2) continue /*empty line*/; |
| 414 | z[n-2] = 0; |
| 415 | } |
| 416 | if (!foundBom) { |
| 417 | z = fossil_mbcs_to_utf8(z); |
| 418 | } |
| 419 | newArgv[j++] = z; |
| 420 | if( z[0]=='-' ){ |
| 421 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 422 | if( z[k] ){ |
| 423 | z[k] = 0; |
| 424 | k++; |
| @@ -416,11 +434,15 @@ | |
| 434 | } |
| 435 | |
| 436 | /* |
| 437 | ** This procedure runs first. |
| 438 | */ |
| 439 | #if defined(_WIN32) && defined(UNICODE) |
| 440 | int wmain(int argc, wchar_t **argv) |
| 441 | #else |
| 442 | int main(int argc, char **argv) |
| 443 | #endif |
| 444 | { |
| 445 | const char *zCmdName = "unknown"; |
| 446 | int idx; |
| 447 | int rc; |
| 448 | |
| @@ -522,15 +544,11 @@ | |
| 544 | |
| 545 | /* |
| 546 | ** Return the name of the current executable. |
| 547 | */ |
| 548 | const char *fossil_nameofexe(void){ |
| 549 | return g.argv[0]; |
| 550 | } |
| 551 | |
| 552 | /* |
| 553 | ** Exit. Take care to close the database first. |
| 554 | */ |
| @@ -699,13 +717,13 @@ | |
| 717 | #if defined(_WIN32) |
| 718 | /* On windows, we have to put double-quotes around the entire command. |
| 719 | ** Who knows why - this is just the way windows works. |
| 720 | */ |
| 721 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 722 | wchar_t *zMbcs = fossil_utf8_to_unicode(zNewCmd); |
| 723 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zNewCmd); |
| 724 | rc = _wsystem(zMbcs); |
| 725 | fossil_mbcs_free(zMbcs); |
| 726 | free(zNewCmd); |
| 727 | #else |
| 728 | /* On unix, evaluate the command directly. |
| 729 | */ |
| 730 |
+34
-16
| --- src/main.c | ||
| +++ src/main.c | ||
| @@ -24,11 +24,13 @@ | ||
| 24 | 24 | #include <time.h> |
| 25 | 25 | #include <fcntl.h> |
| 26 | 26 | #include <sys/types.h> |
| 27 | 27 | #include <sys/stat.h> |
| 28 | 28 | #include <stdlib.h> /* atexit() */ |
| 29 | -#if !defined(_WIN32) | |
| 29 | +#if defined(_WIN32) | |
| 30 | +# include <windows.h> | |
| 31 | +#else | |
| 30 | 32 | # include <errno.h> /* errno global */ |
| 31 | 33 | #endif |
| 32 | 34 | #if INTERFACE |
| 33 | 35 | #ifdef FOSSIL_ENABLE_JSON |
| 34 | 36 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| @@ -36,16 +38,10 @@ | ||
| 36 | 38 | #endif |
| 37 | 39 | #ifdef FOSSIL_ENABLE_TCL |
| 38 | 40 | #include "tcl.h" |
| 39 | 41 | #endif |
| 40 | 42 | |
| 41 | -#if !defined(_WIN32) || !defined(UNICODE) | |
| 42 | -# define fossil_unicode_to_utf8 fossil_mbcs_to_utf8 | |
| 43 | -# define wchar_t char | |
| 44 | -# define wmain main | |
| 45 | -#endif | |
| 46 | - | |
| 47 | 43 | /* |
| 48 | 44 | ** Number of elements in an array |
| 49 | 45 | */ |
| 50 | 46 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 51 | 47 | |
| @@ -355,14 +351,26 @@ | ||
| 355 | 351 | int n; /* Number of bytes in one line */ |
| 356 | 352 | char *z; /* General use string pointer */ |
| 357 | 353 | char **newArgv; /* New expanded g.argv under construction */ |
| 358 | 354 | char const * zFileName; /* input file name */ |
| 359 | 355 | FILE * zInFile; /* input FILE */ |
| 356 | + int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */ | |
| 357 | +#ifdef _WIN32 | |
| 358 | + wchar_t buf[PATH_MAX]; | |
| 359 | +#endif | |
| 360 | 360 | |
| 361 | 361 | g.argc = argc; |
| 362 | 362 | g.argv = argv; |
| 363 | - for(i=0; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); | |
| 363 | +#ifdef _WIN32 | |
| 364 | + GetModuleFileNameW(NULL, buf, PATH_MAX); | |
| 365 | + g.argv[0] = fossil_unicode_to_utf8(buf); | |
| 366 | +#ifdef UNICODE | |
| 367 | + for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); | |
| 368 | +#else | |
| 369 | + for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]); | |
| 370 | +#endif | |
| 371 | +#endif | |
| 364 | 372 | for(i=1; i<g.argc-1; i++){ |
| 365 | 373 | z = g.argv[i]; |
| 366 | 374 | if( z[0]!='-' ) continue; |
| 367 | 375 | z++; |
| 368 | 376 | if( z[0]=='-' ) z++; |
| @@ -392,15 +400,25 @@ | ||
| 392 | 400 | blob_rewind(&file); |
| 393 | 401 | while( (n = blob_line(&file, &line))>0 ){ |
| 394 | 402 | if( n<=1 ) continue; |
| 395 | 403 | z = blob_buffer(&line); |
| 396 | 404 | z[n-1] = 0; |
| 405 | + if (foundBom == -1) { | |
| 406 | + static const char bom[] = { 0xEF, 0xBB, 0xBF }; | |
| 407 | + foundBom = memcmp(z, bom, 3)==0; | |
| 408 | + if( foundBom ) { | |
| 409 | + z += 3; n -= 3; | |
| 410 | + } | |
| 411 | + } | |
| 397 | 412 | if((n>1) && ('\r'==z[n-2])){ |
| 398 | 413 | if(n==2) continue /*empty line*/; |
| 399 | 414 | z[n-2] = 0; |
| 400 | 415 | } |
| 401 | - newArgv[j++] = z = fossil_mbcs_to_utf8(z); | |
| 416 | + if (!foundBom) { | |
| 417 | + z = fossil_mbcs_to_utf8(z); | |
| 418 | + } | |
| 419 | + newArgv[j++] = z; | |
| 402 | 420 | if( z[0]=='-' ){ |
| 403 | 421 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 404 | 422 | if( z[k] ){ |
| 405 | 423 | z[k] = 0; |
| 406 | 424 | k++; |
| @@ -416,11 +434,15 @@ | ||
| 416 | 434 | } |
| 417 | 435 | |
| 418 | 436 | /* |
| 419 | 437 | ** This procedure runs first. |
| 420 | 438 | */ |
| 439 | +#if defined(_WIN32) && defined(UNICODE) | |
| 421 | 440 | int wmain(int argc, wchar_t **argv) |
| 441 | +#else | |
| 442 | +int main(int argc, char **argv) | |
| 443 | +#endif | |
| 422 | 444 | { |
| 423 | 445 | const char *zCmdName = "unknown"; |
| 424 | 446 | int idx; |
| 425 | 447 | int rc; |
| 426 | 448 | |
| @@ -522,15 +544,11 @@ | ||
| 522 | 544 | |
| 523 | 545 | /* |
| 524 | 546 | ** Return the name of the current executable. |
| 525 | 547 | */ |
| 526 | 548 | const char *fossil_nameofexe(void){ |
| 527 | -#ifdef _WIN32 | |
| 528 | - return _pgmptr; | |
| 529 | -#else | |
| 530 | 549 | return g.argv[0]; |
| 531 | -#endif | |
| 532 | 550 | } |
| 533 | 551 | |
| 534 | 552 | /* |
| 535 | 553 | ** Exit. Take care to close the database first. |
| 536 | 554 | */ |
| @@ -699,13 +717,13 @@ | ||
| 699 | 717 | #if defined(_WIN32) |
| 700 | 718 | /* On windows, we have to put double-quotes around the entire command. |
| 701 | 719 | ** Who knows why - this is just the way windows works. |
| 702 | 720 | */ |
| 703 | 721 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 704 | - char *zMbcs = fossil_utf8_to_mbcs(zNewCmd); | |
| 705 | - if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zMbcs); | |
| 706 | - rc = system(zMbcs); | |
| 722 | + wchar_t *zMbcs = fossil_utf8_to_unicode(zNewCmd); | |
| 723 | + if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zNewCmd); | |
| 724 | + rc = _wsystem(zMbcs); | |
| 707 | 725 | fossil_mbcs_free(zMbcs); |
| 708 | 726 | free(zNewCmd); |
| 709 | 727 | #else |
| 710 | 728 | /* On unix, evaluate the command directly. |
| 711 | 729 | */ |
| 712 | 730 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -24,11 +24,13 @@ | |
| 24 | #include <time.h> |
| 25 | #include <fcntl.h> |
| 26 | #include <sys/types.h> |
| 27 | #include <sys/stat.h> |
| 28 | #include <stdlib.h> /* atexit() */ |
| 29 | #if !defined(_WIN32) |
| 30 | # include <errno.h> /* errno global */ |
| 31 | #endif |
| 32 | #if INTERFACE |
| 33 | #ifdef FOSSIL_ENABLE_JSON |
| 34 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| @@ -36,16 +38,10 @@ | |
| 36 | #endif |
| 37 | #ifdef FOSSIL_ENABLE_TCL |
| 38 | #include "tcl.h" |
| 39 | #endif |
| 40 | |
| 41 | #if !defined(_WIN32) || !defined(UNICODE) |
| 42 | # define fossil_unicode_to_utf8 fossil_mbcs_to_utf8 |
| 43 | # define wchar_t char |
| 44 | # define wmain main |
| 45 | #endif |
| 46 | |
| 47 | /* |
| 48 | ** Number of elements in an array |
| 49 | */ |
| 50 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 51 | |
| @@ -355,14 +351,26 @@ | |
| 355 | int n; /* Number of bytes in one line */ |
| 356 | char *z; /* General use string pointer */ |
| 357 | char **newArgv; /* New expanded g.argv under construction */ |
| 358 | char const * zFileName; /* input file name */ |
| 359 | FILE * zInFile; /* input FILE */ |
| 360 | |
| 361 | g.argc = argc; |
| 362 | g.argv = argv; |
| 363 | for(i=0; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); |
| 364 | for(i=1; i<g.argc-1; i++){ |
| 365 | z = g.argv[i]; |
| 366 | if( z[0]!='-' ) continue; |
| 367 | z++; |
| 368 | if( z[0]=='-' ) z++; |
| @@ -392,15 +400,25 @@ | |
| 392 | blob_rewind(&file); |
| 393 | while( (n = blob_line(&file, &line))>0 ){ |
| 394 | if( n<=1 ) continue; |
| 395 | z = blob_buffer(&line); |
| 396 | z[n-1] = 0; |
| 397 | if((n>1) && ('\r'==z[n-2])){ |
| 398 | if(n==2) continue /*empty line*/; |
| 399 | z[n-2] = 0; |
| 400 | } |
| 401 | newArgv[j++] = z = fossil_mbcs_to_utf8(z); |
| 402 | if( z[0]=='-' ){ |
| 403 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 404 | if( z[k] ){ |
| 405 | z[k] = 0; |
| 406 | k++; |
| @@ -416,11 +434,15 @@ | |
| 416 | } |
| 417 | |
| 418 | /* |
| 419 | ** This procedure runs first. |
| 420 | */ |
| 421 | int wmain(int argc, wchar_t **argv) |
| 422 | { |
| 423 | const char *zCmdName = "unknown"; |
| 424 | int idx; |
| 425 | int rc; |
| 426 | |
| @@ -522,15 +544,11 @@ | |
| 522 | |
| 523 | /* |
| 524 | ** Return the name of the current executable. |
| 525 | */ |
| 526 | const char *fossil_nameofexe(void){ |
| 527 | #ifdef _WIN32 |
| 528 | return _pgmptr; |
| 529 | #else |
| 530 | return g.argv[0]; |
| 531 | #endif |
| 532 | } |
| 533 | |
| 534 | /* |
| 535 | ** Exit. Take care to close the database first. |
| 536 | */ |
| @@ -699,13 +717,13 @@ | |
| 699 | #if defined(_WIN32) |
| 700 | /* On windows, we have to put double-quotes around the entire command. |
| 701 | ** Who knows why - this is just the way windows works. |
| 702 | */ |
| 703 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 704 | char *zMbcs = fossil_utf8_to_mbcs(zNewCmd); |
| 705 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zMbcs); |
| 706 | rc = system(zMbcs); |
| 707 | fossil_mbcs_free(zMbcs); |
| 708 | free(zNewCmd); |
| 709 | #else |
| 710 | /* On unix, evaluate the command directly. |
| 711 | */ |
| 712 |
| --- src/main.c | |
| +++ src/main.c | |
| @@ -24,11 +24,13 @@ | |
| 24 | #include <time.h> |
| 25 | #include <fcntl.h> |
| 26 | #include <sys/types.h> |
| 27 | #include <sys/stat.h> |
| 28 | #include <stdlib.h> /* atexit() */ |
| 29 | #if defined(_WIN32) |
| 30 | # include <windows.h> |
| 31 | #else |
| 32 | # include <errno.h> /* errno global */ |
| 33 | #endif |
| 34 | #if INTERFACE |
| 35 | #ifdef FOSSIL_ENABLE_JSON |
| 36 | # include "cson_amalgamation.h" /* JSON API. Needed inside the INTERFACE block! */ |
| @@ -36,16 +38,10 @@ | |
| 38 | #endif |
| 39 | #ifdef FOSSIL_ENABLE_TCL |
| 40 | #include "tcl.h" |
| 41 | #endif |
| 42 | |
| 43 | /* |
| 44 | ** Number of elements in an array |
| 45 | */ |
| 46 | #define count(X) (sizeof(X)/sizeof(X[0])) |
| 47 | |
| @@ -355,14 +351,26 @@ | |
| 351 | int n; /* Number of bytes in one line */ |
| 352 | char *z; /* General use string pointer */ |
| 353 | char **newArgv; /* New expanded g.argv under construction */ |
| 354 | char const * zFileName; /* input file name */ |
| 355 | FILE * zInFile; /* input FILE */ |
| 356 | int foundBom = -1; /* -1= not searched yet, 0 = no; 1=yes */ |
| 357 | #ifdef _WIN32 |
| 358 | wchar_t buf[PATH_MAX]; |
| 359 | #endif |
| 360 | |
| 361 | g.argc = argc; |
| 362 | g.argv = argv; |
| 363 | #ifdef _WIN32 |
| 364 | GetModuleFileNameW(NULL, buf, PATH_MAX); |
| 365 | g.argv[0] = fossil_unicode_to_utf8(buf); |
| 366 | #ifdef UNICODE |
| 367 | for(i=1; i<g.argc; i++) g.argv[i] = fossil_unicode_to_utf8(g.argv[i]); |
| 368 | #else |
| 369 | for(i=1; i<g.argc; i++) g.argv[i] = fossil_mbcs_to_utf8(g.argv[i]); |
| 370 | #endif |
| 371 | #endif |
| 372 | for(i=1; i<g.argc-1; i++){ |
| 373 | z = g.argv[i]; |
| 374 | if( z[0]!='-' ) continue; |
| 375 | z++; |
| 376 | if( z[0]=='-' ) z++; |
| @@ -392,15 +400,25 @@ | |
| 400 | blob_rewind(&file); |
| 401 | while( (n = blob_line(&file, &line))>0 ){ |
| 402 | if( n<=1 ) continue; |
| 403 | z = blob_buffer(&line); |
| 404 | z[n-1] = 0; |
| 405 | if (foundBom == -1) { |
| 406 | static const char bom[] = { 0xEF, 0xBB, 0xBF }; |
| 407 | foundBom = memcmp(z, bom, 3)==0; |
| 408 | if( foundBom ) { |
| 409 | z += 3; n -= 3; |
| 410 | } |
| 411 | } |
| 412 | if((n>1) && ('\r'==z[n-2])){ |
| 413 | if(n==2) continue /*empty line*/; |
| 414 | z[n-2] = 0; |
| 415 | } |
| 416 | if (!foundBom) { |
| 417 | z = fossil_mbcs_to_utf8(z); |
| 418 | } |
| 419 | newArgv[j++] = z; |
| 420 | if( z[0]=='-' ){ |
| 421 | for(k=1; z[k] && !fossil_isspace(z[k]); k++){} |
| 422 | if( z[k] ){ |
| 423 | z[k] = 0; |
| 424 | k++; |
| @@ -416,11 +434,15 @@ | |
| 434 | } |
| 435 | |
| 436 | /* |
| 437 | ** This procedure runs first. |
| 438 | */ |
| 439 | #if defined(_WIN32) && defined(UNICODE) |
| 440 | int wmain(int argc, wchar_t **argv) |
| 441 | #else |
| 442 | int main(int argc, char **argv) |
| 443 | #endif |
| 444 | { |
| 445 | const char *zCmdName = "unknown"; |
| 446 | int idx; |
| 447 | int rc; |
| 448 | |
| @@ -522,15 +544,11 @@ | |
| 544 | |
| 545 | /* |
| 546 | ** Return the name of the current executable. |
| 547 | */ |
| 548 | const char *fossil_nameofexe(void){ |
| 549 | return g.argv[0]; |
| 550 | } |
| 551 | |
| 552 | /* |
| 553 | ** Exit. Take care to close the database first. |
| 554 | */ |
| @@ -699,13 +717,13 @@ | |
| 717 | #if defined(_WIN32) |
| 718 | /* On windows, we have to put double-quotes around the entire command. |
| 719 | ** Who knows why - this is just the way windows works. |
| 720 | */ |
| 721 | char *zNewCmd = mprintf("\"%s\"", zOrigCmd); |
| 722 | wchar_t *zMbcs = fossil_utf8_to_unicode(zNewCmd); |
| 723 | if( g.fSystemTrace ) fprintf(stderr, "SYSTEM: %s\n", zNewCmd); |
| 724 | rc = _wsystem(zMbcs); |
| 725 | fossil_mbcs_free(zMbcs); |
| 726 | free(zNewCmd); |
| 727 | #else |
| 728 | /* On unix, evaluate the command directly. |
| 729 | */ |
| 730 |
+3
-8
| --- src/popen.c | ||
| +++ src/popen.c | ||
| @@ -65,17 +65,17 @@ | ||
| 65 | 65 | ** and stderr channels for that process to use. |
| 66 | 66 | ** |
| 67 | 67 | ** Return the number of errors. |
| 68 | 68 | */ |
| 69 | 69 | static int win32_create_child_process( |
| 70 | - TCHAR *zCmd, /* The command that the child process will run */ | |
| 70 | + wchar_t *zCmd, /* The command that the child process will run */ | |
| 71 | 71 | HANDLE hIn, /* Standard input */ |
| 72 | 72 | HANDLE hOut, /* Standard output */ |
| 73 | 73 | HANDLE hErr, /* Standard error */ |
| 74 | 74 | DWORD *pChildPid /* OUT: Child process handle */ |
| 75 | 75 | ){ |
| 76 | - STARTUPINFO si; | |
| 76 | + STARTUPINFOW si; | |
| 77 | 77 | PROCESS_INFORMATION pi; |
| 78 | 78 | BOOL rc; |
| 79 | 79 | |
| 80 | 80 | memset(&si, 0, sizeof(si)); |
| 81 | 81 | si.cb = sizeof(si); |
| @@ -84,11 +84,11 @@ | ||
| 84 | 84 | si.hStdInput = hIn; |
| 85 | 85 | SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, TRUE); |
| 86 | 86 | si.hStdOutput = hOut; |
| 87 | 87 | SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, TRUE); |
| 88 | 88 | si.hStdError = hErr; |
| 89 | - rc = CreateProcess( | |
| 89 | + rc = CreateProcessW( | |
| 90 | 90 | NULL, /* Application Name */ |
| 91 | 91 | zCmd, /* Command-line */ |
| 92 | 92 | NULL, /* Process attributes */ |
| 93 | 93 | NULL, /* Thread attributes */ |
| 94 | 94 | TRUE, /* Inherit Handles */ |
| @@ -139,17 +139,12 @@ | ||
| 139 | 139 | if( !CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 4096) ){ |
| 140 | 140 | win32_fatal_error("cannot create pipe for stdin"); |
| 141 | 141 | } |
| 142 | 142 | SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); |
| 143 | 143 | |
| 144 | -#ifdef UNICODE | |
| 145 | 144 | win32_create_child_process(fossil_utf8_to_unicode(zCmd), |
| 146 | 145 | hStdinRd, hStdoutWr, hStderr,&childPid); |
| 147 | -#else | |
| 148 | - win32_create_child_process(fossil_utf8_to_mbcs(zCmd), | |
| 149 | - hStdinRd, hStdoutWr, hStderr,&childPid); | |
| 150 | -#endif | |
| 151 | 146 | *pChildPid = childPid; |
| 152 | 147 | *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); |
| 153 | 148 | fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); |
| 154 | 149 | *ppOut = _fdopen(fd, "w"); |
| 155 | 150 | CloseHandle(hStdinRd); |
| 156 | 151 |
| --- src/popen.c | |
| +++ src/popen.c | |
| @@ -65,17 +65,17 @@ | |
| 65 | ** and stderr channels for that process to use. |
| 66 | ** |
| 67 | ** Return the number of errors. |
| 68 | */ |
| 69 | static int win32_create_child_process( |
| 70 | TCHAR *zCmd, /* The command that the child process will run */ |
| 71 | HANDLE hIn, /* Standard input */ |
| 72 | HANDLE hOut, /* Standard output */ |
| 73 | HANDLE hErr, /* Standard error */ |
| 74 | DWORD *pChildPid /* OUT: Child process handle */ |
| 75 | ){ |
| 76 | STARTUPINFO si; |
| 77 | PROCESS_INFORMATION pi; |
| 78 | BOOL rc; |
| 79 | |
| 80 | memset(&si, 0, sizeof(si)); |
| 81 | si.cb = sizeof(si); |
| @@ -84,11 +84,11 @@ | |
| 84 | si.hStdInput = hIn; |
| 85 | SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, TRUE); |
| 86 | si.hStdOutput = hOut; |
| 87 | SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, TRUE); |
| 88 | si.hStdError = hErr; |
| 89 | rc = CreateProcess( |
| 90 | NULL, /* Application Name */ |
| 91 | zCmd, /* Command-line */ |
| 92 | NULL, /* Process attributes */ |
| 93 | NULL, /* Thread attributes */ |
| 94 | TRUE, /* Inherit Handles */ |
| @@ -139,17 +139,12 @@ | |
| 139 | if( !CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 4096) ){ |
| 140 | win32_fatal_error("cannot create pipe for stdin"); |
| 141 | } |
| 142 | SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); |
| 143 | |
| 144 | #ifdef UNICODE |
| 145 | win32_create_child_process(fossil_utf8_to_unicode(zCmd), |
| 146 | hStdinRd, hStdoutWr, hStderr,&childPid); |
| 147 | #else |
| 148 | win32_create_child_process(fossil_utf8_to_mbcs(zCmd), |
| 149 | hStdinRd, hStdoutWr, hStderr,&childPid); |
| 150 | #endif |
| 151 | *pChildPid = childPid; |
| 152 | *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); |
| 153 | fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); |
| 154 | *ppOut = _fdopen(fd, "w"); |
| 155 | CloseHandle(hStdinRd); |
| 156 |
| --- src/popen.c | |
| +++ src/popen.c | |
| @@ -65,17 +65,17 @@ | |
| 65 | ** and stderr channels for that process to use. |
| 66 | ** |
| 67 | ** Return the number of errors. |
| 68 | */ |
| 69 | static int win32_create_child_process( |
| 70 | wchar_t *zCmd, /* The command that the child process will run */ |
| 71 | HANDLE hIn, /* Standard input */ |
| 72 | HANDLE hOut, /* Standard output */ |
| 73 | HANDLE hErr, /* Standard error */ |
| 74 | DWORD *pChildPid /* OUT: Child process handle */ |
| 75 | ){ |
| 76 | STARTUPINFOW si; |
| 77 | PROCESS_INFORMATION pi; |
| 78 | BOOL rc; |
| 79 | |
| 80 | memset(&si, 0, sizeof(si)); |
| 81 | si.cb = sizeof(si); |
| @@ -84,11 +84,11 @@ | |
| 84 | si.hStdInput = hIn; |
| 85 | SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, TRUE); |
| 86 | si.hStdOutput = hOut; |
| 87 | SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, TRUE); |
| 88 | si.hStdError = hErr; |
| 89 | rc = CreateProcessW( |
| 90 | NULL, /* Application Name */ |
| 91 | zCmd, /* Command-line */ |
| 92 | NULL, /* Process attributes */ |
| 93 | NULL, /* Thread attributes */ |
| 94 | TRUE, /* Inherit Handles */ |
| @@ -139,17 +139,12 @@ | |
| 139 | if( !CreatePipe(&hStdinRd, &hStdinWr, &saAttr, 4096) ){ |
| 140 | win32_fatal_error("cannot create pipe for stdin"); |
| 141 | } |
| 142 | SetHandleInformation( hStdinWr, HANDLE_FLAG_INHERIT, FALSE); |
| 143 | |
| 144 | win32_create_child_process(fossil_utf8_to_unicode(zCmd), |
| 145 | hStdinRd, hStdoutWr, hStderr,&childPid); |
| 146 | *pChildPid = childPid; |
| 147 | *pfdIn = _open_osfhandle(PTR_TO_INT(hStdoutRd), 0); |
| 148 | fd = _open_osfhandle(PTR_TO_INT(hStdinWr), 0); |
| 149 | *ppOut = _fdopen(fd, "w"); |
| 150 | CloseHandle(hStdinRd); |
| 151 |
+45
-43
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -17,12 +17,10 @@ | ||
| 17 | 17 | ** |
| 18 | 18 | ** This file implements a very simple (and low-performance) HTTP server |
| 19 | 19 | ** for windows. It also implements a Windows Service which allows the HTTP |
| 20 | 20 | ** server to be run without any user logged on. |
| 21 | 21 | */ |
| 22 | -#undef UNICODE | |
| 23 | -#undef _UNICODE | |
| 24 | 22 | #include "config.h" |
| 25 | 23 | #ifdef _WIN32 |
| 26 | 24 | /* This code is for win32 only */ |
| 27 | 25 | #include <windows.h> |
| 28 | 26 | #include "winhttp.h" |
| @@ -148,11 +146,11 @@ | ||
| 148 | 146 | SOCKET s = INVALID_SOCKET; |
| 149 | 147 | SOCKADDR_IN addr; |
| 150 | 148 | int idCnt = 0; |
| 151 | 149 | int iPort = mnPort; |
| 152 | 150 | Blob options; |
| 153 | - char zTmpPath[MAX_PATH]; | |
| 151 | + wchar_t zTmpPath[MAX_PATH]; | |
| 154 | 152 | |
| 155 | 153 | if( zStopper ) file_delete(zStopper); |
| 156 | 154 | blob_zero(&options); |
| 157 | 155 | if( zNotFound ){ |
| 158 | 156 | blob_appendf(&options, " --notfound %s", zNotFound); |
| @@ -193,14 +191,14 @@ | ||
| 193 | 191 | }else{ |
| 194 | 192 | fossil_fatal("unable to open listening socket on any" |
| 195 | 193 | " port in the range %d..%d", mnPort, mxPort); |
| 196 | 194 | } |
| 197 | 195 | } |
| 198 | - if( !GetTempPath(sizeof(zTmpPath), zTmpPath) ){ | |
| 196 | + if( !GetTempPathW(MAX_PATH, zTmpPath) ){ | |
| 199 | 197 | fossil_fatal("unable to get path to the temporary directory."); |
| 200 | 198 | } |
| 201 | - zTempPrefix = mprintf("%sfossil_server_P%d_", zTmpPath, iPort); | |
| 199 | + zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort); | |
| 202 | 200 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 203 | 201 | if( zBrowser ){ |
| 204 | 202 | zBrowser = mprintf(zBrowser, iPort); |
| 205 | 203 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 206 | 204 | fossil_system(zBrowser); |
| @@ -270,41 +268,41 @@ | ||
| 270 | 268 | ** to store the message string when done. |
| 271 | 269 | */ |
| 272 | 270 | static char *win32_get_last_errmsg(void){ |
| 273 | 271 | DWORD nMsg; |
| 274 | 272 | DWORD nErr = GetLastError(); |
| 275 | - LPTSTR tmp = NULL; | |
| 273 | + LPWSTR tmp = NULL; | |
| 276 | 274 | char *zMsg = NULL; |
| 277 | 275 | |
| 278 | 276 | /* Try first to get the error text in english. */ |
| 279 | - nMsg = FormatMessage( | |
| 277 | + nMsg = FormatMessageW( | |
| 280 | 278 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 281 | 279 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 282 | 280 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 283 | 281 | NULL, |
| 284 | 282 | nErr, |
| 285 | 283 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), |
| 286 | - (LPTSTR) &tmp, | |
| 284 | + (LPWSTR) &tmp, | |
| 287 | 285 | 0, |
| 288 | 286 | NULL |
| 289 | 287 | ); |
| 290 | 288 | if( !nMsg ){ |
| 291 | 289 | /* No english, get what the system has available. */ |
| 292 | - nMsg = FormatMessage( | |
| 290 | + nMsg = FormatMessageW( | |
| 293 | 291 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 294 | 292 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 295 | 293 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 296 | 294 | NULL, |
| 297 | 295 | nErr, |
| 298 | 296 | 0, |
| 299 | - (LPTSTR) &tmp, | |
| 297 | + (LPWSTR) &tmp, | |
| 300 | 298 | 0, |
| 301 | 299 | NULL |
| 302 | 300 | ); |
| 303 | 301 | } |
| 304 | 302 | if( nMsg ){ |
| 305 | - zMsg = fossil_mbcs_to_utf8(tmp); | |
| 303 | + zMsg = fossil_unicode_to_utf8(tmp); | |
| 306 | 304 | }else{ |
| 307 | 305 | fossil_fatal("unable to get system error message."); |
| 308 | 306 | } |
| 309 | 307 | if( tmp ){ |
| 310 | 308 | LocalFree((HLOCAL) tmp); |
| @@ -382,15 +380,19 @@ | ||
| 382 | 380 | ){ |
| 383 | 381 | |
| 384 | 382 | /* Update the service information. */ |
| 385 | 383 | hsData.isRunningAsService = 1; |
| 386 | 384 | if( argc>0 ){ |
| 387 | - hsData.zServiceName = argv[0]; | |
| 385 | +#ifdef UNICODE | |
| 386 | + hsData.zServiceName = fossil_unicode_to_utf8(argv[0]); | |
| 387 | +#else | |
| 388 | + hsData.zServiceName = fossil_mbcs_to_utf8(argv[0]); | |
| 389 | +#endif | |
| 388 | 390 | } |
| 389 | 391 | |
| 390 | 392 | /* Register the service control handler function */ |
| 391 | - sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl); | |
| 393 | + sshStatusHandle = RegisterServiceCtrlHandlerW(L"", win32_http_service_ctrl); | |
| 392 | 394 | if( !sshStatusHandle ){ |
| 393 | 395 | win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0); |
| 394 | 396 | return; |
| 395 | 397 | } |
| 396 | 398 | |
| @@ -430,20 +432,20 @@ | ||
| 430 | 432 | int nPort, /* TCP port number */ |
| 431 | 433 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 432 | 434 | int flags /* One or more HTTP_SERVER_ flags */ |
| 433 | 435 | ){ |
| 434 | 436 | /* Define the service table. */ |
| 435 | - SERVICE_TABLE_ENTRY ServiceTable[] = | |
| 436 | - {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}}; | |
| 437 | + SERVICE_TABLE_ENTRYW ServiceTable[] = | |
| 438 | + {{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}}; | |
| 437 | 439 | |
| 438 | 440 | /* Initialize the HttpService structure. */ |
| 439 | 441 | hsData.port = nPort; |
| 440 | 442 | hsData.zNotFound = zNotFound; |
| 441 | 443 | hsData.flags = flags; |
| 442 | 444 | |
| 443 | 445 | /* Try to start the control dispatcher thread for the service. */ |
| 444 | - if( !StartServiceCtrlDispatcher(ServiceTable) ){ | |
| 446 | + if( !StartServiceCtrlDispatcherW(ServiceTable) ){ | |
| 445 | 447 | if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ |
| 446 | 448 | return 1; |
| 447 | 449 | }else{ |
| 448 | 450 | fossil_fatal("error from StartServiceCtrlDispatcher()"); |
| 449 | 451 | } |
| @@ -567,11 +569,11 @@ | ||
| 567 | 569 | |
| 568 | 570 | if( strncmp(zMethod, "create", n)==0 ){ |
| 569 | 571 | SC_HANDLE hScm; |
| 570 | 572 | SC_HANDLE hSvc; |
| 571 | 573 | SERVICE_DESCRIPTION |
| 572 | - svcDescr = {"Fossil - Distributed Software Configuration Management"}; | |
| 574 | + svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")}; | |
| 573 | 575 | char *zErrFmt = "unable to create service '%s': %s"; |
| 574 | 576 | DWORD dwStartType = SERVICE_DEMAND_START; |
| 575 | 577 | const char *zDisplay = find_option("display", "D", 1); |
| 576 | 578 | const char *zStart = find_option("start", "S", 1); |
| 577 | 579 | const char *zUsername = find_option("username", "U", 1); |
| @@ -622,30 +624,30 @@ | ||
| 622 | 624 | if( zPort ) blob_appendf(&binPath, " --port %s", zPort); |
| 623 | 625 | if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound); |
| 624 | 626 | if( zLocalAuth ) blob_append(&binPath, " --localauth", -1); |
| 625 | 627 | blob_appendf(&binPath, " \"%s\"", g.zRepositoryName); |
| 626 | 628 | /* Create the service. */ |
| 627 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 629 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 628 | 630 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 629 | - hSvc = CreateService( | |
| 631 | + hSvc = CreateServiceW( | |
| 630 | 632 | hScm, /* Handle to the SCM */ |
| 631 | - fossil_utf8_to_mbcs(zSvcName), /* Name of the service */ | |
| 632 | - fossil_utf8_to_mbcs(zDisplay), /* Display name */ | |
| 633 | + fossil_utf8_to_unicode(zSvcName), /* Name of the service */ | |
| 634 | + fossil_utf8_to_unicode(zDisplay), /* Display name */ | |
| 633 | 635 | SERVICE_ALL_ACCESS, /* Desired access */ |
| 634 | 636 | SERVICE_WIN32_OWN_PROCESS, /* Service type */ |
| 635 | 637 | dwStartType, /* Start type */ |
| 636 | 638 | SERVICE_ERROR_NORMAL, /* Error control */ |
| 637 | - fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */ | |
| 639 | + fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */ | |
| 638 | 640 | NULL, /* Load ordering group */ |
| 639 | 641 | NULL, /* Tag value */ |
| 640 | 642 | NULL, /* Service dependencies */ |
| 641 | - fossil_utf8_to_mbcs(zUsername), /* Service account */ | |
| 642 | - fossil_utf8_to_mbcs(zPassword) /* Account password */ | |
| 643 | + fossil_utf8_to_unicode(zUsername), /* Service account */ | |
| 644 | + fossil_utf8_to_unicode(zPassword) /* Account password */ | |
| 643 | 645 | ); |
| 644 | 646 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 645 | 647 | /* Set the service description. */ |
| 646 | - ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); | |
| 648 | + ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); | |
| 647 | 649 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 648 | 650 | CloseServiceHandle(hSvc); |
| 649 | 651 | CloseServiceHandle(hScm); |
| 650 | 652 | }else |
| 651 | 653 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -658,13 +660,13 @@ | ||
| 658 | 660 | if( g.argc==4 ){ |
| 659 | 661 | zSvcName = g.argv[3]; |
| 660 | 662 | }else if( g.argc>4 ){ |
| 661 | 663 | fossil_fatal("to much arguments for delete method."); |
| 662 | 664 | } |
| 663 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 665 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 664 | 666 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 665 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); | |
| 667 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); | |
| 666 | 668 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 667 | 669 | QueryServiceStatus(hSvc, &sstat); |
| 668 | 670 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 669 | 671 | fossil_print("Stopping service '%s'", zSvcName); |
| 670 | 672 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| @@ -693,11 +695,11 @@ | ||
| 693 | 695 | }else |
| 694 | 696 | if( strncmp(zMethod, "show", n)==0 ){ |
| 695 | 697 | SC_HANDLE hScm; |
| 696 | 698 | SC_HANDLE hSvc; |
| 697 | 699 | SERVICE_STATUS sstat; |
| 698 | - LPQUERY_SERVICE_CONFIG pSvcConfig; | |
| 700 | + LPQUERY_SERVICE_CONFIGW pSvcConfig; | |
| 699 | 701 | LPSERVICE_DESCRIPTION pSvcDescr; |
| 700 | 702 | BOOL bStatus; |
| 701 | 703 | DWORD nRequired; |
| 702 | 704 | char *zErrFmt = "unable to show service '%s': %s"; |
| 703 | 705 | static const char *zSvcTypes[] = { |
| @@ -726,21 +728,21 @@ | ||
| 726 | 728 | if( g.argc==4 ){ |
| 727 | 729 | zSvcName = g.argv[3]; |
| 728 | 730 | }else if( g.argc>4 ){ |
| 729 | 731 | fossil_fatal("to much arguments for show method."); |
| 730 | 732 | } |
| 731 | - hScm = OpenSCManager(NULL, NULL, GENERIC_READ); | |
| 733 | + hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ); | |
| 732 | 734 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 733 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ); | |
| 735 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ); | |
| 734 | 736 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 735 | 737 | /* Get the service configuration */ |
| 736 | - bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired); | |
| 738 | + bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired); | |
| 737 | 739 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 738 | 740 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 739 | 741 | } |
| 740 | 742 | pSvcConfig = fossil_malloc(nRequired); |
| 741 | - bStatus = QueryServiceConfig(hSvc, pSvcConfig, nRequired, &nRequired); | |
| 743 | + bStatus = QueryServiceConfigW(hSvc, pSvcConfig, nRequired, &nRequired); | |
| 742 | 744 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 743 | 745 | /* Translate the service type */ |
| 744 | 746 | switch( pSvcConfig->dwServiceType ){ |
| 745 | 747 | case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break; |
| 746 | 748 | case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break; |
| @@ -755,17 +757,17 @@ | ||
| 755 | 757 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 756 | 758 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 757 | 759 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 758 | 760 | } |
| 759 | 761 | /* Get the service description. */ |
| 760 | - bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 762 | + bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 761 | 763 | NULL, 0, &nRequired); |
| 762 | 764 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 763 | 765 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 764 | 766 | } |
| 765 | 767 | pSvcDescr = fossil_malloc(nRequired); |
| 766 | - bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 768 | + bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 767 | 769 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 768 | 770 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 769 | 771 | /* Retrieves the current status of the specified service. */ |
| 770 | 772 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 771 | 773 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| @@ -780,19 +782,19 @@ | ||
| 780 | 782 | case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break; |
| 781 | 783 | } |
| 782 | 784 | /* Print service information to terminal */ |
| 783 | 785 | fossil_print("Service name .......: %s\n", zSvcName); |
| 784 | 786 | fossil_print("Display name .......: %s\n", |
| 785 | - fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName)); | |
| 787 | + fossil_unicode_to_utf8(pSvcConfig->lpDisplayName)); | |
| 786 | 788 | fossil_print("Service description : %s\n", |
| 787 | - fossil_mbcs_to_utf8(pSvcDescr->lpDescription)); | |
| 789 | + fossil_unicode_to_utf8(pSvcDescr->lpDescription)); | |
| 788 | 790 | fossil_print("Service type .......: %s.\n", zSvcType); |
| 789 | 791 | fossil_print("Service start type .: %s.\n", zSvcStartType); |
| 790 | 792 | fossil_print("Binary path name ...: %s\n", |
| 791 | - fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName)); | |
| 793 | + fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName)); | |
| 792 | 794 | fossil_print("Service username ...: %s\n", |
| 793 | - fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName)); | |
| 795 | + fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName)); | |
| 794 | 796 | fossil_print("Current state ......: %s.\n", zSvcState); |
| 795 | 797 | /* Cleanup */ |
| 796 | 798 | fossil_free(pSvcConfig); |
| 797 | 799 | fossil_free(pSvcDescr); |
| 798 | 800 | CloseServiceHandle(hSvc); |
| @@ -808,19 +810,19 @@ | ||
| 808 | 810 | if( g.argc==4 ){ |
| 809 | 811 | zSvcName = g.argv[3]; |
| 810 | 812 | }else if( g.argc>4 ){ |
| 811 | 813 | fossil_fatal("to much arguments for start method."); |
| 812 | 814 | } |
| 813 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 815 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 814 | 816 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 815 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); | |
| 817 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); | |
| 816 | 818 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 817 | 819 | QueryServiceStatus(hSvc, &sstat); |
| 818 | 820 | if( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 819 | 821 | fossil_print("Starting service '%s'", zSvcName); |
| 820 | 822 | if( sstat.dwCurrentState!=SERVICE_START_PENDING ){ |
| 821 | - if( !StartService(hSvc, 0, NULL) ){ | |
| 823 | + if( !StartServiceW(hSvc, 0, NULL) ){ | |
| 822 | 824 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 823 | 825 | } |
| 824 | 826 | } |
| 825 | 827 | while( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 826 | 828 | Sleep(100); |
| @@ -844,13 +846,13 @@ | ||
| 844 | 846 | if( g.argc==4 ){ |
| 845 | 847 | zSvcName = g.argv[3]; |
| 846 | 848 | }else if( g.argc>4 ){ |
| 847 | 849 | fossil_fatal("to much arguments for stop method."); |
| 848 | 850 | } |
| 849 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 851 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 850 | 852 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 851 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); | |
| 853 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); | |
| 852 | 854 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 853 | 855 | QueryServiceStatus(hSvc, &sstat); |
| 854 | 856 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 855 | 857 | fossil_print("Stopping service '%s'", zSvcName); |
| 856 | 858 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| 857 | 859 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -17,12 +17,10 @@ | |
| 17 | ** |
| 18 | ** This file implements a very simple (and low-performance) HTTP server |
| 19 | ** for windows. It also implements a Windows Service which allows the HTTP |
| 20 | ** server to be run without any user logged on. |
| 21 | */ |
| 22 | #undef UNICODE |
| 23 | #undef _UNICODE |
| 24 | #include "config.h" |
| 25 | #ifdef _WIN32 |
| 26 | /* This code is for win32 only */ |
| 27 | #include <windows.h> |
| 28 | #include "winhttp.h" |
| @@ -148,11 +146,11 @@ | |
| 148 | SOCKET s = INVALID_SOCKET; |
| 149 | SOCKADDR_IN addr; |
| 150 | int idCnt = 0; |
| 151 | int iPort = mnPort; |
| 152 | Blob options; |
| 153 | char zTmpPath[MAX_PATH]; |
| 154 | |
| 155 | if( zStopper ) file_delete(zStopper); |
| 156 | blob_zero(&options); |
| 157 | if( zNotFound ){ |
| 158 | blob_appendf(&options, " --notfound %s", zNotFound); |
| @@ -193,14 +191,14 @@ | |
| 193 | }else{ |
| 194 | fossil_fatal("unable to open listening socket on any" |
| 195 | " port in the range %d..%d", mnPort, mxPort); |
| 196 | } |
| 197 | } |
| 198 | if( !GetTempPath(sizeof(zTmpPath), zTmpPath) ){ |
| 199 | fossil_fatal("unable to get path to the temporary directory."); |
| 200 | } |
| 201 | zTempPrefix = mprintf("%sfossil_server_P%d_", zTmpPath, iPort); |
| 202 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 203 | if( zBrowser ){ |
| 204 | zBrowser = mprintf(zBrowser, iPort); |
| 205 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 206 | fossil_system(zBrowser); |
| @@ -270,41 +268,41 @@ | |
| 270 | ** to store the message string when done. |
| 271 | */ |
| 272 | static char *win32_get_last_errmsg(void){ |
| 273 | DWORD nMsg; |
| 274 | DWORD nErr = GetLastError(); |
| 275 | LPTSTR tmp = NULL; |
| 276 | char *zMsg = NULL; |
| 277 | |
| 278 | /* Try first to get the error text in english. */ |
| 279 | nMsg = FormatMessage( |
| 280 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 281 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 282 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 283 | NULL, |
| 284 | nErr, |
| 285 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), |
| 286 | (LPTSTR) &tmp, |
| 287 | 0, |
| 288 | NULL |
| 289 | ); |
| 290 | if( !nMsg ){ |
| 291 | /* No english, get what the system has available. */ |
| 292 | nMsg = FormatMessage( |
| 293 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 294 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 295 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 296 | NULL, |
| 297 | nErr, |
| 298 | 0, |
| 299 | (LPTSTR) &tmp, |
| 300 | 0, |
| 301 | NULL |
| 302 | ); |
| 303 | } |
| 304 | if( nMsg ){ |
| 305 | zMsg = fossil_mbcs_to_utf8(tmp); |
| 306 | }else{ |
| 307 | fossil_fatal("unable to get system error message."); |
| 308 | } |
| 309 | if( tmp ){ |
| 310 | LocalFree((HLOCAL) tmp); |
| @@ -382,15 +380,19 @@ | |
| 382 | ){ |
| 383 | |
| 384 | /* Update the service information. */ |
| 385 | hsData.isRunningAsService = 1; |
| 386 | if( argc>0 ){ |
| 387 | hsData.zServiceName = argv[0]; |
| 388 | } |
| 389 | |
| 390 | /* Register the service control handler function */ |
| 391 | sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl); |
| 392 | if( !sshStatusHandle ){ |
| 393 | win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0); |
| 394 | return; |
| 395 | } |
| 396 | |
| @@ -430,20 +432,20 @@ | |
| 430 | int nPort, /* TCP port number */ |
| 431 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 432 | int flags /* One or more HTTP_SERVER_ flags */ |
| 433 | ){ |
| 434 | /* Define the service table. */ |
| 435 | SERVICE_TABLE_ENTRY ServiceTable[] = |
| 436 | {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}}; |
| 437 | |
| 438 | /* Initialize the HttpService structure. */ |
| 439 | hsData.port = nPort; |
| 440 | hsData.zNotFound = zNotFound; |
| 441 | hsData.flags = flags; |
| 442 | |
| 443 | /* Try to start the control dispatcher thread for the service. */ |
| 444 | if( !StartServiceCtrlDispatcher(ServiceTable) ){ |
| 445 | if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ |
| 446 | return 1; |
| 447 | }else{ |
| 448 | fossil_fatal("error from StartServiceCtrlDispatcher()"); |
| 449 | } |
| @@ -567,11 +569,11 @@ | |
| 567 | |
| 568 | if( strncmp(zMethod, "create", n)==0 ){ |
| 569 | SC_HANDLE hScm; |
| 570 | SC_HANDLE hSvc; |
| 571 | SERVICE_DESCRIPTION |
| 572 | svcDescr = {"Fossil - Distributed Software Configuration Management"}; |
| 573 | char *zErrFmt = "unable to create service '%s': %s"; |
| 574 | DWORD dwStartType = SERVICE_DEMAND_START; |
| 575 | const char *zDisplay = find_option("display", "D", 1); |
| 576 | const char *zStart = find_option("start", "S", 1); |
| 577 | const char *zUsername = find_option("username", "U", 1); |
| @@ -622,30 +624,30 @@ | |
| 622 | if( zPort ) blob_appendf(&binPath, " --port %s", zPort); |
| 623 | if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound); |
| 624 | if( zLocalAuth ) blob_append(&binPath, " --localauth", -1); |
| 625 | blob_appendf(&binPath, " \"%s\"", g.zRepositoryName); |
| 626 | /* Create the service. */ |
| 627 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 628 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 629 | hSvc = CreateService( |
| 630 | hScm, /* Handle to the SCM */ |
| 631 | fossil_utf8_to_mbcs(zSvcName), /* Name of the service */ |
| 632 | fossil_utf8_to_mbcs(zDisplay), /* Display name */ |
| 633 | SERVICE_ALL_ACCESS, /* Desired access */ |
| 634 | SERVICE_WIN32_OWN_PROCESS, /* Service type */ |
| 635 | dwStartType, /* Start type */ |
| 636 | SERVICE_ERROR_NORMAL, /* Error control */ |
| 637 | fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */ |
| 638 | NULL, /* Load ordering group */ |
| 639 | NULL, /* Tag value */ |
| 640 | NULL, /* Service dependencies */ |
| 641 | fossil_utf8_to_mbcs(zUsername), /* Service account */ |
| 642 | fossil_utf8_to_mbcs(zPassword) /* Account password */ |
| 643 | ); |
| 644 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 645 | /* Set the service description. */ |
| 646 | ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); |
| 647 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 648 | CloseServiceHandle(hSvc); |
| 649 | CloseServiceHandle(hScm); |
| 650 | }else |
| 651 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -658,13 +660,13 @@ | |
| 658 | if( g.argc==4 ){ |
| 659 | zSvcName = g.argv[3]; |
| 660 | }else if( g.argc>4 ){ |
| 661 | fossil_fatal("to much arguments for delete method."); |
| 662 | } |
| 663 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 664 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 665 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); |
| 666 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 667 | QueryServiceStatus(hSvc, &sstat); |
| 668 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 669 | fossil_print("Stopping service '%s'", zSvcName); |
| 670 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| @@ -693,11 +695,11 @@ | |
| 693 | }else |
| 694 | if( strncmp(zMethod, "show", n)==0 ){ |
| 695 | SC_HANDLE hScm; |
| 696 | SC_HANDLE hSvc; |
| 697 | SERVICE_STATUS sstat; |
| 698 | LPQUERY_SERVICE_CONFIG pSvcConfig; |
| 699 | LPSERVICE_DESCRIPTION pSvcDescr; |
| 700 | BOOL bStatus; |
| 701 | DWORD nRequired; |
| 702 | char *zErrFmt = "unable to show service '%s': %s"; |
| 703 | static const char *zSvcTypes[] = { |
| @@ -726,21 +728,21 @@ | |
| 726 | if( g.argc==4 ){ |
| 727 | zSvcName = g.argv[3]; |
| 728 | }else if( g.argc>4 ){ |
| 729 | fossil_fatal("to much arguments for show method."); |
| 730 | } |
| 731 | hScm = OpenSCManager(NULL, NULL, GENERIC_READ); |
| 732 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 733 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ); |
| 734 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 735 | /* Get the service configuration */ |
| 736 | bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired); |
| 737 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 738 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 739 | } |
| 740 | pSvcConfig = fossil_malloc(nRequired); |
| 741 | bStatus = QueryServiceConfig(hSvc, pSvcConfig, nRequired, &nRequired); |
| 742 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 743 | /* Translate the service type */ |
| 744 | switch( pSvcConfig->dwServiceType ){ |
| 745 | case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break; |
| 746 | case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break; |
| @@ -755,17 +757,17 @@ | |
| 755 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 756 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 757 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 758 | } |
| 759 | /* Get the service description. */ |
| 760 | bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 761 | NULL, 0, &nRequired); |
| 762 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 763 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 764 | } |
| 765 | pSvcDescr = fossil_malloc(nRequired); |
| 766 | bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 767 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 768 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 769 | /* Retrieves the current status of the specified service. */ |
| 770 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 771 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| @@ -780,19 +782,19 @@ | |
| 780 | case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break; |
| 781 | } |
| 782 | /* Print service information to terminal */ |
| 783 | fossil_print("Service name .......: %s\n", zSvcName); |
| 784 | fossil_print("Display name .......: %s\n", |
| 785 | fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName)); |
| 786 | fossil_print("Service description : %s\n", |
| 787 | fossil_mbcs_to_utf8(pSvcDescr->lpDescription)); |
| 788 | fossil_print("Service type .......: %s.\n", zSvcType); |
| 789 | fossil_print("Service start type .: %s.\n", zSvcStartType); |
| 790 | fossil_print("Binary path name ...: %s\n", |
| 791 | fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName)); |
| 792 | fossil_print("Service username ...: %s\n", |
| 793 | fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName)); |
| 794 | fossil_print("Current state ......: %s.\n", zSvcState); |
| 795 | /* Cleanup */ |
| 796 | fossil_free(pSvcConfig); |
| 797 | fossil_free(pSvcDescr); |
| 798 | CloseServiceHandle(hSvc); |
| @@ -808,19 +810,19 @@ | |
| 808 | if( g.argc==4 ){ |
| 809 | zSvcName = g.argv[3]; |
| 810 | }else if( g.argc>4 ){ |
| 811 | fossil_fatal("to much arguments for start method."); |
| 812 | } |
| 813 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 814 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 815 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); |
| 816 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 817 | QueryServiceStatus(hSvc, &sstat); |
| 818 | if( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 819 | fossil_print("Starting service '%s'", zSvcName); |
| 820 | if( sstat.dwCurrentState!=SERVICE_START_PENDING ){ |
| 821 | if( !StartService(hSvc, 0, NULL) ){ |
| 822 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 823 | } |
| 824 | } |
| 825 | while( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 826 | Sleep(100); |
| @@ -844,13 +846,13 @@ | |
| 844 | if( g.argc==4 ){ |
| 845 | zSvcName = g.argv[3]; |
| 846 | }else if( g.argc>4 ){ |
| 847 | fossil_fatal("to much arguments for stop method."); |
| 848 | } |
| 849 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 850 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 851 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); |
| 852 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 853 | QueryServiceStatus(hSvc, &sstat); |
| 854 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 855 | fossil_print("Stopping service '%s'", zSvcName); |
| 856 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| 857 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -17,12 +17,10 @@ | |
| 17 | ** |
| 18 | ** This file implements a very simple (and low-performance) HTTP server |
| 19 | ** for windows. It also implements a Windows Service which allows the HTTP |
| 20 | ** server to be run without any user logged on. |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #ifdef _WIN32 |
| 24 | /* This code is for win32 only */ |
| 25 | #include <windows.h> |
| 26 | #include "winhttp.h" |
| @@ -148,11 +146,11 @@ | |
| 146 | SOCKET s = INVALID_SOCKET; |
| 147 | SOCKADDR_IN addr; |
| 148 | int idCnt = 0; |
| 149 | int iPort = mnPort; |
| 150 | Blob options; |
| 151 | wchar_t zTmpPath[MAX_PATH]; |
| 152 | |
| 153 | if( zStopper ) file_delete(zStopper); |
| 154 | blob_zero(&options); |
| 155 | if( zNotFound ){ |
| 156 | blob_appendf(&options, " --notfound %s", zNotFound); |
| @@ -193,14 +191,14 @@ | |
| 191 | }else{ |
| 192 | fossil_fatal("unable to open listening socket on any" |
| 193 | " port in the range %d..%d", mnPort, mxPort); |
| 194 | } |
| 195 | } |
| 196 | if( !GetTempPathW(MAX_PATH, zTmpPath) ){ |
| 197 | fossil_fatal("unable to get path to the temporary directory."); |
| 198 | } |
| 199 | zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort); |
| 200 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 201 | if( zBrowser ){ |
| 202 | zBrowser = mprintf(zBrowser, iPort); |
| 203 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 204 | fossil_system(zBrowser); |
| @@ -270,41 +268,41 @@ | |
| 268 | ** to store the message string when done. |
| 269 | */ |
| 270 | static char *win32_get_last_errmsg(void){ |
| 271 | DWORD nMsg; |
| 272 | DWORD nErr = GetLastError(); |
| 273 | LPWSTR tmp = NULL; |
| 274 | char *zMsg = NULL; |
| 275 | |
| 276 | /* Try first to get the error text in english. */ |
| 277 | nMsg = FormatMessageW( |
| 278 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 279 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 280 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 281 | NULL, |
| 282 | nErr, |
| 283 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), |
| 284 | (LPWSTR) &tmp, |
| 285 | 0, |
| 286 | NULL |
| 287 | ); |
| 288 | if( !nMsg ){ |
| 289 | /* No english, get what the system has available. */ |
| 290 | nMsg = FormatMessageW( |
| 291 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 292 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 293 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 294 | NULL, |
| 295 | nErr, |
| 296 | 0, |
| 297 | (LPWSTR) &tmp, |
| 298 | 0, |
| 299 | NULL |
| 300 | ); |
| 301 | } |
| 302 | if( nMsg ){ |
| 303 | zMsg = fossil_unicode_to_utf8(tmp); |
| 304 | }else{ |
| 305 | fossil_fatal("unable to get system error message."); |
| 306 | } |
| 307 | if( tmp ){ |
| 308 | LocalFree((HLOCAL) tmp); |
| @@ -382,15 +380,19 @@ | |
| 380 | ){ |
| 381 | |
| 382 | /* Update the service information. */ |
| 383 | hsData.isRunningAsService = 1; |
| 384 | if( argc>0 ){ |
| 385 | #ifdef UNICODE |
| 386 | hsData.zServiceName = fossil_unicode_to_utf8(argv[0]); |
| 387 | #else |
| 388 | hsData.zServiceName = fossil_mbcs_to_utf8(argv[0]); |
| 389 | #endif |
| 390 | } |
| 391 | |
| 392 | /* Register the service control handler function */ |
| 393 | sshStatusHandle = RegisterServiceCtrlHandlerW(L"", win32_http_service_ctrl); |
| 394 | if( !sshStatusHandle ){ |
| 395 | win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0); |
| 396 | return; |
| 397 | } |
| 398 | |
| @@ -430,20 +432,20 @@ | |
| 432 | int nPort, /* TCP port number */ |
| 433 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 434 | int flags /* One or more HTTP_SERVER_ flags */ |
| 435 | ){ |
| 436 | /* Define the service table. */ |
| 437 | SERVICE_TABLE_ENTRYW ServiceTable[] = |
| 438 | {{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}}; |
| 439 | |
| 440 | /* Initialize the HttpService structure. */ |
| 441 | hsData.port = nPort; |
| 442 | hsData.zNotFound = zNotFound; |
| 443 | hsData.flags = flags; |
| 444 | |
| 445 | /* Try to start the control dispatcher thread for the service. */ |
| 446 | if( !StartServiceCtrlDispatcherW(ServiceTable) ){ |
| 447 | if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ |
| 448 | return 1; |
| 449 | }else{ |
| 450 | fossil_fatal("error from StartServiceCtrlDispatcher()"); |
| 451 | } |
| @@ -567,11 +569,11 @@ | |
| 569 | |
| 570 | if( strncmp(zMethod, "create", n)==0 ){ |
| 571 | SC_HANDLE hScm; |
| 572 | SC_HANDLE hSvc; |
| 573 | SERVICE_DESCRIPTION |
| 574 | svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")}; |
| 575 | char *zErrFmt = "unable to create service '%s': %s"; |
| 576 | DWORD dwStartType = SERVICE_DEMAND_START; |
| 577 | const char *zDisplay = find_option("display", "D", 1); |
| 578 | const char *zStart = find_option("start", "S", 1); |
| 579 | const char *zUsername = find_option("username", "U", 1); |
| @@ -622,30 +624,30 @@ | |
| 624 | if( zPort ) blob_appendf(&binPath, " --port %s", zPort); |
| 625 | if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound); |
| 626 | if( zLocalAuth ) blob_append(&binPath, " --localauth", -1); |
| 627 | blob_appendf(&binPath, " \"%s\"", g.zRepositoryName); |
| 628 | /* Create the service. */ |
| 629 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 630 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 631 | hSvc = CreateServiceW( |
| 632 | hScm, /* Handle to the SCM */ |
| 633 | fossil_utf8_to_unicode(zSvcName), /* Name of the service */ |
| 634 | fossil_utf8_to_unicode(zDisplay), /* Display name */ |
| 635 | SERVICE_ALL_ACCESS, /* Desired access */ |
| 636 | SERVICE_WIN32_OWN_PROCESS, /* Service type */ |
| 637 | dwStartType, /* Start type */ |
| 638 | SERVICE_ERROR_NORMAL, /* Error control */ |
| 639 | fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */ |
| 640 | NULL, /* Load ordering group */ |
| 641 | NULL, /* Tag value */ |
| 642 | NULL, /* Service dependencies */ |
| 643 | fossil_utf8_to_unicode(zUsername), /* Service account */ |
| 644 | fossil_utf8_to_unicode(zPassword) /* Account password */ |
| 645 | ); |
| 646 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 647 | /* Set the service description. */ |
| 648 | ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); |
| 649 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 650 | CloseServiceHandle(hSvc); |
| 651 | CloseServiceHandle(hScm); |
| 652 | }else |
| 653 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -658,13 +660,13 @@ | |
| 660 | if( g.argc==4 ){ |
| 661 | zSvcName = g.argv[3]; |
| 662 | }else if( g.argc>4 ){ |
| 663 | fossil_fatal("to much arguments for delete method."); |
| 664 | } |
| 665 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 666 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 667 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); |
| 668 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 669 | QueryServiceStatus(hSvc, &sstat); |
| 670 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 671 | fossil_print("Stopping service '%s'", zSvcName); |
| 672 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| @@ -693,11 +695,11 @@ | |
| 695 | }else |
| 696 | if( strncmp(zMethod, "show", n)==0 ){ |
| 697 | SC_HANDLE hScm; |
| 698 | SC_HANDLE hSvc; |
| 699 | SERVICE_STATUS sstat; |
| 700 | LPQUERY_SERVICE_CONFIGW pSvcConfig; |
| 701 | LPSERVICE_DESCRIPTION pSvcDescr; |
| 702 | BOOL bStatus; |
| 703 | DWORD nRequired; |
| 704 | char *zErrFmt = "unable to show service '%s': %s"; |
| 705 | static const char *zSvcTypes[] = { |
| @@ -726,21 +728,21 @@ | |
| 728 | if( g.argc==4 ){ |
| 729 | zSvcName = g.argv[3]; |
| 730 | }else if( g.argc>4 ){ |
| 731 | fossil_fatal("to much arguments for show method."); |
| 732 | } |
| 733 | hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ); |
| 734 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 735 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ); |
| 736 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 737 | /* Get the service configuration */ |
| 738 | bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired); |
| 739 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 740 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 741 | } |
| 742 | pSvcConfig = fossil_malloc(nRequired); |
| 743 | bStatus = QueryServiceConfigW(hSvc, pSvcConfig, nRequired, &nRequired); |
| 744 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 745 | /* Translate the service type */ |
| 746 | switch( pSvcConfig->dwServiceType ){ |
| 747 | case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break; |
| 748 | case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break; |
| @@ -755,17 +757,17 @@ | |
| 757 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 758 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 759 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 760 | } |
| 761 | /* Get the service description. */ |
| 762 | bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 763 | NULL, 0, &nRequired); |
| 764 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 765 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 766 | } |
| 767 | pSvcDescr = fossil_malloc(nRequired); |
| 768 | bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 769 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 770 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 771 | /* Retrieves the current status of the specified service. */ |
| 772 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 773 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| @@ -780,19 +782,19 @@ | |
| 782 | case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break; |
| 783 | } |
| 784 | /* Print service information to terminal */ |
| 785 | fossil_print("Service name .......: %s\n", zSvcName); |
| 786 | fossil_print("Display name .......: %s\n", |
| 787 | fossil_unicode_to_utf8(pSvcConfig->lpDisplayName)); |
| 788 | fossil_print("Service description : %s\n", |
| 789 | fossil_unicode_to_utf8(pSvcDescr->lpDescription)); |
| 790 | fossil_print("Service type .......: %s.\n", zSvcType); |
| 791 | fossil_print("Service start type .: %s.\n", zSvcStartType); |
| 792 | fossil_print("Binary path name ...: %s\n", |
| 793 | fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName)); |
| 794 | fossil_print("Service username ...: %s\n", |
| 795 | fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName)); |
| 796 | fossil_print("Current state ......: %s.\n", zSvcState); |
| 797 | /* Cleanup */ |
| 798 | fossil_free(pSvcConfig); |
| 799 | fossil_free(pSvcDescr); |
| 800 | CloseServiceHandle(hSvc); |
| @@ -808,19 +810,19 @@ | |
| 810 | if( g.argc==4 ){ |
| 811 | zSvcName = g.argv[3]; |
| 812 | }else if( g.argc>4 ){ |
| 813 | fossil_fatal("to much arguments for start method."); |
| 814 | } |
| 815 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 816 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 817 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); |
| 818 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 819 | QueryServiceStatus(hSvc, &sstat); |
| 820 | if( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 821 | fossil_print("Starting service '%s'", zSvcName); |
| 822 | if( sstat.dwCurrentState!=SERVICE_START_PENDING ){ |
| 823 | if( !StartServiceW(hSvc, 0, NULL) ){ |
| 824 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 825 | } |
| 826 | } |
| 827 | while( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 828 | Sleep(100); |
| @@ -844,13 +846,13 @@ | |
| 846 | if( g.argc==4 ){ |
| 847 | zSvcName = g.argv[3]; |
| 848 | }else if( g.argc>4 ){ |
| 849 | fossil_fatal("to much arguments for stop method."); |
| 850 | } |
| 851 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 852 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 853 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); |
| 854 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 855 | QueryServiceStatus(hSvc, &sstat); |
| 856 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 857 | fossil_print("Stopping service '%s'", zSvcName); |
| 858 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| 859 |
+45
-43
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -17,12 +17,10 @@ | ||
| 17 | 17 | ** |
| 18 | 18 | ** This file implements a very simple (and low-performance) HTTP server |
| 19 | 19 | ** for windows. It also implements a Windows Service which allows the HTTP |
| 20 | 20 | ** server to be run without any user logged on. |
| 21 | 21 | */ |
| 22 | -#undef UNICODE | |
| 23 | -#undef _UNICODE | |
| 24 | 22 | #include "config.h" |
| 25 | 23 | #ifdef _WIN32 |
| 26 | 24 | /* This code is for win32 only */ |
| 27 | 25 | #include <windows.h> |
| 28 | 26 | #include "winhttp.h" |
| @@ -148,11 +146,11 @@ | ||
| 148 | 146 | SOCKET s = INVALID_SOCKET; |
| 149 | 147 | SOCKADDR_IN addr; |
| 150 | 148 | int idCnt = 0; |
| 151 | 149 | int iPort = mnPort; |
| 152 | 150 | Blob options; |
| 153 | - char zTmpPath[MAX_PATH]; | |
| 151 | + wchar_t zTmpPath[MAX_PATH]; | |
| 154 | 152 | |
| 155 | 153 | if( zStopper ) file_delete(zStopper); |
| 156 | 154 | blob_zero(&options); |
| 157 | 155 | if( zNotFound ){ |
| 158 | 156 | blob_appendf(&options, " --notfound %s", zNotFound); |
| @@ -193,14 +191,14 @@ | ||
| 193 | 191 | }else{ |
| 194 | 192 | fossil_fatal("unable to open listening socket on any" |
| 195 | 193 | " port in the range %d..%d", mnPort, mxPort); |
| 196 | 194 | } |
| 197 | 195 | } |
| 198 | - if( !GetTempPath(sizeof(zTmpPath), zTmpPath) ){ | |
| 196 | + if( !GetTempPathW(MAX_PATH, zTmpPath) ){ | |
| 199 | 197 | fossil_fatal("unable to get path to the temporary directory."); |
| 200 | 198 | } |
| 201 | - zTempPrefix = mprintf("%sfossil_server_P%d_", zTmpPath, iPort); | |
| 199 | + zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort); | |
| 202 | 200 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 203 | 201 | if( zBrowser ){ |
| 204 | 202 | zBrowser = mprintf(zBrowser, iPort); |
| 205 | 203 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 206 | 204 | fossil_system(zBrowser); |
| @@ -270,41 +268,41 @@ | ||
| 270 | 268 | ** to store the message string when done. |
| 271 | 269 | */ |
| 272 | 270 | static char *win32_get_last_errmsg(void){ |
| 273 | 271 | DWORD nMsg; |
| 274 | 272 | DWORD nErr = GetLastError(); |
| 275 | - LPTSTR tmp = NULL; | |
| 273 | + LPWSTR tmp = NULL; | |
| 276 | 274 | char *zMsg = NULL; |
| 277 | 275 | |
| 278 | 276 | /* Try first to get the error text in english. */ |
| 279 | - nMsg = FormatMessage( | |
| 277 | + nMsg = FormatMessageW( | |
| 280 | 278 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 281 | 279 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 282 | 280 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 283 | 281 | NULL, |
| 284 | 282 | nErr, |
| 285 | 283 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), |
| 286 | - (LPTSTR) &tmp, | |
| 284 | + (LPWSTR) &tmp, | |
| 287 | 285 | 0, |
| 288 | 286 | NULL |
| 289 | 287 | ); |
| 290 | 288 | if( !nMsg ){ |
| 291 | 289 | /* No english, get what the system has available. */ |
| 292 | - nMsg = FormatMessage( | |
| 290 | + nMsg = FormatMessageW( | |
| 293 | 291 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 294 | 292 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 295 | 293 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 296 | 294 | NULL, |
| 297 | 295 | nErr, |
| 298 | 296 | 0, |
| 299 | - (LPTSTR) &tmp, | |
| 297 | + (LPWSTR) &tmp, | |
| 300 | 298 | 0, |
| 301 | 299 | NULL |
| 302 | 300 | ); |
| 303 | 301 | } |
| 304 | 302 | if( nMsg ){ |
| 305 | - zMsg = fossil_mbcs_to_utf8(tmp); | |
| 303 | + zMsg = fossil_unicode_to_utf8(tmp); | |
| 306 | 304 | }else{ |
| 307 | 305 | fossil_fatal("unable to get system error message."); |
| 308 | 306 | } |
| 309 | 307 | if( tmp ){ |
| 310 | 308 | LocalFree((HLOCAL) tmp); |
| @@ -382,15 +380,19 @@ | ||
| 382 | 380 | ){ |
| 383 | 381 | |
| 384 | 382 | /* Update the service information. */ |
| 385 | 383 | hsData.isRunningAsService = 1; |
| 386 | 384 | if( argc>0 ){ |
| 387 | - hsData.zServiceName = argv[0]; | |
| 385 | +#ifdef UNICODE | |
| 386 | + hsData.zServiceName = fossil_unicode_to_utf8(argv[0]); | |
| 387 | +#else | |
| 388 | + hsData.zServiceName = fossil_mbcs_to_utf8(argv[0]); | |
| 389 | +#endif | |
| 388 | 390 | } |
| 389 | 391 | |
| 390 | 392 | /* Register the service control handler function */ |
| 391 | - sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl); | |
| 393 | + sshStatusHandle = RegisterServiceCtrlHandlerW(L"", win32_http_service_ctrl); | |
| 392 | 394 | if( !sshStatusHandle ){ |
| 393 | 395 | win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0); |
| 394 | 396 | return; |
| 395 | 397 | } |
| 396 | 398 | |
| @@ -430,20 +432,20 @@ | ||
| 430 | 432 | int nPort, /* TCP port number */ |
| 431 | 433 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 432 | 434 | int flags /* One or more HTTP_SERVER_ flags */ |
| 433 | 435 | ){ |
| 434 | 436 | /* Define the service table. */ |
| 435 | - SERVICE_TABLE_ENTRY ServiceTable[] = | |
| 436 | - {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}}; | |
| 437 | + SERVICE_TABLE_ENTRYW ServiceTable[] = | |
| 438 | + {{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}}; | |
| 437 | 439 | |
| 438 | 440 | /* Initialize the HttpService structure. */ |
| 439 | 441 | hsData.port = nPort; |
| 440 | 442 | hsData.zNotFound = zNotFound; |
| 441 | 443 | hsData.flags = flags; |
| 442 | 444 | |
| 443 | 445 | /* Try to start the control dispatcher thread for the service. */ |
| 444 | - if( !StartServiceCtrlDispatcher(ServiceTable) ){ | |
| 446 | + if( !StartServiceCtrlDispatcherW(ServiceTable) ){ | |
| 445 | 447 | if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ |
| 446 | 448 | return 1; |
| 447 | 449 | }else{ |
| 448 | 450 | fossil_fatal("error from StartServiceCtrlDispatcher()"); |
| 449 | 451 | } |
| @@ -567,11 +569,11 @@ | ||
| 567 | 569 | |
| 568 | 570 | if( strncmp(zMethod, "create", n)==0 ){ |
| 569 | 571 | SC_HANDLE hScm; |
| 570 | 572 | SC_HANDLE hSvc; |
| 571 | 573 | SERVICE_DESCRIPTION |
| 572 | - svcDescr = {"Fossil - Distributed Software Configuration Management"}; | |
| 574 | + svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")}; | |
| 573 | 575 | char *zErrFmt = "unable to create service '%s': %s"; |
| 574 | 576 | DWORD dwStartType = SERVICE_DEMAND_START; |
| 575 | 577 | const char *zDisplay = find_option("display", "D", 1); |
| 576 | 578 | const char *zStart = find_option("start", "S", 1); |
| 577 | 579 | const char *zUsername = find_option("username", "U", 1); |
| @@ -622,30 +624,30 @@ | ||
| 622 | 624 | if( zPort ) blob_appendf(&binPath, " --port %s", zPort); |
| 623 | 625 | if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound); |
| 624 | 626 | if( zLocalAuth ) blob_append(&binPath, " --localauth", -1); |
| 625 | 627 | blob_appendf(&binPath, " \"%s\"", g.zRepositoryName); |
| 626 | 628 | /* Create the service. */ |
| 627 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 629 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 628 | 630 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 629 | - hSvc = CreateService( | |
| 631 | + hSvc = CreateServiceW( | |
| 630 | 632 | hScm, /* Handle to the SCM */ |
| 631 | - fossil_utf8_to_mbcs(zSvcName), /* Name of the service */ | |
| 632 | - fossil_utf8_to_mbcs(zDisplay), /* Display name */ | |
| 633 | + fossil_utf8_to_unicode(zSvcName), /* Name of the service */ | |
| 634 | + fossil_utf8_to_unicode(zDisplay), /* Display name */ | |
| 633 | 635 | SERVICE_ALL_ACCESS, /* Desired access */ |
| 634 | 636 | SERVICE_WIN32_OWN_PROCESS, /* Service type */ |
| 635 | 637 | dwStartType, /* Start type */ |
| 636 | 638 | SERVICE_ERROR_NORMAL, /* Error control */ |
| 637 | - fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */ | |
| 639 | + fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */ | |
| 638 | 640 | NULL, /* Load ordering group */ |
| 639 | 641 | NULL, /* Tag value */ |
| 640 | 642 | NULL, /* Service dependencies */ |
| 641 | - fossil_utf8_to_mbcs(zUsername), /* Service account */ | |
| 642 | - fossil_utf8_to_mbcs(zPassword) /* Account password */ | |
| 643 | + fossil_utf8_to_unicode(zUsername), /* Service account */ | |
| 644 | + fossil_utf8_to_unicode(zPassword) /* Account password */ | |
| 643 | 645 | ); |
| 644 | 646 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 645 | 647 | /* Set the service description. */ |
| 646 | - ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); | |
| 648 | + ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); | |
| 647 | 649 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 648 | 650 | CloseServiceHandle(hSvc); |
| 649 | 651 | CloseServiceHandle(hScm); |
| 650 | 652 | }else |
| 651 | 653 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -658,13 +660,13 @@ | ||
| 658 | 660 | if( g.argc==4 ){ |
| 659 | 661 | zSvcName = g.argv[3]; |
| 660 | 662 | }else if( g.argc>4 ){ |
| 661 | 663 | fossil_fatal("to much arguments for delete method."); |
| 662 | 664 | } |
| 663 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 665 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 664 | 666 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 665 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); | |
| 667 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); | |
| 666 | 668 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 667 | 669 | QueryServiceStatus(hSvc, &sstat); |
| 668 | 670 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 669 | 671 | fossil_print("Stopping service '%s'", zSvcName); |
| 670 | 672 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| @@ -693,11 +695,11 @@ | ||
| 693 | 695 | }else |
| 694 | 696 | if( strncmp(zMethod, "show", n)==0 ){ |
| 695 | 697 | SC_HANDLE hScm; |
| 696 | 698 | SC_HANDLE hSvc; |
| 697 | 699 | SERVICE_STATUS sstat; |
| 698 | - LPQUERY_SERVICE_CONFIG pSvcConfig; | |
| 700 | + LPQUERY_SERVICE_CONFIGW pSvcConfig; | |
| 699 | 701 | LPSERVICE_DESCRIPTION pSvcDescr; |
| 700 | 702 | BOOL bStatus; |
| 701 | 703 | DWORD nRequired; |
| 702 | 704 | char *zErrFmt = "unable to show service '%s': %s"; |
| 703 | 705 | static const char *zSvcTypes[] = { |
| @@ -726,21 +728,21 @@ | ||
| 726 | 728 | if( g.argc==4 ){ |
| 727 | 729 | zSvcName = g.argv[3]; |
| 728 | 730 | }else if( g.argc>4 ){ |
| 729 | 731 | fossil_fatal("to much arguments for show method."); |
| 730 | 732 | } |
| 731 | - hScm = OpenSCManager(NULL, NULL, GENERIC_READ); | |
| 733 | + hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ); | |
| 732 | 734 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 733 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ); | |
| 735 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ); | |
| 734 | 736 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 735 | 737 | /* Get the service configuration */ |
| 736 | - bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired); | |
| 738 | + bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired); | |
| 737 | 739 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 738 | 740 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 739 | 741 | } |
| 740 | 742 | pSvcConfig = fossil_malloc(nRequired); |
| 741 | - bStatus = QueryServiceConfig(hSvc, pSvcConfig, nRequired, &nRequired); | |
| 743 | + bStatus = QueryServiceConfigW(hSvc, pSvcConfig, nRequired, &nRequired); | |
| 742 | 744 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 743 | 745 | /* Translate the service type */ |
| 744 | 746 | switch( pSvcConfig->dwServiceType ){ |
| 745 | 747 | case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break; |
| 746 | 748 | case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break; |
| @@ -755,17 +757,17 @@ | ||
| 755 | 757 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 756 | 758 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 757 | 759 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 758 | 760 | } |
| 759 | 761 | /* Get the service description. */ |
| 760 | - bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 762 | + bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 761 | 763 | NULL, 0, &nRequired); |
| 762 | 764 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 763 | 765 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 764 | 766 | } |
| 765 | 767 | pSvcDescr = fossil_malloc(nRequired); |
| 766 | - bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 768 | + bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 767 | 769 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 768 | 770 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 769 | 771 | /* Retrieves the current status of the specified service. */ |
| 770 | 772 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 771 | 773 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| @@ -780,19 +782,19 @@ | ||
| 780 | 782 | case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break; |
| 781 | 783 | } |
| 782 | 784 | /* Print service information to terminal */ |
| 783 | 785 | fossil_print("Service name .......: %s\n", zSvcName); |
| 784 | 786 | fossil_print("Display name .......: %s\n", |
| 785 | - fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName)); | |
| 787 | + fossil_unicode_to_utf8(pSvcConfig->lpDisplayName)); | |
| 786 | 788 | fossil_print("Service description : %s\n", |
| 787 | - fossil_mbcs_to_utf8(pSvcDescr->lpDescription)); | |
| 789 | + fossil_unicode_to_utf8(pSvcDescr->lpDescription)); | |
| 788 | 790 | fossil_print("Service type .......: %s.\n", zSvcType); |
| 789 | 791 | fossil_print("Service start type .: %s.\n", zSvcStartType); |
| 790 | 792 | fossil_print("Binary path name ...: %s\n", |
| 791 | - fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName)); | |
| 793 | + fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName)); | |
| 792 | 794 | fossil_print("Service username ...: %s\n", |
| 793 | - fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName)); | |
| 795 | + fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName)); | |
| 794 | 796 | fossil_print("Current state ......: %s.\n", zSvcState); |
| 795 | 797 | /* Cleanup */ |
| 796 | 798 | fossil_free(pSvcConfig); |
| 797 | 799 | fossil_free(pSvcDescr); |
| 798 | 800 | CloseServiceHandle(hSvc); |
| @@ -808,19 +810,19 @@ | ||
| 808 | 810 | if( g.argc==4 ){ |
| 809 | 811 | zSvcName = g.argv[3]; |
| 810 | 812 | }else if( g.argc>4 ){ |
| 811 | 813 | fossil_fatal("to much arguments for start method."); |
| 812 | 814 | } |
| 813 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 815 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 814 | 816 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 815 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); | |
| 817 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); | |
| 816 | 818 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 817 | 819 | QueryServiceStatus(hSvc, &sstat); |
| 818 | 820 | if( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 819 | 821 | fossil_print("Starting service '%s'", zSvcName); |
| 820 | 822 | if( sstat.dwCurrentState!=SERVICE_START_PENDING ){ |
| 821 | - if( !StartService(hSvc, 0, NULL) ){ | |
| 823 | + if( !StartServiceW(hSvc, 0, NULL) ){ | |
| 822 | 824 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 823 | 825 | } |
| 824 | 826 | } |
| 825 | 827 | while( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 826 | 828 | Sleep(100); |
| @@ -844,13 +846,13 @@ | ||
| 844 | 846 | if( g.argc==4 ){ |
| 845 | 847 | zSvcName = g.argv[3]; |
| 846 | 848 | }else if( g.argc>4 ){ |
| 847 | 849 | fossil_fatal("to much arguments for stop method."); |
| 848 | 850 | } |
| 849 | - hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 851 | + hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); | |
| 850 | 852 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 851 | - hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); | |
| 853 | + hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); | |
| 852 | 854 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 853 | 855 | QueryServiceStatus(hSvc, &sstat); |
| 854 | 856 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 855 | 857 | fossil_print("Stopping service '%s'", zSvcName); |
| 856 | 858 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| 857 | 859 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -17,12 +17,10 @@ | |
| 17 | ** |
| 18 | ** This file implements a very simple (and low-performance) HTTP server |
| 19 | ** for windows. It also implements a Windows Service which allows the HTTP |
| 20 | ** server to be run without any user logged on. |
| 21 | */ |
| 22 | #undef UNICODE |
| 23 | #undef _UNICODE |
| 24 | #include "config.h" |
| 25 | #ifdef _WIN32 |
| 26 | /* This code is for win32 only */ |
| 27 | #include <windows.h> |
| 28 | #include "winhttp.h" |
| @@ -148,11 +146,11 @@ | |
| 148 | SOCKET s = INVALID_SOCKET; |
| 149 | SOCKADDR_IN addr; |
| 150 | int idCnt = 0; |
| 151 | int iPort = mnPort; |
| 152 | Blob options; |
| 153 | char zTmpPath[MAX_PATH]; |
| 154 | |
| 155 | if( zStopper ) file_delete(zStopper); |
| 156 | blob_zero(&options); |
| 157 | if( zNotFound ){ |
| 158 | blob_appendf(&options, " --notfound %s", zNotFound); |
| @@ -193,14 +191,14 @@ | |
| 193 | }else{ |
| 194 | fossil_fatal("unable to open listening socket on any" |
| 195 | " port in the range %d..%d", mnPort, mxPort); |
| 196 | } |
| 197 | } |
| 198 | if( !GetTempPath(sizeof(zTmpPath), zTmpPath) ){ |
| 199 | fossil_fatal("unable to get path to the temporary directory."); |
| 200 | } |
| 201 | zTempPrefix = mprintf("%sfossil_server_P%d_", zTmpPath, iPort); |
| 202 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 203 | if( zBrowser ){ |
| 204 | zBrowser = mprintf(zBrowser, iPort); |
| 205 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 206 | fossil_system(zBrowser); |
| @@ -270,41 +268,41 @@ | |
| 270 | ** to store the message string when done. |
| 271 | */ |
| 272 | static char *win32_get_last_errmsg(void){ |
| 273 | DWORD nMsg; |
| 274 | DWORD nErr = GetLastError(); |
| 275 | LPTSTR tmp = NULL; |
| 276 | char *zMsg = NULL; |
| 277 | |
| 278 | /* Try first to get the error text in english. */ |
| 279 | nMsg = FormatMessage( |
| 280 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 281 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 282 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 283 | NULL, |
| 284 | nErr, |
| 285 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), |
| 286 | (LPTSTR) &tmp, |
| 287 | 0, |
| 288 | NULL |
| 289 | ); |
| 290 | if( !nMsg ){ |
| 291 | /* No english, get what the system has available. */ |
| 292 | nMsg = FormatMessage( |
| 293 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 294 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 295 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 296 | NULL, |
| 297 | nErr, |
| 298 | 0, |
| 299 | (LPTSTR) &tmp, |
| 300 | 0, |
| 301 | NULL |
| 302 | ); |
| 303 | } |
| 304 | if( nMsg ){ |
| 305 | zMsg = fossil_mbcs_to_utf8(tmp); |
| 306 | }else{ |
| 307 | fossil_fatal("unable to get system error message."); |
| 308 | } |
| 309 | if( tmp ){ |
| 310 | LocalFree((HLOCAL) tmp); |
| @@ -382,15 +380,19 @@ | |
| 382 | ){ |
| 383 | |
| 384 | /* Update the service information. */ |
| 385 | hsData.isRunningAsService = 1; |
| 386 | if( argc>0 ){ |
| 387 | hsData.zServiceName = argv[0]; |
| 388 | } |
| 389 | |
| 390 | /* Register the service control handler function */ |
| 391 | sshStatusHandle = RegisterServiceCtrlHandler("", win32_http_service_ctrl); |
| 392 | if( !sshStatusHandle ){ |
| 393 | win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0); |
| 394 | return; |
| 395 | } |
| 396 | |
| @@ -430,20 +432,20 @@ | |
| 430 | int nPort, /* TCP port number */ |
| 431 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 432 | int flags /* One or more HTTP_SERVER_ flags */ |
| 433 | ){ |
| 434 | /* Define the service table. */ |
| 435 | SERVICE_TABLE_ENTRY ServiceTable[] = |
| 436 | {{"", (LPSERVICE_MAIN_FUNCTION)win32_http_service_main}, {NULL, NULL}}; |
| 437 | |
| 438 | /* Initialize the HttpService structure. */ |
| 439 | hsData.port = nPort; |
| 440 | hsData.zNotFound = zNotFound; |
| 441 | hsData.flags = flags; |
| 442 | |
| 443 | /* Try to start the control dispatcher thread for the service. */ |
| 444 | if( !StartServiceCtrlDispatcher(ServiceTable) ){ |
| 445 | if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ |
| 446 | return 1; |
| 447 | }else{ |
| 448 | fossil_fatal("error from StartServiceCtrlDispatcher()"); |
| 449 | } |
| @@ -567,11 +569,11 @@ | |
| 567 | |
| 568 | if( strncmp(zMethod, "create", n)==0 ){ |
| 569 | SC_HANDLE hScm; |
| 570 | SC_HANDLE hSvc; |
| 571 | SERVICE_DESCRIPTION |
| 572 | svcDescr = {"Fossil - Distributed Software Configuration Management"}; |
| 573 | char *zErrFmt = "unable to create service '%s': %s"; |
| 574 | DWORD dwStartType = SERVICE_DEMAND_START; |
| 575 | const char *zDisplay = find_option("display", "D", 1); |
| 576 | const char *zStart = find_option("start", "S", 1); |
| 577 | const char *zUsername = find_option("username", "U", 1); |
| @@ -622,30 +624,30 @@ | |
| 622 | if( zPort ) blob_appendf(&binPath, " --port %s", zPort); |
| 623 | if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound); |
| 624 | if( zLocalAuth ) blob_append(&binPath, " --localauth", -1); |
| 625 | blob_appendf(&binPath, " \"%s\"", g.zRepositoryName); |
| 626 | /* Create the service. */ |
| 627 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 628 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 629 | hSvc = CreateService( |
| 630 | hScm, /* Handle to the SCM */ |
| 631 | fossil_utf8_to_mbcs(zSvcName), /* Name of the service */ |
| 632 | fossil_utf8_to_mbcs(zDisplay), /* Display name */ |
| 633 | SERVICE_ALL_ACCESS, /* Desired access */ |
| 634 | SERVICE_WIN32_OWN_PROCESS, /* Service type */ |
| 635 | dwStartType, /* Start type */ |
| 636 | SERVICE_ERROR_NORMAL, /* Error control */ |
| 637 | fossil_utf8_to_mbcs(blob_str(&binPath)), /* Binary path */ |
| 638 | NULL, /* Load ordering group */ |
| 639 | NULL, /* Tag value */ |
| 640 | NULL, /* Service dependencies */ |
| 641 | fossil_utf8_to_mbcs(zUsername), /* Service account */ |
| 642 | fossil_utf8_to_mbcs(zPassword) /* Account password */ |
| 643 | ); |
| 644 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 645 | /* Set the service description. */ |
| 646 | ChangeServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); |
| 647 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 648 | CloseServiceHandle(hSvc); |
| 649 | CloseServiceHandle(hScm); |
| 650 | }else |
| 651 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -658,13 +660,13 @@ | |
| 658 | if( g.argc==4 ){ |
| 659 | zSvcName = g.argv[3]; |
| 660 | }else if( g.argc>4 ){ |
| 661 | fossil_fatal("to much arguments for delete method."); |
| 662 | } |
| 663 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 664 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 665 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); |
| 666 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 667 | QueryServiceStatus(hSvc, &sstat); |
| 668 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 669 | fossil_print("Stopping service '%s'", zSvcName); |
| 670 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| @@ -693,11 +695,11 @@ | |
| 693 | }else |
| 694 | if( strncmp(zMethod, "show", n)==0 ){ |
| 695 | SC_HANDLE hScm; |
| 696 | SC_HANDLE hSvc; |
| 697 | SERVICE_STATUS sstat; |
| 698 | LPQUERY_SERVICE_CONFIG pSvcConfig; |
| 699 | LPSERVICE_DESCRIPTION pSvcDescr; |
| 700 | BOOL bStatus; |
| 701 | DWORD nRequired; |
| 702 | char *zErrFmt = "unable to show service '%s': %s"; |
| 703 | static const char *zSvcTypes[] = { |
| @@ -726,21 +728,21 @@ | |
| 726 | if( g.argc==4 ){ |
| 727 | zSvcName = g.argv[3]; |
| 728 | }else if( g.argc>4 ){ |
| 729 | fossil_fatal("to much arguments for show method."); |
| 730 | } |
| 731 | hScm = OpenSCManager(NULL, NULL, GENERIC_READ); |
| 732 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 733 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), GENERIC_READ); |
| 734 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 735 | /* Get the service configuration */ |
| 736 | bStatus = QueryServiceConfig(hSvc, NULL, 0, &nRequired); |
| 737 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 738 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 739 | } |
| 740 | pSvcConfig = fossil_malloc(nRequired); |
| 741 | bStatus = QueryServiceConfig(hSvc, pSvcConfig, nRequired, &nRequired); |
| 742 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 743 | /* Translate the service type */ |
| 744 | switch( pSvcConfig->dwServiceType ){ |
| 745 | case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break; |
| 746 | case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break; |
| @@ -755,17 +757,17 @@ | |
| 755 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 756 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 757 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 758 | } |
| 759 | /* Get the service description. */ |
| 760 | bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 761 | NULL, 0, &nRequired); |
| 762 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 763 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 764 | } |
| 765 | pSvcDescr = fossil_malloc(nRequired); |
| 766 | bStatus = QueryServiceConfig2(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 767 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 768 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 769 | /* Retrieves the current status of the specified service. */ |
| 770 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 771 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| @@ -780,19 +782,19 @@ | |
| 780 | case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break; |
| 781 | } |
| 782 | /* Print service information to terminal */ |
| 783 | fossil_print("Service name .......: %s\n", zSvcName); |
| 784 | fossil_print("Display name .......: %s\n", |
| 785 | fossil_mbcs_to_utf8(pSvcConfig->lpDisplayName)); |
| 786 | fossil_print("Service description : %s\n", |
| 787 | fossil_mbcs_to_utf8(pSvcDescr->lpDescription)); |
| 788 | fossil_print("Service type .......: %s.\n", zSvcType); |
| 789 | fossil_print("Service start type .: %s.\n", zSvcStartType); |
| 790 | fossil_print("Binary path name ...: %s\n", |
| 791 | fossil_mbcs_to_utf8(pSvcConfig->lpBinaryPathName)); |
| 792 | fossil_print("Service username ...: %s\n", |
| 793 | fossil_mbcs_to_utf8(pSvcConfig->lpServiceStartName)); |
| 794 | fossil_print("Current state ......: %s.\n", zSvcState); |
| 795 | /* Cleanup */ |
| 796 | fossil_free(pSvcConfig); |
| 797 | fossil_free(pSvcDescr); |
| 798 | CloseServiceHandle(hSvc); |
| @@ -808,19 +810,19 @@ | |
| 808 | if( g.argc==4 ){ |
| 809 | zSvcName = g.argv[3]; |
| 810 | }else if( g.argc>4 ){ |
| 811 | fossil_fatal("to much arguments for start method."); |
| 812 | } |
| 813 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 814 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 815 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); |
| 816 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 817 | QueryServiceStatus(hSvc, &sstat); |
| 818 | if( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 819 | fossil_print("Starting service '%s'", zSvcName); |
| 820 | if( sstat.dwCurrentState!=SERVICE_START_PENDING ){ |
| 821 | if( !StartService(hSvc, 0, NULL) ){ |
| 822 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 823 | } |
| 824 | } |
| 825 | while( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 826 | Sleep(100); |
| @@ -844,13 +846,13 @@ | |
| 844 | if( g.argc==4 ){ |
| 845 | zSvcName = g.argv[3]; |
| 846 | }else if( g.argc>4 ){ |
| 847 | fossil_fatal("to much arguments for stop method."); |
| 848 | } |
| 849 | hScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 850 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 851 | hSvc = OpenService(hScm, fossil_utf8_to_mbcs(zSvcName), SERVICE_ALL_ACCESS); |
| 852 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 853 | QueryServiceStatus(hSvc, &sstat); |
| 854 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 855 | fossil_print("Stopping service '%s'", zSvcName); |
| 856 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| 857 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -17,12 +17,10 @@ | |
| 17 | ** |
| 18 | ** This file implements a very simple (and low-performance) HTTP server |
| 19 | ** for windows. It also implements a Windows Service which allows the HTTP |
| 20 | ** server to be run without any user logged on. |
| 21 | */ |
| 22 | #include "config.h" |
| 23 | #ifdef _WIN32 |
| 24 | /* This code is for win32 only */ |
| 25 | #include <windows.h> |
| 26 | #include "winhttp.h" |
| @@ -148,11 +146,11 @@ | |
| 146 | SOCKET s = INVALID_SOCKET; |
| 147 | SOCKADDR_IN addr; |
| 148 | int idCnt = 0; |
| 149 | int iPort = mnPort; |
| 150 | Blob options; |
| 151 | wchar_t zTmpPath[MAX_PATH]; |
| 152 | |
| 153 | if( zStopper ) file_delete(zStopper); |
| 154 | blob_zero(&options); |
| 155 | if( zNotFound ){ |
| 156 | blob_appendf(&options, " --notfound %s", zNotFound); |
| @@ -193,14 +191,14 @@ | |
| 191 | }else{ |
| 192 | fossil_fatal("unable to open listening socket on any" |
| 193 | " port in the range %d..%d", mnPort, mxPort); |
| 194 | } |
| 195 | } |
| 196 | if( !GetTempPathW(MAX_PATH, zTmpPath) ){ |
| 197 | fossil_fatal("unable to get path to the temporary directory."); |
| 198 | } |
| 199 | zTempPrefix = mprintf("%sfossil_server_P%d_", fossil_unicode_to_utf8(zTmpPath), iPort); |
| 200 | fossil_print("Listening for HTTP requests on TCP port %d\n", iPort); |
| 201 | if( zBrowser ){ |
| 202 | zBrowser = mprintf(zBrowser, iPort); |
| 203 | fossil_print("Launch webbrowser: %s\n", zBrowser); |
| 204 | fossil_system(zBrowser); |
| @@ -270,41 +268,41 @@ | |
| 268 | ** to store the message string when done. |
| 269 | */ |
| 270 | static char *win32_get_last_errmsg(void){ |
| 271 | DWORD nMsg; |
| 272 | DWORD nErr = GetLastError(); |
| 273 | LPWSTR tmp = NULL; |
| 274 | char *zMsg = NULL; |
| 275 | |
| 276 | /* Try first to get the error text in english. */ |
| 277 | nMsg = FormatMessageW( |
| 278 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 279 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 280 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 281 | NULL, |
| 282 | nErr, |
| 283 | MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), |
| 284 | (LPWSTR) &tmp, |
| 285 | 0, |
| 286 | NULL |
| 287 | ); |
| 288 | if( !nMsg ){ |
| 289 | /* No english, get what the system has available. */ |
| 290 | nMsg = FormatMessageW( |
| 291 | FORMAT_MESSAGE_ALLOCATE_BUFFER | |
| 292 | FORMAT_MESSAGE_FROM_SYSTEM | |
| 293 | FORMAT_MESSAGE_IGNORE_INSERTS, |
| 294 | NULL, |
| 295 | nErr, |
| 296 | 0, |
| 297 | (LPWSTR) &tmp, |
| 298 | 0, |
| 299 | NULL |
| 300 | ); |
| 301 | } |
| 302 | if( nMsg ){ |
| 303 | zMsg = fossil_unicode_to_utf8(tmp); |
| 304 | }else{ |
| 305 | fossil_fatal("unable to get system error message."); |
| 306 | } |
| 307 | if( tmp ){ |
| 308 | LocalFree((HLOCAL) tmp); |
| @@ -382,15 +380,19 @@ | |
| 380 | ){ |
| 381 | |
| 382 | /* Update the service information. */ |
| 383 | hsData.isRunningAsService = 1; |
| 384 | if( argc>0 ){ |
| 385 | #ifdef UNICODE |
| 386 | hsData.zServiceName = fossil_unicode_to_utf8(argv[0]); |
| 387 | #else |
| 388 | hsData.zServiceName = fossil_mbcs_to_utf8(argv[0]); |
| 389 | #endif |
| 390 | } |
| 391 | |
| 392 | /* Register the service control handler function */ |
| 393 | sshStatusHandle = RegisterServiceCtrlHandlerW(L"", win32_http_service_ctrl); |
| 394 | if( !sshStatusHandle ){ |
| 395 | win32_report_service_status(SERVICE_STOPPED, NO_ERROR, 0); |
| 396 | return; |
| 397 | } |
| 398 | |
| @@ -430,20 +432,20 @@ | |
| 432 | int nPort, /* TCP port number */ |
| 433 | const char *zNotFound, /* The --notfound option, or NULL */ |
| 434 | int flags /* One or more HTTP_SERVER_ flags */ |
| 435 | ){ |
| 436 | /* Define the service table. */ |
| 437 | SERVICE_TABLE_ENTRYW ServiceTable[] = |
| 438 | {{L"", (LPSERVICE_MAIN_FUNCTIONW)win32_http_service_main}, {NULL, NULL}}; |
| 439 | |
| 440 | /* Initialize the HttpService structure. */ |
| 441 | hsData.port = nPort; |
| 442 | hsData.zNotFound = zNotFound; |
| 443 | hsData.flags = flags; |
| 444 | |
| 445 | /* Try to start the control dispatcher thread for the service. */ |
| 446 | if( !StartServiceCtrlDispatcherW(ServiceTable) ){ |
| 447 | if( GetLastError()==ERROR_FAILED_SERVICE_CONTROLLER_CONNECT ){ |
| 448 | return 1; |
| 449 | }else{ |
| 450 | fossil_fatal("error from StartServiceCtrlDispatcher()"); |
| 451 | } |
| @@ -567,11 +569,11 @@ | |
| 569 | |
| 570 | if( strncmp(zMethod, "create", n)==0 ){ |
| 571 | SC_HANDLE hScm; |
| 572 | SC_HANDLE hSvc; |
| 573 | SERVICE_DESCRIPTION |
| 574 | svcDescr = {TEXT("Fossil - Distributed Software Configuration Management")}; |
| 575 | char *zErrFmt = "unable to create service '%s': %s"; |
| 576 | DWORD dwStartType = SERVICE_DEMAND_START; |
| 577 | const char *zDisplay = find_option("display", "D", 1); |
| 578 | const char *zStart = find_option("start", "S", 1); |
| 579 | const char *zUsername = find_option("username", "U", 1); |
| @@ -622,30 +624,30 @@ | |
| 624 | if( zPort ) blob_appendf(&binPath, " --port %s", zPort); |
| 625 | if( zNotFound ) blob_appendf(&binPath, " --notfound \"%s\"", zNotFound); |
| 626 | if( zLocalAuth ) blob_append(&binPath, " --localauth", -1); |
| 627 | blob_appendf(&binPath, " \"%s\"", g.zRepositoryName); |
| 628 | /* Create the service. */ |
| 629 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 630 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 631 | hSvc = CreateServiceW( |
| 632 | hScm, /* Handle to the SCM */ |
| 633 | fossil_utf8_to_unicode(zSvcName), /* Name of the service */ |
| 634 | fossil_utf8_to_unicode(zDisplay), /* Display name */ |
| 635 | SERVICE_ALL_ACCESS, /* Desired access */ |
| 636 | SERVICE_WIN32_OWN_PROCESS, /* Service type */ |
| 637 | dwStartType, /* Start type */ |
| 638 | SERVICE_ERROR_NORMAL, /* Error control */ |
| 639 | fossil_utf8_to_unicode(blob_str(&binPath)), /* Binary path */ |
| 640 | NULL, /* Load ordering group */ |
| 641 | NULL, /* Tag value */ |
| 642 | NULL, /* Service dependencies */ |
| 643 | fossil_utf8_to_unicode(zUsername), /* Service account */ |
| 644 | fossil_utf8_to_unicode(zPassword) /* Account password */ |
| 645 | ); |
| 646 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 647 | /* Set the service description. */ |
| 648 | ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); |
| 649 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 650 | CloseServiceHandle(hSvc); |
| 651 | CloseServiceHandle(hScm); |
| 652 | }else |
| 653 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -658,13 +660,13 @@ | |
| 660 | if( g.argc==4 ){ |
| 661 | zSvcName = g.argv[3]; |
| 662 | }else if( g.argc>4 ){ |
| 663 | fossil_fatal("to much arguments for delete method."); |
| 664 | } |
| 665 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 666 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 667 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); |
| 668 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 669 | QueryServiceStatus(hSvc, &sstat); |
| 670 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 671 | fossil_print("Stopping service '%s'", zSvcName); |
| 672 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| @@ -693,11 +695,11 @@ | |
| 695 | }else |
| 696 | if( strncmp(zMethod, "show", n)==0 ){ |
| 697 | SC_HANDLE hScm; |
| 698 | SC_HANDLE hSvc; |
| 699 | SERVICE_STATUS sstat; |
| 700 | LPQUERY_SERVICE_CONFIGW pSvcConfig; |
| 701 | LPSERVICE_DESCRIPTION pSvcDescr; |
| 702 | BOOL bStatus; |
| 703 | DWORD nRequired; |
| 704 | char *zErrFmt = "unable to show service '%s': %s"; |
| 705 | static const char *zSvcTypes[] = { |
| @@ -726,21 +728,21 @@ | |
| 728 | if( g.argc==4 ){ |
| 729 | zSvcName = g.argv[3]; |
| 730 | }else if( g.argc>4 ){ |
| 731 | fossil_fatal("to much arguments for show method."); |
| 732 | } |
| 733 | hScm = OpenSCManagerW(NULL, NULL, GENERIC_READ); |
| 734 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 735 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), GENERIC_READ); |
| 736 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 737 | /* Get the service configuration */ |
| 738 | bStatus = QueryServiceConfigW(hSvc, NULL, 0, &nRequired); |
| 739 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 740 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 741 | } |
| 742 | pSvcConfig = fossil_malloc(nRequired); |
| 743 | bStatus = QueryServiceConfigW(hSvc, pSvcConfig, nRequired, &nRequired); |
| 744 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 745 | /* Translate the service type */ |
| 746 | switch( pSvcConfig->dwServiceType ){ |
| 747 | case SERVICE_KERNEL_DRIVER: zSvcType = zSvcTypes[0]; break; |
| 748 | case SERVICE_FILE_SYSTEM_DRIVER: zSvcType = zSvcTypes[1]; break; |
| @@ -755,17 +757,17 @@ | |
| 757 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 758 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 759 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 760 | } |
| 761 | /* Get the service description. */ |
| 762 | bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 763 | NULL, 0, &nRequired); |
| 764 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 765 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 766 | } |
| 767 | pSvcDescr = fossil_malloc(nRequired); |
| 768 | bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 769 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 770 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 771 | /* Retrieves the current status of the specified service. */ |
| 772 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 773 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| @@ -780,19 +782,19 @@ | |
| 782 | case SERVICE_PAUSED: zSvcState = zSvcStates[6]; break; |
| 783 | } |
| 784 | /* Print service information to terminal */ |
| 785 | fossil_print("Service name .......: %s\n", zSvcName); |
| 786 | fossil_print("Display name .......: %s\n", |
| 787 | fossil_unicode_to_utf8(pSvcConfig->lpDisplayName)); |
| 788 | fossil_print("Service description : %s\n", |
| 789 | fossil_unicode_to_utf8(pSvcDescr->lpDescription)); |
| 790 | fossil_print("Service type .......: %s.\n", zSvcType); |
| 791 | fossil_print("Service start type .: %s.\n", zSvcStartType); |
| 792 | fossil_print("Binary path name ...: %s\n", |
| 793 | fossil_unicode_to_utf8(pSvcConfig->lpBinaryPathName)); |
| 794 | fossil_print("Service username ...: %s\n", |
| 795 | fossil_unicode_to_utf8(pSvcConfig->lpServiceStartName)); |
| 796 | fossil_print("Current state ......: %s.\n", zSvcState); |
| 797 | /* Cleanup */ |
| 798 | fossil_free(pSvcConfig); |
| 799 | fossil_free(pSvcDescr); |
| 800 | CloseServiceHandle(hSvc); |
| @@ -808,19 +810,19 @@ | |
| 810 | if( g.argc==4 ){ |
| 811 | zSvcName = g.argv[3]; |
| 812 | }else if( g.argc>4 ){ |
| 813 | fossil_fatal("to much arguments for start method."); |
| 814 | } |
| 815 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 816 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 817 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); |
| 818 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 819 | QueryServiceStatus(hSvc, &sstat); |
| 820 | if( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 821 | fossil_print("Starting service '%s'", zSvcName); |
| 822 | if( sstat.dwCurrentState!=SERVICE_START_PENDING ){ |
| 823 | if( !StartServiceW(hSvc, 0, NULL) ){ |
| 824 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 825 | } |
| 826 | } |
| 827 | while( sstat.dwCurrentState!=SERVICE_RUNNING ){ |
| 828 | Sleep(100); |
| @@ -844,13 +846,13 @@ | |
| 846 | if( g.argc==4 ){ |
| 847 | zSvcName = g.argv[3]; |
| 848 | }else if( g.argc>4 ){ |
| 849 | fossil_fatal("to much arguments for stop method."); |
| 850 | } |
| 851 | hScm = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS); |
| 852 | if( !hScm ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 853 | hSvc = OpenServiceW(hScm, fossil_utf8_to_unicode(zSvcName), SERVICE_ALL_ACCESS); |
| 854 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 855 | QueryServiceStatus(hSvc, &sstat); |
| 856 | if( sstat.dwCurrentState!=SERVICE_STOPPED ){ |
| 857 | fossil_print("Stopping service '%s'", zSvcName); |
| 858 | if( sstat.dwCurrentState!=SERVICE_STOP_PENDING ){ |
| 859 |