// create directory for lock files and set appropriate access rights void createLockDirectory(const char* pathname) { static bool errorLogged = false; DWORD attr = GetFileAttributes(pathname); DWORD errcode = 0; if (attr == INVALID_FILE_ATTRIBUTES) { errcode = GetLastError(); if (errcode == ERROR_FILE_NOT_FOUND) { if (!CreateDirectory(pathname, NULL)) { errcode = GetLastError(); } else { adjustLockDirectoryAccess(pathname); attr = GetFileAttributes(pathname); if (attr == INVALID_FILE_ATTRIBUTES) { errcode = GetLastError(); } } } } Firebird::string err; if (attr == INVALID_FILE_ATTRIBUTES) { err.printf("Can't create directory \"%s\". OS errno is %d", pathname, errcode); if (!errorLogged) { errorLogged = true; gds__log(err.c_str()); } Firebird::fatal_exception::raise(err.c_str()); } if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { err.printf("Can't create directory \"%s\". File with same name already exists", pathname); if (!errorLogged) { errorLogged = true; gds__log(err.c_str()); } Firebird::fatal_exception::raise(err.c_str()); } if (attr & FILE_ATTRIBUTE_READONLY) { err.printf("Can't create directory \"%s\". Readonly directory with same name already exists", pathname); if (!errorLogged) { errorLogged = true; gds__log(err.c_str()); } Firebird::fatal_exception::raise(err.c_str()); } }
void grantRevokeAdmin(Firebird::IUser* user, bool ignoreRevoke = false) { if (!user->admin()->entered()) { return; } Firebird::LocalStatus s; Firebird::CheckStatusWrapper statusWrapper(&s); Firebird::string userName(user->userName()->get()); prepareName(userName, '"'); Firebird::string sql; if (user->admin()->get() == 0) { Firebird::string userName2(user->userName()->get()); prepareName(userName2, '\''); Firebird::string selGrantor; selGrantor.printf("SELECT RDB$GRANTOR FROM RDB$USER_PRIVILEGES " "WHERE RDB$USER = '******' AND RDB$RELATION_NAME = '%s' AND RDB$PRIVILEGE = 'M'", userName2.c_str(), ADMIN_ROLE); Message out; Field<Varying> grantor(out, MAX_SQL_IDENTIFIER_SIZE); Firebird::IResultSet* curs = att->openCursor(&statusWrapper, tra, selGrantor.length(), selGrantor.c_str(), SQL_DIALECT_V6, NULL, NULL, out.getMetadata(), NULL, 0); check(&statusWrapper); bool hasGrant = curs->fetchNext(&statusWrapper, out.getBuffer()) == Firebird::IStatus::RESULT_OK; curs->close(&statusWrapper); check(&statusWrapper); if (hasGrant) { selGrantor = grantor; prepareName(selGrantor, '"'); sql.printf("REVOKE %s FROM \"%s\" GRANTED BY \"%s\"", ADMIN_ROLE, userName.c_str(), selGrantor.c_str()); } else { if (ignoreRevoke) return; // no grant - let engine produce correct error message sql.printf("REVOKE %s FROM \"%s\"", ADMIN_ROLE, userName.c_str()); } } else { sql.printf("GRANT %s TO \"%s\"", ADMIN_ROLE, userName.c_str()); } att->execute(&statusWrapper, tra, sql.length(), sql.c_str(), SQL_DIALECT_V6, NULL, NULL, NULL, NULL); check(&statusWrapper); }
TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, TraceInitInfo* initInfo) { Firebird::MasterInterfacePtr master; const char* dbname = NULL; try { master->upgradeInterface(initInfo, FB_TRACE_INIT_INFO_VERSION, upInfo); dbname = initInfo->getDatabaseName(); if (!dbname) dbname = ""; TracePluginConfig config; TraceCfgReader::readTraceConfiguration(initInfo->getConfigText(), dbname, config); TraceDatabaseConnection* connection = initInfo->getConnection(); if (connection) master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); if (!config.enabled || (config.connection_id && connection && (connection->getConnectionID() != SLONG(config.connection_id)))) { return NULL; // Plugin is not needed, no error happened. } Firebird::AutoPtr<TraceLogWriter, Firebird::SimpleRelease<TraceLogWriter> > logWriter(initInfo->getLogWriter()); if (logWriter) config.log_filename = ""; return new TracePluginImpl(config, initInfo); // Everything is ok, we created a plugin } catch (Firebird::Exception& ex) { // put error into trace log TraceLogWriter* logWriter = initInfo->getLogWriter(); if (logWriter) { master->upgradeInterface(logWriter, FB_TRACE_LOG_WRITER_VERSION, upInfo); const char* strEx = TracePluginImpl::marshal_exception(ex); Firebird::string err; if (dbname) err.printf("Error creating trace session for database \"%s\":\n%s\n", dbname, strEx); else err.printf("Error creating trace session for service manager attachment:\n%s\n", strEx); logWriter->write(err.c_str(), err.length()); logWriter->release(); } else ex.stuffException(status); } return NULL; }
Firebird::string pagtype(UCHAR type) { // Print pretty name for database page type const char* nameArray[pag_max + 1] = { "purposely undefined", "database header", "page inventory", "transaction inventory", "pointer", "data", "index root", "index B-tree", "blob", "generators", "SCN inventory" }; Firebird::string rc; if (type < FB_NELEM(nameArray)) rc = nameArray[type]; else rc.printf("unknown (%d)", type); return rc; }
ModuleLoader::Module* ModuleLoader::loadModule(ISC_STATUS* status, const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { if (status) { status[0] = isc_arg_gds; status[1] = isc_random; status[2] = isc_arg_string; status[3] = (ISC_STATUS) dlerror(); status[4] = isc_arg_end; } return 0; } #ifdef DEBUG_THREAD_IN_UNLOADED_LIBRARY Firebird::string command; command.printf("echo +++ %s +++ >>/tmp/fbmaps;date >> /tmp/fbmaps;cat /proc/%d/maps >>/tmp/fbmaps", modPath.c_str(), getpid()); system(command.c_str()); #endif return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(*getDefaultMemoryPool(), modPath, module); }
// Lookup and format message. Return as much of formatted string as fits in caller's buffer. int fb_msg_format(void* handle, USHORT facility, USHORT number, unsigned int bsize, TEXT* buffer, const MsgFormat::SafeArg& arg) { // The field MESSAGES.TEXT is 118 bytes long. int total_msg = 0; char msg[120] = ""; const int n = gds__msg_lookup(handle, facility, number, sizeof(msg), msg, NULL); if (n > 0 && unsigned(n) < sizeof(msg)) { // Shameful bridge, gds__msg_format emulation for old format messages. if (strchr(msg, '%')) { const TEXT* rep[5]; arg.dump(rep, 5); total_msg = fb_utils::snprintf(buffer, bsize, msg, rep[0], rep[1], rep[2], rep[3], rep[4]); } else total_msg = MsgPrint(buffer, bsize, msg, arg); } else { Firebird::string s; s.printf("can't format message %d:%d -- ", facility, number); if (n == -1) s += "message text not found"; else if (n == -2) { s += "message file "; s += fb_utils::getPrefix(Firebird::DirType::FB_DIR_MSG, MSG_FILE).ToString(); s += " not found"; } else { fb_utils::snprintf(buffer, bsize, "message system code %d", n); s += buffer; } total_msg = s.copyTo(buffer, bsize); } return (n > 0 ? total_msg : -total_msg); }
ModuleLoader::Module* ModuleLoader::loadModule(const Firebird::PathName& modPath) { void* module = dlopen(modPath.nullStr(), FB_RTLD_MODE); if (module == NULL) { #ifdef DEV_BUILD // gds__log("loadModule failed loading %s: %s", modPath.c_str(), dlerror()); #endif return 0; } #ifdef DEBUG_THREAD_IN_UNLOADED_LIBRARY Firebird::string command; command.printf("echo +++ %s +++ >>/tmp/fbmaps;date >> /tmp/fbmaps;cat /proc/%d/maps >>/tmp/fbmaps", modPath.c_str(), getpid()); system(command.c_str()); #endif return FB_NEW_POOL(*getDefaultMemoryPool()) DlfcnModule(module); }
// allow different users to read\write\delete files in lock directory // in case of any error just log it and don't stop engine execution void adjustLockDirectoryAccess(const char* pathname) { PSECURITY_DESCRIPTOR pSecDesc = NULL; PSID pSID_Users = NULL; PSID pSID_Administrators = NULL; PACL pNewACL = NULL; try { // We should pass root directory in format "C:\" into GetVolumeInformation(). // In case of pathname is not local folder (i.e. \\share\folder) let // GetVolumeInformation() return an error. Firebird::PathName root(pathname); const Firebird::PathName::size_type pos = root.find(':', 0); if (pos == 1) { root.erase(pos + 1, root.length()); PathUtils::ensureSeparator(root); } DWORD fsflags; if (!GetVolumeInformation(root.c_str(), NULL, 0, NULL, NULL, &fsflags, NULL, 0)) Firebird::system_error::raise("GetVolumeInformation"); if (!(fsflags & FS_PERSISTENT_ACLS)) return; // Adjust security for our new folder : allow BUILTIN\Users group to // read\write\delete files PACL pOldACL = NULL; if (GetNamedSecurityInfo((LPSTR) pathname, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, &pOldACL, NULL, &pSecDesc) != ERROR_SUCCESS) { Firebird::system_error::raise("GetNamedSecurityInfo"); } SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY; if (!AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, 0, 0, 0, 0, 0, 0, &pSID_Users)) { Firebird::system_error::raise("AllocateAndInitializeSid"); } if (!AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &pSID_Administrators)) { Firebird::system_error::raise("AllocateAndInitializeSid"); } EXPLICIT_ACCESS eas[2]; memset(eas, 0, sizeof(eas)); eas[0].grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE; eas[0].grfAccessMode = GRANT_ACCESS; eas[0].grfInheritance = SUB_OBJECTS_ONLY_INHERIT; eas[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; eas[0].Trustee.TrusteeType = TRUSTEE_IS_GROUP; eas[0].Trustee.ptstrName = (LPSTR) pSID_Users; eas[1].grfAccessPermissions = FILE_GENERIC_READ | FILE_GENERIC_WRITE | DELETE; eas[1].grfAccessMode = GRANT_ACCESS; eas[1].grfInheritance = SUB_OBJECTS_ONLY_INHERIT; eas[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; eas[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; eas[1].Trustee.ptstrName = (LPSTR) pSID_Administrators; if (SetEntriesInAcl(2, eas, pOldACL, &pNewACL) != ERROR_SUCCESS) Firebird::system_error::raise("SetEntriesInAcl"); if (SetNamedSecurityInfo((LPSTR) pathname, SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, NULL, NULL, pNewACL, NULL) != ERROR_SUCCESS) { Firebird::system_error::raise("SetNamedSecurityInfo"); } } catch (const Firebird::Exception& ex) { Firebird::string str; str.printf("Error adjusting access rights for folder \"%s\" :", pathname); iscLogException(str.c_str(), ex); } if (pSID_Users) { FreeSid(pSID_Users); } if (pSID_Administrators) { FreeSid(pSID_Administrators); } if (pNewACL) { LocalFree(pNewACL); } if (pSecDesc) { LocalFree(pSecDesc); } }
void EVL_validate(thread_db* tdbb, const Item& item, const ItemInfo* itemInfo, dsc* desc, bool null) { /************************************** * * E V L _ v a l i d a t e * ************************************** * * Functional description * Validate argument/variable for not null and check constraint * **************************************/ if (itemInfo == NULL) return; jrd_req* request = tdbb->getRequest(); bool err = false; if (null && !itemInfo->nullable) err = true; const char* value = NULL_STRING_MARK; VaryStr<128> temp; MapFieldInfo::ValueType fieldInfo; if (!err && itemInfo->fullDomain && request->getStatement()->mapFieldInfo.get(itemInfo->field, fieldInfo) && fieldInfo.validationExpr) { if (desc && null) desc->dsc_flags |= DSC_null; const bool desc_is_null = !desc || (desc->dsc_flags & DSC_null); request->req_domain_validation = desc; const USHORT flags = request->req_flags; if (!fieldInfo.validationExpr->execute(tdbb, request) && !(request->req_flags & req_null)) { const USHORT length = desc_is_null ? 0 : MOV_make_string(desc, ttype_dynamic, &value, &temp, sizeof(temp) - 1); if (desc_is_null) value = NULL_STRING_MARK; else if (!length) value = ""; else const_cast<char*>(value)[length] = 0; // safe cast - data is on our local stack err = true; } request->req_flags = flags; } Firebird::string s; if (err) { ISC_STATUS status = isc_not_valid_for_var; const char* arg; if (item.type == Item::TYPE_CAST) { status = isc_not_valid_for; arg = "CAST"; } else { if (itemInfo->name.isEmpty()) { int index = item.index + 1; status = isc_not_valid_for; if (item.type == Item::TYPE_VARIABLE) { const jrd_prc* procedure = request->getStatement()->procedure; if (procedure) { if (index <= int(procedure->getOutputFields().getCount())) s.printf("output parameter number %d", index); else { s.printf("variable number %d", index - int(procedure->getOutputFields().getCount())); } } else s.printf("variable number %d", index); } else if (item.type == Item::TYPE_PARAMETER && item.subType == 0) s.printf("input parameter number %d", (index - 1) / 2 + 1); else if (item.type == Item::TYPE_PARAMETER && item.subType == 1) s.printf("output parameter number %d", index); if (s.isEmpty()) arg = UNKNOWN_STRING_MARK; else arg = s.c_str(); } else arg = itemInfo->name.c_str(); } ERR_post(Arg::Gds(status) << Arg::Str(arg) << Arg::Str(value)); } }
int gsec(Firebird::UtilSvc* uSvc) { /************************************** * * c o m m o n _ m a i n * ************************************** * * Functional description * If there is no command line, prompt for one, read it * and make an artificial argv. Otherwise, pass * the specified argv to SECURITY_exec_line (see below). * **************************************/ int exit_code = FINI_OK; Firebird::UtilSvc::ArgvType& argv = uSvc->argv; TEXT stuff[MAXSTUFF]; // a place to put stuff in interactive mode tsec tsecInstance(uSvc); tsec* tdsec = &tsecInstance; tsec::putSpecific(tdsec); StackUserData u; tdsec->tsec_user_data = &u; const unsigned char* block; unsigned int bs = uSvc->getAuthBlock(&block); if (bs) { u.authenticationBlock.add(block, bs); } try { // Perform some special handling when run as a Firebird service. tdsec->tsec_throw = true; tdsec->tsec_interactive = !uSvc->isService(); UserData* user_data = tdsec->tsec_user_data; //if (!uSvc->isService() && argv.getCount() == 1) // GSEC_error(GsecMsg101); // use gsec -? to get help int ret = parse_cmd_line(argv, tdsec); if (!uSvc->isService() && ret == -2) // user asked for help GSEC_exit(); Firebird::PathName databaseName; const bool databaseNameEntered = user_data->database.entered(); if (databaseNameEntered) { databaseName = user_data->database.get(); } else { const Firebird::RefPtr<Config> defConf(Config::getDefaultConfig()); databaseName = defConf->getSecurityDatabase(); } const Firebird::string sqlRoleName(user_data->role.entered() ? user_data->role.get() : ""); Firebird::PathName serverName; const bool useServices = !uSvc->isService(); switch (ISC_extract_host(databaseName, serverName, true)) { case ISC_PROTOCOL_TCPIP: serverName += ":"; break; case ISC_PROTOCOL_WLAN: serverName = "\\\\" + serverName + "\\"; break; } if (!useServices) { serverName = ""; } Firebird::LocalStatus s; user_data->database.set(&s, databaseName.c_str()); check(&s); Firebird::RefPtr<IManagement> manager; ISC_STATUS_ARRAY status; if (!useServices) { // Get remote address info for management plugin Firebird::string network_protocol, remote_address; Firebird::ClumpletWriter tmp(Firebird::ClumpletReader::Tagged, MAX_DPB_SIZE, isc_dpb_version1); uSvc->fillDpb(tmp); if (tmp.find(isc_dpb_address_path)) { Firebird::ClumpletReader address_stack(Firebird::ClumpletReader::UnTagged, tmp.getBytes(), tmp.getClumpLength()); while (!address_stack.isEof()) { if (address_stack.getClumpTag() != isc_dpb_address) { address_stack.moveNext(); continue; } Firebird::ClumpletReader address(Firebird::ClumpletReader::UnTagged, address_stack.getBytes(), address_stack.getClumpLength()); while (!address.isEof()) { switch (address.getClumpTag()) { case isc_dpb_addr_protocol: address.getString(network_protocol); break; case isc_dpb_addr_endpoint: address.getString(remote_address); break; default: break; } address.moveNext(); } break; } } // Create config to pass -DATABASE parameter value to plugin Firebird::string databaseText; databaseText.printf("SecurityDatabase = %s\n", databaseName.c_str()); ConfigFile gsecDatabase(ConfigFile::USE_TEXT, databaseText.c_str()); Firebird::RefPtr<Config> defaultConfig(Config::getDefaultConfig()); Firebird::RefPtr<Config> pseudoConfig(new Config(gsecDatabase, *defaultConfig)); uSvc->checkService(); fb_assert(user_data->dba.entered() || user_data->authenticationBlock.hasData()); if (user_data->dba.entered() || user_data->authenticationBlock.hasData()) { class GsecInfo : public Firebird::AutoIface<ILogonInfo, FB_AUTH_LOGON_INFO_VERSION> { public: GsecInfo(const char* pDba, const char* pRole, const char* pProtocol, const char* pAddress, const UserData::AuthenticationBlock* pAuthBlock) : dba(pDba), sqlRole(pRole), protocol(pProtocol), address(pAddress), authBytes(pAuthBlock->getCount() ? pAuthBlock->begin() : NULL), authLength(pAuthBlock->getCount()) { } // ILogonInfo implementation const char* FB_CARG name() { return dba; } const char* FB_CARG role() { return sqlRole; } const char* FB_CARG networkProtocol() { return protocol; } const char* FB_CARG remoteAddress() { return address; } const unsigned char* FB_CARG authBlock(unsigned* length) { *length = authLength; return authBytes; } private: const char* dba; const char* sqlRole; const char* protocol; const char* address; const unsigned char* authBytes; unsigned int authLength; };
static void setAttr(Firebird::string& attr, IIntUserField* field) { attr.printf("%d", field->get()); }
int CLIB_ROUTINE main( int argc, char **argv) { /************************************** * * m a i n * ************************************** * * Functional description * Install or remove a Firebird service. * **************************************/ USHORT sw_command = COMMAND_NONE; bool sw_version = false; USHORT sw_startup = STARTUP_AUTO; USHORT sw_mode = DEFAULT_PRIORITY; USHORT sw_guardian = NO_GUARDIAN; USHORT sw_arch = ARCH_SS; bool sw_interactive = false; const TEXT* instance = FB_DEFAULT_INSTANCE; const TEXT* username = NULL; const TEXT* password = NULL; // Let's get the root directory from the instance path of this program. // argv[0] is only _mostly_ guaranteed to give this info, // so we GetModuleFileName() TEXT directory[MAXPATHLEN]; const USHORT len = GetModuleFileName(NULL, directory, sizeof(directory)); if (len == 0) return svc_error(GetLastError(), "GetModuleFileName", NULL); fb_assert(len <= sizeof(directory)); // Get to the last '\' (this one precedes the filename part). There is // always one after a call to GetModuleFileName(). TEXT* p = directory + len; while (p != directory) { --p; if ((*p) == '\\') break; } *p = '\0'; TEXT full_username[128]; TEXT oem_username[128]; TEXT keyb_password[64]; const TEXT* const* const end = argv + argc; while (++argv < end) { if (**argv != '-') { int i; const TEXT* cmd; for (i = 0; cmd = commands[i].name; i++) { const TEXT* q; for (p = *argv, q = cmd; *p && UPPER(*p) == *q; p++, q++) ; if (!*p && commands[i].abbrev <= (USHORT) (q - cmd)) break; } if (!cmd) { printf("Unknown command \"%s\"\n", *argv); usage_exit(); } sw_command = commands[i].code; } else { p = *argv + 1; switch (UPPER(*p)) { case 'A': sw_startup = STARTUP_AUTO; break; case 'D': sw_startup = STARTUP_DEMAND; break; /* case 'R': sw_mode = NORMAL_PRIORITY; break; */ case 'B': sw_mode = HIGH_PRIORITY; break; case 'Z': sw_version = true; break; case 'G': sw_guardian = USE_GUARDIAN; break; case 'L': if (++argv < end) username = *argv; if (++argv < end) { if (**argv == '-') // Next switch --argv; else password = *argv; } break; case 'I': sw_interactive = true; break; case 'N': if (++argv < end) instance = *argv; break; case '?': usage_exit(); default: printf("Unknown switch \"%s\"\n", p); usage_exit(); } } } if (sw_version) printf("instsvc version %s\n", FB_VERSION); if (sw_command == COMMAND_NONE || (username && sw_command != COMMAND_INSTALL)) { usage_exit(); } if (sw_command == COMMAND_INSTALL && username != 0) { if (sw_interactive) { printf("\"Interact with desktop\" mode can be set for LocalSystem account only"); exit(FINI_ERROR); } const char* limit = username; while (*limit != '\0' && *limit != '\\') ++limit; if (!*limit) { DWORD cnlen = sizeof(full_username) - 1; GetComputerName(full_username, &cnlen); strcat(full_username, "\\"); strncat(full_username, username, sizeof(full_username) - (cnlen + 1)); } else { strncpy(full_username, username, sizeof(full_username)); } full_username[sizeof(full_username) - 1] = '\0'; CharToOem(full_username, oem_username); username = full_username; if (password == 0) { printf("Enter %s user password : "******"\n"); OemToChar(keyb_password, keyb_password); password = keyb_password; } // Let's grant "Logon as a Service" right to the -login user switch (SERVICES_grant_privilege(full_username, svc_error, L"SeServiceLogonRight")) { case FB_PRIVILEGE_ALREADY_GRANTED: /* // OM - I think it is better not to bother the admin with this message. printf("The 'Logon as a Service' right was already granted to %s\n", oem_username); */ break; case FB_SUCCESS: printf("The 'Logon as a Service' right has been granted to %s\n", oem_username); break; case FB_FAILURE: default: printf("Failed granting the 'Logon as a Service' right to %s\n", oem_username); exit(FINI_ERROR); break; } // Let's grant "Adjust memory quotas for a process" right to the -login user switch (SERVICES_grant_privilege(full_username, svc_error, L"SeIncreaseQuotaPrivilege")) { case FB_PRIVILEGE_ALREADY_GRANTED: break; case FB_SUCCESS: printf("The 'Adjust memory quotas for a process' right has been granted to %s\n", oem_username); break; case FB_FAILURE: default: printf("Failed granting the 'Adjust memory quotas for a process' right to %s\n", oem_username); exit(FINI_ERROR); break; } } DWORD dwScmManagerAccess = SC_MANAGER_ALL_ACCESS; switch (sw_command) { case COMMAND_INSTALL: case COMMAND_REMOVE: dwScmManagerAccess = SC_MANAGER_CREATE_SERVICE; break; case COMMAND_START: case COMMAND_STOP: dwScmManagerAccess = SC_MANAGER_CONNECT; break; case COMMAND_QUERY: dwScmManagerAccess = SC_MANAGER_ENUMERATE_SERVICE; break; } const SC_HANDLE manager = OpenSCManager(NULL, NULL, dwScmManagerAccess); if (manager == NULL) { svc_error(GetLastError(), "OpenSCManager", NULL); exit(FINI_ERROR); } USHORT status, status2; SC_HANDLE service; Firebird::string guard_service_name, guard_display_name; guard_service_name.printf(ISCGUARD_SERVICE, instance); guard_display_name.printf(ISCGUARD_DISPLAY_NAME, instance); Firebird::string remote_service_name, remote_display_name; remote_service_name.printf(REMOTE_SERVICE, instance); remote_display_name.printf(REMOTE_DISPLAY_NAME, instance); Firebird::string switches; if (strchr(instance, ' ')) switches.printf("-s \"%s\"", instance); else switches.printf("-s %s", instance); switch (sw_command) { case COMMAND_INSTALL: // First, lets do the guardian, if it has been specified if (sw_guardian) { status = SERVICES_install(manager, guard_service_name.c_str(), guard_display_name.c_str(), ISCGUARD_DISPLAY_DESCR, ISCGUARD_EXECUTABLE, directory, switches.c_str(), NULL, sw_startup, username, password, false, // interactive_mode true, // auto_restart svc_error); status2 = FB_SUCCESS; if (username != 0) { status2 = SERVICES_grant_access_rights(guard_service_name.c_str(), username, svc_error); } if (status == FB_SUCCESS && status2 == FB_SUCCESS) { printf("Service \"%s\" successfully created.\n", guard_display_name.c_str()); } // Set sw_startup to manual in preparation for install the service sw_startup = STARTUP_DEMAND; } // do the install of the server status = SERVICES_install(manager, remote_service_name.c_str(), remote_display_name.c_str(), REMOTE_DISPLAY_DESCR, REMOTE_EXECUTABLE, directory, switches.c_str(), NULL, sw_startup, username, password, sw_interactive, !sw_guardian, svc_error); status2 = FB_SUCCESS; if (username != 0) { status2 = SERVICES_grant_access_rights(remote_service_name.c_str(), username, svc_error); } if (status == FB_SUCCESS && status2 == FB_SUCCESS) { printf("Service \"%s\" successfully created.\n", remote_display_name.c_str()); } break; case COMMAND_REMOVE: service = OpenService(manager, guard_service_name.c_str(), SERVICE_ALL_ACCESS); if (service) { CloseServiceHandle(service); status = SERVICES_remove(manager, guard_service_name.c_str(), /*guard_display_name.c_str(),*/ svc_error); if (status == FB_SUCCESS) { printf("Service \"%s\" successfully deleted.\n", guard_display_name.c_str()); } else if (status == IB_SERVICE_RUNNING) { printf("Service \"%s\" not deleted.\n", guard_display_name.c_str()); printf("You must stop it before attempting to delete it.\n\n"); } } else { status = (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) ? FB_SUCCESS : FB_FAILURE; } service = OpenService(manager, remote_service_name.c_str(), SERVICE_ALL_ACCESS); if (service) { CloseServiceHandle(service); status2 = SERVICES_remove(manager, remote_service_name.c_str(), /*remote_display_name.c_str(),*/ svc_error); if (status2 == FB_SUCCESS) { printf("Service \"%s\" successfully deleted.\n", remote_display_name.c_str()); } else if (status2 == IB_SERVICE_RUNNING) { printf("Service \"%s\" not deleted.\n", remote_display_name.c_str()); printf("You must stop it before attempting to delete it.\n\n"); } } else { status2 = (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST) ? FB_SUCCESS : FB_FAILURE; } if (status != FB_SUCCESS && status2 != FB_SUCCESS) status = FB_FAILURE; break; case COMMAND_START: // Test for use of the guardian. If so, start the guardian else start the server service = OpenService(manager, guard_service_name.c_str(), SERVICE_START); if (service) { CloseServiceHandle(service); status = SERVICES_start(manager, guard_service_name.c_str(), /*guard_display_name.c_str(),*/ sw_mode, svc_error); if (status == FB_SUCCESS) { printf("Service \"%s\" successfully started.\n", guard_display_name.c_str()); } } else { CloseServiceHandle(service); status = SERVICES_start(manager, remote_service_name.c_str(), /*remote_display_name.c_str(),*/ sw_mode, svc_error); if (status == FB_SUCCESS) { printf("Service \"%s\" successfully started.\n", remote_display_name.c_str()); } } break; case COMMAND_STOP: // Test for use of the guardian. If so, stop the guardian else stop the server service = OpenService(manager, guard_service_name.c_str(), SERVICE_STOP); if (service) { CloseServiceHandle(service); status = SERVICES_stop(manager, guard_service_name.c_str(), /*guard_display_name.c_str(),*/ svc_error); if (status == FB_SUCCESS) { printf("Service \"%s\" successfully stopped.\n", guard_display_name.c_str()); } } else { CloseServiceHandle(service); status = SERVICES_stop(manager, remote_service_name.c_str(), /*remote_display_name.c_str(),*/ svc_error); if (status == FB_SUCCESS) { printf("Service \"%s\" successfully stopped.\n", remote_display_name.c_str()); } } break; case COMMAND_QUERY: if (svc_query_ex(manager) == FB_FAILURE) { svc_query(guard_service_name.c_str(), guard_display_name.c_str(), manager); svc_query(remote_service_name.c_str(), remote_display_name.c_str(), manager); } status = FB_SUCCESS; break; default: status = FB_SUCCESS; } CloseServiceHandle(manager); return (status == FB_SUCCESS) ? FINI_OK : FINI_ERROR; }