Fossil SCM
Patch from Edward Berner for Windows NT 4.0
Commit
8a84c6e82e906117e860f8a2a916ea3b17540470
Parent
d9aa512e203bd53…
1 file changed
+44
-10
+44
-10
| --- src/winhttp.c | ||
| +++ src/winhttp.c | ||
| @@ -455,10 +455,19 @@ | ||
| 455 | 455 | } |
| 456 | 456 | } |
| 457 | 457 | return 0; |
| 458 | 458 | } |
| 459 | 459 | |
| 460 | +/* | |
| 461 | +** The ChangeServiceConfig2W and QueryServiceConfig2W functions are | |
| 462 | +** loaded at run time in the cmd_win32_service function. These | |
| 463 | +** typedefs provide proper types for the function pointers. | |
| 464 | +*/ | |
| 465 | +typedef BOOL (WINAPI *CHANGESERVICECONFIG2W)(SC_HANDLE, DWORD, LPVOID); | |
| 466 | +typedef BOOL (WINAPI *QUERYSERVICECONFIG2W)(SC_HANDLE, DWORD, LPBYTE, | |
| 467 | + DWORD, LPDWORD); | |
| 468 | + | |
| 460 | 469 | /* dupe ifdef needed for mkindex |
| 461 | 470 | ** COMMAND: winsrv* |
| 462 | 471 | ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 463 | 472 | ** |
| 464 | 473 | ** Where METHOD is one of: create delete show start stop. |
| @@ -562,10 +571,25 @@ | ||
| 562 | 571 | */ |
| 563 | 572 | void cmd_win32_service(void){ |
| 564 | 573 | int n; |
| 565 | 574 | const char *zMethod; |
| 566 | 575 | const char *zSvcName = "Fossil-DSCM"; /* Default service name */ |
| 576 | + HINSTANCE hinstLib = NULL; | |
| 577 | + CHANGESERVICECONFIG2W ChangeServiceConfig2WAddr = NULL; | |
| 578 | + QUERYSERVICECONFIG2W QueryServiceConfig2WAddr = NULL; | |
| 579 | + | |
| 580 | + /* The ChangeServiceConfig2W and QueryServiceConfig2W functions are | |
| 581 | + ** not supported on Windows NT 4.0, so we load them at run time with | |
| 582 | + ** GetProcAddress and only call them if they exist. | |
| 583 | + */ | |
| 584 | + hinstLib = LoadLibrary(TEXT("advapi32.dll")); | |
| 585 | + if( NULL != hinstLib ){ | |
| 586 | + ChangeServiceConfig2WAddr = | |
| 587 | + (CHANGESERVICECONFIG2W) GetProcAddress(hinstLib, "ChangeServiceConfig2W"); | |
| 588 | + QueryServiceConfig2WAddr = | |
| 589 | + (QUERYSERVICECONFIG2W) GetProcAddress(hinstLib, "QueryServiceConfig2W"); | |
| 590 | + } | |
| 567 | 591 | |
| 568 | 592 | if( g.argc<3 ){ |
| 569 | 593 | usage("create|delete|show|start|stop ..."); |
| 570 | 594 | } |
| 571 | 595 | zMethod = g.argv[2]; |
| @@ -649,11 +673,13 @@ | ||
| 649 | 673 | fossil_utf8_to_unicode(zUsername), /* Service account */ |
| 650 | 674 | fossil_utf8_to_unicode(zPassword) /* Account password */ |
| 651 | 675 | ); |
| 652 | 676 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 653 | 677 | /* Set the service description. */ |
| 654 | - ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); | |
| 678 | + if( ChangeServiceConfig2WAddr ){ | |
| 679 | + ChangeServiceConfig2WAddr(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); | |
| 680 | + } | |
| 655 | 681 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 656 | 682 | CloseServiceHandle(hSvc); |
| 657 | 683 | CloseServiceHandle(hScm); |
| 658 | 684 | }else |
| 659 | 685 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -764,19 +790,24 @@ | ||
| 764 | 790 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 765 | 791 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 766 | 792 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 767 | 793 | } |
| 768 | 794 | /* Get the service description. */ |
| 769 | - bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 770 | - NULL, 0, &nRequired); | |
| 771 | - if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ | |
| 772 | - fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); | |
| 773 | - } | |
| 774 | - pSvcDescr = fossil_malloc(nRequired); | |
| 775 | - bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 776 | - (LPBYTE)pSvcDescr, nRequired, &nRequired); | |
| 777 | - if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); | |
| 795 | + if( QueryServiceConfig2WAddr ){ | |
| 796 | + bStatus = QueryServiceConfig2WAddr(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 797 | + NULL, 0, &nRequired); | |
| 798 | + if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ | |
| 799 | + fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); | |
| 800 | + } | |
| 801 | + pSvcDescr = fossil_malloc(nRequired); | |
| 802 | + bStatus = QueryServiceConfig2WAddr(hSvc, SERVICE_CONFIG_DESCRIPTION, | |
| 803 | + (LPBYTE)pSvcDescr, nRequired, &nRequired); | |
| 804 | + if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); | |
| 805 | + }else{ | |
| 806 | + pSvcDescr = fossil_malloc(sizeof(SERVICE_DESCRIPTIONW)); | |
| 807 | + pSvcDescr->lpDescription = L""; | |
| 808 | + } | |
| 778 | 809 | /* Retrieves the current status of the specified service. */ |
| 779 | 810 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 780 | 811 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 781 | 812 | /* Translate the current state. */ |
| 782 | 813 | switch( sstat.dwCurrentState ){ |
| @@ -883,8 +914,11 @@ | ||
| 883 | 914 | }else |
| 884 | 915 | { |
| 885 | 916 | fossil_fatal("METHOD should be one of:" |
| 886 | 917 | " create delete show start stop"); |
| 887 | 918 | } |
| 919 | + if( NULL != hinstLib ){ | |
| 920 | + FreeLibrary(hinstLib); | |
| 921 | + } | |
| 888 | 922 | return; |
| 889 | 923 | } |
| 890 | 924 | #endif /* _WIN32 -- This code is for win32 only */ |
| 891 | 925 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -455,10 +455,19 @@ | |
| 455 | } |
| 456 | } |
| 457 | return 0; |
| 458 | } |
| 459 | |
| 460 | /* dupe ifdef needed for mkindex |
| 461 | ** COMMAND: winsrv* |
| 462 | ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 463 | ** |
| 464 | ** Where METHOD is one of: create delete show start stop. |
| @@ -562,10 +571,25 @@ | |
| 562 | */ |
| 563 | void cmd_win32_service(void){ |
| 564 | int n; |
| 565 | const char *zMethod; |
| 566 | const char *zSvcName = "Fossil-DSCM"; /* Default service name */ |
| 567 | |
| 568 | if( g.argc<3 ){ |
| 569 | usage("create|delete|show|start|stop ..."); |
| 570 | } |
| 571 | zMethod = g.argv[2]; |
| @@ -649,11 +673,13 @@ | |
| 649 | fossil_utf8_to_unicode(zUsername), /* Service account */ |
| 650 | fossil_utf8_to_unicode(zPassword) /* Account password */ |
| 651 | ); |
| 652 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 653 | /* Set the service description. */ |
| 654 | ChangeServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); |
| 655 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 656 | CloseServiceHandle(hSvc); |
| 657 | CloseServiceHandle(hScm); |
| 658 | }else |
| 659 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -764,19 +790,24 @@ | |
| 764 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 765 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 766 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 767 | } |
| 768 | /* Get the service description. */ |
| 769 | bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 770 | NULL, 0, &nRequired); |
| 771 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 772 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 773 | } |
| 774 | pSvcDescr = fossil_malloc(nRequired); |
| 775 | bStatus = QueryServiceConfig2W(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 776 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 777 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 778 | /* Retrieves the current status of the specified service. */ |
| 779 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 780 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 781 | /* Translate the current state. */ |
| 782 | switch( sstat.dwCurrentState ){ |
| @@ -883,8 +914,11 @@ | |
| 883 | }else |
| 884 | { |
| 885 | fossil_fatal("METHOD should be one of:" |
| 886 | " create delete show start stop"); |
| 887 | } |
| 888 | return; |
| 889 | } |
| 890 | #endif /* _WIN32 -- This code is for win32 only */ |
| 891 |
| --- src/winhttp.c | |
| +++ src/winhttp.c | |
| @@ -455,10 +455,19 @@ | |
| 455 | } |
| 456 | } |
| 457 | return 0; |
| 458 | } |
| 459 | |
| 460 | /* |
| 461 | ** The ChangeServiceConfig2W and QueryServiceConfig2W functions are |
| 462 | ** loaded at run time in the cmd_win32_service function. These |
| 463 | ** typedefs provide proper types for the function pointers. |
| 464 | */ |
| 465 | typedef BOOL (WINAPI *CHANGESERVICECONFIG2W)(SC_HANDLE, DWORD, LPVOID); |
| 466 | typedef BOOL (WINAPI *QUERYSERVICECONFIG2W)(SC_HANDLE, DWORD, LPBYTE, |
| 467 | DWORD, LPDWORD); |
| 468 | |
| 469 | /* dupe ifdef needed for mkindex |
| 470 | ** COMMAND: winsrv* |
| 471 | ** Usage: fossil winsrv METHOD ?SERVICE-NAME? ?OPTIONS? |
| 472 | ** |
| 473 | ** Where METHOD is one of: create delete show start stop. |
| @@ -562,10 +571,25 @@ | |
| 571 | */ |
| 572 | void cmd_win32_service(void){ |
| 573 | int n; |
| 574 | const char *zMethod; |
| 575 | const char *zSvcName = "Fossil-DSCM"; /* Default service name */ |
| 576 | HINSTANCE hinstLib = NULL; |
| 577 | CHANGESERVICECONFIG2W ChangeServiceConfig2WAddr = NULL; |
| 578 | QUERYSERVICECONFIG2W QueryServiceConfig2WAddr = NULL; |
| 579 | |
| 580 | /* The ChangeServiceConfig2W and QueryServiceConfig2W functions are |
| 581 | ** not supported on Windows NT 4.0, so we load them at run time with |
| 582 | ** GetProcAddress and only call them if they exist. |
| 583 | */ |
| 584 | hinstLib = LoadLibrary(TEXT("advapi32.dll")); |
| 585 | if( NULL != hinstLib ){ |
| 586 | ChangeServiceConfig2WAddr = |
| 587 | (CHANGESERVICECONFIG2W) GetProcAddress(hinstLib, "ChangeServiceConfig2W"); |
| 588 | QueryServiceConfig2WAddr = |
| 589 | (QUERYSERVICECONFIG2W) GetProcAddress(hinstLib, "QueryServiceConfig2W"); |
| 590 | } |
| 591 | |
| 592 | if( g.argc<3 ){ |
| 593 | usage("create|delete|show|start|stop ..."); |
| 594 | } |
| 595 | zMethod = g.argv[2]; |
| @@ -649,11 +673,13 @@ | |
| 673 | fossil_utf8_to_unicode(zUsername), /* Service account */ |
| 674 | fossil_utf8_to_unicode(zPassword) /* Account password */ |
| 675 | ); |
| 676 | if( !hSvc ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 677 | /* Set the service description. */ |
| 678 | if( ChangeServiceConfig2WAddr ){ |
| 679 | ChangeServiceConfig2WAddr(hSvc, SERVICE_CONFIG_DESCRIPTION, &svcDescr); |
| 680 | } |
| 681 | fossil_print("Service '%s' successfully created.\n", zSvcName); |
| 682 | CloseServiceHandle(hSvc); |
| 683 | CloseServiceHandle(hScm); |
| 684 | }else |
| 685 | if( strncmp(zMethod, "delete", n)==0 ){ |
| @@ -764,19 +790,24 @@ | |
| 790 | case SERVICE_AUTO_START: zSvcStartType = zSvcStartTypes[2]; break; |
| 791 | case SERVICE_DEMAND_START: zSvcStartType = zSvcStartTypes[3]; break; |
| 792 | case SERVICE_DISABLED: zSvcStartType = zSvcStartTypes[4]; break; |
| 793 | } |
| 794 | /* Get the service description. */ |
| 795 | if( QueryServiceConfig2WAddr ){ |
| 796 | bStatus = QueryServiceConfig2WAddr(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 797 | NULL, 0, &nRequired); |
| 798 | if( !bStatus && GetLastError()!=ERROR_INSUFFICIENT_BUFFER ){ |
| 799 | fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 800 | } |
| 801 | pSvcDescr = fossil_malloc(nRequired); |
| 802 | bStatus = QueryServiceConfig2WAddr(hSvc, SERVICE_CONFIG_DESCRIPTION, |
| 803 | (LPBYTE)pSvcDescr, nRequired, &nRequired); |
| 804 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 805 | }else{ |
| 806 | pSvcDescr = fossil_malloc(sizeof(SERVICE_DESCRIPTIONW)); |
| 807 | pSvcDescr->lpDescription = L""; |
| 808 | } |
| 809 | /* Retrieves the current status of the specified service. */ |
| 810 | bStatus = QueryServiceStatus(hSvc, &sstat); |
| 811 | if( !bStatus ) fossil_fatal(zErrFmt, zSvcName, win32_get_last_errmsg()); |
| 812 | /* Translate the current state. */ |
| 813 | switch( sstat.dwCurrentState ){ |
| @@ -883,8 +914,11 @@ | |
| 914 | }else |
| 915 | { |
| 916 | fossil_fatal("METHOD should be one of:" |
| 917 | " create delete show start stop"); |
| 918 | } |
| 919 | if( NULL != hinstLib ){ |
| 920 | FreeLibrary(hinstLib); |
| 921 | } |
| 922 | return; |
| 923 | } |
| 924 | #endif /* _WIN32 -- This code is for win32 only */ |
| 925 |