%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% module #include "dk3all.h" #include "dkt.h" #include "dkwt.h" $!trace-include /** Job structure for dkwt boot/login/logout/shutdown. */ typedef struct { dk3_app_t *app; /**< Application structure. */ dkChar const * const *msg; /**< Localized message texts. */ dkChar const * const *kwnl; /**< Keywords, not localized. */ dk3_option_set_t *opt; /**< Options set. */ dkChar const *userName; /**< User name. */ dkChar const *profBase; /**< Profile base directory. */ dkChar const *systemUser; /**< System user account. */ dkChar const *everyUser; /**< Everyone user account. */ dk3_sto_t *s_users; /**< Storage users. */ dk3_sto_it_t *i_users; /**< Iterator users. */ dk3_sto_t *s_pubdir; /**< Storage public directories. */ dk3_sto_it_t *i_pubdir; /**< Iterator public directories. */ dk3_sto_t *s_queues; /**< Remote queues to clean up. */ dk3_sto_it_t *i_queues; /**< Iterator for remote queues. */ DWORD versMaj; /**< Major version number. */ DWORD versMin; /**< Minor version number. */ int exval; /**< Exit status code. */ int event; /**< Event to process. */ int curSection; /**< Current configuration file sect. */ int useIcacls; /**< Flag: Use icalcs. */ int testOnly; /**< Flag: Test only. */ int clp; /**< Flag: Clean up local print queues. */ } DKWT_EV_J; /** Unknown section type. */ #define DKWT_EV_SECTION_UNKNOWN (-1) /** In the options section. */ #define DKWT_EV_SECTION_OPTIONS 0 /** In the profiles section. */ #define DKWT_EV_SECTION_PROFILES 1 /** In the public directories section. */ #define DKWT_EV_SECTION_PUBLIC 2 /** Configuration file section names. */ static dkChar const * const dkwt_ev_section_names[] = { $!string-table macro=dkT # 0 options # 1 profiles # 2 public $!end }; /** Configuration file option names. */ static dkChar const * const dkwt_ev_option_names[] = { $!string-table macro=dkT # 0 system-user # 1 everyone-user # 2 print-jobs $!end }; /** Names of profiles to keep. */ static dkChar const * const dkwt_ev_profiles_to_keep[] = { $!text macro=dkT All Users Default User Public LocalService NetworkService Administrator $!end }; /** Options. */ static dk3_option_t const dkwt_ev_options[] = { { dkT('t'), dkT("test"), 0 } }; /** Number of options in the dkwt_ev_options array. */ static size_t const dkwt_ev_szoptions = sizeof(dkwt_ev_options)/sizeof(dk3_option_t); /** Print queue name for local printers. */ static dkChar const dkwt_pq_name_local[] = { dkT("local") }; /** Retrieve value of keep flag. @param app Application structure. @param msg Localized message texts. @param kwnl Keywords, not localized. @param reset Reset the flag. @return Flag value (before reset). */ static int dkwt_ev_get_keep_value( dk3_app_t *app, dkChar const * const *msg, dkChar const * const *kwnl, int reset ) { long result; DWORD dw0; DWORD dwType; DWORD dwValue; DWORD dwSz; int back = 0; HKEY hk; REGSAM regsam; $? "+ dkwt_ev_get_keep_value" dw0 = (DWORD)0; dwType = REG_DWORD; dwValue = 0; dwSz = sizeof(DWORD); regsam = KEY_QUERY_VALUE; if(reset) { regsam = (KEY_READ | KEY_WRITE); } result = dkwt_tool_reg_open_key( HKEY_LOCAL_MACHINE, kwnl[15], KEY_QUERY_VALUE, &hk ); if(result == ERROR_SUCCESS) { result = dkwt_tool_reg_query_value( hk, kwnl[16], &dwType, &dwValue, &dwSz ); if(result == ERROR_SUCCESS) { if(dwType == REG_DWORD) { if(dwSz == sizeof(DWORD)) { if(dwValue) { back = 1; } } } } if(reset) { (void)dkwt_tool_reg_delete_value(hk, kwnl[16]); } RegCloseKey(hk); } $? "- dkwt_et_get_keep_value %d", back return back; } /** Compare two strings. @param l Left string. @param r Right string. @param cr Comparison criteria (ignored). @return Comparison result. */ static int dkwt_ev_compare_string(void const *l, void const *r, int cr) { dkChar const *pl; dkChar const *pr; int back = 0; if(l) { if(r) { pl = (dkChar const *)l; pr = (dkChar const *)r; back = dk3str_casecmp(pl, pr); } else { back = 1; } } else { if(r) { back = -1; } } if(back > 1) back = 1; if(back < -1) back = -1; return back; } /** Initialize job structure. @param j Structure to initialize. */ static void dkwt_ev_job_init(DKWT_EV_J *j) { OSVERSIONINFO ovi; j->app = NULL; j->msg = NULL; j->kwnl = NULL; j->profBase = NULL; j->userName = NULL; j->systemUser = NULL; j->everyUser = NULL; j->s_users = NULL; j->i_users = NULL; j->s_pubdir = NULL; j->i_pubdir = NULL; j->exval = DKT_RESULT_ERR_UNSPECIFIC; j->curSection = -1; j->useIcacls = 0; j->testOnly = 0; j->clp = 0; j->opt = NULL; j->s_queues = NULL; j->i_queues = NULL; j->versMaj = 5; j->versMin = 1; ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); ovi.dwMajorVersion = 0L; ovi.dwMinorVersion = 0L; ovi.dwBuildNumber = 0L; ovi.dwPlatformId = 0L; if(GetVersionEx(&ovi)) { j->versMaj = ovi.dwMajorVersion; j->versMin = ovi.dwMinorVersion; if(ovi.dwMajorVersion > 5) { j->useIcacls = 1; $? ". icacls" } else { if(ovi.dwMajorVersion == 5) { if(ovi.dwMinorVersion > 1) { j->useIcacls = 1; $? ". icacls" } } } } } /** Clean up job structure, release memory. @param j Job structure. */ static void dkwt_ev_job_cleanup(DKWT_EV_J *j) { dkChar *un; void *vp; if(j) { if(j->s_queues) { if(j->i_queues) { dk3sto_it_reset(j->i_queues); while(NULL != (vp = dk3sto_it_next(j->i_queues))) { dk3_delete(vp); } dk3sto_it_close(j->i_queues); } dk3sto_close(j->s_queues); } j->s_queues = NULL; j->i_queues = NULL; if(j->s_users) { if(j->i_users) { dk3sto_it_reset(j->i_users); while((un = (dkChar *)dk3sto_it_next(j->i_users)) != NULL) { dk3_release(un); } dk3sto_it_close(j->i_users); } dk3sto_close(j->s_users); } j->s_users = NULL; j->i_users = NULL; if(j->s_pubdir) { if(j->i_pubdir) { dk3sto_it_reset(j->i_pubdir); while((un = (dkChar *)dk3sto_it_next(j->i_pubdir)) != NULL) { dk3_release(un); } dk3sto_it_close(j->i_pubdir); } dk3sto_close(j->s_pubdir); } j->s_pubdir = NULL; j->i_pubdir = NULL; dk3_release(j->profBase); dk3_release(j->userName); dk3_release(j->systemUser); dk3_release(j->everyUser); if(j->opt) { dk3opt_close(j->opt); j->opt = NULL; } } } /** Handler for one input line. @param obj Job structure. @param il Input line to process. @return 1 on success, 0 on recoverable error, -1 to abort processing. */ static int dkwt_ev_line_handler(void *obj, dkChar *il) { DKWT_EV_J *j; dkChar *p1; dkChar *p2; dkChar *p3; dkChar *nq; int back = 1; $? "+ dkwt_ev_line_handler \"%s\"", TR_STR(il) j = (DKWT_EV_J *)obj; p1 = dk3str_start(il, NULL); if(p1) { if(*p1 != dkT('#')) { back = -1; dk3str_delnl(p1); if(*p1 == dkT('[')) { /* New section header. */ p1++; p1 = dk3str_start(p1, NULL); if(p1) { j->curSection = DKWT_EV_SECTION_UNKNOWN; p2 = dk3str_rchr(p1, dkT(']')); if(p2) { *p2 = dkT('\0'); p2 = dk3str_next(p1, NULL); switch(dk3str_array_index(dkwt_ev_section_names, p1, 0)) { case 0: { j->curSection = DKWT_EV_SECTION_OPTIONS; back = 1; } break; case 1: { j->curSection = DKWT_EV_SECTION_PROFILES; if(p2) { if(!(j->profBase)) { j->profBase = dk3str_dup_app(p2, j->app); if(j->profBase) { back = 1; } else { back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } else { back = -1; j->exval = DKT_RESULT_ERR_INPUT; /* ERROR: Redefinition of profile base dir! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 66); } } else { j->exval = DKT_RESULT_ERR_INPUT; /* ERROR: No profile base dir specified! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 67); } } break; case 2: { j->curSection = DKWT_EV_SECTION_PUBLIC; back = 1; } break; default: { back = -1; j->exval = DKT_RESULT_ERR_INPUT; /* ERROR: Unknown section type. */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 68); } break; } } else { back = -1; /* ERROR: Incomplete section header. */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 69); j->exval = DKT_RESULT_ERR_INPUT; } } else { back = -1; /* ERROR: No section header! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 70); j->exval = DKT_RESULT_ERR_INPUT; } } else { /* Section contents line. */ switch(j->curSection) { case DKWT_EV_SECTION_OPTIONS: { p2 = dk3str_chr(p1, dkT('=')); if(p2) { *(p2++) = dkT('\0'); p2 = dk3str_start(p2, NULL); if(p2) { /* dk3str_chomp(p1, NULL); */ dk3str_normalize(p1, NULL, dkT('-')); #if 0 dk3str_normalize(p2, NULL, dkT('-')); #endif switch(dk3str_array_index(dkwt_ev_option_names, p1, 0)) { case 0: { if(!(j->systemUser)) { j->systemUser = dk3str_dup_app(p2, j->app); if(j->systemUser) { back = 1; } else { back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } else { /* ERROR: Redefinition of system user! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 71); back = -1; j->exval = DKT_RESULT_ERR_INPUT; } } break; case 1: { if(!(j->everyUser)) { j->everyUser = dk3str_dup_app(p2, j->app); if(j->everyUser) { back = 1; } else { back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } else { /* ERROR: Redefinition of everyone user! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 72); back = -1; j->exval = DKT_RESULT_ERR_INPUT; } } break; case 2: { back = 1; while(p2) { p3 = dk3str_next(p2, NULL); if(0 == dk3str_cmp(dkwt_pq_name_local, p2)) { j->clp = 1; } else { if(!(j->s_queues)) { j->s_queues = dk3sto_open_app(j->app); } if(!(j->i_queues)) { if(j->s_queues) { j->i_queues = dk3sto_it_open(j->s_queues); } } if((j->s_queues) && (j->i_queues)) { nq = dk3str_dup_app(p2, j->app); if(nq) { if(!dk3sto_add(j->s_queues, (void *)nq)) { dk3_delete(nq); back = 0; } } else { back = 0; } } else { back = 0; } } p2 = p3; } } break; default: { /* ERROR: Unknown option! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 73); back = -1; j->exval = DKT_RESULT_ERR_INPUT; } break; } } else { /* ERROR: Not a key/value pair */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 74); back = -1; j->exval = DKT_RESULT_ERR_INPUT; } } else { /* ERROR: Not a key/value pair */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 74); back = -1; j->exval = DKT_RESULT_ERR_INPUT; } } break; case DKWT_EV_SECTION_PROFILES: { $? ". add user name to list" dk3str_normalize(p1, NULL, dkT(' ')); p2 = dk3str_dup_app(p1, j->app); if(p2) { if(dk3sto_add(j->s_users, (void *)p2)) { back = 1; $? ". added user name \"%s\"", TR_STR(p2) } else { $? "! failed to add" dk3_release(p2); back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } else { $? "! empty user name" back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } break; case DKWT_EV_SECTION_PUBLIC: { $? ". add public dir to list" dk3str_normalize(p1, NULL, dkT(' ')); p2 = dk3str_dup_app(p1, j->app); if(p2) { $? ". p2" if(dk3sto_add(j->s_pubdir, (void *)p2)) { back = 1; $? ". added" } else { $? "! failed to add" dk3_release(p2); back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } else { $? "! p2" back = -1; j->exval = DKT_RESULT_ERR_MEMORY; } } break; default: { back = -1; j->exval = DKT_RESULT_ERR_INPUT; } break; } } } else { /* Comment line ok. */ } } else { /* Empty line ok. */ } $? "- dkwt_ev_line_handler %d", back return back; } /** Run a command. @param j Job structure. @param cmd Command to run. */ static void dkwt_ev_execute_command(DKWT_EV_J *j, dkChar const *cmd) { int value = 0; /* PROGRESS: Execute command ... */ dk3app_log_3(j->app, DK3_LL_PROGRESS, j->msg, 118, 119, cmd); dk3sf_initialize_stdout(); dk3sf_fputs(cmd, stdout); dk3sf_fputc(dkT('\n'), stdout); if(!(j->testOnly)) { #if DK3_CHAR_SIZE > 1 value = _wsystem(cmd); #else value = system(cmd); #endif if(value != 0) { /* ERROR: Command execution failed! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 79, 80, cmd); j->exval = DKT_RESULT_ERR_SYSEXEC; } } } /** Remove a directory. First attempt to use the RD command, next use own routines. @param j Job structure. @param dn Directory name. @param dolog Flag: Do logging in dk3dir_remove_app(). */ static void dkwt_ev_remove_directory(DKWT_EV_J *j, dkChar const *dn, int dolog) { dkChar bu[2 * DK3_MAX_PATH]; dk3_stat_t stb; size_t sz; $? "+ dkwt_ev_remove_directory \"%ls\"", dn /* PROGRESS: Remove directory ... */ dk3app_log_3(j->app, DK3_LL_PROGRESS, j->msg, 120, 121, dn); if(!(j->testOnly)) { #if 0 dk3sf_remove_dir(dn); #endif dk3dir_remove_app(dn, ((dolog) ? j->app : NULL)); if(dk3sf_stat_app(&stb, dn, NULL)) { sz = dk3str_len(dn); sz += dk3str_len((j->kwnl)[4]); sz += dk3str_len((j->kwnl)[5]); if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, (j->kwnl)[4]); dk3str_cat(bu, dn); dk3str_cat(bu, (j->kwnl)[5]); dkwt_ev_execute_command(j, bu); } else { $? "! name too long" /* ERROR: File name too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 59, 60, dn); j->exval = DKT_RESULT_ERR_FILENAME; } } } $? "- dkwt_ev_remove_directory" } /** Remove a file. First attempt to use the DEL command, next use own routines. @param j Job structure. @param fn File name. */ static void dkwt_ev_remove_file(DKWT_EV_J *j, dkChar const *fn) { dkChar bu[2 * DK3_MAX_PATH]; dk3_stat_t stb; size_t sz; /* PROGRESS: Remove file ... */ dk3app_log_3(j->app, DK3_LL_PROGRESS, j->msg, 122, 123, fn); if(!(j->testOnly)) { dk3sf_remove_file_app(fn, NULL); if(dk3sf_stat_app(&stb, fn, NULL)) { sz = dk3str_len(fn); sz += dk3str_len((j->kwnl)[6]); sz += dk3str_len((j->kwnl)[5]); if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, (j->kwnl)[6]); dk3str_cat(bu, fn); dk3str_cat(bu, (j->kwnl)[5]); dkwt_ev_execute_command(j, bu); } else { /* ERROR: File name too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); j->exval = DKT_RESULT_ERR_FILENAME; } } } } /** Check whether or not to keep a profile subdirectory. @param j Job structure. @param un User name (short directory name). @return 1 to keep the directory, 0 to delete it. */ static int dkwt_ev_must_keep(DKWT_EV_J *j, dkChar const *un) { int back = 0; $? "+ dkwt_ev_must_keep" if(j->userName) { if(dk3str_casecmp(j->userName, un) == 0) { back = 1; } } if(!(back)) { if(dk3sto_it_find_like(j->i_users, (void *)un, 0)) { back = 1; } } if(!(back)) { if(dk3str_array_index(dkwt_ev_profiles_to_keep, un, 0) >= 0) { back = 1; } } $? "- dkwt_ev_must_keep %d", back return back; } #ifdef VERSION_BEFORE_20120320 /** Clean up the profile directory. @param j Job structure. */ static void dkwt_ev_cleanup_profiles(DKWT_EV_J *j) { dkChar bu1[DK3_MAX_PATH]; dk3_dir_t *dir; dkChar const *en; dkChar const *es; dkChar *ptr; int must_delete = 1; $? "+ dkwt_ev_cleanup_profiles %d", must_delete if(j->profBase) { if(j->versMaj < 6) { dir = dk3dir_open_app(j->profBase, j->app); if(dir) { $? ". directory opened" while(dk3dir_get_next_directory(dir)) { en = dk3dir_get_fullname(dir); es = dk3dir_get_shortname(dir); if((en) && (es)) { $? ". entry \"%ls\"", es must_delete = 1; if(dkwt_ev_must_keep(j, es)) { must_delete = 0; $? ". must keep" } else { $? ". can delete" if(dk3str_len(es) < DK3_SIZEOF(bu1,dkChar)) { dk3str_cpy_not_overlapped(bu1, es); ptr = dk3str_chr(bu1, dkT('.')); if(ptr) { *ptr = dkT('\0'); if(dkwt_ev_must_keep(j, bu1)) { must_delete = 0; $? ". must keep" } else { $? ". can delete" } } else { $? ". no need to test again" } } else { $? "! name too long for test" must_delete = 0; } } $? ". must_delete=%d", must_delete if(must_delete) { $? ". must delete \"%ls\"", en dkwt_ev_remove_directory(j, en, 0); } } } dk3dir_close(dir); } } else { } } $? "- dkwt_ev_cleanup_profiles" } #else /** Directory entry for deletion. */ typedef struct { dkChar const *n; /**< Directory name. */ char f; /**< Flag: Can delete. */ } DKWT_EV_DIR; /** Release directory name. @param d Directory name entry to delete. */ static void dkwt_ev_ddel_del(DKWT_EV_DIR *d) { if(d) { dk3_release(d->n); d->f = 0x00; dk3_delete(d); } } /** Create directory name entry. @param j Job structure. @param fn File name of directory. @return New entry on success, NULL on error. */ static DKWT_EV_DIR * dkwt_ev_ddel_new(DKWT_EV_J *j, dkChar const *fn) { DKWT_EV_DIR *back = NULL; if(fn) { back = dk3_new_app(DKWT_EV_DIR,1,j->app); if(back) { back->f = 0x01; back->n = dk3str_dup_app(fn, j->app); if(!(back->n)) { dkwt_ev_ddel_del(back); back = NULL; } } } return back; } /** Compare two entries for directories. @param l Left directory object. @param r Right directory object. @param cr Comparison criteria (0=dir/dir, 1=dir/name). @return Comparison result. */ static int dkwt_ev_ddel_comp(void const *l, void const *r, int cr) { int back = 0; DKWT_EV_DIR const *pl; DKWT_EV_DIR const *pr; if(l) { if(r) { pl = (DKWT_EV_DIR const *)l; switch(cr) { case 1: { if(pl->n) { back = dk3str_casecmp(pl->n, (dkChar const *)r); if(back < -1) back = -1; if(back > 1) back = 1; } else back = -1; } break; default: { pr = (DKWT_EV_DIR const *)r; if(pl->n) { if(pr->n) { back = dk3str_casecmp(pl->n, pr->n); if(back < -1) back = -1; if(back > 1) back = 1; } else back = 1; } else { if(pr->n) back = -1; } } break; } } else back = 1; } else { if(r) back = -1; } return back; } /** Delete a registry key structure for a user profile. @param j Job structure. @param kn Key name (short name). */ static void dkwt_ev_del_rk_profile(DKWT_EV_J *j, dkChar const *kn) { HKEY hk; long res; $? "+ dkwt_ev_del_rk_profile \"%s\"", kn /* Log message */ /* PROGRESS: Deleting registry key ... */ dk3app_log_5( j->app, DK3_LL_PROGRESS, j->msg, 124, 125, 126, (j->kwnl)[19], kn ); /* Delete the key. */ if(!(j->testOnly)) { res = dkwt_tool_reg_open_key( HKEY_LOCAL_MACHINE, (j->kwnl)[19], KEY_ALL_ACCESS, &hk ); if(ERROR_SUCCESS == res) { $? ". parent key opened" res = dkwt_tool_reg_delete_tree(hk, kn); if(ERROR_SUCCESS == res) { $? ". deleted successfully" /* DEBUG: Registry key ... deleted. */ dk3app_log_3(j->app, DK3_LL_DEBUG, j->msg, 127, 128, kn); } else { $? "! failed to delete" /* ERROR: Failed to remove registry hierarchy ... */ dk3app_log_5( j->app, DK3_LL_ERROR, j->msg, 129, 130, 131, (j->kwnl)[19], kn ); } RegCloseKey(hk); } else { $? "! failed to open parent" /* ERROR: Failed to open registry key ... */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 132, 133, (j->kwnl)[19]); } } $? "- dkwt_ev_del_rk_profile" } /** Clean up the profile directory. @param j Job structure. */ static void dkwt_ev_cleanup_profiles(DKWT_EV_J *j) { dkChar knb[DK3_MAX_PATH]; /* Buffer for key name. */ dkChar ppb[DK3_MAX_PATH]; /* Profile path buffer. */ dkChar esb[DK3_MAX_PATH]; /* Expanded string buffer. */ dkChar bu1[DK3_MAX_PATH]; /* Buffer for full file name. */ void *vp; /* void pointer for cleanup. */ dk3_sto_t *s_fn; /* Storage of directories to delete. */ dk3_sto_it_t *i_fn; /* Iterator for directory storage. */ dk3_sto_t *s_rk; /* Storage for registry keys. */ dk3_sto_it_t *i_rk; /* Iterator for registry keys storage. */ dk3_sto_t *s_rd; /* Storage for registry keys to delete. */ dk3_sto_it_t *i_rd; /* Iterator for keys to delete. `*/ dk3_dir_t *dir; /* Directory. */ dkChar const *en; /* Entry name. */ dkChar const *es; /* Short entry name. */ dkChar const *kn; /* Current key name, copy. */ dkChar *ptr; /* Pointer to dot in file name. */ DKWT_EV_DIR *ddel; /* Directory to delete. */ HKEY hk; /* Handle for registry key. */ REGSAM regs; /* Access type to registry key. */ long res; /* Result from operation. */ size_t stlgt; /* String length. */ DWORD dw0; /* Used to open registry keys. */ DWORD dwInd; /* INdex of current key. */ DWORD dwSz; /* Size of knb buffer. */ DWORD dwEx; /* Result from string expansion. */ DWORD dwTp; /* Result type. */ int md; /* Flag: Must delete this entry. */ int ec; /* Error code. */ $? "+ dkwt_ev_cleanup_profiles" ec = 0; if(j->profBase) { /* PROGRESS: Cleanin up profiles (start) */ dk3app_log_1(j->app, DK3_LL_PROGRESS, j->msg, 134); s_fn = dk3sto_open_app(j->app); if(s_fn) { dk3sto_set_comp(s_fn, dkwt_ev_ddel_comp, 0); i_fn = dk3sto_it_open(s_fn); if(i_fn) { s_rk = dk3sto_open_app(j->app); if(s_rk) { dk3sto_set_comp(s_rk, dkwt_ev_compare_string, 0); i_rk = dk3sto_it_open(s_rk); if(i_rk) { s_rd = dk3sto_open_app(j->app); if(s_rd) { i_rd = dk3sto_it_open(s_rd); if(i_rd) { /* DEBUG: Storages ok. */ dir = dk3dir_open_app(j->profBase, j->app); if(dir) { /* DEBUG: Directory opened successfully. */ while(dk3dir_get_next_directory(dir)) { en = dk3dir_get_fullname(dir); es = dk3dir_get_shortname(dir); if((en) && (es)) { $? ". entry \"%s\"", es md = 1; if(dkwt_ev_must_keep(j, es)) { md = 0; } else { if(dk3str_len(es) < DK3_SIZEOF(bu1,dkChar)) { dk3str_cpy_not_overlapped(bu1, es); ptr = dk3str_chr(bu1, dkT('.')); if(ptr) { *ptr = dkT('\0'); if(dkwt_ev_must_keep(j, bu1)) { md = 0; } } } else { $? "! name too long" /* ERROR: Name too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 59, 60, es); if(!(ec)) { ec = DK3_ERROR_TOO_LARGE; } md = 0; } } $? ". md = %d", md if(md) { ddel = dkwt_ev_ddel_new(j, en); if(ddel) { if(!dk3sto_add(s_fn, (void *)ddel)) { $? "! add" dkwt_ev_ddel_del(ddel); if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } else { $? "! ddel_new" if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } } else { $? "! bug" /* ERROR: Failed to obtain name for directory entry! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 135); if(!(ec)) { ec = DK3_ERROR_SYSTEM; } } } dk3dir_close(dir); /* Now search the registry keys */ dw0 = (DWORD)0; regs = KEY_READ; res = dkwt_tool_reg_open_key( HKEY_LOCAL_MACHINE, (j->kwnl)[19], KEY_READ, &hk ); if(ERROR_SUCCESS == res) { dwInd = 0; do { dwSz = DK3_SIZEOF(knb,dkChar); res = dkwt_tool_reg_enum_key( hk, dwInd, knb, &dwSz, NULL, NULL, NULL ); if(ERROR_SUCCESS == res) { if(dwSz > 0) { kn = dk3str_dup_app(knb, j->app); if(kn) { if(!dk3sto_add(s_rk, (void *)kn)) { $? "! add" dk3_delete(kn); if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } else { $? "! strdup" if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } } else { $? "! reg_enum_key" if(res != ERROR_NO_MORE_ITEMS) { if(!(ec)) { ec = DK3_ERROR_DURING_READ; } } } dwInd++; } while(res != ERROR_NO_MORE_ITEMS); RegCloseKey(hk); /* For each key found check whether ProfileImagePath is in s_fn. */ dk3sto_it_reset(i_rk); while(NULL != (kn = (dkChar const *)dk3sto_it_next(i_rk))) { stlgt = dk3str_len((j->kwnl)[19]); stlgt++; stlgt += dk3str_len(kn); if(stlgt < DK3_SIZEOF(knb,dkChar)) { dk3str_cpy_not_overlapped(knb, (j->kwnl)[19]); dk3str_cat(knb, (j->kwnl)[20]); dk3str_cat(knb, kn); dw0 = 0; regs = KEY_QUERY_VALUE; res = dkwt_tool_reg_open_key( HKEY_LOCAL_MACHINE, knb, KEY_QUERY_VALUE, &hk ); if(ERROR_SUCCESS == res) { dwTp = REG_EXPAND_SZ; dwSz = sizeof(ppb); res = dkwt_tool_reg_query_value( hk, (j->kwnl)[21], &dwTp, ppb, &dwSz ); if(ERROR_SUCCESS == res) { #if DK3_CHAR_SIZE > 1 if(dwSz < (sizeof(ppb) - 1)) { ppb[dwSz] = '\0'; ppb[dwSz+1] = '\0'; } else { ppb[sizeof(ppb)-2] = '\0'; ppb[sizeof(ppb)-1] = '\0'; } #else if(dwSz < sizeof(ppb)) { ppb[dwSz] = '\0'; } else { ppb[sizeof(ppb)-1] = '\0'; } #endif switch(dwTp) { case REG_SZ: { ddel = (DKWT_EV_DIR *)dk3sto_it_find_like( i_fn, (void *)ppb, 1 ); if(ddel) { /* Save kn as registry key to delete */ if(!dk3sto_add(s_rd, (void *)kn)) { $? "! add" ddel->f = 0x00; if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } } break; case REG_EXPAND_SZ: { dwEx = ExpandEnvironmentStrings( ppb, esb, DK3_SIZEOF(esb,dkChar) ); if(dwEx > 0) { if(dwEx < DK3_SIZEOF(esb,dkChar)) { ddel = (DKWT_EV_DIR *)dk3sto_it_find_like( i_fn, (void *)esb, 1 ); if(ddel) { /* Save kn as registry key to delete */ if(!dk3sto_add(s_rd,(void *)kn)) { $? "! add" ddel->f = 0x00; if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } } else { $? "! ExpandEnvironmentStrings" /* ERROR: String too long! */ dk3app_log_3( j->app, DK3_LL_ERROR, j->msg, 136, 137, ppb ); if(!(ec)) { ec = DK3_ERROR_TOO_LARGE; } } } else { ddel = (DKWT_EV_DIR *)dk3sto_it_find_like( i_fn, (void *)ppb, 1 ); if(ddel) { /* Save kn as registry key to delete */ if(!dk3sto_add(s_rd, (void *)kn)) { $? "! add" ddel->f = 0x00; if(!(ec)) { ec = DK3_ERROR_MEMORY; } } } } } break; } } RegCloseKey(hk); } else { $? "! registry open key" /* ERROR: Failed to open registry key ... */ dk3app_log_3( j->app, DK3_LL_ERROR, j->msg, 132, 133, knb ); if(!(ec)) { ec = DK3_ERROR_NOT_OPENED_FOR_READING; } } } else { $? "! key name too long \"%s\"", kn /* ERROR: Key name too long! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 138, 139, kn); if(!(ec)) { ec = DK3_ERROR_TOO_LARGE; } } } } else { $? "! failed to open registry key" /* ERROR: Failed to open registry key! */ dk3app_log_3( j->app, DK3_LL_ERROR, j->msg, 132, 133, (j->kwnl)[19] ); if(!(ec)) { ec = DK3_ERROR_NOT_OPENED_FOR_READING; } } } else { $? "! dir" } if(!(ec)) { $? ". no error, delete registry keys" dk3sto_it_reset(i_rd); while(NULL != (kn = (dkChar const *)dk3sto_it_next(i_rd))) { /* */ dkwt_ev_del_rk_profile(j, kn); } } else { /* ERROR: Skipping profile cleanup due to previous errors! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 140); } /* In s_rd and i_rd we have copies of strings from s_rk and i_rk. No deletion necessary. */ dk3sto_it_close(i_rd); } else { $? "! i_rd" } dk3sto_close(s_rd); } else { $? "! s_rd" } dk3sto_it_reset(i_rk); while(NULL != (vp = dk3sto_it_next(i_rk))) { dk3_delete(vp); } dk3sto_it_close(i_rk); } else { $? "! i_rk" } dk3sto_close(s_rk); } else { $? "! s_rk" } dk3sto_it_reset(i_fn); while(NULL != (ddel = (DKWT_EV_DIR *)dk3sto_it_next(i_fn))) { /* Remove the directory. */ if(!(ec)) { if(ddel->f) { dkwt_ev_remove_directory(j, ddel->n, 0); } } /* Free list entry. */ dkwt_ev_ddel_del(ddel); } dk3sto_it_close(i_fn); i_fn = NULL; } else { $? "! i_fn" } dk3sto_close(s_fn); s_fn = NULL; } else { $? "! s_fn" } /* PROGRESS: Cleaning up profiles (finished). */ dk3app_log_1(j->app, DK3_LL_PROGRESS, j->msg, 141); } else { $? ". no profile base configured" } $? "- dkwt_ev_cleanup_profiles" } #endif /** Clean up public directories. @param j Job structure. */ static void dkwt_ev_cleanup_public(DKWT_EV_J *j) { dkChar const *fn; dkChar const *en; dk3_dir_t *dir; $? "+ dkwt_ev_cleanup_public" dk3sto_it_reset(j->i_pubdir); while((fn = (dkChar const *)dk3sto_it_next(j->i_pubdir)) != NULL) { dir = dk3dir_open_app(fn, j->app); if(dir) { while(dk3dir_get_next_directory(dir)) { en = dk3dir_get_fullname(dir); if(en) { dkwt_ev_remove_directory(j, en, 1); } } while(dk3dir_get_next_file(dir)) { en = dk3dir_get_fullname(dir); if(en) { dkwt_ev_remove_file(j, en); } } dk3dir_close(dir); } } $? "- dkwt_ev_cleanup_public" } /** Change permissions for one path. @param j Job structure. @param fn File name. @param un User name. @param isdir Flag: Is directory. */ static void dkwt_ev_user_permissions( DKWT_EV_J *j, dkChar const *fn, dkChar const *un, int isdir ) { dkChar bu[2 * DK3_MAX_PATH]; size_t sz = 0; $? "+ dkwt_ev_user_permissions" if(j->useIcacls) { if(isdir) { sz = dk3str_len((j->kwnl)[10]); sz += dk3str_len(fn); sz += dk3str_len((j->kwnl)[11]); sz += dk3str_len(un); sz += dk3str_len((j->kwnl)[12]); if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, (j->kwnl)[10]); dk3str_cat(bu, fn); dk3str_cat(bu, (j->kwnl)[11]); dk3str_cat(bu, un); dk3str_cat(bu, (j->kwnl)[12]); dkwt_ev_execute_command(j, bu); } else { /* ERROR: Line too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); j->exval = DKT_RESULT_ERR_FILENAME; } } else { sz = dk3str_len((j->kwnl)[10]); sz += dk3str_len(fn); sz += dk3str_len((j->kwnl)[11]); sz += dk3str_len(un); sz += dk3str_len((j->kwnl)[13]); if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, (j->kwnl)[10]); dk3str_cat(bu, fn); dk3str_cat(bu, (j->kwnl)[11]); dk3str_cat(bu, un); dk3str_cat(bu, (j->kwnl)[13]); dkwt_ev_execute_command(j, bu); } else { /* ERROR: Line too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); j->exval = DKT_RESULT_ERR_FILENAME; } } } else { if(isdir) { sz = dk3str_len((j->kwnl)[7]); sz += dk3str_len(fn); sz += dk3str_len((j->kwnl)[8]); sz += dk3str_len(un); sz += dk3str_len((j->kwnl)[9]); if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, (j->kwnl)[7]); dk3str_cat(bu, fn); dk3str_cat(bu, (j->kwnl)[8]); dk3str_cat(bu, un); dk3str_cat(bu, (j->kwnl)[9]); dkwt_ev_execute_command(j, bu); } else { /* ERROR: Line too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); j->exval = DKT_RESULT_ERR_FILENAME; } } else { sz = dk3str_len((j->kwnl)[7]); sz += dk3str_len(fn); sz += dk3str_len((j->kwnl)[14]); sz += dk3str_len(un); sz += dk3str_len((j->kwnl)[9]); if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, (j->kwnl)[7]); dk3str_cat(bu, fn); dk3str_cat(bu, (j->kwnl)[14]); dk3str_cat(bu, un); dk3str_cat(bu, (j->kwnl)[9]); dkwt_ev_execute_command(j, bu); } else { /* ERROR: Line too long! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); j->exval = DKT_RESULT_ERR_FILENAME; } } } $? "- dkwt_ev_user_permissions" } /** Change permissions for one path. @param j Job structure. @param fn File name. @param isdir Flag: Is directory. */ static void dkwt_ev_permissions(DKWT_EV_J *j, dkChar const *fn, int isdir) { $? "+ dkwt_ev_permissions" if(j->systemUser) { dkwt_ev_user_permissions(j, fn, j->systemUser, isdir); } else { dkwt_ev_user_permissions(j, fn, (j->kwnl)[2], isdir); } if(j->everyUser) { dkwt_ev_user_permissions(j, fn, j->everyUser, isdir); } else { dkwt_ev_user_permissions(j, fn, (j->kwnl)[3], isdir); } $? "- dkwt_ev_permissions" } /** Change permissions to own profile, grant full access to system and everyone. @param j Job structure. */ static void dkwt_ev_permissions_profile(DKWT_EV_J *j) { dkChar bu[DK3_MAX_PATH]; size_t sz; $? "+ dkwt_ev_permissions_profile" if((j->profBase) && (j->userName)) { sz = dk3str_len(j->profBase); sz += dk3str_len(j->userName); sz += 1; if(sz < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, j->profBase); dk3str_cat(bu, dk3app_not_localized(20)); dk3str_cat(bu, j->userName); dkwt_ev_permissions(j, bu, 1); } } $? "- dkwt_ev_permissions_profile" } /** Change permissions to public directory contents, grant full access to system and everyone. @param j Job structure. */ static void dkwt_ev_permissions_public(DKWT_EV_J *j) { dkChar const *fn; dkChar const *en; dk3_dir_t *dir; $? "+ dkwt_ev_permissions_public" dk3sto_it_reset(j->i_pubdir); while((fn = (dkChar const *)dk3sto_it_next(j->i_pubdir)) != NULL) { dir = dk3dir_open_app(fn, j->app); if(dir) { while(dk3dir_get_next_directory(dir)) { en = dk3dir_get_fullname(dir); if(en) { dkwt_ev_permissions(j, en, 1); } } while(dk3dir_get_next_file(dir)) { en = dk3dir_get_fullname(dir); if(en) { dkwt_ev_permissions(j, en, 0); } } dk3dir_close(dir); } } $? "- dkwt_ev_permissions_public" } /** Do processing. @param j Job structure. */ static void dkwt_ev_do_processing(DKWT_EV_J *j) { $? "+ dkwt_ev_do_processing" switch(j->event) { case 0: { $? ". boot" if(!dkwt_ev_get_keep_value(j->app, j->msg, j->kwnl, 0)) { if(j->versMaj < 6) { dkwt_ev_cleanup_profiles(j); } dkwt_ev_cleanup_public(j); } } break; case 1: { $? ". shutdown" if(!dkwt_ev_get_keep_value(j->app, j->msg, j->kwnl, 0)) { if(j->versMaj < 6) { dkwt_ev_cleanup_profiles(j); } dkwt_ev_cleanup_public(j); } } break; case 2: { $? ". login" if(!dkwt_ev_get_keep_value(j->app, j->msg, j->kwnl, 1)) { if(j->versMaj < 6) { dkwt_ev_cleanup_profiles(j); } dkwt_ev_cleanup_public(j); } } break; case 3: { $? ". logout" if(j->versMaj < 6) { dkwt_ev_permissions_profile(j); } dkwt_ev_permissions_public(j); if(!dkwt_ev_get_keep_value(j->app, j->msg, j->kwnl, 0)) { if(j->versMaj < 6) { dkwt_ev_cleanup_profiles(j); } dkwt_ev_cleanup_public(j); } if(j->clp) { dkwt_clear_printers_local(j->app, j->msg, j->kwnl, j->userName); } if((j->s_queues) && (j->i_queues)) { dkwt_clear_printers_remote(j->app, j->msg, j->kwnl, j->userName, j->i_queues); } } break; case 4: { $? ". cleanup_profiles" dkwt_ev_cleanup_profiles(j); } break; } $? "- dkwt_ev_do_processing" } /** Find account name for a SID. @param j Job structure. @param dp Destination buffer. @param ind Index of string SID in message array. */ static void dkwt_find_account_name_for_sid( DKWT_EV_J *j, dkChar const * *dp, size_t ind ) { dkChar b1[DK3_MAX_PATH]; dkChar b2[DK3_MAX_PATH]; PSID psid; DWORD dwSz1; DWORD dwSz2; int success = 0; BOOL res; SID_NAME_USE sidNameUse; dwSz1 = DK3_SIZEOF(b1,dkChar); dwSz2 = DK3_SIZEOF(b2,dkChar); psid = NULL; #if DK3_CHAR_SIZE > 1 res = ConvertStringSidToSidW((j->kwnl)[ind], &psid); #else res = ConvertStringSidToSidA((j->kwnl)[ind], &psid); #endif if(res) { if(psid) { #if DK3_CHAR_SIZE > 1 res = LookupAccountSidW( NULL, psid, b1, &dwSz1, b2, &dwSz2, &sidNameUse ); #else res = LookupAccountSidA( NULL, psid, b1, &dwSz1, b2, &dwSz2, &sidNameUse ); #endif if(res) { if(dwSz1 > 0) { if(dwSz1 < DK3_SIZEOF(b1,dkChar)) { b1[dwSz1] = dkT('\0'); } else { b1[DK3_SIZEOF(b1,dkChar) - 1] = dkT('\0'); } if(dk3str_len(b1) > 0) { *dp = dk3str_dup_app(b1, NULL); if(*dp) { success = 1; } else { $? "! memory" j->exval = DKT_RESULT_ERR_MEMORY; } } else { $? "! size" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { $? "! Size" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { $? "! LookupAccountSid" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } LocalFree(psid); } else { $? "! NULL pointer" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { $? "! ConvertStringSidToSid" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } if(!(success)) { /* ERROR: Failed to find Group name for SID! */ dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 80, 81, (j->kwnl)[ind]); } } /** Complete account names for system and everyone user. @param j Job structure. */ static void dkwt_complete_account_names( DKWT_EV_J *j ) { if(!(j->systemUser)) { dkwt_find_account_name_for_sid(j, &(j->systemUser), 18); } if(!(j->everyUser)) { dkwt_find_account_name_for_sid(j, &(j->everyUser), 17); } } /** Run with a found configuration file name. Process the configuration file and call dkwt_ev_do_processing(). @param j Job structure. @param fn Configuration file name. */ static void dkwt_ev_run_with_config_file_name(DKWT_EV_J *j, dkChar const *fn) { dkChar bu[DK3_MAX_PATH]; dkwt_account_list_t *al; dkwt_account_t *ac; dkChar *p1; int ok = 0; $? "+ dkwt_ev_run_with_config_file_name" ok = dk3stream_process_filename_lines_app( (void *)j, dkwt_ev_line_handler, fn, bu, DK3_SIZEOF(bu,dkChar), dk3app_get_encoding(j->app), dk3app_get_input_file_encoding(j->app), j->app ); if(ok) { $? ". ok" dkwt_complete_account_names(j); al = dkwt_tool_open_account_list(j->app, 0); if(al) { $? ". al" dkwt_tool_reset_account_list(al); while((ac = dkwt_tool_get_account_from_list(al)) != NULL) { p1 = dk3str_dup_app(ac->logname, j->app); if(p1) { $? ". p1" if(!(dk3sto_add(j->s_users, (void *)p1))) { ok = 0; $? "! dk3sto_add" j->exval = DKT_RESULT_ERR_MEMORY; dk3_release(p1); } } else { $? "! p1" j->exval = DKT_RESULT_ERR_MEMORY; } } dkwt_tool_close_account_list(al); if(ok) { $? ". ok" dkwt_ev_do_processing(j); } else { $? "! ok" } } else { $? "! al" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { $? "! ok" } $? "- dkwt_ev_run_with_config_file_name" } /** Continue after allocating the storages. Find the users login name if necessary and one configuration file and call dkwt_ev_run_with_config_file_name(). @param j Job structure. */ static void dkwt_ev_run_with_storages(DKWT_EV_J *j) { dkChar bu[DK3_MAX_PATH]; /* Buffer for user name. */ dkChar const *fn; /* Configuration file name. */ dk3_search_t *sr; /* Search result. */ int ok = 1; /* Flag: OK so far. */ $? "+ dkwt_ev_run_with_storages" switch(j->event) { case 2: case 3: { ok = 0; if(dk3sf_get_logname_app(bu, DK3_SIZEOF(bu,dkChar), j->app)) { j->userName = dk3str_dup_app(bu, j->app); if(j->userName) { ok = 1; } else { j->exval = DKT_RESULT_ERR_MEMORY; } } else { j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } break; } if(ok) { $? ". ok" sr = dk3app_find_config_file_revers(j->app, (j->kwnl)[1], 1); if(sr) { $? ". sr" dk3search_reset(sr); fn = dk3search_next(sr); if(fn) { $? ". fn" dkwt_ev_run_with_config_file_name(j, fn); } else { $? "! fn" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } dk3search_close(sr); } else { $? "! sr" j->exval = DKT_RESULT_ERR_UNSPECIFIC; } } else { $? "! ok" } $? "- dkwt_ev_run_with_storages" } /** Run for event. Allocate the storages needed later und call dkwt_ev_run_with_storages(). @param j Job structure. */ static void dkwt_ev_run(DKWT_EV_J *j) { dkChar const * const *xargv; int xargc; $? "+ dkwt_ev_run" xargc = dk3app_get_argc(j->app); xargv = dk3app_get_argv(j->app); xargv++; xargv++; xargc--; xargc--; j->opt = dk3opt_open_app( dkwt_ev_options, dkwt_ev_szoptions, dkT('\0'), NULL, xargc, xargv, j->app ); if(j->opt) { if(0 == dk3opt_get_error_code(j->opt)) { if(dk3opt_is_set(j->opt, dkT('t'))) { j->testOnly = 1; } j->s_users = dk3sto_open_app(j->app); if(j->s_users) { dk3sto_set_comp(j->s_users, dkwt_ev_compare_string, 0); j->i_users = dk3sto_it_open(j->s_users); if(j->i_users) { j->s_pubdir= dk3sto_open_app(j->app); if(j->s_pubdir) { dk3sto_set_comp(j->s_pubdir, dkwt_ev_compare_string, 0); j->i_pubdir = dk3sto_it_open(j->s_pubdir); if(j->i_pubdir) { dkwt_ev_run_with_storages(j); } else { j->exval = DKT_RESULT_ERR_MEMORY; } } else { j->exval = DKT_RESULT_ERR_MEMORY; } } else { j->exval = DKT_RESULT_ERR_MEMORY; } } else { j->exval = DKT_RESULT_ERR_MEMORY; } } else { j->exval = DKT_RESULT_ERR_OPTION; } } else { j->exval = DKT_RESULT_ERR_OPTION; } $? "- dkwt_ev_run" } int dkwt_event( dk3_app_t *app, dkChar const * const *msg, dkChar const * const *kwnl, int evt ) { DKWT_EV_J j; int back = DKT_RESULT_ERR_UNSPECIFIC; $? "+ dkwt_event" dkwt_ev_job_init(&j); j.app = app; j.msg = msg; j.kwnl = kwnl; j.event = evt; back = j.exval = DKT_RESULT_OK; dkwt_ev_run(&j); back = j.exval; dkwt_ev_job_cleanup(&j); switch(evt) { case 0: case 1: case 2: case 3: { /* Always indicate success, otherwise Windows might shut down or log the user off. */ back = 0; } break; } $? "- dkwt_event" return back; } int dkwt_event_keep( dk3_app_t *app, dkChar const * const *msg, dkChar const * const *kwnl ) { int back = 1; long result; DWORD dw0; HKEY hk; DWORD dwDisp; DWORD dwType; DWORD dwValue; DWORD dwSize; dwDisp = 0L; dw0 = 0L; result = dkwt_tool_reg_create_key( HKEY_LOCAL_MACHINE, kwnl[15], dw0, (KEY_READ | KEY_SET_VALUE), &hk, &dwDisp ); if(result == ERROR_SUCCESS) { dw0 = 0L; dwType = REG_DWORD; dwValue = 1L; dwSize = sizeof(DWORD); result = dkwt_ev_reg_set_value( hk, kwnl[16], dwType, &dwValue, dwSize ); if(result == ERROR_SUCCESS) { back = 0; } } dk3sf_initialize_stdout(); if(back) { dk3sf_fputs(msg[77], stdout); } else { dk3sf_fputs(msg[78], stdout); } dk3sf_fputc(dkT('\n'), stdout); fflush(stdout); return back; } int dkwt_event_unkeep( dk3_app_t *app, dkChar const * const *msg, dkChar const * const *kwnl ) { (void)dkwt_ev_get_keep_value(app, msg, kwnl, 1); return 0; }