2 * Copyright (c) 2004 Massachusetts Institute of Technology
\r
4 * Permission is hereby granted, free of charge, to any person
\r
5 * obtaining a copy of this software and associated documentation
\r
6 * files (the "Software"), to deal in the Software without
\r
7 * restriction, including without limitation the rights to use, copy,
\r
8 * modify, merge, publish, distribute, sublicense, and/or sell copies
\r
9 * of the Software, and to permit persons to whom the Software is
\r
10 * furnished to do so, subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be
\r
13 * included in all copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
\r
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
\r
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
\r
18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
\r
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
\r
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
\r
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
\r
27 #include<kcreddbinternal.h>
\r
30 CRITICAL_SECTION cs_type;
\r
31 hashtable * kcdb_type_namemap;
\r
32 kcdb_type_i ** kcdb_type_tbl;
\r
33 kcdb_type_i * kcdb_types = NULL;
\r
37 #define GENERIC_VOID_STR L"(Void)"
\r
39 khm_int32 KHMAPI kcdb_type_void_toString(
\r
49 return KHM_ERROR_INVALID_PARM;
\r
51 cbsize = sizeof(GENERIC_VOID_STR);
\r
53 if(!buffer || *cb_buf < cbsize) {
\r
55 return KHM_ERROR_TOO_LONG;
\r
58 StringCbCopy(buffer, *cb_buf, GENERIC_VOID_STR);
\r
62 return KHM_ERROR_SUCCESS;
\r
65 khm_boolean KHMAPI kcdb_type_void_isValid(
\r
69 /* void is always valid, even if d is NULL */
\r
73 khm_int32 KHMAPI kcdb_type_void_comp(
\r
79 /* voids can not be compared */
\r
83 khm_int32 KHMAPI kcdb_type_void_dup(
\r
90 return KHM_ERROR_INVALID_PARM;
\r
94 /* copying a void doesn't do much */
\r
95 return KHM_ERROR_SUCCESS;
\r
100 khm_int32 KHMAPI kcdb_type_string_toString(
\r
104 khm_size * cb_buf,
\r
111 return KHM_ERROR_INVALID_PARM;
\r
113 sd = (wchar_t *) d;
\r
115 if(FAILED(StringCbLength(sd, KCDB_TYPE_MAXCB, &cbsize)))
\r
116 return KHM_ERROR_INVALID_PARM;
\r
118 cbsize += sizeof(wchar_t);
\r
120 if(!buffer || *cb_buf < cbsize) {
\r
122 return KHM_ERROR_TOO_LONG;
\r
125 StringCbCopy(buffer, *cb_buf, sd);
\r
129 return KHM_ERROR_SUCCESS;
\r
132 khm_boolean KHMAPI kcdb_type_string_isValid(
\r
138 if(cbd == KCDB_CBSIZE_AUTO)
\r
139 cbd = KCDB_TYPE_MAXCB;
\r
141 if(FAILED(StringCbLength((wchar_t *) d, cbd, &cbsize)))
\r
147 khm_int32 KHMAPI kcdb_type_string_comp(
\r
153 return wcscmp((const wchar_t *) d1, (const wchar_t *) d2);
\r
156 khm_int32 KHMAPI kcdb_type_string_dup(
\r
157 const void * d_src,
\r
160 khm_size * cbd_dst)
\r
165 return KHM_ERROR_INVALID_PARM;
\r
167 if(cbd_src == KCDB_CBSIZE_AUTO) {
\r
168 cbd_src = KCDB_TYPE_MAXCB;
\r
171 if(FAILED(StringCbLength((const wchar_t *) d_src, cbd_src, &cbsize))) {
\r
172 return KHM_ERROR_UNKNOWN;
\r
175 cbsize += sizeof(wchar_t);
\r
177 if(!d_dst || *cbd_dst < cbsize) {
\r
179 return KHM_ERROR_TOO_LONG;
\r
182 StringCbCopy((wchar_t *) d_dst, *cbd_dst, (const wchar_t *) d_src);
\r
185 return KHM_ERROR_SUCCESS;
\r
188 /* Date and time */
\r
191 khm_int32 KHMAPI kcdb_type_date_toString(
\r
195 khm_size * cb_buf,
\r
208 return KHM_ERROR_INVALID_PARM;
\r
210 ft = (FILETIME *) d;
\r
212 GetLocalTime(&st_now);
\r
213 FileTimeToSystemTime(ft, &st_d);
\r
214 SystemTimeToTzSpecificLocalTime(NULL, &st_d, &st_dl);
\r
215 if(st_now.wYear == st_dl.wYear &&
\r
216 st_now.wMonth == st_dl.wMonth &&
\r
217 st_now.wDay == st_dl.wDay)
\r
220 if(today && (flags & KCDB_TS_SHORT)) {
\r
223 cbsize = GetDateFormat(
\r
224 LOCALE_USER_DEFAULT,
\r
229 0) * sizeof(wchar_t);
\r
230 cbsize += sizeof(wchar_t);
\r
233 cbsize += GetTimeFormat(
\r
234 LOCALE_USER_DEFAULT,
\r
239 0) * sizeof(wchar_t);
\r
241 cbsize += sizeof(wchar_t);
\r
243 if(!buffer || *cb_buf < cbsize) {
\r
245 return KHM_ERROR_TOO_LONG;
\r
248 cchsize = cbsize / sizeof(wchar_t);
\r
250 if(!today || !(flags & KCDB_TS_SHORT)) {
\r
251 size_t cch_buf_len;
\r
254 LOCALE_USER_DEFAULT,
\r
261 StringCchCat(buffer, cchsize, L" ");
\r
263 StringCchLength(buffer, cchsize, &cch_buf_len);
\r
265 bufend = buffer + cch_buf_len;
\r
266 cchsize -= cch_buf_len;
\r
272 LOCALE_USER_DEFAULT,
\r
281 return KHM_ERROR_SUCCESS;
\r
284 khm_boolean KHMAPI kcdb_type_date_isValid(
\r
288 return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(FILETIME)));
\r
291 khm_int32 KHMAPI kcdb_type_date_comp(
\r
297 return (khm_int32) CompareFileTime((CONST FILETIME *) d1, (CONST FILETIME *) d2);
\r
300 khm_int32 KHMAPI kcdb_type_date_dup(
\r
301 const void * d_src,
\r
304 khm_size * cbd_dst)
\r
306 if(d_dst && *cbd_dst >= sizeof(FILETIME)) {
\r
307 *cbd_dst = sizeof(FILETIME);
\r
308 *((FILETIME *) d_dst) = *((FILETIME *) d_src);
\r
309 return KHM_ERROR_SUCCESS;
\r
311 *cbd_dst = sizeof(FILETIME);
\r
312 return KHM_ERROR_TOO_LONG;
\r
318 /* returns the number of milliseconds that must elapse away from the
\r
319 interval specified in pft for the representation of pft to change
\r
320 from whatever it is right now */
\r
321 KHMEXP long KHMAPI FtIntervalMsToRepChange(LPFILETIME pft)
\r
323 __int64 ms,s,m,h,d;
\r
326 ms = *((__int64 *) pft) / 10000i64;
\r
328 if(ms < 0 || *((__int64 *) pft) == _I64_MAX)
\r
337 /* rep change at next hour change */
\r
338 l = (long) (ms % (3600*1000i64));
\r
340 /* rep change at next minute change */
\r
341 l = (long) (ms % (60*1000i64));
\r
343 l = (long) (ms % 1000);
\r
349 KHMEXP khm_int32 KHMAPI FtIntervalToString(LPFILETIME data, wchar_t * buffer, khm_size * cb_buf)
\r
358 return KHM_ERROR_INVALID_PARM;
\r
359 s = *((__int64 *) data) / 10000000i64;
\r
365 if(*((__int64 *) data) == _I64_MAX) {
\r
366 LoadString(hinst_kcreddb, IDS_IVL_UNKNOWN, ibuf, sizeof(ibuf)/sizeof(wchar_t));
\r
368 LoadString(hinst_kcreddb, IDS_IVL_EXPIRED, ibuf, sizeof(ibuf)/sizeof(wchar_t));
\r
370 h = (s - (d * 3600 * 24)) / 3600;
\r
372 LoadString(hinst_kcreddb, IDS_IVL_1D, ibuf, ARRAYLENGTH(ibuf));
\r
374 LoadString(hinst_kcreddb, IDS_IVL_D, fbuf, ARRAYLENGTH(fbuf));
\r
375 StringCbPrintf(ibuf, sizeof(ibuf), fbuf, d);
\r
378 StringCbCat(ibuf, sizeof(ibuf), L" ");
\r
379 t = ibuf + wcslen(ibuf);
\r
382 LoadString(hinst_kcreddb, IDS_IVL_1H, t, ARRAYLENGTH(ibuf) - wcslen(ibuf));
\r
384 LoadString(hinst_kcreddb, IDS_IVL_H, fbuf, ARRAYLENGTH(fbuf));
\r
385 StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, h);
\r
389 m = (s - (h * 3600)) / 60;
\r
391 LoadString(hinst_kcreddb, IDS_IVL_1H, ibuf, ARRAYLENGTH(ibuf));
\r
393 LoadString(hinst_kcreddb, IDS_IVL_H, fbuf, ARRAYLENGTH(fbuf));
\r
394 StringCbPrintf(ibuf, sizeof(ibuf), fbuf, h);
\r
397 StringCbCat(ibuf, sizeof(ibuf), L" ");
\r
398 t = ibuf + wcslen(ibuf);
\r
401 LoadString(hinst_kcreddb, IDS_IVL_1M, t, ARRAYLENGTH(ibuf) - wcslen(ibuf));
\r
403 LoadString(hinst_kcreddb, IDS_IVL_M, fbuf, ARRAYLENGTH(fbuf));
\r
404 StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, m);
\r
410 LoadString(hinst_kcreddb, IDS_IVL_1M, ibuf, ARRAYLENGTH(ibuf));
\r
412 LoadString(hinst_kcreddb, IDS_IVL_M, fbuf, ARRAYLENGTH(fbuf));
\r
413 StringCbPrintf(ibuf, sizeof(ibuf), fbuf, m);
\r
416 StringCbCat(ibuf, sizeof(ibuf), L" ");
\r
417 t = ibuf + wcslen(ibuf);
\r
420 LoadString(hinst_kcreddb, IDS_IVL_1S, t, ARRAYLENGTH(ibuf) - wcslen(ibuf));
\r
422 LoadString(hinst_kcreddb, IDS_IVL_S, fbuf, ARRAYLENGTH(fbuf));
\r
423 StringCbPrintf(t, sizeof(ibuf) - wcslen(ibuf)*sizeof(wchar_t), fbuf, s);
\r
428 LoadString(hinst_kcreddb, IDS_IVL_1S, ibuf, ARRAYLENGTH(ibuf));
\r
430 LoadString(hinst_kcreddb, IDS_IVL_S, fbuf, sizeof(fbuf)/sizeof(wchar_t));
\r
431 StringCbPrintf(ibuf, sizeof(ibuf), fbuf, s);
\r
435 StringCbLength(ibuf, sizeof(ibuf), &cbsize);
\r
436 cbsize += sizeof(wchar_t);
\r
438 if(!buffer || *cb_buf < cbsize) {
\r
440 return KHM_ERROR_TOO_LONG;
\r
443 StringCbCopy(buffer, *cb_buf, ibuf);
\r
446 return KHM_ERROR_SUCCESS;
\r
449 khm_int32 KHMAPI kcdb_type_interval_toString(
\r
450 const void * data,
\r
453 khm_size * cb_buf,
\r
456 return FtIntervalToString((LPFILETIME) data, buffer, cb_buf);
\r
459 khm_boolean KHMAPI kcdb_type_interval_isValid(
\r
463 return (d && (cbd == sizeof(FILETIME) || cbd == KCDB_CBSIZE_AUTO));
\r
466 khm_int32 KHMAPI kcdb_type_interval_comp(
\r
474 i1 = *((__int64 *) d1);
\r
475 i2 = *((__int64 *) d2);
\r
485 khm_int32 KHMAPI kcdb_type_interval_dup(
\r
486 const void * d_src,
\r
489 khm_size * cbd_dst)
\r
491 if(d_dst && *cbd_dst >= sizeof(__int64)) {
\r
492 *cbd_dst = sizeof(__int64);
\r
493 *((__int64 *) d_dst) = *((__int64 *) d_src);
\r
494 return KHM_ERROR_SUCCESS;
\r
496 *cbd_dst = sizeof(__int64);
\r
497 return KHM_ERROR_TOO_LONG;
\r
503 khm_int32 KHMAPI kcdb_type_int32_toString(
\r
507 khm_size * cb_buf,
\r
514 return KHM_ERROR_INVALID_PARM;
\r
516 StringCbPrintf(ibuf, sizeof(ibuf), L"%d", *((khm_int32 *) d));
\r
517 StringCbLength(ibuf, sizeof(ibuf), &cbsize);
\r
518 cbsize += sizeof(wchar_t);
\r
520 if(!buffer || *cb_buf < cbsize) {
\r
522 return KHM_ERROR_TOO_LONG;
\r
525 StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf);
\r
528 return KHM_ERROR_SUCCESS;
\r
531 khm_boolean KHMAPI kcdb_type_int32_isValid(
\r
535 return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(khm_int32)));
\r
538 khm_int32 KHMAPI kcdb_type_int32_comp(
\r
544 return *((khm_int32 *) d1) - *((khm_int32 *) d2);
\r
547 khm_int32 KHMAPI kcdb_type_int32_dup(
\r
548 const void * d_src,
\r
551 khm_size * cbd_dst)
\r
553 if(d_dst && (*cbd_dst >= sizeof(khm_int32))) {
\r
554 *cbd_dst = sizeof(khm_int32);
\r
555 *((khm_int32 *) d_dst) = *((khm_int32 *) d_src);
\r
556 return KHM_ERROR_SUCCESS;
\r
558 *cbd_dst = sizeof(khm_int32);
\r
559 return KHM_ERROR_TOO_LONG;
\r
565 khm_int32 KHMAPI kcdb_type_int64_toString(
\r
569 khm_size * cb_buf,
\r
576 return KHM_ERROR_INVALID_PARM;
\r
578 StringCbPrintf(ibuf, sizeof(ibuf), L"%I64d", *((__int64 *) d));
\r
579 StringCbLength(ibuf, sizeof(ibuf), &cbsize);
\r
580 cbsize += sizeof(wchar_t);
\r
582 if(!buffer || *cb_buf < cbsize) {
\r
584 return KHM_ERROR_TOO_LONG;
\r
587 StringCbCopy((wchar_t *) buffer, *cb_buf, ibuf);
\r
590 return KHM_ERROR_SUCCESS;
\r
593 khm_boolean KHMAPI kcdb_type_int64_isValid(
\r
597 return (d && (cbd == KCDB_CBSIZE_AUTO || cbd == sizeof(__int64)));
\r
600 khm_int32 KHMAPI kcdb_type_int64_comp(
\r
606 __int64 r = *((__int64 *) d1) - *((__int64 *) d2);
\r
607 return (r==0i64)?0:((r>0i64)?1:-1);
\r
610 khm_int32 KHMAPI kcdb_type_int64_dup(
\r
611 const void * d_src,
\r
614 khm_size * cbd_dst)
\r
616 if(d_dst && (*cbd_dst >= sizeof(__int64))) {
\r
617 *cbd_dst = sizeof(__int64);
\r
618 *((__int64 *) d_dst) = *((__int64 *) d_src);
\r
619 return KHM_ERROR_SUCCESS;
\r
621 *cbd_dst = sizeof(__int64);
\r
622 return KHM_ERROR_TOO_LONG;
\r
627 #define GENERIC_DATA_STR L"(Data)"
\r
629 khm_int32 KHMAPI kcdb_type_data_toString(
\r
633 khm_size * cb_buf,
\r
639 return KHM_ERROR_INVALID_PARM;
\r
641 cbsize = sizeof(GENERIC_DATA_STR);
\r
643 if(!buffer || *cb_buf < cbsize) {
\r
645 return KHM_ERROR_TOO_LONG;
\r
648 StringCbCopy(buffer, *cb_buf, GENERIC_DATA_STR);
\r
652 return KHM_ERROR_SUCCESS;
\r
655 khm_boolean KHMAPI kcdb_type_data_isValid(
\r
659 /* data is always valid, even if d is NULL */
\r
663 khm_int32 KHMAPI kcdb_type_data_comp(
\r
669 /* datas can not be compared */
\r
673 khm_int32 KHMAPI kcdb_type_data_dup(
\r
674 const void * d_src,
\r
677 khm_size * cbd_dst)
\r
680 return KHM_ERROR_INVALID_PARM;
\r
682 *cbd_dst = cbd_src;
\r
684 if(!d_dst || *cbd_dst < cbd_src) {
\r
685 return KHM_ERROR_TOO_LONG;
\r
687 memcpy(d_dst, d_src, cbd_src);
\r
688 return KHM_ERROR_SUCCESS;
\r
693 void kcdb_type_msg_completion(kmq_message * m)
\r
695 kcdb_type_release((kcdb_type_i *) m->vparam);
\r
698 void kcdb_type_post_message(khm_int32 op, kcdb_type_i * t)
\r
701 kmq_post_message(KMSG_KCDB, KMSG_KCDB_TYPE, op, (void *) t);
\r
704 void kcdb_type_init(void)
\r
708 InitializeCriticalSection(&cs_type);
\r
709 kcdb_type_namemap = hash_new_hashtable(
\r
710 KCDB_TYPE_HASH_SIZE,
\r
714 kcdb_type_del_ref);
\r
715 kcdb_type_tbl = malloc(sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1));
\r
716 ZeroMemory(kcdb_type_tbl, sizeof(kcdb_type_i *) * (KCDB_TYPE_MAX_ID + 1));
\r
719 /*TODO: register standard data types */
\r
721 ZeroMemory(&type, sizeof(type));
\r
722 type.comp = kcdb_type_void_comp;
\r
723 type.dup = kcdb_type_void_dup;
\r
724 type.isValid = kcdb_type_void_isValid;
\r
725 type.toString = kcdb_type_void_toString;
\r
726 type.name = KCDB_TYPENAME_VOID;
\r
727 type.id = KCDB_TYPE_VOID;
\r
729 kcdb_type_register(&type, NULL);
\r
731 ZeroMemory(&type, sizeof(type));
\r
732 type.comp = kcdb_type_string_comp;
\r
733 type.dup = kcdb_type_string_dup;
\r
734 type.isValid = kcdb_type_string_isValid;
\r
735 type.toString = kcdb_type_string_toString;
\r
736 type.name = KCDB_TYPENAME_STRING;
\r
737 type.id = KCDB_TYPE_STRING;
\r
738 type.flags = KCDB_TYPE_FLAG_CB_AUTO;
\r
740 kcdb_type_register(&type, NULL);
\r
742 ZeroMemory(&type, sizeof(type));
\r
743 type.comp = kcdb_type_date_comp;
\r
744 type.dup = kcdb_type_date_dup;
\r
745 type.isValid = kcdb_type_date_isValid;
\r
746 type.toString = kcdb_type_date_toString;
\r
747 type.name = KCDB_TYPENAME_DATE;
\r
748 type.id = KCDB_TYPE_DATE;
\r
749 type.cb_max = sizeof(FILETIME);
\r
750 type.cb_min = sizeof(FILETIME);
\r
751 type.flags = KCDB_TYPE_FLAG_CB_FIXED;
\r
753 kcdb_type_register(&type, NULL);
\r
755 ZeroMemory(&type, sizeof(type));
\r
756 type.comp = kcdb_type_interval_comp;
\r
757 type.dup = kcdb_type_interval_dup;
\r
758 type.isValid = kcdb_type_interval_isValid;
\r
759 type.toString = kcdb_type_interval_toString;
\r
760 type.name = KCDB_TYPENAME_INTERVAL;
\r
761 type.id = KCDB_TYPE_INTERVAL;
\r
762 type.cb_max = sizeof(__int64);
\r
763 type.cb_min = sizeof(__int64);
\r
764 type.flags = KCDB_TYPE_FLAG_CB_FIXED;
\r
766 kcdb_type_register(&type, NULL);
\r
768 ZeroMemory(&type, sizeof(type));
\r
769 type.comp = kcdb_type_int32_comp;
\r
770 type.dup = kcdb_type_int32_dup;
\r
771 type.isValid = kcdb_type_int32_isValid;
\r
772 type.toString = kcdb_type_int32_toString;
\r
773 type.name = KCDB_TYPENAME_INT32;
\r
774 type.id = KCDB_TYPE_INT32;
\r
775 type.cb_max = sizeof(khm_int32);
\r
776 type.cb_min = sizeof(khm_int32);
\r
777 type.flags = KCDB_TYPE_FLAG_CB_FIXED;
\r
779 kcdb_type_register(&type, NULL);
\r
781 ZeroMemory(&type, sizeof(type));
\r
782 type.comp = kcdb_type_int64_comp;
\r
783 type.dup = kcdb_type_int64_dup;
\r
784 type.isValid = kcdb_type_int64_isValid;
\r
785 type.toString = kcdb_type_int64_toString;
\r
786 type.name = KCDB_TYPENAME_INT64;
\r
787 type.id = KCDB_TYPE_INT64;
\r
788 type.cb_max = sizeof(__int64);
\r
789 type.cb_min = sizeof(__int64);
\r
790 type.flags = KCDB_TYPE_FLAG_CB_FIXED;
\r
792 kcdb_type_register(&type, NULL);
\r
794 ZeroMemory(&type, sizeof(type));
\r
795 type.comp = kcdb_type_data_comp;
\r
796 type.dup = kcdb_type_data_dup;
\r
797 type.isValid = kcdb_type_data_isValid;
\r
798 type.toString = kcdb_type_data_toString;
\r
799 type.name = KCDB_TYPENAME_DATA;
\r
800 type.id = KCDB_TYPE_DATA;
\r
802 kcdb_type_register(&type, NULL);
\r
805 void kcdb_type_add_ref(const void *key, void *vt)
\r
807 kcdb_type_hold((kcdb_type_i *) vt);
\r
810 void kcdb_type_del_ref(const void *key, void *vt)
\r
812 kcdb_type_release((kcdb_type_i *) vt);
\r
815 khm_int32 kcdb_type_hold(kcdb_type_i * t)
\r
818 return KHM_ERROR_INVALID_PARM;
\r
820 EnterCriticalSection(&cs_type);
\r
822 LeaveCriticalSection(&cs_type);
\r
824 return KHM_ERROR_SUCCESS;
\r
827 khm_int32 kcdb_type_release(kcdb_type_i * t)
\r
830 return KHM_ERROR_INVALID_PARM;
\r
832 EnterCriticalSection(&cs_type);
\r
834 kcdb_type_check_and_delete(t->type.id);
\r
835 LeaveCriticalSection(&cs_type);
\r
837 return KHM_ERROR_SUCCESS;
\r
840 void kcdb_type_exit(void)
\r
842 EnterCriticalSection(&cs_type);
\r
843 free(kcdb_type_tbl);
\r
844 /*TODO: free up the individual types */
\r
845 LeaveCriticalSection(&cs_type);
\r
846 DeleteCriticalSection(&cs_type);
\r
849 void kcdb_type_check_and_delete(khm_int32 id)
\r
853 if(id < 0 || id > KCDB_TYPE_MAX_ID)
\r
856 EnterCriticalSection(&cs_type);
\r
857 t = kcdb_type_tbl[id];
\r
858 if(t && !t->refcount) {
\r
859 kcdb_type_tbl[id] = NULL;
\r
860 LDELETE(&kcdb_types, t);
\r
861 /* must already be out of the hash-table, otherwise refcount should not
\r
863 free(t->type.name);
\r
866 LeaveCriticalSection(&cs_type);
\r
869 KHMEXP khm_int32 KHMAPI kcdb_type_get_id(wchar_t *name, khm_int32 * id)
\r
874 if(FAILED(StringCbLength(name, KCDB_MAXCB_NAME, &cbsize))) {
\r
875 /* also fails of name is NULL */
\r
876 return KHM_ERROR_INVALID_PARM;
\r
879 EnterCriticalSection(&cs_type);
\r
880 t = hash_lookup(kcdb_type_namemap, (void*) name);
\r
881 LeaveCriticalSection(&cs_type);
\r
884 *id = KCDB_TYPE_INVALID;
\r
885 return KHM_ERROR_NOT_FOUND;
\r
888 return KHM_ERROR_SUCCESS;
\r
892 KHMEXP khm_int32 KHMAPI kcdb_type_get_info(khm_int32 id, kcdb_type ** info)
\r
896 if(id < 0 || id > KCDB_TYPE_MAX_ID)
\r
897 return KHM_ERROR_INVALID_PARM;
\r
899 EnterCriticalSection(&cs_type);
\r
900 t = kcdb_type_tbl[id];
\r
904 LeaveCriticalSection(&cs_type);
\r
907 *info = (kcdb_type *) t;
\r
909 kcdb_type_release(t);
\r
911 return (t)? KHM_ERROR_SUCCESS : KHM_ERROR_NOT_FOUND;
\r
914 KHMEXP khm_int32 KHMAPI kcdb_type_release_info(kcdb_type * info)
\r
916 return kcdb_type_release((kcdb_type_i *) info);
\r
919 KHMEXP khm_int32 KHMAPI kcdb_type_get_name(khm_int32 id, wchar_t * buffer, khm_size * cbbuf)
\r
924 if(id < 0 || id > KCDB_TYPE_MAX_ID || !cbbuf)
\r
925 return KHM_ERROR_INVALID_PARM;
\r
927 t = kcdb_type_tbl[id];
\r
930 return KHM_ERROR_NOT_FOUND;
\r
932 if(FAILED(StringCbLength(t->type.name, KCDB_MAXCB_NAME, &cbsize)))
\r
933 return KHM_ERROR_UNKNOWN;
\r
935 cbsize += sizeof(wchar_t);
\r
937 if(!buffer || *cbbuf < cbsize) {
\r
939 return KHM_ERROR_TOO_LONG;
\r
942 StringCbCopy(buffer, *cbbuf, t->type.name);
\r
945 return KHM_ERROR_SUCCESS;
\r
948 KHMEXP khm_int32 KHMAPI kcdb_type_register(kcdb_type * type, khm_int32 * new_id)
\r
958 !type->toString ||
\r
960 return KHM_ERROR_INVALID_PARM;
\r
962 if((type->flags & KCDB_TYPE_FLAG_CB_MIN) &&
\r
963 (type->cb_min < 0 || type->cb_min > KCDB_TYPE_MAXCB))
\r
965 return KHM_ERROR_INVALID_PARM;
\r
968 if((type->flags & KCDB_TYPE_FLAG_CB_MAX) &&
\r
969 (type->cb_max < 0 || type->cb_max > KCDB_TYPE_MAXCB))
\r
971 return KHM_ERROR_INVALID_PARM;
\r
974 if((type->flags & KCDB_TYPE_FLAG_CB_MIN) &&
\r
975 (type->flags & KCDB_TYPE_FLAG_CB_MAX) &&
\r
976 (type->cb_max < type->cb_min))
\r
978 return KHM_ERROR_INVALID_PARM;
\r
981 if(FAILED(StringCbLength(type->name, KCDB_MAXCB_NAME, &cbsize)))
\r
982 return KHM_ERROR_TOO_LONG;
\r
984 cbsize += sizeof(wchar_t);
\r
986 EnterCriticalSection(&cs_type);
\r
987 if(type->id == KCDB_TYPE_INVALID) {
\r
988 kcdb_type_get_next_free(&type_id);
\r
989 } else if(type->id < 0 || type->id > KCDB_TYPE_MAX_ID) {
\r
990 LeaveCriticalSection(&cs_type);
\r
991 return KHM_ERROR_INVALID_PARM;
\r
992 } else if(kcdb_type_tbl[type->id]) {
\r
993 LeaveCriticalSection(&cs_type);
\r
994 return KHM_ERROR_DUPLICATE;
\r
996 type_id = type->id;
\r
999 if(type_id == KCDB_TYPE_INVALID) {
\r
1000 LeaveCriticalSection(&cs_type);
\r
1001 return KHM_ERROR_NO_RESOURCES;
\r
1004 t = malloc(sizeof(kcdb_type_i));
\r
1005 ZeroMemory(t, sizeof(kcdb_type_i));
\r
1007 t->type.name = malloc(cbsize);
\r
1008 StringCbCopy(t->type.name, cbsize, type->name);
\r
1010 t->type.comp = type->comp;
\r
1011 t->type.dup = type->dup;
\r
1012 t->type.flags = type->flags;
\r
1013 t->type.id = type_id;
\r
1014 t->type.isValid = type->isValid;
\r
1015 t->type.toString = type->toString;
\r
1019 kcdb_type_tbl[type_id] = t;
\r
1020 LPUSH(&kcdb_types, t);
\r
1022 hash_add(kcdb_type_namemap, (void *) t->type.name, (void *) t);
\r
1024 LeaveCriticalSection(&cs_type);
\r
1027 *new_id = type_id;
\r
1029 kcdb_type_post_message(KCDB_OP_INSERT, t);
\r
1031 return KHM_ERROR_SUCCESS;
\r
1034 KHMEXP khm_int32 KHMAPI kcdb_type_unregister(khm_int32 id)
\r
1038 if(id < 0 || id > KCDB_TYPE_MAX_ID)
\r
1039 return KHM_ERROR_INVALID_PARM;
\r
1041 EnterCriticalSection(&cs_type);
\r
1042 t = kcdb_type_tbl[id];
\r
1044 kcdb_type_post_message(KCDB_OP_DELETE, t);
\r
1045 /* we are going to remove t from the hash table. If no one is holding
\r
1046 a reference to it, then we can free it (actually, the del_ref code
\r
1047 will take care of that anyway). If there is a hold, then it will
\r
1048 get freed when they release it.
\r
1050 Actually, the post_message call above pretty much guarantees that
\r
1051 the type has a hold on it.*/
\r
1052 t->type.flags |= KCDB_TYPE_FLAG_DELETED;
\r
1053 hash_del(kcdb_type_namemap, t->type.name);
\r
1055 LeaveCriticalSection(&cs_type);
\r
1058 return KHM_ERROR_SUCCESS;
\r
1060 return KHM_ERROR_NOT_FOUND;
\r
1063 KHMEXP khm_int32 KHMAPI kcdb_type_get_next_free(khm_int32 * id)
\r
1068 return KHM_ERROR_INVALID_PARM;
\r
1070 /* do a linear search because this function only gets called a few times */
\r
1071 EnterCriticalSection(&cs_type);
\r
1072 for(i=0; i <= KCDB_TYPE_MAX_ID; i++) {
\r
1073 if(!kcdb_type_tbl[i])
\r
1076 LeaveCriticalSection(&cs_type);
\r
1078 if(i <= KCDB_TYPE_MAX_ID) {
\r
1080 return KHM_ERROR_SUCCESS;
\r
1082 *id = KCDB_TYPE_INVALID;
\r
1083 return KHM_ERROR_NO_RESOURCES;
\r
1087 /* Conversion functions */
\r
1089 KHMEXP void KHMAPI TimetToFileTime( time_t t, LPFILETIME pft )
\r
1091 LONGLONG ll = Int32x32To64(t, 10000000) + 116444736000000000i64;
\r
1092 pft->dwLowDateTime = (DWORD) ll;
\r
1093 pft->dwHighDateTime = (DWORD) (ll >> 32);
\r
1096 KHMEXP void KHMAPI TimetToFileTimeInterval(time_t t, LPFILETIME pft)
\r
1098 LONGLONG ll = Int32x32To64(t, 10000000);
\r
1099 pft->dwLowDateTime = (DWORD) ll;
\r
1100 pft->dwHighDateTime = (DWORD) (ll >> 32);
\r
1103 KHMEXP long KHMAPI FtIntervalToSeconds(LPFILETIME pft)
\r
1105 __int64 i = *((__int64 *) pft);
\r
1106 return (long) (i / 10000000i64);
\r
1109 KHMEXP long KHMAPI FtIntervalToMilliseconds(LPFILETIME pft)
\r
1111 __int64 i = *((__int64 *) pft);
\r
1112 return (long) (i / 10000i64);
\r
1115 KHMEXP long KHMAPI FtCompare(LPFILETIME pft1, LPFILETIME pft2) {
\r
1116 __int64 i1 = *((__int64 *) pft1);
\r
1117 __int64 i2 = *((__int64 *) pft2);
\r
1126 KHMEXP int KHMAPI AnsiStrToUnicode( wchar_t * wstr, size_t cbwstr, const char * astr)
\r
1133 nc = strlen(astr);
\r
1134 if(nc == MultiByteToWideChar(
\r
1140 (int)(cbwstr / sizeof(wchar_t) - 1))) {
\r
1150 KHMEXP int KHMAPI UnicodeStrToAnsi( char * dest, size_t cbdest, const wchar_t * src)
\r
1159 if(FAILED(StringCchLength(src, cbdest, &nc)) || nc*sizeof(char) >= cbdest)
\r
1160 // note that cbdest counts the terminating NULL, while nc doesn't
\r
1163 nc = WideCharToMultiByte(
\r
1165 WC_NO_BEST_FIT_CHARS,
\r
1178 #define MAX_IVL_SPECLIST_LEN 256
\r
1179 #define MAX_IVL_UNITS 5
\r
1181 enum _ivl_indices {
\r
1189 typedef struct ivspec_t {
\r
1190 wchar_t str[MAX_IVL_SPECLIST_LEN];
\r
1194 static ivspec ivspecs[MAX_IVL_UNITS];
\r
1195 static BOOL ivspecs_loaded = FALSE;
\r
1197 int _iv_is_in_spec(wchar_t *s, int n, wchar_t * spec)
\r
1199 /* spec strigns are comma separated */
\r
1204 e = wcschr(b, L',');
\r
1206 e = b + wcslen(b);
\r
1208 if((e - b) == n && !wcsnicmp(b, s, n)) {
\r
1221 KHMEXP khm_int32 KHMAPI IntervalStringToFt(FILETIME * pft, wchar_t * str)
\r
1227 pr = (__int64 *) pft;
\r
1230 /* ideally we should synchronize this, but it doesn't hurt if two
\r
1231 threads do this at the same time, because we only set the ivspecs_loaded
\r
1232 flag when we are done */
\r
1233 if(!ivspecs_loaded) {
\r
1234 LoadString(hinst_kcreddb, IDS_IVL_S_SPEC, ivspecs[IVL_SECONDS].str, MAX_IVL_SPECLIST_LEN);
\r
1235 ivspecs[IVL_SECONDS].mul = 10000000i64;
\r
1236 LoadString(hinst_kcreddb, IDS_IVL_M_SPEC, ivspecs[IVL_MINUTES].str, MAX_IVL_SPECLIST_LEN);
\r
1237 ivspecs[IVL_MINUTES].mul = ivspecs[IVL_SECONDS].mul * 60;
\r
1238 LoadString(hinst_kcreddb, IDS_IVL_H_SPEC, ivspecs[2].str, MAX_IVL_SPECLIST_LEN);
\r
1239 ivspecs[IVL_HOURS].mul = ivspecs[IVL_MINUTES].mul * 60;
\r
1240 LoadString(hinst_kcreddb, IDS_IVL_D_SPEC, ivspecs[3].str, MAX_IVL_SPECLIST_LEN);
\r
1241 ivspecs[IVL_DAYS].mul = ivspecs[IVL_HOURS].mul * 24;
\r
1242 LoadString(hinst_kcreddb, IDS_IVL_W_SPEC, ivspecs[4].str, MAX_IVL_SPECLIST_LEN);
\r
1243 ivspecs[IVL_WEEKS].mul = ivspecs[IVL_DAYS].mul * 7;
\r
1245 ivspecs_loaded = TRUE;
\r
1248 if(!str || FAILED(StringCbLength(str, MAX_IVL_SPECLIST_LEN, &cb)))
\r
1249 return KHM_ERROR_INVALID_PARM;
\r
1258 while(*b && iswspace(*b))
\r
1261 if(*b && iswdigit(*b)) {
\r
1264 while(*b && iswdigit(*b))
\r
1268 while(*b && iswspace(*b))
\r
1271 if(!*b) /* no unit specified */
\r
1272 return KHM_ERROR_INVALID_PARM;
\r
1276 while(*e && !iswspace(*e))
\r
1279 for(i=0; i < MAX_IVL_UNITS; i++) {
\r
1280 if(_iv_is_in_spec(b, (int)(e-b), ivspecs[i].str))
\r
1284 if(i==MAX_IVL_UNITS)
\r
1285 return KHM_ERROR_INVALID_PARM;
\r
1287 t += f * ivspecs[i].mul;
\r
1294 return KHM_ERROR_SUCCESS;
\r