1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2011-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8 9%% module 10 11#include <libdk3c/dk3all.h> 12#include <dkwt/dkt.h> 13#include <dkwt/dkwt.h> 14#include <libdk3c/dk3unused.h> 15 16 17 18$!trace-include 19 20 21 22/** Job structure for dkwt boot/login/logout/shutdown. 23*/ 24typedef struct { 25 dk3_app_t *app; /**< Application structure. */ 26 dkChar const * const *msg; /**< Localized message texts. */ 27 dkChar const * const *kwnl; /**< Keywords, not localized. */ 28 dk3_option_set_t *opt; /**< Options set. */ 29 dkChar const *userName; /**< User name. */ 30 dkChar const *profBase; /**< Profile base directory. */ 31 dkChar const *systemUser; /**< System user account. */ 32 dkChar const *everyUser; /**< Everyone user account. */ 33 dk3_sto_t *s_users; /**< Storage users. */ 34 dk3_sto_it_t *i_users; /**< Iterator users. */ 35 dk3_sto_t *s_pubdir; /**< Storage public directories. */ 36 dk3_sto_it_t *i_pubdir; /**< Iterator public directories. */ 37 dk3_sto_t *s_queues; /**< Remote queues to clean up. */ 38 dk3_sto_it_t *i_queues; /**< Iterator for remote queues. */ 39 int exval; /**< Exit status code. */ 40 int event; /**< Event to process. */ 41 int curSection; /**< Current configuration file sect. */ 42 int useIcacls; /**< Flag: Use icalcs. */ 43 int clrProfiles; /**< Flag: Clean profiles automatically. */ 44 int testOnly; /**< Flag: Test only. */ 45 int clp; /**< Flag: Clean up local print queues. */ 46} DKWT_EV_J; 47 48 49/** Unknown section type. 50*/ 51#define DKWT_EV_SECTION_UNKNOWN (-1) 52 53/** In the options section. 54*/ 55#define DKWT_EV_SECTION_OPTIONS 0 56 57/** In the profiles section. 58*/ 59#define DKWT_EV_SECTION_PROFILES 1 60 61/** In the public directories section. 62*/ 63#define DKWT_EV_SECTION_PUBLIC 2 64 65 66 67/** Configuration file section names. 68*/ 69static dkChar const * const dkwt_ev_section_names[] = { 70$!string-table macro=dkT 71# 0 72options 73# 1 74profiles 75# 2 76public 77$!end 78}; 79 80 81 82/** Configuration file option names. 83*/ 84static dkChar const * const dkwt_ev_option_names[] = { 85$!string-table macro=dkT 86# 0 87system-user 88# 1 89everyone-user 90# 2 91print-jobs 92$!end 93}; 94 95 96 97/** Names of profiles to keep. 98*/ 99static dkChar const * const dkwt_ev_profiles_to_keep[] = { 100$!text macro=dkT 101All Users 102Default User 103Public 104LocalService 105NetworkService 106Administrator 107$!end 108}; 109 110 111 112/** Options. 113*/ 114static dk3_option_t const dkwt_ev_options[] = { 115 { dkT('t'), dkT("test"), 0 } 116}; 117 118/** Number of options in the dkwt_ev_options array. 119*/ 120static size_t const dkwt_ev_szoptions = 121sizeof(dkwt_ev_options)/sizeof(dk3_option_t); 122 123 124 125/** Print queue name for local printers. 126*/ 127static dkChar const dkwt_pq_name_local[] = { dkT("local") }; 128 129 130/** Retrieve value of keep flag. 131 @param kwnl Keywords, not localized. 132 @param reset Reset the flag. 133 @return Flag value (before reset). 134*/ 135static 136int 137dkwt_ev_get_keep_value( 138 dkChar const * const *kwnl, 139 int reset 140) 141{ 142 long result; 143#if VERSION_BEFORE_2019_10_20 144 DWORD dw0; 145#endif 146 DWORD dwType; 147 DWORD dwValue; 148 DWORD dwSz; 149 int back = 0; 150 HKEY hk; 151#if VERSION_BEFORE_2019_10_20 152 REGSAM regsam; 153#endif 154 155 $? "+ dkwt_ev_get_keep_value" 156#if VERSION_BEFORE_2019_10_20 157 dw0 = (DWORD)0; 158#endif 159 dwType = REG_DWORD; 160 dwValue = 0; 161 dwSz = sizeof(DWORD); 162#if VERSION_BEFORE_2019_10_20 163 /* 164 KEY_QUERY_VALUE is always used in the 165 dkwt_tool_reg_open_key() function call below. 166 */ 167 regsam = KEY_QUERY_VALUE; 168 if(reset) { 169 regsam = (KEY_READ | KEY_WRITE); 170 } 171#endif 172 result = dkwt_tool_reg_open_key( 173 HKEY_LOCAL_MACHINE, kwnl[15], KEY_QUERY_VALUE, &hk 174 ); 175 if(result == ERROR_SUCCESS) { 176 result = dkwt_tool_reg_query_value( 177 hk, kwnl[16], &dwType, &dwValue, &dwSz 178 ); 179 if(result == ERROR_SUCCESS) { 180 if(dwType == REG_DWORD) { 181 if(dwSz == sizeof(DWORD)) { 182 if(dwValue) { 183 back = 1; 184 } 185 } 186 } 187 } 188 if(reset) { 189 (void)dkwt_tool_reg_delete_value(hk, kwnl[16]); 190 } 191 RegCloseKey(hk); 192 } 193 $? "- dkwt_et_get_keep_value %d", back 194 return back; 195} 196 197 198 199/** Compare two strings. 200 @param l Left string. 201 @param r Right string. 202 @param cr Comparison criteria (ignored). 203 @return Comparison result. 204*/ 205static 206int 207dkwt_ev_compare_string(void const *l, void const *r, int DK3_ARG_UNUSED(cr)) 208{ 209 dkChar const *pl; 210 dkChar const *pr; 211 int back = 0; 212 DK3_UNUSED_ARG(cr) 213 if(l) { 214 if(r) { 215 pl = (dkChar const *)l; pr = (dkChar const *)r; 216 back = dk3str_casecmp(pl, pr); 217 } else { 218 back = 1; 219 } 220 } else { 221 if(r) { 222 back = -1; 223 } 224 } 225 if(back > 1) back = 1; 226 if(back < -1) back = -1; 227 return back; 228} 229 230 231 232/** Initialize job structure. 233 @param j Structure to initialize. 234*/ 235static 236void 237dkwt_ev_job_init(DKWT_EV_J *j) 238{ 239#if (!(_WIN32)) || (!(defined(_WIN32_WINNT))) || (_WIN32_WINNT < 0x0603) 240 OSVERSIONINFO ovi; 241#endif 242 243 j->app = NULL; j->msg = NULL; j->kwnl = NULL; 244 j->profBase = NULL; 245 j->userName = NULL; 246 j->systemUser = NULL; 247 j->everyUser = NULL; 248 j->s_users = NULL; j->i_users = NULL; 249 j->s_pubdir = NULL; j->i_pubdir = NULL; 250 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 251 j->curSection = -1; 252 j->useIcacls = 0; 253 j->testOnly = 0; 254 j->clp = 0; 255 j->opt = NULL; 256 j->s_queues = NULL; 257 j->i_queues = NULL; 258 j->clrProfiles = 0; 259#if (!(_WIN32)) || (!(defined(_WIN32_WINNT))) || (_WIN32_WINNT < 0x0603) 260 ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 261 ovi.dwMajorVersion = 0L; 262 ovi.dwMinorVersion = 0L; 263 ovi.dwBuildNumber = 0L; 264 ovi.dwPlatformId = 0L; 265 if(GetVersionEx(&ovi)) { 266 if(ovi.dwMajorVersion > 5) { 267 j->useIcacls = 1; $? ". icacls" 268 } else { 269 if(ovi.dwMajorVersion == 5) { 270 if(ovi.dwMinorVersion > 1) { 271 j->useIcacls = 1; $? ". icacls" 272 } 273 } 274 } 275 if(ovi.dwMajorVersion < 6) { 276 j->clrProfiles = 1; 277 } 278 } 279#else 280 if (!IsWindowsVistaOrGreater()) { 281 j->clrProfiles = 1; 282 } 283 if (IsWindowsXPOrGreater()) { 284 j->useIcacls = 1; 285 } 286#endif 287} 288 289 290 291/** Clean up job structure, release memory. 292 @param j Job structure. 293*/ 294static 295void 296dkwt_ev_job_cleanup(DKWT_EV_J *j) 297{ 298 dkChar *un; 299 void *vp; 300 if(j) { 301 if(j->s_queues) { 302 if(j->i_queues) { 303 dk3sto_it_reset(j->i_queues); 304 while(NULL != (vp = dk3sto_it_next(j->i_queues))) { 305 dk3_delete(vp); 306 } 307 dk3sto_it_close(j->i_queues); 308 } 309 dk3sto_close(j->s_queues); 310 } j->s_queues = NULL; j->i_queues = NULL; 311 if(j->s_users) { 312 if(j->i_users) { 313 dk3sto_it_reset(j->i_users); 314 while((un = (dkChar *)dk3sto_it_next(j->i_users)) != NULL) 315 { 316 dk3_release(un); 317 } 318 dk3sto_it_close(j->i_users); 319 } 320 dk3sto_close(j->s_users); 321 } j->s_users = NULL; j->i_users = NULL; 322 if(j->s_pubdir) { 323 if(j->i_pubdir) { 324 dk3sto_it_reset(j->i_pubdir); 325 while((un = (dkChar *)dk3sto_it_next(j->i_pubdir)) != NULL) 326 { 327 dk3_release(un); 328 } 329 dk3sto_it_close(j->i_pubdir); 330 } 331 dk3sto_close(j->s_pubdir); 332 } j->s_pubdir = NULL; j->i_pubdir = NULL; 333 dk3_release(j->profBase); 334 dk3_release(j->userName); 335 dk3_release(j->systemUser); 336 dk3_release(j->everyUser); 337 if(j->opt) { 338 dk3opt_close(j->opt); j->opt = NULL; 339 } 340 } 341} 342 343 344 345/** Handler for one input line. 346 @param obj Job structure. 347 @param il Input line to process. 348 @return 1 on success, 0 on recoverable error, -1 to abort processing. 349*/ 350static 351int 352dkwt_ev_line_handler(void *obj, dkChar *il) 353{ 354 DKWT_EV_J *j; 355 dkChar *p1; 356 dkChar *p2; 357 dkChar *p3; 358 dkChar *nq; 359 int back = 1; 360 $? "+ dkwt_ev_line_handler \"%!ds\"", TR_STR(il) 361 j = (DKWT_EV_J *)obj; 362 p1 = dk3str_start(il, NULL); 363 if(p1) { 364 if(*p1 != dkT('#')) { 365 back = -1; 366 dk3str_delnl(p1); 367 if(*p1 == dkT('[')) { /* New section header. */ 368 p1++; 369 p1 = dk3str_start(p1, NULL); 370 if(p1) { 371 j->curSection = DKWT_EV_SECTION_UNKNOWN; 372 p2 = dk3str_rchr(p1, dkT(']')); 373 if(p2) { 374 *p2 = dkT('\0'); 375 p2 = dk3str_next(p1, NULL); 376 switch(dk3str_array_index(dkwt_ev_section_names, p1, 0)) { 377 case 0: { 378 j->curSection = DKWT_EV_SECTION_OPTIONS; 379 back = 1; 380 } break; 381 case 1: { 382 j->curSection = DKWT_EV_SECTION_PROFILES; 383 if(p2) { 384 if(!(j->profBase)) { 385 j->profBase = dk3str_dup_app(p2, j->app); 386 if(j->profBase) { 387 back = 1; 388 } else { 389 back = -1; 390 j->exval = DKT_RESULT_ERR_MEMORY; 391 } 392 } else { 393 back = -1; 394 j->exval = DKT_RESULT_ERR_INPUT; 395 /* ERROR: Redefinition of profile base dir! */ 396 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 66); 397 } 398 } else { 399 j->exval = DKT_RESULT_ERR_INPUT; 400 /* ERROR: No profile base dir specified! */ 401 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 67); 402 } 403 } break; 404 case 2: { 405 j->curSection = DKWT_EV_SECTION_PUBLIC; back = 1; 406 } break; 407 default: { 408 back = -1; 409 j->exval = DKT_RESULT_ERR_INPUT; 410 /* ERROR: Unknown section type. */ 411 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 68); 412 } break; 413 } 414 } else { 415 back = -1; 416 /* ERROR: Incomplete section header. */ 417 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 69); 418 j->exval = DKT_RESULT_ERR_INPUT; 419 } 420 } else { 421 back = -1; 422 /* ERROR: No section header! */ 423 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 70); 424 j->exval = DKT_RESULT_ERR_INPUT; 425 } 426 } else { /* Section contents line. */ 427 switch(j->curSection) { 428 case DKWT_EV_SECTION_OPTIONS: { 429 p2 = dk3str_chr(p1, dkT('=')); 430 if(p2) { 431 *(p2++) = dkT('\0'); 432 p2 = dk3str_start(p2, NULL); 433 if(p2) { 434 /* dk3str_chomp(p1, NULL); */ 435 dk3str_normalize(p1, NULL, dkT('-')); 436#if 0 437 dk3str_normalize(p2, NULL, dkT('-')); 438#endif 439 switch(dk3str_array_index(dkwt_ev_option_names, p1, 0)) { 440 case 0: { 441 if(!(j->systemUser)) { 442 j->systemUser = dk3str_dup_app(p2, j->app); 443 if(j->systemUser) { 444 back = 1; 445 } else { 446 back = -1; 447 j->exval = DKT_RESULT_ERR_MEMORY; 448 } 449 } else { 450 /* ERROR: Redefinition of system user! */ 451 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 71); 452 back = -1; 453 j->exval = DKT_RESULT_ERR_INPUT; 454 } 455 } break; 456 case 1: { 457 if(!(j->everyUser)) { 458 j->everyUser = dk3str_dup_app(p2, j->app); 459 if(j->everyUser) { 460 back = 1; 461 } else { 462 back = -1; 463 j->exval = DKT_RESULT_ERR_MEMORY; 464 } 465 } else { 466 /* ERROR: Redefinition of everyone user! */ 467 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 72); 468 back = -1; 469 j->exval = DKT_RESULT_ERR_INPUT; 470 } 471 } break; 472 case 2: { 473 back = 1; 474 while(p2) { 475 p3 = dk3str_next(p2, NULL); 476 if(0 == dk3str_cmp(dkwt_pq_name_local, p2)) { 477 j->clp = 1; 478 } else { 479 if(!(j->s_queues)) { 480 j->s_queues = dk3sto_open_app(j->app); 481 } 482 if(!(j->i_queues)) { 483 if(j->s_queues) { 484 j->i_queues = dk3sto_it_open(j->s_queues); 485 } 486 } 487 if((j->s_queues) && (j->i_queues)) { 488 nq = dk3str_dup_app(p2, j->app); 489 if(nq) { 490 if(!dk3sto_add(j->s_queues, (void *)nq)) { 491 dk3_delete(nq); 492 back = 0; 493 } 494 } else { 495 back = 0; 496 } 497 } else { 498 back = 0; 499 } 500 } 501 p2 = p3; 502 } 503 } break; 504 default: { 505 /* ERROR: Unknown option! */ 506 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 73); 507 back = -1; 508 j->exval = DKT_RESULT_ERR_INPUT; 509 } break; 510 } 511 } else { 512 /* ERROR: Not a key/value pair */ 513 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 74); 514 back = -1; 515 j->exval = DKT_RESULT_ERR_INPUT; 516 } 517 } else { 518 /* ERROR: Not a key/value pair */ 519 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 74); 520 back = -1; 521 j->exval = DKT_RESULT_ERR_INPUT; 522 } 523 } break; 524 case DKWT_EV_SECTION_PROFILES: { $? ". add user name to list" 525 dk3str_normalize(p1, NULL, dkT(' ')); 526 p2 = dk3str_dup_app(p1, j->app); 527 if(p2) { 528 if(dk3sto_add(j->s_users, (void *)p2)) { 529 back = 1; $? ". added user name \"%!ds\"", TR_STR(p2) 530 } else { $? "! failed to add" 531 dk3_release(p2); 532 back = -1; 533 j->exval = DKT_RESULT_ERR_MEMORY; 534 } 535 } else { $? "! empty user name" 536 back = -1; 537 j->exval = DKT_RESULT_ERR_MEMORY; 538 } 539 } break; 540 case DKWT_EV_SECTION_PUBLIC: { $? ". add public dir to list" 541 dk3str_normalize(p1, NULL, dkT(' ')); 542 p2 = dk3str_dup_app(p1, j->app); 543 if(p2) { $? ". p2" 544 if(dk3sto_add(j->s_pubdir, (void *)p2)) { 545 back = 1; $? ". added" 546 } else { $? "! failed to add" 547 dk3_release(p2); 548 back = -1; 549 j->exval = DKT_RESULT_ERR_MEMORY; 550 } 551 } else { $? "! p2" 552 back = -1; 553 j->exval = DKT_RESULT_ERR_MEMORY; 554 } 555 } break; 556 default: { 557 back = -1; 558 j->exval = DKT_RESULT_ERR_INPUT; 559 } break; 560 } 561 } 562 } else { 563 /* Comment line ok. */ 564 } 565 } else { 566 /* Empty line ok. */ 567 } $? "- dkwt_ev_line_handler %d", back 568 return back; 569} 570 571 572 573/** Run a command. 574 @param j Job structure. 575 @param cmd Command to run. 576*/ 577static 578void 579dkwt_ev_execute_command(DKWT_EV_J *j, dkChar const *cmd) 580{ 581 int value = 0; 582 /* PROGRESS: Execute command ... */ 583 dk3app_log_3(j->app, DK3_LL_PROGRESS, j->msg, 118, 119, cmd); 584 dk3sf_initialize_stdout(); 585 dk3sf_fputs(cmd, stdout); 586 dk3sf_fputc(dkT('\n'), stdout); 587 if(!(j->testOnly)) { 588#if DK3_CHAR_SIZE > 1 589 value = _wsystem(cmd); 590#else 591 value = system(cmd); 592#endif 593 if(value != 0) { 594 /* ERROR: Command execution failed! */ 595 dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 79, 80, cmd); 596 j->exval = DKT_RESULT_ERR_SYSEXEC; 597 } 598 } 599} 600 601 602 603/** Remove a directory. 604 First attempt to use the RD command, next use own routines. 605 @param j Job structure. 606 @param dn Directory name. 607 @param dolog Flag: Do logging in dk3dir_remove_app(). 608*/ 609static 610void 611dkwt_ev_remove_directory(DKWT_EV_J *j, dkChar const *dn, int dolog) 612{ 613 dkChar bu[2 * DK3_MAX_PATH]; 614 dk3_stat_t stb; 615 size_t sz; 616 $? "+ dkwt_ev_remove_directory \"%ls\"", dn 617 /* PROGRESS: Remove directory ... */ 618 dk3app_log_3(j->app, DK3_LL_PROGRESS, j->msg, 120, 121, dn); 619 if(!(j->testOnly)) { 620#if 0 621 dk3sf_remove_dir(dn); 622#endif 623 dk3dir_remove_app(dn, ((dolog) ? j->app : NULL)); 624 if(dk3sf_stat_app(&stb, dn, NULL)) { 625 sz = dk3str_len(dn); 626 sz += dk3str_len((j->kwnl)[4]); 627 sz += dk3str_len((j->kwnl)[5]); 628 if(sz < DK3_SIZEOF(bu,dkChar)) { 629 dk3str_cpy_not_overlapped(bu, (j->kwnl)[4]); 630 dk3str_cat(bu, dn); 631 dk3str_cat(bu, (j->kwnl)[5]); 632 dkwt_ev_execute_command(j, bu); 633 } else { $? "! name too long" 634 /* ERROR: File name too long! */ 635 dk3app_log_i3(j->app, DK3_LL_ERROR, 59, 60, dn); 636 j->exval = DKT_RESULT_ERR_FILENAME; 637 } 638 } 639 } 640 $? "- dkwt_ev_remove_directory" 641} 642 643 644 645/** Remove a file. 646 First attempt to use the DEL command, next use own routines. 647 @param j Job structure. 648 @param fn File name. 649*/ 650static 651void 652dkwt_ev_remove_file(DKWT_EV_J *j, dkChar const *fn) 653{ 654 dkChar bu[2 * DK3_MAX_PATH]; 655 dk3_stat_t stb; 656 size_t sz; 657 658 /* PROGRESS: Remove file ... */ 659 dk3app_log_3(j->app, DK3_LL_PROGRESS, j->msg, 122, 123, fn); 660 if(!(j->testOnly)) { 661 dk3sf_remove_file_app(fn, NULL); 662 if(dk3sf_stat_app(&stb, fn, NULL)) { 663 sz = dk3str_len(fn); 664 sz += dk3str_len((j->kwnl)[6]); 665 sz += dk3str_len((j->kwnl)[5]); 666 if(sz < DK3_SIZEOF(bu,dkChar)) { 667 dk3str_cpy_not_overlapped(bu, (j->kwnl)[6]); 668 dk3str_cat(bu, fn); 669 dk3str_cat(bu, (j->kwnl)[5]); 670 dkwt_ev_execute_command(j, bu); 671 } else { 672 /* ERROR: File name too long! */ 673 dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); 674 j->exval = DKT_RESULT_ERR_FILENAME; 675 } 676 } 677 } 678} 679 680 681 682/** Check whether or not to keep a profile subdirectory. 683 @param j Job structure. 684 @param un User name (short directory name). 685 @return 1 to keep the directory, 0 to delete it. 686*/ 687static 688int 689dkwt_ev_must_keep(DKWT_EV_J *j, dkChar const *un) 690{ 691 int back = 0; 692 $? "+ dkwt_ev_must_keep" 693 if(j->userName) { 694 if(dk3str_casecmp(j->userName, un) == 0) { 695 back = 1; 696 } 697 } 698 if(!(back)) { 699 if(dk3sto_it_find_like(j->i_users, (void *)un, 0)) { 700 back = 1; 701 } 702 } 703 if(!(back)) { 704 if(dk3str_array_index(dkwt_ev_profiles_to_keep, un, 0) >= 0) { 705 back = 1; 706 } 707 } $? "- dkwt_ev_must_keep %d", back 708 return back; 709} 710 711 712 713#ifdef VERSION_BEFORE_20120320 714/** Clean up the profile directory. 715 @param j Job structure. 716*/ 717static 718void 719dkwt_ev_cleanup_profiles(DKWT_EV_J *j) 720{ 721 dkChar bu1[DK3_MAX_PATH]; 722 dk3_dir_t *dir; 723 dkChar const *en; 724 dkChar const *es; 725 dkChar *ptr; 726 int must_delete = 1; 727 $? "+ dkwt_ev_cleanup_profiles %d", must_delete 728 if(j->profBase) { 729 if(j->clrProfiles != 0) { 730 dir = dk3dir_open_app(j->profBase, j->app); 731 if(dir) { $? ". directory opened" 732 while(dk3dir_get_next_directory(dir)) { 733 en = dk3dir_get_fullname(dir); 734 es = dk3dir_get_shortname(dir); 735 if((en) && (es)) { $? ". entry \"%ls\"", es 736 must_delete = 1; 737 if(dkwt_ev_must_keep(j, es)) { 738 must_delete = 0; $? ". must keep" 739 } else { $? ". can delete" 740 if(dk3str_len(es) < DK3_SIZEOF(bu1,dkChar)) { 741 dk3str_cpy_not_overlapped(bu1, es); 742 ptr = dk3str_chr(bu1, dkT('.')); 743 if(ptr) { 744 *ptr = dkT('\0'); 745 if(dkwt_ev_must_keep(j, bu1)) { 746 must_delete = 0; $? ". must keep" 747 } else { $? ". can delete" 748 } 749 } else { $? ". no need to test again" 750 } 751 } else { $? "! name too long for test" 752 must_delete = 0; 753 } 754 } $? ". must_delete=%d", must_delete 755 if(must_delete) { $? ". must delete \"%ls\"", en 756 dkwt_ev_remove_directory(j, en, 0); 757 } 758 } 759 } 760 dk3dir_close(dir); 761 } 762 } else { 763 } 764 } 765 $? "- dkwt_ev_cleanup_profiles" 766} 767#else 768 769 770 771/** Directory entry for deletion. 772*/ 773typedef struct { 774 dkChar const *n; /**< Directory name. */ 775 char f; /**< Flag: Can delete. */ 776} DKWT_EV_DIR; 777 778 779 780/** Release directory name. 781 @param d Directory name entry to delete. 782*/ 783static 784void 785dkwt_ev_ddel_del(DKWT_EV_DIR *d) 786{ 787 if(d) { 788 dk3_release(d->n); 789 d->f = 0x00; 790 dk3_delete(d); 791 } 792} 793 794 795 796/** Create directory name entry. 797 @param j Job structure. 798 @param fn File name of directory. 799 @return New entry on success, NULL on error. 800*/ 801static 802DKWT_EV_DIR * 803dkwt_ev_ddel_new(DKWT_EV_J *j, dkChar const *fn) 804{ 805 DKWT_EV_DIR *back = NULL; 806 if(fn) { 807 back = dk3_new_app(DKWT_EV_DIR,1,j->app); 808 if(back) { 809 back->f = 0x01; 810 back->n = dk3str_dup_app(fn, j->app); 811 if(!(back->n)) { 812 dkwt_ev_ddel_del(back); 813 back = NULL; 814 } 815 } 816 } 817 return back; 818} 819 820 821 822/** Compare two entries for directories. 823 @param l Left directory object. 824 @param r Right directory object. 825 @param cr Comparison criteria (0=dir/dir, 1=dir/name). 826 @return Comparison result. 827*/ 828static 829int 830dkwt_ev_ddel_comp(void const *l, void const *r, int cr) 831{ 832 int back = 0; 833 DKWT_EV_DIR const *pl; 834 DKWT_EV_DIR const *pr; 835 if(l) { 836 if(r) { 837 pl = (DKWT_EV_DIR const *)l; 838 switch(cr) { 839 case 1: { 840 if(pl->n) { 841 back = dk3str_casecmp(pl->n, (dkChar const *)r); 842 if(back < -1) back = -1; 843 if(back > 1) back = 1; 844 } else back = -1; 845 } break; 846 default: { 847 pr = (DKWT_EV_DIR const *)r; 848 if(pl->n) { 849 if(pr->n) { 850 back = dk3str_casecmp(pl->n, pr->n); 851 if(back < -1) back = -1; 852 if(back > 1) back = 1; 853 } else back = 1; 854 } else { 855 if(pr->n) back = -1; 856 } 857 } break; 858 } 859 } else back = 1; 860 } else { 861 if(r) back = -1; 862 } 863 return back; 864} 865 866 867 868/** Delete a registry key structure for a user profile. 869 @param j Job structure. 870 @param kn Key name (short name). 871*/ 872static 873void 874dkwt_ev_del_rk_profile(DKWT_EV_J *j, dkChar const *kn) 875{ 876 HKEY hk; 877 long res; 878 $? "+ dkwt_ev_del_rk_profile \"%!ds\"", kn 879 /* 880 Log message 881 */ 882 /* PROGRESS: Deleting registry key ... */ 883 dk3app_log_5( 884 j->app, DK3_LL_PROGRESS, 885 j->msg, 124, 125, 126, (j->kwnl)[19], kn 886 ); 887 /* 888 Delete the key. 889 */ 890 if(!(j->testOnly)) { 891 res = dkwt_tool_reg_open_key( 892 HKEY_LOCAL_MACHINE, (j->kwnl)[19], KEY_ALL_ACCESS, &hk 893 ); 894 if(ERROR_SUCCESS == res) { $? ". parent key opened" 895 res = dkwt_tool_reg_delete_tree(hk, kn); 896 if(ERROR_SUCCESS == res) { $? ". deleted successfully" 897 /* DEBUG: Registry key ... deleted. */ 898 dk3app_log_3(j->app, DK3_LL_DEBUG, j->msg, 127, 128, kn); 899 } else { $? "! failed to delete" 900 /* ERROR: Failed to remove registry hierarchy ... */ 901 dk3app_log_5( 902 j->app, DK3_LL_ERROR, j->msg, 903 129, 130, 131, (j->kwnl)[19], kn 904 ); 905 } 906 RegCloseKey(hk); 907 } else { $? "! failed to open parent" 908 /* ERROR: Failed to open registry key ... */ 909 dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 132, 133, (j->kwnl)[19]); 910 } 911 } 912 $? "- dkwt_ev_del_rk_profile" 913} 914 915 916 917/** Clean up the profile directory. 918 @param j Job structure. 919*/ 920static 921void 922dkwt_ev_cleanup_profiles(DKWT_EV_J *j) 923{ 924 dkChar knb[DK3_MAX_PATH]; /* Buffer for key name. */ 925 dkChar ppb[DK3_MAX_PATH]; /* Profile path buffer. */ 926 dkChar esb[DK3_MAX_PATH]; /* Expanded string buffer. */ 927 dkChar bu1[DK3_MAX_PATH]; /* Buffer for full file name. */ 928 unsigned char *ptrppb; 929 void *vp; /* void pointer for cleanup. */ 930 dk3_sto_t *s_fn; /* Storage of directories to delete. */ 931 dk3_sto_it_t *i_fn; /* Iterator for directory storage. */ 932 dk3_sto_t *s_rk; /* Storage for registry keys. */ 933 dk3_sto_it_t *i_rk; /* Iterator for registry keys storage. */ 934 dk3_sto_t *s_rd; /* Storage for registry keys to delete. */ 935 dk3_sto_it_t *i_rd; /* Iterator for keys to delete. `*/ 936 dk3_dir_t *dir; /* Directory. */ 937 dkChar const *en; /* Entry name. */ 938 dkChar const *es; /* Short entry name. */ 939 dkChar const *kn; /* Current key name, copy. */ 940 dkChar *ptr; /* Pointer to dot in file name. */ 941 DKWT_EV_DIR *ddel; /* Directory to delete. */ 942 HKEY hk; /* Handle for registry key. */ 943#if VERSION_BEFORE_2019_10_20 944 REGSAM regs; /* Access type to registry key. */ 945#endif 946 long res; /* Result from operation. */ 947 size_t stlgt; /* String length. */ 948#if VERSION_BEFORE_2019_10_20 949 DWORD dw0; /* Used to open registry keys. */ 950#endif 951 DWORD dwInd; /* INdex of current key. */ 952 DWORD dwSz; /* Size of knb buffer. */ 953 DWORD dwEx; /* Result from string expansion. */ 954 DWORD dwTp; /* Result type. */ 955 int md; /* Flag: Must delete this entry. */ 956 int ec; /* Error code. */ 957 $? "+ dkwt_ev_cleanup_profiles" 958 ec = 0; 959 ptrppb = (unsigned char *)ppb; 960 if(j->profBase) { 961 /* PROGRESS: Cleanin up profiles (start) */ 962 dk3app_log_1(j->app, DK3_LL_PROGRESS, j->msg, 134); 963 s_fn = dk3sto_open_app(j->app); 964 if(s_fn) { 965 dk3sto_set_comp(s_fn, dkwt_ev_ddel_comp, 0); 966 i_fn = dk3sto_it_open(s_fn); 967 if(i_fn) { 968 s_rk = dk3sto_open_app(j->app); 969 if(s_rk) { 970 dk3sto_set_comp(s_rk, dkwt_ev_compare_string, 0); 971 i_rk = dk3sto_it_open(s_rk); 972 if(i_rk) { 973 s_rd = dk3sto_open_app(j->app); 974 if(s_rd) { 975 i_rd = dk3sto_it_open(s_rd); 976 if(i_rd) { 977 /* DEBUG: Storages ok. */ 978 dir = dk3dir_open_app(j->profBase, j->app); 979 if(dir) { 980 /* DEBUG: Directory opened successfully. */ 981 while(dk3dir_get_next_directory(dir)) { 982 en = dk3dir_get_fullname(dir); 983 es = dk3dir_get_shortname(dir); 984 if((en) && (es)) { $? ". entry \"%!ds\"", es 985 md = 1; 986 if(dkwt_ev_must_keep(j, es)) { 987 md = 0; 988 } else { 989 if(dk3str_len(es) < DK3_SIZEOF(bu1,dkChar)) { 990 dk3str_cpy_not_overlapped(bu1, es); 991 ptr = dk3str_chr(bu1, dkT('.')); 992 if(ptr) { 993 *ptr = dkT('\0'); 994 if(dkwt_ev_must_keep(j, bu1)) { 995 md = 0; 996 } 997 } 998 } else { $? "! name too long" 999 /* ERROR: Name too long! */ 1000 dk3app_log_i3(j->app, DK3_LL_ERROR, 59, 60, es); 1001 if(!(ec)) { ec = DK3_ERROR_TOO_LARGE; } 1002 md = 0; 1003 } 1004 } $? ". md = %d", md 1005 if(md) { 1006 ddel = dkwt_ev_ddel_new(j, en); 1007 if(ddel) { 1008 if(!dk3sto_add(s_fn, (void *)ddel)) { $? "! add" 1009 dkwt_ev_ddel_del(ddel); 1010 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1011 } 1012 } else { $? "! ddel_new" 1013 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1014 } 1015 } 1016 } else { $? "! bug" 1017 /* ERROR: Failed to obtain name for directory entry! */ 1018 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 135); 1019 if(!(ec)) { ec = DK3_ERROR_SYSTEM; } 1020 } 1021 } 1022 dk3dir_close(dir); 1023 /* 1024 Now search the registry keys 1025 */ 1026#if VERSION_BEFORE_2019_10_20 1027 dw0 = (DWORD)0; 1028#endif 1029#if VERSION_BEFORE_2019_10_20 1030 regs = KEY_READ; 1031#endif 1032 res = dkwt_tool_reg_open_key( 1033 HKEY_LOCAL_MACHINE, (j->kwnl)[19], KEY_READ, &hk 1034 ); 1035 if(ERROR_SUCCESS == res) { 1036 dwInd = 0; 1037 do { 1038 dwSz = DK3_SIZEOF(knb,dkChar); 1039 res = dkwt_tool_reg_enum_key( 1040 hk, dwInd, knb, &dwSz, NULL, NULL, NULL 1041 ); 1042 if(ERROR_SUCCESS == res) { 1043 if(dwSz > 0) { 1044 kn = dk3str_dup_app(knb, j->app); 1045 if(kn) { 1046 if(!dk3sto_add(s_rk, (void *)kn)) { $? "! add" 1047 dk3_delete(kn); 1048 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1049 } 1050 } else { $? "! strdup" 1051 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1052 } 1053 } 1054 } else { $? "! reg_enum_key" 1055 if(res != ERROR_NO_MORE_ITEMS) { 1056 if(!(ec)) { ec = DK3_ERROR_DURING_READ; } 1057 } 1058 } 1059 dwInd++; 1060 } while(res != ERROR_NO_MORE_ITEMS); 1061 RegCloseKey(hk); 1062 /* 1063 For each key found check whether ProfileImagePath is in s_fn. 1064 */ 1065 dk3sto_it_reset(i_rk); 1066 while(NULL != (kn = (dkChar const *)dk3sto_it_next(i_rk))) { 1067 stlgt = dk3str_len((j->kwnl)[19]); 1068 stlgt++; 1069 stlgt += dk3str_len(kn); 1070 if(stlgt < DK3_SIZEOF(knb,dkChar)) { 1071 dk3str_cpy_not_overlapped(knb, (j->kwnl)[19]); 1072 dk3str_cat(knb, (j->kwnl)[20]); 1073 dk3str_cat(knb, kn); 1074#if VERSION_BEFORE_2019_10_20 1075 dw0 = 0; 1076#endif 1077#if VERSION_BEFORE_2019_10_20 1078 regs = KEY_QUERY_VALUE; 1079#endif 1080 res = dkwt_tool_reg_open_key( 1081 HKEY_LOCAL_MACHINE, knb, KEY_QUERY_VALUE, &hk 1082 ); 1083 if(ERROR_SUCCESS == res) { 1084 dwTp = REG_EXPAND_SZ; 1085 dwSz = sizeof(ppb); 1086 res = dkwt_tool_reg_query_value( 1087 hk, (j->kwnl)[21], &dwTp, ppb, &dwSz 1088 ); 1089 if(ERROR_SUCCESS == res) { 1090#if DK3_CHAR_SIZE > 1 1091 if(dwSz < (sizeof(ppb) - 1)) { 1092 ptrppb[dwSz] = '\0'; 1093 ptrppb[dwSz+1] = '\0'; 1094 } else { 1095 ptrppb[DK3_SIZEOF(ppb,dkChar)-2] = '\0'; 1096 ptrppb[DK3_SIZEOF(ppb,dkChar)-1] = '\0'; 1097 } 1098#else 1099 if(dwSz < sizeof(ppb)) { 1100 ppb[dwSz] = '\0'; 1101 } else { 1102 ppb[sizeof(ppb)-1] = '\0'; 1103 } 1104#endif 1105 switch(dwTp) { 1106 case REG_SZ: { 1107 ddel = (DKWT_EV_DIR *)dk3sto_it_find_like( 1108 i_fn, (void *)ppb, 1 1109 ); 1110 if(ddel) { 1111 /* Save kn as registry key to delete */ 1112 if(!dk3sto_add(s_rd, (void *)kn)) { $? "! add" 1113 ddel->f = 0x00; 1114 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1115 } 1116 } 1117 } break; 1118 case REG_EXPAND_SZ: { 1119#if DK3_CHAR_SIZE > 1 1120 dwEx = ExpandEnvironmentStringsW( 1121 ppb, 1122 esb, 1123 DK3_SIZEOF(esb,dkChar) 1124 ); 1125#else 1126 dwEx = ExpandEnvironmentStringsA( 1127 ppb, 1128 esb, 1129 DK3_SIZEOF(esb,dkChar) 1130 ); 1131#endif 1132 if(dwEx > 0) { 1133 if(dwEx < DK3_SIZEOF(esb,dkChar)) { 1134 ddel = (DKWT_EV_DIR *)dk3sto_it_find_like( 1135 i_fn, (void *)esb, 1 1136 ); 1137 if(ddel) { 1138 /* Save kn as registry key to delete */ 1139 if(!dk3sto_add(s_rd,(void *)kn)) { $? "! add" 1140 ddel->f = 0x00; 1141 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1142 } 1143 } 1144 } else { $? "! ExpandEnvironmentStrings" 1145 /* ERROR: String too long! */ 1146 dk3app_log_3( 1147 j->app, DK3_LL_ERROR, j->msg, 1148 136, 137, ppb 1149 ); 1150 if(!(ec)) { ec = DK3_ERROR_TOO_LARGE; } 1151 } 1152 } else { 1153 ddel = (DKWT_EV_DIR *)dk3sto_it_find_like( 1154 i_fn, (void *)ppb, 1 1155 ); 1156 if(ddel) { 1157 /* Save kn as registry key to delete */ 1158 if(!dk3sto_add(s_rd, (void *)kn)) { $? "! add" 1159 ddel->f = 0x00; 1160 if(!(ec)) { ec = DK3_ERROR_MEMORY; } 1161 } 1162 } 1163 } 1164 } break; 1165 } 1166 } 1167 RegCloseKey(hk); 1168 } else { $? "! registry open key" 1169 /* ERROR: Failed to open registry key ... */ 1170 dk3app_log_3( 1171 j->app, DK3_LL_ERROR, j->msg, 132, 133, knb 1172 ); 1173 if(!(ec)) { ec = DK3_ERROR_NOT_OPENED_FOR_READING; } 1174 } 1175 } else { $? "! key name too long \"%!ds\"", kn 1176 /* ERROR: Key name too long! */ 1177 dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 138, 139, kn); 1178 if(!(ec)) { ec = DK3_ERROR_TOO_LARGE; } 1179 } 1180 } 1181 } else { $? "! failed to open registry key" 1182 /* ERROR: Failed to open registry key! */ 1183 dk3app_log_3( 1184 j->app, DK3_LL_ERROR, j->msg, 132, 133, (j->kwnl)[19] 1185 ); 1186 if(!(ec)) { ec = DK3_ERROR_NOT_OPENED_FOR_READING; } 1187 } 1188 } else { $? "! dir" 1189 } 1190 if(!(ec)) { $? ". no error, delete registry keys" 1191 dk3sto_it_reset(i_rd); 1192 while(NULL != (kn = (dkChar const *)dk3sto_it_next(i_rd))) { 1193 /* 1194 */ 1195 dkwt_ev_del_rk_profile(j, kn); 1196 } 1197 } else { 1198 /* ERROR: Skipping profile cleanup due to previous errors! */ 1199 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 140); 1200 } 1201 /* 1202 In s_rd and i_rd we have copies of strings from s_rk and i_rk. 1203 No deletion necessary. 1204 */ 1205 dk3sto_it_close(i_rd); 1206 } else { $? "! i_rd" 1207 } 1208 dk3sto_close(s_rd); 1209 } else { $? "! s_rd" 1210 } 1211 dk3sto_it_reset(i_rk); 1212 while(NULL != (vp = dk3sto_it_next(i_rk))) { 1213 dk3_delete(vp); 1214 } 1215 dk3sto_it_close(i_rk); 1216 } else { $? "! i_rk" 1217 } 1218 dk3sto_close(s_rk); 1219 } else { $? "! s_rk" 1220 } 1221 dk3sto_it_reset(i_fn); 1222 while(NULL != (ddel = (DKWT_EV_DIR *)dk3sto_it_next(i_fn))) { 1223 /* 1224 Remove the directory. 1225 */ 1226 if(!(ec)) { 1227 if(ddel->f) { 1228 dkwt_ev_remove_directory(j, ddel->n, 0); 1229 } 1230 } 1231 /* 1232 Free list entry. 1233 */ 1234 dkwt_ev_ddel_del(ddel); 1235 } 1236 dk3sto_it_close(i_fn); i_fn = NULL; 1237 } else { $? "! i_fn" 1238 } 1239 dk3sto_close(s_fn); s_fn = NULL; 1240 } else { $? "! s_fn" 1241 } 1242 /* PROGRESS: Cleaning up profiles (finished). */ 1243 dk3app_log_1(j->app, DK3_LL_PROGRESS, j->msg, 141); 1244 } else { $? ". no profile base configured" 1245 } 1246 $? "- dkwt_ev_cleanup_profiles" 1247} 1248 1249 1250#endif 1251 1252 1253 1254/** Clean up public directories. 1255 @param j Job structure. 1256*/ 1257static 1258void 1259dkwt_ev_cleanup_public(DKWT_EV_J *j) 1260{ 1261 dkChar const *fn; 1262 dkChar const *en; 1263 dk3_dir_t *dir; 1264 $? "+ dkwt_ev_cleanup_public" 1265 dk3sto_it_reset(j->i_pubdir); 1266 while((fn = (dkChar const *)dk3sto_it_next(j->i_pubdir)) != NULL) { 1267 dir = dk3dir_open_app(fn, j->app); 1268 if(dir) { 1269 while(dk3dir_get_next_directory(dir)) { 1270 en = dk3dir_get_fullname(dir); 1271 if(en) { 1272 dkwt_ev_remove_directory(j, en, 1); 1273 } 1274 } 1275 while(dk3dir_get_next_file(dir)) { 1276 en = dk3dir_get_fullname(dir); 1277 if(en) { 1278 dkwt_ev_remove_file(j, en); 1279 } 1280 } 1281 dk3dir_close(dir); 1282 } 1283 } 1284 $? "- dkwt_ev_cleanup_public" 1285} 1286 1287 1288 1289/** Change permissions for one path. 1290 @param j Job structure. 1291 @param fn File name. 1292 @param un User name. 1293 @param isdir Flag: Is directory. 1294*/ 1295static 1296void 1297dkwt_ev_user_permissions( 1298 DKWT_EV_J *j, dkChar const *fn, dkChar const *un, int isdir 1299) 1300{ 1301 dkChar bu[2 * DK3_MAX_PATH]; 1302 size_t sz = 0; 1303 $? "+ dkwt_ev_user_permissions" 1304 if(j->useIcacls) { 1305 if(isdir) { 1306 sz = dk3str_len((j->kwnl)[10]); 1307 sz += dk3str_len(fn); 1308 sz += dk3str_len((j->kwnl)[11]); 1309 sz += dk3str_len(un); 1310 sz += dk3str_len((j->kwnl)[12]); 1311 if(sz < DK3_SIZEOF(bu,dkChar)) { 1312 dk3str_cpy_not_overlapped(bu, (j->kwnl)[10]); 1313 dk3str_cat(bu, fn); 1314 dk3str_cat(bu, (j->kwnl)[11]); 1315 dk3str_cat(bu, un); 1316 dk3str_cat(bu, (j->kwnl)[12]); 1317 dkwt_ev_execute_command(j, bu); 1318 } else { 1319 /* ERROR: Line too long! */ 1320 dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); 1321 j->exval = DKT_RESULT_ERR_FILENAME; 1322 } 1323 } else { 1324 sz = dk3str_len((j->kwnl)[10]); 1325 sz += dk3str_len(fn); 1326 sz += dk3str_len((j->kwnl)[11]); 1327 sz += dk3str_len(un); 1328 sz += dk3str_len((j->kwnl)[13]); 1329 if(sz < DK3_SIZEOF(bu,dkChar)) { 1330 dk3str_cpy_not_overlapped(bu, (j->kwnl)[10]); 1331 dk3str_cat(bu, fn); 1332 dk3str_cat(bu, (j->kwnl)[11]); 1333 dk3str_cat(bu, un); 1334 dk3str_cat(bu, (j->kwnl)[13]); 1335 dkwt_ev_execute_command(j, bu); 1336 } else { 1337 /* ERROR: Line too long! */ 1338 dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); 1339 j->exval = DKT_RESULT_ERR_FILENAME; 1340 } 1341 } 1342 } else { 1343 if(isdir) { 1344 sz = dk3str_len((j->kwnl)[7]); 1345 sz += dk3str_len(fn); 1346 sz += dk3str_len((j->kwnl)[8]); 1347 sz += dk3str_len(un); 1348 sz += dk3str_len((j->kwnl)[9]); 1349 if(sz < DK3_SIZEOF(bu,dkChar)) { 1350 dk3str_cpy_not_overlapped(bu, (j->kwnl)[7]); 1351 dk3str_cat(bu, fn); 1352 dk3str_cat(bu, (j->kwnl)[8]); 1353 dk3str_cat(bu, un); 1354 dk3str_cat(bu, (j->kwnl)[9]); 1355 dkwt_ev_execute_command(j, bu); 1356 } else { 1357 /* ERROR: Line too long! */ 1358 dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); 1359 j->exval = DKT_RESULT_ERR_FILENAME; 1360 } 1361 } else { 1362 sz = dk3str_len((j->kwnl)[7]); 1363 sz += dk3str_len(fn); 1364 sz += dk3str_len((j->kwnl)[14]); 1365 sz += dk3str_len(un); 1366 sz += dk3str_len((j->kwnl)[9]); 1367 if(sz < DK3_SIZEOF(bu,dkChar)) { 1368 dk3str_cpy_not_overlapped(bu, (j->kwnl)[7]); 1369 dk3str_cat(bu, fn); 1370 dk3str_cat(bu, (j->kwnl)[14]); 1371 dk3str_cat(bu, un); 1372 dk3str_cat(bu, (j->kwnl)[9]); 1373 dkwt_ev_execute_command(j, bu); 1374 } else { 1375 /* ERROR: Line too long! */ 1376 dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); 1377 j->exval = DKT_RESULT_ERR_FILENAME; 1378 } 1379 } 1380 } 1381 $? "- dkwt_ev_user_permissions" 1382} 1383 1384 1385 1386/** Change permissions for one path. 1387 @param j Job structure. 1388 @param fn File name. 1389 @param isdir Flag: Is directory. 1390*/ 1391static 1392void 1393dkwt_ev_permissions(DKWT_EV_J *j, dkChar const *fn, int isdir) 1394{ 1395 $? "+ dkwt_ev_permissions" 1396 if(j->systemUser) { 1397 dkwt_ev_user_permissions(j, fn, j->systemUser, isdir); 1398 } else { 1399 dkwt_ev_user_permissions(j, fn, (j->kwnl)[2], isdir); 1400 } 1401 if(j->everyUser) { 1402 dkwt_ev_user_permissions(j, fn, j->everyUser, isdir); 1403 } else { 1404 dkwt_ev_user_permissions(j, fn, (j->kwnl)[3], isdir); 1405 } 1406 $? "- dkwt_ev_permissions" 1407} 1408 1409 1410 1411/** Change permissions to own profile, grant full access 1412 to system and everyone. 1413 @param j Job structure. 1414*/ 1415static 1416void 1417dkwt_ev_permissions_profile(DKWT_EV_J *j) 1418{ 1419 dkChar bu[DK3_MAX_PATH]; 1420 size_t sz; 1421 $? "+ dkwt_ev_permissions_profile" 1422 if((j->profBase) && (j->userName)) { 1423 sz = dk3str_len(j->profBase); 1424 sz += dk3str_len(j->userName); 1425 sz += 1; 1426 if(sz < DK3_SIZEOF(bu,dkChar)) { 1427 dk3str_cpy_not_overlapped(bu, j->profBase); 1428 dk3str_cat(bu, dk3app_not_localized(20)); 1429 dk3str_cat(bu, j->userName); 1430 dkwt_ev_permissions(j, bu, 1); 1431 } 1432 } 1433 $? "- dkwt_ev_permissions_profile" 1434} 1435 1436 1437 1438/** Change permissions to public directory contents, grant full 1439 access to system and everyone. 1440 @param j Job structure. 1441*/ 1442static 1443void 1444dkwt_ev_permissions_public(DKWT_EV_J *j) 1445{ 1446 dkChar const *fn; 1447 dkChar const *en; 1448 dk3_dir_t *dir; 1449 $? "+ dkwt_ev_permissions_public" 1450 dk3sto_it_reset(j->i_pubdir); 1451 while((fn = (dkChar const *)dk3sto_it_next(j->i_pubdir)) != NULL) { 1452 dir = dk3dir_open_app(fn, j->app); 1453 if(dir) { 1454 while(dk3dir_get_next_directory(dir)) { 1455 en = dk3dir_get_fullname(dir); 1456 if(en) { 1457 dkwt_ev_permissions(j, en, 1); 1458 } 1459 } 1460 while(dk3dir_get_next_file(dir)) { 1461 en = dk3dir_get_fullname(dir); 1462 if(en) { 1463 dkwt_ev_permissions(j, en, 0); 1464 } 1465 } 1466 dk3dir_close(dir); 1467 } 1468 } 1469 $? "- dkwt_ev_permissions_public" 1470} 1471 1472 1473 1474/** Do processing. 1475 @param j Job structure. 1476*/ 1477static 1478void 1479dkwt_ev_do_processing(DKWT_EV_J *j) 1480{ 1481 $? "+ dkwt_ev_do_processing" 1482 switch(j->event) { 1483 case 0: { $? ". boot" 1484 if(!dkwt_ev_get_keep_value(j->kwnl, 0)) { 1485 if(j->clrProfiles != 0) { 1486 dkwt_ev_cleanup_profiles(j); 1487 } 1488 dkwt_ev_cleanup_public(j); 1489 } 1490 } break; 1491 case 1: { $? ". shutdown" 1492 if(!dkwt_ev_get_keep_value(j->kwnl, 0)) { 1493 if(j->clrProfiles != 0) { 1494 dkwt_ev_cleanup_profiles(j); 1495 } 1496 dkwt_ev_cleanup_public(j); 1497 } 1498 } break; 1499 case 2: { $? ". login" 1500 if(!dkwt_ev_get_keep_value(j->kwnl, 1)) { 1501 if(j->clrProfiles != 0) { 1502 dkwt_ev_cleanup_profiles(j); 1503 } 1504 dkwt_ev_cleanup_public(j); 1505 } 1506 } break; 1507 case 3: { $? ". logout" 1508 if(j->clrProfiles != 0) { 1509 dkwt_ev_permissions_profile(j); 1510 } 1511 dkwt_ev_permissions_public(j); 1512 if(!dkwt_ev_get_keep_value(j->kwnl, 0)) { 1513 if(j->clrProfiles != 0) { 1514 dkwt_ev_cleanup_profiles(j); 1515 } 1516 dkwt_ev_cleanup_public(j); 1517 } 1518 if(j->clp) { 1519 dkwt_clear_printers_local(j->app, j->msg, j->kwnl, j->userName); 1520 } 1521 if((j->s_queues) && (j->i_queues)) { 1522 dkwt_clear_printers_remote(j->app, j->msg, j->kwnl, j->userName, j->i_queues); 1523 } 1524 } break; 1525 case 4: { $? ". cleanup_profiles" 1526 if (1 == dkwt_is_admin()) { 1527 dkwt_ev_cleanup_profiles(j); 1528 } else { 1529 dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 145); 1530 } 1531 } break; 1532 } 1533 $? "- dkwt_ev_do_processing" 1534} 1535 1536 1537 1538/** Find account name for a SID. 1539 @param j Job structure. 1540 @param dp Destination buffer. 1541 @param ind Index of string SID in message array. 1542*/ 1543static 1544void 1545dkwt_find_account_name_for_sid( 1546 DKWT_EV_J *j, 1547 dkChar const * *dp, 1548 size_t ind 1549) 1550{ 1551 dkChar b1[DK3_MAX_PATH]; 1552 dkChar b2[DK3_MAX_PATH]; 1553 PSID psid; 1554 DWORD dwSz1; 1555 DWORD dwSz2; 1556 int success = 0; 1557 BOOL res; 1558 SID_NAME_USE sidNameUse; 1559 1560 dwSz1 = DK3_SIZEOF(b1,dkChar); 1561 dwSz2 = DK3_SIZEOF(b2,dkChar); 1562 psid = NULL; 1563#if DK3_CHAR_SIZE > 1 1564 res = ConvertStringSidToSidW((j->kwnl)[ind], &psid); 1565#else 1566 res = ConvertStringSidToSidA((j->kwnl)[ind], &psid); 1567#endif 1568 if(res) { 1569 if(psid) { 1570#if DK3_CHAR_SIZE > 1 1571 res = LookupAccountSidW( 1572 NULL, 1573 psid, 1574 b1, 1575 &dwSz1, 1576 b2, 1577 &dwSz2, 1578 &sidNameUse 1579 ); 1580#else 1581 res = LookupAccountSidA( 1582 NULL, 1583 psid, 1584 b1, 1585 &dwSz1, 1586 b2, 1587 &dwSz2, 1588 &sidNameUse 1589 ); 1590#endif 1591 if(res) { 1592 if(dwSz1 > 0) { 1593 if(dwSz1 < DK3_SIZEOF(b1,dkChar)) { 1594 b1[dwSz1] = dkT('\0'); 1595 } else { 1596 b1[DK3_SIZEOF(b1,dkChar) - 1] = dkT('\0'); 1597 } 1598 if(dk3str_len(b1) > 0) { 1599 *dp = dk3str_dup_app(b1, NULL); 1600 if(*dp) { 1601 success = 1; 1602 } else { $? "! memory" 1603 j->exval = DKT_RESULT_ERR_MEMORY; 1604 } 1605 } else { $? "! size" 1606 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1607 } 1608 } else { $? "! Size" 1609 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1610 } 1611 } else { $? "! LookupAccountSid" 1612 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1613 } 1614 LocalFree(psid); 1615 } else { $? "! NULL pointer" 1616 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1617 } 1618 } else { $? "! ConvertStringSidToSid" 1619 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1620 } 1621 if(!(success)) { 1622 /* ERROR: Failed to find Group name for SID! */ 1623 dk3app_log_3(j->app, DK3_LL_ERROR, j->msg, 80, 81, (j->kwnl)[ind]); 1624 } 1625} 1626 1627 1628 1629/** Complete account names for system and everyone user. 1630 @param j Job structure. 1631*/ 1632static 1633void 1634dkwt_complete_account_names( 1635 DKWT_EV_J *j 1636) 1637{ 1638 if(!(j->systemUser)) { 1639 dkwt_find_account_name_for_sid(j, &(j->systemUser), 18); 1640 } 1641 if(!(j->everyUser)) { 1642 dkwt_find_account_name_for_sid(j, &(j->everyUser), 17); 1643 } 1644} 1645 1646 1647 1648/** Run with a found configuration file name. 1649 Process the configuration file and call dkwt_ev_do_processing(). 1650 @param j Job structure. 1651 @param fn Configuration file name. 1652*/ 1653static 1654void 1655dkwt_ev_run_with_config_file_name(DKWT_EV_J *j, dkChar const *fn) 1656{ 1657 dkChar bu[DK3_MAX_PATH]; 1658 dkwt_account_list_t *al; 1659 dkwt_account_t *ac; 1660 dkChar *p1; 1661 int ok = 0; 1662 $? "+ dkwt_ev_run_with_config_file_name" 1663 ok = dk3stream_process_filename_lines_app( 1664 (void *)j, 1665 dkwt_ev_line_handler, 1666 fn, 1667 bu, 1668 DK3_SIZEOF(bu,dkChar), 1669 dk3app_get_encoding(j->app), 1670 dk3app_get_input_file_encoding(j->app), 1671 j->app 1672 ); 1673 if(ok) { $? ". ok" 1674 dkwt_complete_account_names(j); 1675 al = dkwt_tool_open_account_list(j->app, 0); 1676 if(al) { $? ". al" 1677 dkwt_tool_reset_account_list(al); 1678 while((ac = dkwt_tool_get_account_from_list(al)) != NULL) { 1679 p1 = dk3str_dup_app(ac->logname, j->app); 1680 if(p1) { $? ". p1" 1681 if(!(dk3sto_add(j->s_users, (void *)p1))) { 1682 ok = 0; $? "! dk3sto_add" 1683 j->exval = DKT_RESULT_ERR_MEMORY; 1684 dk3_release(p1); 1685 } 1686 } else { $? "! p1" 1687 j->exval = DKT_RESULT_ERR_MEMORY; 1688 } 1689 } 1690 dkwt_tool_close_account_list(al); 1691 if(ok) { $? ". ok" 1692 dkwt_ev_do_processing(j); 1693 } else { $? "! ok" 1694 } 1695 } else { $? "! al" 1696 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1697 } 1698 } else { $? "! ok" 1699 } $? "- dkwt_ev_run_with_config_file_name" 1700} 1701 1702 1703 1704/** Continue after allocating the storages. 1705 Find the users login name if necessary and one configuration file 1706 and call dkwt_ev_run_with_config_file_name(). 1707 @param j Job structure. 1708*/ 1709static 1710void 1711dkwt_ev_run_with_storages(DKWT_EV_J *j) 1712{ 1713 dkChar bu[DK3_MAX_PATH]; /* Buffer for user name. */ 1714 dkChar const *fn; /* Configuration file name. */ 1715 dk3_search_t *sr; /* Search result. */ 1716 int ok = 1; /* Flag: OK so far. */ 1717 $? "+ dkwt_ev_run_with_storages" 1718 switch(j->event) { 1719 case 2: case 3: { 1720 ok = 0; 1721 if(dk3sf_get_logname_app(bu, DK3_SIZEOF(bu,dkChar), j->app)) { 1722 j->userName = dk3str_dup_app(bu, j->app); 1723 if(j->userName) { 1724 ok = 1; 1725 } else { 1726 j->exval = DKT_RESULT_ERR_MEMORY; 1727 } 1728 } else { 1729 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1730 } 1731 } break; 1732 } 1733 if(ok) { $? ". ok" 1734 sr = dk3app_find_config_file_revers(j->app, (j->kwnl)[1], 1); 1735 if(sr) { $? ". sr" 1736 dk3search_reset(sr); 1737 fn = dk3search_next(sr); 1738 if(fn) { $? ". fn" 1739 dkwt_ev_run_with_config_file_name(j, fn); 1740 } else { $? "! fn" 1741 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1742 } 1743 dk3search_close(sr); 1744 } else { $? "! sr" 1745 j->exval = DKT_RESULT_ERR_UNSPECIFIC; 1746 } 1747 } else { $? "! ok" 1748 } $? "- dkwt_ev_run_with_storages" 1749} 1750 1751 1752 1753/** Run for event. 1754 Allocate the storages needed later und call dkwt_ev_run_with_storages(). 1755 @param j Job structure. 1756*/ 1757static 1758void 1759dkwt_ev_run(DKWT_EV_J *j) 1760{ 1761 dkChar const * const *xargv; 1762 int xargc; 1763 $? "+ dkwt_ev_run" 1764 xargc = dk3app_get_argc(j->app); 1765 xargv = dk3app_get_argv(j->app); 1766 xargv++; xargv++; xargc--; xargc--; 1767 j->opt = dk3opt_open_app( 1768 dkwt_ev_options, 1769 dkwt_ev_szoptions, 1770 dkT('\0'), 1771 NULL, 1772 xargc, 1773 xargv, 1774 j->app 1775 ); 1776 if(j->opt) { 1777 if(0 == dk3opt_get_error_code(j->opt)) { 1778 if(dk3opt_is_set(j->opt, dkT('t'))) { 1779 j->testOnly = 1; 1780 } 1781 j->s_users = dk3sto_open_app(j->app); 1782 if(j->s_users) { 1783 dk3sto_set_comp(j->s_users, dkwt_ev_compare_string, 0); 1784 j->i_users = dk3sto_it_open(j->s_users); 1785 if(j->i_users) { 1786 j->s_pubdir= dk3sto_open_app(j->app); 1787 if(j->s_pubdir) { 1788 dk3sto_set_comp(j->s_pubdir, dkwt_ev_compare_string, 0); 1789 j->i_pubdir = dk3sto_it_open(j->s_pubdir); 1790 if(j->i_pubdir) { 1791 dkwt_ev_run_with_storages(j); 1792 } else { 1793 j->exval = DKT_RESULT_ERR_MEMORY; 1794 } 1795 } else { 1796 j->exval = DKT_RESULT_ERR_MEMORY; 1797 } 1798 } else { 1799 j->exval = DKT_RESULT_ERR_MEMORY; 1800 } 1801 } else { 1802 j->exval = DKT_RESULT_ERR_MEMORY; 1803 } 1804 } else { 1805 j->exval = DKT_RESULT_ERR_OPTION; 1806 } 1807 } else { 1808 j->exval = DKT_RESULT_ERR_OPTION; 1809 } 1810 $? "- dkwt_ev_run" 1811} 1812 1813 1814 1815int 1816dkwt_event( 1817 dk3_app_t *app, 1818 dkChar const * const *msg, 1819 dkChar const * const *kwnl, 1820 int evt 1821) 1822{ 1823 DKWT_EV_J j; 1824 int back = DKT_RESULT_ERR_UNSPECIFIC; 1825 $? "+ dkwt_event" 1826 dkwt_ev_job_init(&j); 1827 j.app = app; j.msg = msg; j.kwnl = kwnl; j.event = evt; 1828 back = j.exval = DKT_RESULT_OK; 1829 dkwt_ev_run(&j); 1830 back = j.exval; 1831 dkwt_ev_job_cleanup(&j); 1832 switch(evt) { 1833 case 0: case 1: case 2: case 3: { 1834 /* 1835 Always indicate success, otherwise Windows might shut down 1836 or log the user off. 1837 */ 1838 back = 0; 1839 } break; 1840 } 1841 $? "- dkwt_event" 1842 return back; 1843} 1844 1845 1846 1847int 1848dkwt_event_keep( 1849 dk3_app_t *app, 1850 dkChar const * const *msg, 1851 dkChar const * const *kwnl 1852) 1853{ 1854 int back = 1; 1855 long result; 1856 DWORD dw0; 1857 HKEY hk; 1858 DWORD dwDisp; 1859 DWORD dwType; 1860 DWORD dwValue; 1861 DWORD dwSize; 1862 1863 dwDisp = 0L; 1864 dw0 = 0L; 1865 1866 result = dkwt_tool_reg_create_key( 1867 HKEY_LOCAL_MACHINE, kwnl[15], dw0, 1868 (KEY_READ | KEY_SET_VALUE), &hk, &dwDisp 1869 ); 1870 if(result == ERROR_SUCCESS) { 1871 dw0 = 0L; 1872 dwType = REG_DWORD; 1873 dwValue = 1L; 1874 dwSize = sizeof(DWORD); 1875 result = dkwt_ev_reg_set_value( 1876 hk, kwnl[16], dwType, &dwValue, dwSize 1877 ); 1878 if(result == ERROR_SUCCESS) { 1879 back = 0; 1880 } 1881 } 1882 dk3sf_initialize_stdout(); 1883 if(back) { 1884 dk3app_log_1(app, DK3_LL_ERROR, msg, 77); 1885 if (1 != dkwt_is_admin()) { 1886 dk3app_log_1(app, DK3_LL_ERROR, msg, 145); 1887 } 1888 } else { 1889 dk3sf_fputs(msg[78], stdout); 1890 } 1891 dk3sf_fputc(dkT('\n'), stdout); 1892 fflush(stdout); 1893 return back; 1894} 1895 1896 1897 1898int 1899dkwt_event_unkeep( 1900 dk3_app_t * DK3_ARG_UNUSED(app), 1901 dkChar const * const * DK3_ARG_UNUSED(msg), 1902 dkChar const * const *kwnl 1903) 1904{ 1905 DK3_UNUSED_ARG(app) 1906 DK3_UNUSED_ARG(msg) 1907 (void)dkwt_ev_get_keep_value(kwnl, 1); 1908 return 0; 1909} 1910 1911