00001
00002
00003 #include "ace/Lib_Find.h"
00004 #include "ace/Log_Msg.h"
00005 #include "ace/OS_NS_string.h"
00006 #include "ace/OS_NS_errno.h"
00007 #include "ace/OS_NS_stdio.h"
00008 #include "ace/OS_NS_unistd.h"
00009 #include "ace/OS_NS_stdlib.h"
00010 #include "ace/OS_Memory.h"
00011 #include "ace/OS_NS_fcntl.h"
00012
00013 #if defined (ACE_WIN32)
00014 # include "ace/OS_NS_strings.h"
00015 #endif
00016
00017 #if defined (ACE_OPENVMS)
00018 #include "ace/RB_Tree.h"
00019 #include "ace/Thread_Mutex.h"
00020 #include "ace/Singleton.h"
00021
00022 #include "descrip.h"
00023 #include "chfdef.h"
00024 #include "stsdef.h"
00025 #include "libdef.h"
00026
00027 extern "C" int LIB$FIND_IMAGE_SYMBOL(...);
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 class ACE_LD_Symbol_Registry
00052 {
00053 public:
00054
00055 typedef ACE_RB_Tree<const ACE_TCHAR*,
00056 void*,
00057 ACE_Less_Than<const ACE_TCHAR*>,
00058 ACE_Thread_Mutex>
00059 TREE;
00060
00061 void register_symbol (const ACE_TCHAR* symname, void* symaddr);
00062
00063 void* find_symbol (const ACE_TCHAR* symname);
00064
00065 ACE_LD_Symbol_Registry () {}
00066 private:
00067
00068 TREE symbol_registry_;
00069 };
00070
00071 void
00072 ACE_LD_Symbol_Registry::register_symbol (const ACE_TCHAR* symname,
00073 void* symaddr)
00074 {
00075 int const result = symbol_registry_.bind (symname, symaddr);
00076 if (result == 1)
00077 {
00078 ACE_DEBUG((LM_INFO, ACE_TEXT ("ACE_LD_Symbol_Registry:")
00079 ACE_TEXT (" duplicate symbol %s registered\n"),
00080 ACE_TEXT_ALWAYS_CHAR (symname)));
00081 }
00082 else if (result == -1)
00083 {
00084 ACE_ERROR((LM_ERROR, ACE_TEXT ("ACE_LD_Symbol_Registry:")
00085 ACE_TEXT (" failed to register symbol %s\n"),
00086 ACE_TEXT_ALWAYS_CHAR (symname)));
00087 }
00088 }
00089
00090 void*
00091 ACE_LD_Symbol_Registry::find_symbol (const ACE_TCHAR* symname)
00092 {
00093 void* symaddr = 0;
00094 int const result = symbol_registry_.find (symname, symaddr);
00095
00096 return (result == 0 ? symaddr : 0);
00097 }
00098
00099
00100 ACE_SINGLETON_DECLARE (ACE_Singleton,
00101 ACE_LD_Symbol_Registry,
00102 ACE_Thread_Mutex)
00103
00104 typedef ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>
00105 ACE_LD_SYMBOL_REGISTRY;
00106
00107 #if defined (ACE_HAS_EXPLICIT_STATIC_TEMPLATE_MEMBER_INSTANTIATION)
00108 template ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex> *
00109 ACE_Singleton<ACE_LD_Symbol_Registry, ACE_Thread_Mutex>::singleton_;
00110 #endif
00111 #endif
00112
00113 ACE_RCSID(ace, Lib_Find, "$Id: Lib_Find.cpp 85473 2009-06-01 08:09:31Z johnnyw $")
00114
00115 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00116
00117 int
00118 ACE::ldfind (const ACE_TCHAR* filename,
00119 ACE_TCHAR pathname[],
00120 size_t maxpathnamelen)
00121 {
00122 ACE_TRACE ("ACE::ldfind");
00123 #if defined (ACE_OPENVMS)
00124 if (ACE_OS::strlen(filename) >= maxpathnamelen)
00125 {
00126 errno = ENOMEM;
00127 return -1;
00128 }
00129
00130 dsc$descriptor nameDsc;
00131 nameDsc.dsc$b_class = DSC$K_CLASS_S;
00132 nameDsc.dsc$b_dtype = DSC$K_DTYPE_T;
00133 nameDsc.dsc$w_length = ACE_OS::strlen(filename);
00134 nameDsc.dsc$a_pointer = (char*)filename;
00135
00136 char symbol[] = "NULL";
00137 dsc$descriptor symbolDsc;
00138 symbolDsc.dsc$b_class = DSC$K_CLASS_S;
00139 symbolDsc.dsc$b_dtype = DSC$K_DTYPE_T;
00140 symbolDsc.dsc$w_length = ACE_OS::strlen(symbol);
00141 symbolDsc.dsc$a_pointer = symbol;
00142
00143 int symbolValue;
00144 int result;
00145 try
00146 {
00147 result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0);
00148 }
00149 catch (chf$signal_array& sig)
00150 {
00151 result = sig.chf$l_sig_name;
00152 }
00153
00154 int severity = result & STS$M_SEVERITY;
00155 int conditionId = result & STS$M_COND_ID;
00156 if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO ||
00157 (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID)))
00158 {
00159 ACE_OS::strcpy(pathname, filename);
00160 return 0;
00161 }
00162
00163 if (ACE_OS::strlen(filename) + ACE_OS::strlen(ACE_DLL_PREFIX) >= maxpathnamelen)
00164 {
00165 errno = ENOMEM;
00166 return -1;
00167 }
00168
00169
00170 ACE_OS::strcpy(pathname, ACE_DLL_PREFIX);
00171 ACE_OS::strcat(pathname, filename);
00172 nameDsc.dsc$w_length = ACE_OS::strlen(pathname);
00173 nameDsc.dsc$a_pointer = pathname;
00174 try
00175 {
00176 result = LIB$FIND_IMAGE_SYMBOL(&nameDsc, &symbolDsc, &symbolValue, 0, 0);
00177 }
00178 catch (chf$signal_array& sig)
00179 {
00180 result = sig.chf$l_sig_name;
00181 }
00182
00183 severity = result & STS$M_SEVERITY;
00184 conditionId = result & STS$M_COND_ID;
00185 if (severity == STS$K_SUCCESS || severity == STS$K_WARNING || severity == STS$K_INFO ||
00186 (severity == STS$K_ERROR && conditionId == (LIB$_KEYNOTFOU & STS$M_COND_ID)))
00187 {
00188 return 0;
00189 }
00190 errno = ENOENT;
00191 return -1;
00192 #endif
00193
00194 #if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) && \
00195 !defined (ACE_HAS_PHARLAP)
00196 ACE_TCHAR expanded_filename[MAXPATHLEN];
00197 if (ACE_TEXT_ExpandEnvironmentStrings (filename,
00198 expanded_filename,
00199 sizeof expanded_filename
00200 / sizeof (ACE_TCHAR)))
00201 filename = expanded_filename;
00202 #endif
00203
00204 ACE_TCHAR tempcopy[MAXPATHLEN + 1];
00205 ACE_TCHAR searchpathname[MAXPATHLEN + 1];
00206 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
00207 ACE_TCHAR decorator[] = ACE_LD_DECORATOR_STR;
00208 ACE_TCHAR searchfilename[MAXPATHLEN + sizeof(decorator) / sizeof (ACE_TCHAR)];
00209 #else
00210 ACE_TCHAR searchfilename[MAXPATHLEN + 1];
00211 #endif
00212
00213
00214 if (ACE_OS::strlen (filename) + 1
00215 > (sizeof tempcopy / sizeof (ACE_TCHAR)))
00216 {
00217 errno = ENOMEM;
00218 return -1;
00219 }
00220 else
00221 ACE_OS::strcpy (tempcopy, filename);
00222
00223
00224 ACE_TCHAR *separator_ptr;
00225
00226 #if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
00227
00228
00229 ACE::strrepl (tempcopy, ACE_DIRECTORY_SEPARATOR_CHAR, '/');
00230 #endif
00231
00232
00233 separator_ptr = ACE_OS::strrchr (tempcopy, '/');
00234
00235
00236 if (separator_ptr == 0)
00237 {
00238 searchpathname[0] = '\0';
00239 ACE_OS::strcpy (searchfilename, tempcopy);
00240 }
00241 else
00242 {
00243 ACE_OS::strcpy (searchfilename, separator_ptr + 1);
00244 separator_ptr[1] = '\0';
00245 ACE_OS::strcpy (searchpathname, tempcopy);
00246 }
00247
00248 bool has_suffix = false;
00249
00250
00251
00252 ACE_TCHAR *s = ACE_OS::strrchr (searchfilename, '.');
00253
00254 const ACE_TCHAR *dll_suffix = ACE_DLL_SUFFIX;
00255
00256 if (s != 0)
00257 {
00258
00259 has_suffix = true;
00260
00261
00262
00263 #if defined (ACE_WIN32)
00264
00265
00266 if (ACE_OS::strcasecmp (s, dll_suffix) != 0)
00267 #else
00268 if (ACE_OS::strcmp (s, dll_suffix) != 0)
00269 #endif
00270 {
00271 ACE_ERROR ((LM_WARNING,
00272 ACE_TEXT ("Warning: improper suffix for a ")
00273 ACE_TEXT ("shared library on this platform: %s\n"),
00274 s));
00275 }
00276 }
00277
00278
00279 if (ACE_OS::strlen (searchfilename)
00280 + ACE_OS::strlen (ACE_DLL_PREFIX)
00281 + (has_suffix ? 0 : ACE_OS::strlen (dll_suffix))
00282 >= (sizeof searchfilename / sizeof (ACE_TCHAR)))
00283 {
00284 errno = ENOMEM;
00285 return -1;
00286 }
00287
00288 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
00289 size_t const len_searchfilename = ACE_OS::strlen (searchfilename);
00290 if (!has_suffix)
00291 ACE_OS::strcpy (searchfilename + len_searchfilename, decorator);
00292
00293 for (int tag = 1; tag >= 0; tag --)
00294 {
00295 if (tag == 0)
00296 searchfilename [len_searchfilename] = 0;
00297
00298 #endif
00299
00300 if (ACE_OS::strlen (searchpathname) > 0)
00301 {
00302 if (ACE_OS::strlen (searchfilename)
00303 + ACE_OS::strlen (searchpathname) >= maxpathnamelen)
00304 {
00305 errno = ENOMEM;
00306 return -1;
00307 }
00308 else
00309 {
00310 #if (ACE_DIRECTORY_SEPARATOR_CHAR != '/')
00311
00312 ACE::strrepl (searchpathname,
00313 '/',
00314 ACE_DIRECTORY_SEPARATOR_CHAR);
00315 #endif
00316
00317
00318 ACE_OS::sprintf (pathname,
00319 ACE_TEXT ("%s%s%s"),
00320 searchpathname,
00321 searchfilename,
00322 has_suffix ? ACE_TEXT ("") : dll_suffix);
00323 if (ACE_OS::access (pathname, F_OK) == 0)
00324 return 0;
00325
00326
00327 ACE_OS::sprintf (pathname,
00328 ACE_TEXT ("%s%s%s%s"),
00329 searchpathname,
00330 ACE_DLL_PREFIX,
00331 searchfilename,
00332 has_suffix ? ACE_TEXT ("") : dll_suffix);
00333 if (ACE_OS::access (pathname, F_OK) == 0)
00334 return 0;
00335 }
00336 }
00337
00338
00339
00340 else
00341 {
00342 #if defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
00343 ACE_TCHAR *file_component = 0;
00344 DWORD pathlen =
00345 ACE_TEXT_SearchPath (0,
00346 searchfilename,
00347 dll_suffix,
00348 static_cast<DWORD> (maxpathnamelen),
00349 pathname,
00350 &file_component);
00351 if (pathlen >= maxpathnamelen)
00352 {
00353 errno = ENOMEM;
00354 return -1;
00355 }
00356 else if (pathlen > 0)
00357 return 0;
00358
00359
00360
00361 ACE_OS::strcpy (searchfilename, ACE_DLL_PREFIX);
00362 ACE_OS::strcat (searchfilename, tempcopy);
00363 pathlen =
00364 ACE_TEXT_SearchPath (0,
00365 searchfilename,
00366 dll_suffix,
00367 static_cast<DWORD> (maxpathnamelen),
00368 pathname,
00369 &file_component);
00370 if (pathlen >= maxpathnamelen)
00371 {
00372 errno = ENOMEM;
00373 return -1;
00374 }
00375 else if (pathlen > 0)
00376 return 0;
00377 #else
00378 ACE_TCHAR *ld_path = 0;
00379 # if defined ACE_DEFAULT_LD_SEARCH_PATH
00380 ld_path = const_cast <ACE_TCHAR*> (ACE_DEFAULT_LD_SEARCH_PATH);
00381 # else
00382 # if defined (ACE_WIN32) || !defined (ACE_USES_WCHAR)
00383 ld_path = ACE_OS::getenv (ACE_LD_SEARCH_PATH);
00384 # else
00385
00386
00387 ACE_Ascii_To_Wide wide_ldpath
00388 (ACE_OS::getenv (ACE_TEXT_ALWAYS_CHAR (ACE_LD_SEARCH_PATH)));
00389 ld_path = wide_ldpath.wchar_rep ();
00390 # endif
00391 # endif
00392
00393 #if defined (ACE_HAS_WINCE)
00394 ACE_TCHAR *ld_path_temp = 0;
00395 if (ld_path != 0)
00396 {
00397 ld_path_temp = (ACE_TCHAR *)
00398 ACE_OS::malloc ((ACE_OS::strlen (ld_path) + 2)
00399 * sizeof (ACE_TCHAR));
00400 if (ld_path_temp != 0)
00401 {
00402 ACE_OS::strcpy (ld_path_temp,
00403 ACE_LD_SEARCH_PATH_SEPARATOR_STR);
00404
00405 ACE_OS::strcat (ld_path_temp, ld_path);
00406 ld_path = ld_path_temp;
00407 }
00408 else
00409 {
00410 ACE_OS::free ((void *) ld_path_temp);
00411 ld_path = ld_path_temp = 0;
00412 }
00413 }
00414 #endif
00415
00416 if (ld_path != 0
00417 && (ld_path = ACE_OS::strdup (ld_path)) != 0)
00418 {
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434 ACE_TCHAR *nextholder = 0;
00435 const ACE_TCHAR *path_entry =
00436 ACE::strsplit_r (ld_path,
00437 ACE_LD_SEARCH_PATH_SEPARATOR_STR,
00438 nextholder);
00439 int result = 0;
00440
00441 for (;;)
00442 {
00443
00444 if (path_entry == 0)
00445 {
00446 errno = ENOENT;
00447 result = -1;
00448 break;
00449 }
00450 else if (ACE_OS::strlen (path_entry)
00451 + 1
00452 + ACE_OS::strlen (searchfilename)
00453 >= maxpathnamelen)
00454 {
00455 errno = ENOMEM;
00456 result = -1;
00457 break;
00458 }
00459
00460
00461
00462
00463 else if (path_entry[0] == '\0')
00464 path_entry = ACE_TEXT (".");
00465
00466
00467
00468 ACE_OS::sprintf (pathname,
00469 ACE_TEXT ("%s%c%s%s"),
00470 path_entry,
00471 ACE_DIRECTORY_SEPARATOR_CHAR,
00472 searchfilename,
00473 has_suffix ? ACE_TEXT ("") : dll_suffix);
00474 if (ACE_OS::access (pathname, F_OK) == 0)
00475 break;
00476
00477
00478
00479 ACE_OS::sprintf (pathname,
00480 ACE_TEXT ("%s%c%s%s%s"),
00481 path_entry,
00482 ACE_DIRECTORY_SEPARATOR_CHAR,
00483 ACE_DLL_PREFIX,
00484 searchfilename,
00485 has_suffix ? ACE_TEXT ("") : dll_suffix);
00486 if (ACE_OS::access (pathname, F_OK) == 0)
00487 break;
00488
00489
00490 path_entry =
00491 ACE::strsplit_r (0,
00492 ACE_LD_SEARCH_PATH_SEPARATOR_STR,
00493 nextholder);
00494 }
00495
00496 #if defined (ACE_HAS_WINCE)
00497 if (ld_path_temp != 0)
00498 ACE_OS::free (ld_path_temp);
00499 #endif
00500 ACE_OS::free ((void *) ld_path);
00501 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
00502 if (result == 0 || tag == 0)
00503 #endif
00504 return result;
00505 }
00506 #endif
00507 }
00508 #if defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)
00509 }
00510 #endif
00511
00512 errno = ENOENT;
00513 return -1;
00514 }
00515
00516 FILE *
00517 ACE::ldopen (const ACE_TCHAR *filename,
00518 const ACE_TCHAR *type)
00519 {
00520 ACE_TRACE ("ACE::ldopen");
00521
00522 ACE_TCHAR buf[MAXPATHLEN + 1];
00523 if (ACE::ldfind (filename,
00524 buf,
00525 sizeof (buf) /sizeof (ACE_TCHAR)) == -1)
00526 return 0;
00527 else
00528 return ACE_OS::fopen (buf, type);
00529 }
00530
00531 ACE_TCHAR *
00532 ACE::ldname (const ACE_TCHAR *entry_point)
00533 {
00534 ACE_TRACE ("ACE::ldname");
00535
00536 #if defined(ACE_NEEDS_DL_UNDERSCORE)
00537 size_t size =
00538 1
00539 + ACE_OS::strlen (entry_point)
00540 + 1;
00541
00542 ACE_TCHAR *new_name;
00543 ACE_NEW_RETURN (new_name,
00544 ACE_TCHAR[size],
00545 0);
00546
00547 ACE_OS::strcpy (new_name, ACE_TEXT ("_"));
00548 ACE_OS::strcat (new_name, entry_point);
00549
00550 return new_name;
00551 #else
00552 size_t size =
00553 ACE_OS::strlen (entry_point)
00554 + 1;
00555
00556 ACE_TCHAR *new_name;
00557 ACE_NEW_RETURN (new_name,
00558 ACE_TCHAR[size],
00559 0);
00560
00561 ACE_OS::strcpy (new_name, entry_point);
00562 return new_name;
00563 #endif
00564 }
00565
00566 #if defined (ACE_OPENVMS)
00567 void
00568 ACE::ldregister (const ACE_TCHAR *entry_point,
00569 void* entry_addr)
00570 {
00571 ACE_LD_SYMBOL_REGISTRY::instance ()->register_symbol (entry_point,
00572 entry_addr);
00573 }
00574
00575 void *
00576 ACE::ldsymbol (ACE_SHLIB_HANDLE sh, const ACE_TCHAR *entry_point)
00577 {
00578 void* symaddr = ACE_OS::dlsym (sh, entry_point);
00579
00580 if (symaddr == 0)
00581 symaddr = ACE_LD_SYMBOL_REGISTRY::instance ()->find_symbol (entry_point);
00582
00583 return symaddr;
00584 }
00585 #endif
00586
00587 int
00588 ACE::get_temp_dir (ACE_TCHAR *buffer, size_t buffer_len)
00589 {
00590 int result;
00591 #if defined (ACE_WIN32)
00592 result = ACE_TEXT_GetTempPath (static_cast<DWORD> (buffer_len),
00593 buffer);
00594
00595
00596 if ((result == 0 && ::GetLastError () != ERROR_SUCCESS)
00597 || (result > static_cast<int> (buffer_len)))
00598 result = -1;
00599
00600 #else
00601
00602
00603
00604
00605
00606
00607
00608 const char *tmpdir = ACE_OS::getenv ("TMPDIR");
00609
00610 if (tmpdir == 0)
00611 tmpdir = "/tmp";
00612
00613 size_t len = ACE_OS::strlen (tmpdir);
00614
00615
00616
00617 if ((len + 2) > buffer_len)
00618 {
00619 result = -1;
00620 }
00621 else
00622 {
00623 ACE_OS::strcpy (buffer, ACE_TEXT_CHAR_TO_TCHAR (tmpdir));
00624
00625
00626
00627 buffer[len] = ACE_TEXT ('/');
00628 buffer[len + 1] = 0;
00629 result = 0;
00630 }
00631 #endif
00632 return result;
00633 }
00634
00635 ACE_HANDLE
00636 ACE::open_temp_file (const ACE_TCHAR *name, int mode, int perm)
00637 {
00638 #if defined (ACE_WIN32)
00639 ACE_UNUSED_ARG (perm);
00640 ACE_HANDLE handle = ACE_OS::open (name,
00641 mode,
00642 FILE_SHARE_READ
00643 | FILE_SHARE_WRITE
00644 | FILE_SHARE_DELETE);
00645 #else
00646
00647 ACE_HANDLE handle = ACE_OS::open (name, mode, perm);
00648 #endif
00649
00650 if (handle == ACE_INVALID_HANDLE)
00651 return ACE_INVALID_HANDLE;
00652
00653
00654
00655 if (ACE_OS::unlink (name) == -1)
00656 return ACE_INVALID_HANDLE;
00657 else
00658
00659 return handle;
00660 }
00661
00662 size_t
00663 ACE::strrepl (char *s, char search, char replace)
00664 {
00665 ACE_TRACE ("ACE::strrepl");
00666
00667 size_t replaced = 0;
00668
00669 for (size_t i = 0; s[i] != '\0'; i++)
00670 if (s[i] == search)
00671 {
00672 s[i] = replace;
00673 ++replaced;
00674 }
00675
00676 return replaced;
00677 }
00678
00679
00680
00681
00682
00683 char *
00684 ACE::strsplit_r (char *str,
00685 const char *token,
00686 char *&next_start)
00687 {
00688 char *result = 0;
00689
00690 if (str != 0)
00691 next_start = str;
00692
00693 if (next_start != 0)
00694 {
00695 char *tok_loc = ACE_OS::strstr (next_start, token);
00696
00697 if (tok_loc != 0)
00698 {
00699
00700 result = next_start;
00701
00702
00703 *tok_loc = '\0';
00704 next_start = tok_loc + ACE_OS::strlen (token);
00705 }
00706 else
00707 {
00708 result = next_start;
00709 next_start = (char *) 0;
00710 }
00711 }
00712
00713 return result;
00714 }
00715
00716 #if defined (ACE_HAS_WCHAR)
00717 wchar_t *
00718 ACE::strsplit_r (wchar_t *str,
00719 const wchar_t *token,
00720 wchar_t *&next_start)
00721 {
00722 wchar_t *result = 0;
00723
00724 if (str != 0)
00725 next_start = str;
00726
00727 if (next_start != 0)
00728 {
00729 wchar_t *tok_loc = ACE_OS::strstr (next_start, token);
00730
00731 if (tok_loc != 0)
00732 {
00733
00734 result = next_start;
00735
00736
00737 *tok_loc = '\0';
00738 next_start = tok_loc + ACE_OS::strlen (token);
00739 }
00740 else
00741 {
00742 result = next_start;
00743 next_start = (wchar_t *) 0;
00744 }
00745 }
00746
00747 return result;
00748 }
00749
00750 size_t
00751 ACE::strrepl (wchar_t *s, wchar_t search, wchar_t replace)
00752 {
00753 ACE_TRACE ("ACE::strrepl");
00754
00755 size_t replaced = 0;
00756
00757 for (size_t i = 0; s[i] != '\0'; i++)
00758 if (s[i] == search)
00759 {
00760 s[i] = replace;
00761 ++replaced;
00762 }
00763
00764 return replaced;
00765 }
00766 #endif
00767
00768 ACE_END_VERSIONED_NAMESPACE_DECL