ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rpc_binding.c
Go to the documentation of this file.
00001 /*
00002  * RPC binding API
00003  *
00004  * Copyright 2001 Ove Kåven, TransGaming Technologies
00005  * Copyright 2003 Mike Hearn
00006  * Copyright 2004 Filip Navara
00007  * Copyright 2006 CodeWeavers
00008  *
00009  * This library is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 2.1 of the License, or (at your option) any later version.
00013  *
00014  * This library is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00022  */
00023 
00024 #include <stdarg.h>
00025 #include <stdio.h>
00026 #include <string.h>
00027 #include <assert.h>
00028 
00029 #include "windef.h"
00030 #include "winbase.h"
00031 #include "winnls.h"
00032 #include "winerror.h"
00033 #include "winternl.h"
00034 #include "wine/unicode.h"
00035 
00036 #include "rpc.h"
00037 #include "rpcndr.h"
00038 
00039 #include "wine/debug.h"
00040 
00041 #include "rpc_binding.h"
00042 #include "rpc_assoc.h"
00043 
00044 WINE_DEFAULT_DEBUG_CHANNEL(rpc);
00045 
00046 LPSTR RPCRT4_strndupA(LPCSTR src, INT slen)
00047 {
00048   DWORD len;
00049   LPSTR s;
00050   if (!src) return NULL;
00051   if (slen == -1) slen = strlen(src);
00052   len = slen;
00053   s = HeapAlloc(GetProcessHeap(), 0, len+1);
00054   memcpy(s, src, len);
00055   s[len] = 0;
00056   return s;
00057 }
00058 
00059 LPSTR RPCRT4_strdupWtoA(LPCWSTR src)
00060 {
00061   DWORD len;
00062   LPSTR s;
00063   if (!src) return NULL;
00064   len = WideCharToMultiByte(CP_ACP, 0, src, -1, NULL, 0, NULL, NULL);
00065   s = HeapAlloc(GetProcessHeap(), 0, len);
00066   WideCharToMultiByte(CP_ACP, 0, src, -1, s, len, NULL, NULL);
00067   return s;
00068 }
00069 
00070 LPWSTR RPCRT4_strdupAtoW(LPCSTR src)
00071 {
00072   DWORD len;
00073   LPWSTR s;
00074   if (!src) return NULL;
00075   len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0);
00076   s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
00077   MultiByteToWideChar(CP_ACP, 0, src, -1, s, len);
00078   return s;
00079 }
00080 
00081 static LPWSTR RPCRT4_strndupAtoW(LPCSTR src, INT slen)
00082 {
00083   DWORD len;
00084   LPWSTR s;
00085   if (!src) return NULL;
00086   len = MultiByteToWideChar(CP_ACP, 0, src, slen, NULL, 0);
00087   s = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
00088   MultiByteToWideChar(CP_ACP, 0, src, slen, s, len);
00089   return s;
00090 }
00091 
00092 LPWSTR RPCRT4_strndupW(LPCWSTR src, INT slen)
00093 {
00094   DWORD len;
00095   LPWSTR s;
00096   if (!src) return NULL;
00097   if (slen == -1) slen = strlenW(src);
00098   len = slen;
00099   s = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
00100   memcpy(s, src, len*sizeof(WCHAR));
00101   s[len] = 0;
00102   return s;
00103 }
00104 
00105 void RPCRT4_strfree(LPSTR src)
00106 {
00107   HeapFree(GetProcessHeap(), 0, src);
00108 }
00109 
00110 static RPC_STATUS RPCRT4_AllocBinding(RpcBinding** Binding, BOOL server)
00111 {
00112   RpcBinding* NewBinding;
00113 
00114   NewBinding = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(RpcBinding));
00115   NewBinding->refs = 1;
00116   NewBinding->server = server;
00117 
00118   *Binding = NewBinding;
00119 
00120   return RPC_S_OK;
00121 }
00122 
00123 static RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPCSTR Protseq)
00124 {
00125   RpcBinding* NewBinding;
00126 
00127   RPCRT4_AllocBinding(&NewBinding, server);
00128   NewBinding->Protseq = RPCRT4_strdupA(Protseq);
00129 
00130   TRACE("binding: %p\n", NewBinding);
00131   *Binding = NewBinding;
00132 
00133   return RPC_S_OK;
00134 }
00135 
00136 static RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPCWSTR Protseq)
00137 {
00138   RpcBinding* NewBinding;
00139 
00140   RPCRT4_AllocBinding(&NewBinding, server);
00141   NewBinding->Protseq = RPCRT4_strdupWtoA(Protseq);
00142 
00143   TRACE("binding: %p\n", NewBinding);
00144   *Binding = NewBinding;
00145 
00146   return RPC_S_OK;
00147 }
00148 
00149 static RPC_STATUS RPCRT4_CompleteBindingA(RpcBinding* Binding, LPCSTR NetworkAddr,
00150                                           LPCSTR Endpoint, LPCSTR NetworkOptions)
00151 {
00152   RPC_STATUS status;
00153 
00154   TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding,
00155    debugstr_a(NetworkAddr), debugstr_a(Endpoint), debugstr_a(NetworkOptions));
00156 
00157   RPCRT4_strfree(Binding->NetworkAddr);
00158   Binding->NetworkAddr = RPCRT4_strdupA(NetworkAddr);
00159   RPCRT4_strfree(Binding->Endpoint);
00160   Binding->Endpoint = RPCRT4_strdupA(Endpoint);
00161   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
00162   Binding->NetworkOptions = RPCRT4_strdupAtoW(NetworkOptions);
00163 
00164   /* only attempt to get an association if the binding is complete */
00165   if (Endpoint && Endpoint[0] != '\0')
00166   {
00167     status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
00168                                    Binding->Endpoint, Binding->NetworkOptions,
00169                                    &Binding->Assoc);
00170     if (status != RPC_S_OK)
00171         return status;
00172   }
00173 
00174   return RPC_S_OK;
00175 }
00176 
00177 static RPC_STATUS RPCRT4_CompleteBindingW(RpcBinding* Binding, LPCWSTR NetworkAddr,
00178                                           LPCWSTR Endpoint, LPCWSTR NetworkOptions)
00179 {
00180   RPC_STATUS status;
00181 
00182   TRACE("(RpcBinding == ^%p, NetworkAddr == %s, EndPoint == %s, NetworkOptions == %s)\n", Binding, 
00183    debugstr_w(NetworkAddr), debugstr_w(Endpoint), debugstr_w(NetworkOptions));
00184 
00185   RPCRT4_strfree(Binding->NetworkAddr);
00186   Binding->NetworkAddr = RPCRT4_strdupWtoA(NetworkAddr);
00187   RPCRT4_strfree(Binding->Endpoint);
00188   Binding->Endpoint = RPCRT4_strdupWtoA(Endpoint);
00189   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
00190   Binding->NetworkOptions = RPCRT4_strdupW(NetworkOptions);
00191 
00192   /* only attempt to get an association if the binding is complete */
00193   if (Endpoint && Endpoint[0] != '\0')
00194   {
00195     status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
00196                                    Binding->Endpoint, Binding->NetworkOptions,
00197                                    &Binding->Assoc);
00198     if (status != RPC_S_OK)
00199         return status;
00200   }
00201 
00202   return RPC_S_OK;
00203 }
00204 
00205 RPC_STATUS RPCRT4_ResolveBinding(RpcBinding* Binding, LPCSTR Endpoint)
00206 {
00207   RPC_STATUS status;
00208 
00209   TRACE("(RpcBinding == ^%p, EndPoint == \"%s\"\n", Binding, Endpoint);
00210 
00211   RPCRT4_strfree(Binding->Endpoint);
00212   Binding->Endpoint = RPCRT4_strdupA(Endpoint);
00213 
00214   if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
00215   Binding->Assoc = NULL;
00216   status = RPCRT4_GetAssociation(Binding->Protseq, Binding->NetworkAddr,
00217                                  Binding->Endpoint, Binding->NetworkOptions,
00218                                  &Binding->Assoc);
00219   if (status != RPC_S_OK)
00220       return status;
00221 
00222   return RPC_S_OK;
00223 }
00224 
00225 RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, const UUID* ObjectUuid)
00226 {
00227   TRACE("(*RpcBinding == ^%p, UUID == %s)\n", Binding, debugstr_guid(ObjectUuid)); 
00228   if (ObjectUuid) Binding->ObjectUuid = *ObjectUuid;
00229   else UuidCreateNil(&Binding->ObjectUuid);
00230   return RPC_S_OK;
00231 }
00232 
00233 RPC_STATUS RPCRT4_MakeBinding(RpcBinding** Binding, RpcConnection* Connection)
00234 {
00235   RpcBinding* NewBinding;
00236   TRACE("(RpcBinding == ^%p, Connection == ^%p)\n", Binding, Connection);
00237 
00238   RPCRT4_AllocBinding(&NewBinding, Connection->server);
00239   NewBinding->Protseq = RPCRT4_strdupA(rpcrt4_conn_get_name(Connection));
00240   NewBinding->NetworkAddr = RPCRT4_strdupA(Connection->NetworkAddr);
00241   NewBinding->Endpoint = RPCRT4_strdupA(Connection->Endpoint);
00242   NewBinding->FromConn = Connection;
00243 
00244   TRACE("binding: %p\n", NewBinding);
00245   *Binding = NewBinding;
00246 
00247   return RPC_S_OK;
00248 }
00249 
00250 void RPCRT4_AddRefBinding(RpcBinding* Binding)
00251 {
00252   InterlockedIncrement(&Binding->refs);
00253 }
00254 
00255 RPC_STATUS RPCRT4_ReleaseBinding(RpcBinding* Binding)
00256 {
00257   if (InterlockedDecrement(&Binding->refs))
00258     return RPC_S_OK;
00259 
00260   TRACE("binding: %p\n", Binding);
00261   if (Binding->Assoc) RpcAssoc_Release(Binding->Assoc);
00262   RPCRT4_strfree(Binding->Endpoint);
00263   RPCRT4_strfree(Binding->NetworkAddr);
00264   RPCRT4_strfree(Binding->Protseq);
00265   HeapFree(GetProcessHeap(), 0, Binding->NetworkOptions);
00266   if (Binding->AuthInfo) RpcAuthInfo_Release(Binding->AuthInfo);
00267   if (Binding->QOS) RpcQualityOfService_Release(Binding->QOS);
00268   HeapFree(GetProcessHeap(), 0, Binding);
00269   return RPC_S_OK;
00270 }
00271 
00272 RPC_STATUS RPCRT4_OpenBinding(RpcBinding* Binding, RpcConnection** Connection,
00273                               const RPC_SYNTAX_IDENTIFIER *TransferSyntax,
00274                               const RPC_SYNTAX_IDENTIFIER *InterfaceId)
00275 {
00276   TRACE("(Binding == ^%p)\n", Binding);
00277 
00278   if (!Binding->server) {
00279      return RpcAssoc_GetClientConnection(Binding->Assoc, InterfaceId,
00280          TransferSyntax, Binding->AuthInfo, Binding->QOS, Connection);
00281   } else {
00282     /* we already have a connection with acceptable binding, so use it */
00283     if (Binding->FromConn) {
00284       *Connection = Binding->FromConn;
00285       return RPC_S_OK;
00286     } else {
00287        ERR("no connection in binding\n");
00288        return RPC_S_INTERNAL_ERROR;
00289     }
00290   }
00291 }
00292 
00293 RPC_STATUS RPCRT4_CloseBinding(RpcBinding* Binding, RpcConnection* Connection)
00294 {
00295   TRACE("(Binding == ^%p)\n", Binding);
00296   if (!Connection) return RPC_S_OK;
00297   if (Binding->server) {
00298     /* don't destroy a connection that is cached in the binding */
00299     if (Binding->FromConn == Connection)
00300       return RPC_S_OK;
00301     return RPCRT4_DestroyConnection(Connection);
00302   }
00303   else {
00304     RpcAssoc_ReleaseIdleConnection(Binding->Assoc, Connection);
00305     return RPC_S_OK;
00306   }
00307 }
00308 
00309 static LPSTR RPCRT4_strconcatA(LPSTR dst, LPCSTR src)
00310 {
00311   DWORD len = strlen(dst), slen = strlen(src);
00312   LPSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(CHAR));
00313   if (!ndst)
00314   {
00315     HeapFree(GetProcessHeap(), 0, dst);
00316     return NULL;
00317   }
00318   ndst[len] = ',';
00319   memcpy(ndst+len+1, src, slen+1);
00320   return ndst;
00321 }
00322 
00323 static LPWSTR RPCRT4_strconcatW(LPWSTR dst, LPCWSTR src)
00324 {
00325   DWORD len = strlenW(dst), slen = strlenW(src);
00326   LPWSTR ndst = HeapReAlloc(GetProcessHeap(), 0, dst, (len+slen+2)*sizeof(WCHAR));
00327   if (!ndst) 
00328   {
00329     HeapFree(GetProcessHeap(), 0, dst);
00330     return NULL;
00331   }
00332   ndst[len] = ',';
00333   memcpy(ndst+len+1, src, (slen+1)*sizeof(WCHAR));
00334   return ndst;
00335 }
00336 
00337 /* Copies the escaped version of a component into a string binding.
00338  * Note: doesn't nul-terminate the string */
00339 static RPC_CSTR escape_string_binding_component(RPC_CSTR string_binding,
00340                                                 const unsigned char *component)
00341 {
00342   for (; *component; component++) {
00343     switch (*component) {
00344       case '@':
00345       case ':':
00346       case '[':
00347       case ']':
00348       case '\\':
00349         *string_binding++ = '\\';
00350         *string_binding++ = *component;
00351         break;
00352       default:
00353         *string_binding++ = *component;
00354         break;
00355     }
00356   }
00357   return string_binding;
00358 }
00359 
00360 static RPC_WSTR escape_string_binding_componentW(RPC_WSTR string_binding,
00361                                                  const WCHAR *component)
00362 {
00363   for (; *component; component++) {
00364     switch (*component) {
00365       case '@':
00366       case ':':
00367       case '[':
00368       case ']':
00369       case '\\':
00370         *string_binding++ = '\\';
00371         *string_binding++ = *component;
00372         break;
00373       default:
00374         *string_binding++ = *component;
00375         break;
00376     }
00377   }
00378   return string_binding;
00379 }
00380 
00381 static const unsigned char *string_binding_find_delimiter(
00382     const unsigned char *string_binding, unsigned char delim)
00383 {
00384   const unsigned char *next;
00385   for (next = string_binding; *next; next++) {
00386     if (*next == '\\') {
00387       next++;
00388       continue;
00389     }
00390     if (*next == delim)
00391       return next;
00392   }
00393   return NULL;
00394 }
00395 
00396 static const WCHAR *string_binding_find_delimiterW(
00397     const WCHAR *string_binding, WCHAR delim)
00398 {
00399   const WCHAR *next;
00400   for (next = string_binding; *next; next++) {
00401     if (*next == '\\') {
00402       next++;
00403       continue;
00404     }
00405     if (*next == delim)
00406       return next;
00407   }
00408   return NULL;
00409 }
00410 
00411 static RPC_CSTR unescape_string_binding_component(
00412     const unsigned char *string_binding, int len)
00413 {
00414   RPC_CSTR component, p;
00415 
00416   if (len == -1) len = strlen((const char *)string_binding);
00417 
00418   component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
00419   if (!component) return NULL;
00420   for (p = component; len > 0; string_binding++, len--) {
00421     if (*string_binding == '\\') {
00422       string_binding++;
00423       len--;
00424       *p++ = *string_binding;
00425     } else {
00426       *p++ = *string_binding;
00427     }
00428   }
00429   *p = '\0';
00430   return component;
00431 }
00432 
00433 static RPC_WSTR unescape_string_binding_componentW(
00434     const WCHAR *string_binding, int len)
00435 {
00436   RPC_WSTR component, p;
00437 
00438   if (len == -1) len = strlenW(string_binding);
00439 
00440   component = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*component));
00441   if (!component) return NULL;
00442   for (p = component; len > 0; string_binding++, len--) {
00443     if (*string_binding == '\\') {
00444       string_binding++;
00445       len--;
00446       *p++ = *string_binding;
00447     } else {
00448       *p++ = *string_binding;
00449     }
00450   }
00451   *p = '\0';
00452   return component;
00453 }
00454 
00455 /***********************************************************************
00456  *             RpcStringBindingComposeA (RPCRT4.@)
00457  */
00458 RPC_STATUS WINAPI RpcStringBindingComposeA(RPC_CSTR ObjUuid, RPC_CSTR Protseq,
00459                                            RPC_CSTR NetworkAddr, RPC_CSTR Endpoint,
00460                                            RPC_CSTR Options, RPC_CSTR *StringBinding )
00461 {
00462   DWORD len = 1;
00463   RPC_CSTR data;
00464 
00465   TRACE( "(%s,%s,%s,%s,%s,%p)\n",
00466         debugstr_a( (char*)ObjUuid ), debugstr_a( (char*)Protseq ),
00467         debugstr_a( (char*)NetworkAddr ), debugstr_a( (char*)Endpoint ),
00468         debugstr_a( (char*)Options ), StringBinding );
00469 
00470   /* overestimate for each component for escaping of delimiters */
00471   if (ObjUuid && *ObjUuid) len += strlen((char*)ObjUuid) * 2 + 1;
00472   if (Protseq && *Protseq) len += strlen((char*)Protseq) * 2 + 1;
00473   if (NetworkAddr && *NetworkAddr) len += strlen((char*)NetworkAddr) * 2;
00474   if (Endpoint && *Endpoint) len += strlen((char*)Endpoint) * 2 + 2;
00475   if (Options && *Options) len += strlen((char*)Options) * 2 + 2;
00476 
00477   data = HeapAlloc(GetProcessHeap(), 0, len);
00478   *StringBinding = data;
00479 
00480   if (ObjUuid && *ObjUuid) {
00481     data = escape_string_binding_component(data, ObjUuid);
00482     *data++ = '@';
00483   }
00484   if (Protseq && *Protseq) {
00485     data = escape_string_binding_component(data, Protseq);
00486     *data++ = ':';
00487   }
00488   if (NetworkAddr && *NetworkAddr)
00489     data = escape_string_binding_component(data, NetworkAddr);
00490 
00491   if ((Endpoint && *Endpoint) ||
00492       (Options && *Options)) {
00493     *data++ = '[';
00494     if (Endpoint && *Endpoint) {
00495       data = escape_string_binding_component(data, Endpoint);
00496       if (Options && *Options) *data++ = ',';
00497     }
00498     if (Options && *Options) {
00499       data = escape_string_binding_component(data, Options);
00500     }
00501     *data++ = ']';
00502   }
00503   *data = 0;
00504 
00505   return RPC_S_OK;
00506 }
00507 
00508 /***********************************************************************
00509  *             RpcStringBindingComposeW (RPCRT4.@)
00510  */
00511 RPC_STATUS WINAPI RpcStringBindingComposeW( RPC_WSTR ObjUuid, RPC_WSTR Protseq,
00512                                             RPC_WSTR NetworkAddr, RPC_WSTR Endpoint,
00513                                             RPC_WSTR Options, RPC_WSTR* StringBinding )
00514 {
00515   DWORD len = 1;
00516   RPC_WSTR data;
00517 
00518   TRACE("(%s,%s,%s,%s,%s,%p)\n",
00519        debugstr_w( ObjUuid ), debugstr_w( Protseq ),
00520        debugstr_w( NetworkAddr ), debugstr_w( Endpoint ),
00521        debugstr_w( Options ), StringBinding);
00522 
00523   /* overestimate for each component for escaping of delimiters */
00524   if (ObjUuid && *ObjUuid) len += strlenW(ObjUuid) * 2 + 1;
00525   if (Protseq && *Protseq) len += strlenW(Protseq) * 2 + 1;
00526   if (NetworkAddr && *NetworkAddr) len += strlenW(NetworkAddr) * 2;
00527   if (Endpoint && *Endpoint) len += strlenW(Endpoint) * 2 + 2;
00528   if (Options && *Options) len += strlenW(Options) * 2 + 2;
00529 
00530   data = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
00531   *StringBinding = data;
00532 
00533   if (ObjUuid && *ObjUuid) {
00534     data = escape_string_binding_componentW(data, ObjUuid);
00535     *data++ = '@';
00536   }
00537   if (Protseq && *Protseq) {
00538     data = escape_string_binding_componentW(data, Protseq);
00539     *data++ = ':';
00540   }
00541   if (NetworkAddr && *NetworkAddr) {
00542     data = escape_string_binding_componentW(data, NetworkAddr);
00543   }
00544   if ((Endpoint && *Endpoint) ||
00545       (Options && *Options)) {
00546     *data++ = '[';
00547     if (Endpoint && *Endpoint) {
00548       data = escape_string_binding_componentW(data, Endpoint);
00549       if (Options && *Options) *data++ = ',';
00550     }
00551     if (Options && *Options) {
00552       data = escape_string_binding_componentW(data, Options);
00553     }
00554     *data++ = ']';
00555   }
00556   *data = 0;
00557 
00558   return RPC_S_OK;
00559 }
00560 
00561 
00562 /***********************************************************************
00563  *             RpcStringBindingParseA (RPCRT4.@)
00564  */
00565 RPC_STATUS WINAPI RpcStringBindingParseA( RPC_CSTR StringBinding, RPC_CSTR *ObjUuid,
00566                                           RPC_CSTR *Protseq, RPC_CSTR *NetworkAddr,
00567                                           RPC_CSTR *Endpoint, RPC_CSTR *Options)
00568 {
00569   const unsigned char *data, *next;
00570   static const char ep_opt[] = "endpoint=";
00571   BOOL endpoint_already_found = FALSE;
00572 
00573   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_a((char*)StringBinding),
00574        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
00575 
00576   if (ObjUuid) *ObjUuid = NULL;
00577   if (Protseq) *Protseq = NULL;
00578   if (NetworkAddr) *NetworkAddr = NULL;
00579   if (Endpoint) *Endpoint = NULL;
00580   if (Options) *Options = NULL;
00581 
00582   data = StringBinding;
00583 
00584   next = string_binding_find_delimiter(data, '@');
00585   if (next) {
00586     UUID uuid;
00587     RPC_STATUS status;
00588     RPC_CSTR str_uuid = unescape_string_binding_component(data, next - data);
00589     status = UuidFromStringA(str_uuid, &uuid);
00590     if (status != RPC_S_OK) {
00591       HeapFree(GetProcessHeap(), 0, str_uuid);
00592       return status;
00593     }
00594     if (ObjUuid)
00595       *ObjUuid = str_uuid;
00596     else
00597       HeapFree(GetProcessHeap(), 0, str_uuid);
00598     data = next+1;
00599   }
00600 
00601   next = string_binding_find_delimiter(data, ':');
00602   if (next) {
00603     if (Protseq) *Protseq = unescape_string_binding_component(data, next - data);
00604     data = next+1;
00605   }
00606 
00607   next = string_binding_find_delimiter(data, '[');
00608   if (next) {
00609     const unsigned char *close;
00610     RPC_CSTR opt;
00611 
00612     if (NetworkAddr) *NetworkAddr = unescape_string_binding_component(data, next - data);
00613     data = next+1;
00614     close = string_binding_find_delimiter(data, ']');
00615     if (!close) goto fail;
00616 
00617     /* tokenize options */
00618     while (data < close) {
00619       next = string_binding_find_delimiter(data, ',');
00620       if (!next || next > close) next = close;
00621       /* FIXME: this is kind of inefficient */
00622       opt = unescape_string_binding_component(data, next - data);
00623       data = next+1;
00624 
00625       /* parse option */
00626       next = string_binding_find_delimiter(opt, '=');
00627       if (!next) {
00628         /* not an option, must be an endpoint */
00629         if (endpoint_already_found) goto fail;
00630         if (Endpoint) *Endpoint = opt;
00631         else HeapFree(GetProcessHeap(), 0, opt);
00632         endpoint_already_found = TRUE;
00633       } else {
00634         if (strncmp((const char *)opt, ep_opt, strlen(ep_opt)) == 0) {
00635           /* endpoint option */
00636           if (endpoint_already_found) goto fail;
00637           if (Endpoint) *Endpoint = unescape_string_binding_component(next+1, -1);
00638           HeapFree(GetProcessHeap(), 0, opt);
00639           endpoint_already_found = TRUE;
00640         } else {
00641           /* network option */
00642           if (Options) {
00643             if (*Options) {
00644               /* FIXME: this is kind of inefficient */
00645               *Options = (unsigned char*) RPCRT4_strconcatA( (char*)*Options, (char *)opt);
00646               HeapFree(GetProcessHeap(), 0, opt);
00647             } else
00648               *Options = opt;
00649           } else
00650             HeapFree(GetProcessHeap(), 0, opt);
00651         }
00652       }
00653     }
00654 
00655     data = close+1;
00656     if (*data) goto fail;
00657   }
00658   else if (NetworkAddr) 
00659     *NetworkAddr = unescape_string_binding_component(data, -1);
00660 
00661   return RPC_S_OK;
00662 
00663 fail:
00664   if (ObjUuid) RpcStringFreeA(ObjUuid);
00665   if (Protseq) RpcStringFreeA(Protseq);
00666   if (NetworkAddr) RpcStringFreeA(NetworkAddr);
00667   if (Endpoint) RpcStringFreeA(Endpoint);
00668   if (Options) RpcStringFreeA(Options);
00669   return RPC_S_INVALID_STRING_BINDING;
00670 }
00671 
00672 /***********************************************************************
00673  *             RpcStringBindingParseW (RPCRT4.@)
00674  */
00675 RPC_STATUS WINAPI RpcStringBindingParseW( RPC_WSTR StringBinding, RPC_WSTR *ObjUuid,
00676                                           RPC_WSTR *Protseq, RPC_WSTR *NetworkAddr,
00677                                           RPC_WSTR *Endpoint, RPC_WSTR *Options)
00678 {
00679   const WCHAR *data, *next;
00680   static const WCHAR ep_opt[] = {'e','n','d','p','o','i','n','t','=',0};
00681   BOOL endpoint_already_found = FALSE;
00682 
00683   TRACE("(%s,%p,%p,%p,%p,%p)\n", debugstr_w(StringBinding),
00684        ObjUuid, Protseq, NetworkAddr, Endpoint, Options);
00685 
00686   if (ObjUuid) *ObjUuid = NULL;
00687   if (Protseq) *Protseq = NULL;
00688   if (NetworkAddr) *NetworkAddr = NULL;
00689   if (Endpoint) *Endpoint = NULL;
00690   if (Options) *Options = NULL;
00691 
00692   data = StringBinding;
00693 
00694   next = string_binding_find_delimiterW(data, '@');
00695   if (next) {
00696     UUID uuid;
00697     RPC_STATUS status;
00698     RPC_WSTR str_uuid = unescape_string_binding_componentW(data, next - data);
00699     status = UuidFromStringW(str_uuid, &uuid);
00700     if (status != RPC_S_OK) {
00701       HeapFree(GetProcessHeap(), 0, str_uuid);
00702       return status;
00703     }
00704     if (ObjUuid)
00705       *ObjUuid = str_uuid;
00706     else
00707       HeapFree(GetProcessHeap(), 0, str_uuid);
00708     data = next+1;
00709   }
00710 
00711   next = string_binding_find_delimiterW(data, ':');
00712   if (next) {
00713     if (Protseq) *Protseq = unescape_string_binding_componentW(data, next - data);
00714     data = next+1;
00715   }
00716 
00717   next = string_binding_find_delimiterW(data, '[');
00718   if (next) {
00719     const WCHAR *close;
00720     RPC_WSTR opt;
00721 
00722     if (NetworkAddr) *NetworkAddr = unescape_string_binding_componentW(data, next - data);
00723     data = next+1;
00724     close = string_binding_find_delimiterW(data, ']');
00725     if (!close) goto fail;
00726 
00727     /* tokenize options */
00728     while (data < close) {
00729       next = string_binding_find_delimiterW(data, ',');
00730       if (!next || next > close) next = close;
00731       /* FIXME: this is kind of inefficient */
00732       opt = unescape_string_binding_componentW(data, next - data);
00733       data = next+1;
00734 
00735       /* parse option */
00736       next = string_binding_find_delimiterW(opt, '=');
00737       if (!next) {
00738         /* not an option, must be an endpoint */
00739         if (endpoint_already_found) goto fail;
00740         if (Endpoint) *Endpoint = opt;
00741         else HeapFree(GetProcessHeap(), 0, opt);
00742         endpoint_already_found = TRUE;
00743       } else {
00744         if (strncmpW(opt, ep_opt, strlenW(ep_opt)) == 0) {
00745           /* endpoint option */
00746           if (endpoint_already_found) goto fail;
00747           if (Endpoint) *Endpoint = unescape_string_binding_componentW(next+1, -1);
00748           HeapFree(GetProcessHeap(), 0, opt);
00749           endpoint_already_found = TRUE;
00750         } else {
00751           /* network option */
00752           if (Options) {
00753             if (*Options) {
00754               /* FIXME: this is kind of inefficient */
00755               *Options = RPCRT4_strconcatW(*Options, opt);
00756               HeapFree(GetProcessHeap(), 0, opt);
00757             } else
00758               *Options = opt;
00759           } else
00760             HeapFree(GetProcessHeap(), 0, opt);
00761         }
00762       }
00763     }
00764 
00765     data = close+1;
00766     if (*data) goto fail;
00767   } else if (NetworkAddr) 
00768     *NetworkAddr = unescape_string_binding_componentW(data, -1);
00769 
00770   return RPC_S_OK;
00771 
00772 fail:
00773   if (ObjUuid) RpcStringFreeW(ObjUuid);
00774   if (Protseq) RpcStringFreeW(Protseq);
00775   if (NetworkAddr) RpcStringFreeW(NetworkAddr);
00776   if (Endpoint) RpcStringFreeW(Endpoint);
00777   if (Options) RpcStringFreeW(Options);
00778   return RPC_S_INVALID_STRING_BINDING;
00779 }
00780 
00781 /***********************************************************************
00782  *             RpcBindingFree (RPCRT4.@)
00783  */
00784 RPC_STATUS WINAPI RpcBindingFree( RPC_BINDING_HANDLE* Binding )
00785 {
00786   RPC_STATUS status;
00787   TRACE("(%p) = %p\n", Binding, *Binding);
00788   if (*Binding)
00789     status = RPCRT4_ReleaseBinding(*Binding);
00790   else
00791     status = RPC_S_INVALID_BINDING;
00792   if (status == RPC_S_OK) *Binding = NULL;
00793   return status;
00794 }
00795   
00796 /***********************************************************************
00797  *             RpcBindingVectorFree (RPCRT4.@)
00798  */
00799 RPC_STATUS WINAPI RpcBindingVectorFree( RPC_BINDING_VECTOR** BindingVector )
00800 {
00801   ULONG c;
00802 
00803   TRACE("(%p)\n", BindingVector);
00804   for (c=0; c<(*BindingVector)->Count; c++) RpcBindingFree(&(*BindingVector)->BindingH[c]);
00805   HeapFree(GetProcessHeap(), 0, *BindingVector);
00806   *BindingVector = NULL;
00807   return RPC_S_OK;
00808 }
00809   
00810 /***********************************************************************
00811  *             RpcBindingInqObject (RPCRT4.@)
00812  */
00813 RPC_STATUS WINAPI RpcBindingInqObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
00814 {
00815   RpcBinding* bind = Binding;
00816 
00817   TRACE("(%p,%p) = %s\n", Binding, ObjectUuid, debugstr_guid(&bind->ObjectUuid));
00818   *ObjectUuid = bind->ObjectUuid;
00819   return RPC_S_OK;
00820 }
00821 
00822 /***********************************************************************
00823  *             RpcBindingSetObject (RPCRT4.@)
00824  */
00825 RPC_STATUS WINAPI RpcBindingSetObject( RPC_BINDING_HANDLE Binding, UUID* ObjectUuid )
00826 {
00827   RpcBinding* bind = Binding;
00828 
00829   TRACE("(%p,%s)\n", Binding, debugstr_guid(ObjectUuid));
00830   if (bind->server) return RPC_S_WRONG_KIND_OF_BINDING;
00831   return RPCRT4_SetBindingObject(Binding, ObjectUuid);
00832 }
00833 
00834 /***********************************************************************
00835  *             RpcBindingFromStringBindingA (RPCRT4.@)
00836  */
00837 RPC_STATUS WINAPI RpcBindingFromStringBindingA( RPC_CSTR StringBinding, RPC_BINDING_HANDLE* Binding )
00838 {
00839   RPC_STATUS ret;
00840   RpcBinding* bind = NULL;
00841   RPC_CSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
00842   UUID Uuid;
00843 
00844   TRACE("(%s,%p)\n", debugstr_a((char*)StringBinding), Binding);
00845 
00846   ret = RpcStringBindingParseA(StringBinding, &ObjectUuid, &Protseq,
00847                               &NetworkAddr, &Endpoint, &Options);
00848   if (ret != RPC_S_OK) return ret;
00849 
00850   ret = UuidFromStringA(ObjectUuid, &Uuid);
00851 
00852   if (ret == RPC_S_OK)
00853     ret = RPCRT4_CreateBindingA(&bind, FALSE, (char*)Protseq);
00854   if (ret != RPC_S_OK) return ret;
00855   ret = RPCRT4_SetBindingObject(bind, &Uuid);
00856   if (ret == RPC_S_OK)
00857     ret = RPCRT4_CompleteBindingA(bind, (char*)NetworkAddr, (char*)Endpoint, (char*)Options);
00858 
00859   RpcStringFreeA(&Options);
00860   RpcStringFreeA(&Endpoint);
00861   RpcStringFreeA(&NetworkAddr);
00862   RpcStringFreeA(&Protseq);
00863   RpcStringFreeA(&ObjectUuid);
00864 
00865   if (ret == RPC_S_OK) 
00866     *Binding = (RPC_BINDING_HANDLE)bind;
00867   else 
00868     RPCRT4_ReleaseBinding(bind);
00869 
00870   return ret;
00871 }
00872 
00873 /***********************************************************************
00874  *             RpcBindingFromStringBindingW (RPCRT4.@)
00875  */
00876 RPC_STATUS WINAPI RpcBindingFromStringBindingW( RPC_WSTR StringBinding, RPC_BINDING_HANDLE* Binding )
00877 {
00878   RPC_STATUS ret;
00879   RpcBinding* bind = NULL;
00880   RPC_WSTR ObjectUuid, Protseq, NetworkAddr, Endpoint, Options;
00881   UUID Uuid;
00882 
00883   TRACE("(%s,%p)\n", debugstr_w(StringBinding), Binding);
00884 
00885   ret = RpcStringBindingParseW(StringBinding, &ObjectUuid, &Protseq,
00886                               &NetworkAddr, &Endpoint, &Options);
00887   if (ret != RPC_S_OK) return ret;
00888 
00889   ret = UuidFromStringW(ObjectUuid, &Uuid);
00890 
00891   if (ret == RPC_S_OK)
00892     ret = RPCRT4_CreateBindingW(&bind, FALSE, Protseq);
00893   if (ret != RPC_S_OK) return ret;
00894   ret = RPCRT4_SetBindingObject(bind, &Uuid);
00895   if (ret == RPC_S_OK)
00896     ret = RPCRT4_CompleteBindingW(bind, NetworkAddr, Endpoint, Options);
00897 
00898   RpcStringFreeW(&Options);
00899   RpcStringFreeW(&Endpoint);
00900   RpcStringFreeW(&NetworkAddr);
00901   RpcStringFreeW(&Protseq);
00902   RpcStringFreeW(&ObjectUuid);
00903 
00904   if (ret == RPC_S_OK)
00905     *Binding = (RPC_BINDING_HANDLE)bind;
00906   else
00907     RPCRT4_ReleaseBinding(bind);
00908 
00909   return ret;
00910 }
00911   
00912 /***********************************************************************
00913  *             RpcBindingToStringBindingA (RPCRT4.@)
00914  */
00915 RPC_STATUS WINAPI RpcBindingToStringBindingA( RPC_BINDING_HANDLE Binding, RPC_CSTR *StringBinding )
00916 {
00917   RPC_STATUS ret;
00918   RpcBinding* bind = Binding;
00919   RPC_CSTR ObjectUuid;
00920 
00921   TRACE("(%p,%p)\n", Binding, StringBinding);
00922 
00923   if (UuidIsNil(&bind->ObjectUuid, &ret))
00924     ObjectUuid = NULL;
00925   else
00926   {
00927     ret = UuidToStringA(&bind->ObjectUuid, &ObjectUuid);
00928     if (ret != RPC_S_OK) return ret;
00929   }
00930 
00931   ret = RpcStringBindingComposeA(ObjectUuid, (unsigned char*)bind->Protseq, (unsigned char*) bind->NetworkAddr,
00932                                  (unsigned char*) bind->Endpoint, NULL, StringBinding);
00933 
00934   RpcStringFreeA(&ObjectUuid);
00935 
00936   return ret;
00937 }
00938   
00939 /***********************************************************************
00940  *             RpcBindingToStringBindingW (RPCRT4.@)
00941  */
00942 RPC_STATUS WINAPI RpcBindingToStringBindingW( RPC_BINDING_HANDLE Binding, RPC_WSTR *StringBinding )
00943 {
00944   RPC_STATUS ret;
00945   unsigned char *str = NULL;
00946   TRACE("(%p,%p)\n", Binding, StringBinding);
00947   ret = RpcBindingToStringBindingA(Binding, &str);
00948   *StringBinding = RPCRT4_strdupAtoW((char*)str);
00949   RpcStringFreeA(&str);
00950   return ret;
00951 }
00952 
00953 /***********************************************************************
00954  *             I_RpcBindingInqTransportType (RPCRT4.@)
00955  */
00956 RPC_STATUS WINAPI I_RpcBindingInqTransportType( RPC_BINDING_HANDLE Binding, unsigned int * Type )
00957 {
00958 
00959   FIXME( "(%p,%p): stub\n", Binding, Type);
00960   *Type = TRANSPORT_TYPE_LPC;
00961   return RPC_S_OK;
00962 }
00963 
00964 /***********************************************************************
00965  *             I_RpcBindingSetAsync (RPCRT4.@)
00966  * NOTES
00967  *  Exists in win9x and winNT, but with different number of arguments
00968  *  (9x version has 3 arguments, NT has 2).
00969  */
00970 RPC_STATUS WINAPI I_RpcBindingSetAsync( RPC_BINDING_HANDLE Binding, RPC_BLOCKING_FN BlockingFn)
00971 {
00972   RpcBinding* bind = Binding;
00973 
00974   TRACE( "(%p,%p): stub\n", Binding, BlockingFn );
00975 
00976   bind->BlockingFn = BlockingFn;
00977 
00978   return RPC_S_OK;
00979 }
00980 
00981 /***********************************************************************
00982  *             RpcBindingCopy (RPCRT4.@)
00983  */
00984 RPC_STATUS RPC_ENTRY RpcBindingCopy(
00985   RPC_BINDING_HANDLE SourceBinding,
00986   RPC_BINDING_HANDLE* DestinationBinding)
00987 {
00988   RpcBinding *DestBinding;
00989   RpcBinding *SrcBinding = SourceBinding;
00990   RPC_STATUS status;
00991 
00992   TRACE("(%p, %p)\n", SourceBinding, DestinationBinding);
00993 
00994   status = RPCRT4_AllocBinding(&DestBinding, SrcBinding->server);
00995   if (status != RPC_S_OK) return status;
00996 
00997   DestBinding->ObjectUuid = SrcBinding->ObjectUuid;
00998   DestBinding->BlockingFn = SrcBinding->BlockingFn;
00999   DestBinding->Protseq = RPCRT4_strndupA(SrcBinding->Protseq, -1);
01000   DestBinding->NetworkAddr = RPCRT4_strndupA(SrcBinding->NetworkAddr, -1);
01001   DestBinding->Endpoint = RPCRT4_strndupA(SrcBinding->Endpoint, -1);
01002   DestBinding->NetworkOptions = RPCRT4_strdupW(SrcBinding->NetworkOptions);
01003   if (SrcBinding->Assoc) SrcBinding->Assoc->refs++;
01004   DestBinding->Assoc = SrcBinding->Assoc;
01005 
01006   if (SrcBinding->AuthInfo) RpcAuthInfo_AddRef(SrcBinding->AuthInfo);
01007   DestBinding->AuthInfo = SrcBinding->AuthInfo;
01008   if (SrcBinding->QOS) RpcQualityOfService_AddRef(SrcBinding->QOS);
01009   DestBinding->QOS = SrcBinding->QOS;
01010 
01011   *DestinationBinding = DestBinding;
01012   return RPC_S_OK;
01013 }
01014 
01015 /***********************************************************************
01016  *             RpcBindingReset (RPCRT4.@)
01017  */
01018 RPC_STATUS RPC_ENTRY RpcBindingReset(RPC_BINDING_HANDLE Binding)
01019 {
01020     RpcBinding *bind = Binding;
01021 
01022     TRACE("(%p)\n", Binding);
01023 
01024     RPCRT4_strfree(bind->Endpoint);
01025     bind->Endpoint = NULL;
01026     if (bind->Assoc) RpcAssoc_Release(bind->Assoc);
01027     bind->Assoc = NULL;
01028 
01029     return RPC_S_OK;
01030 }
01031 
01032 /***********************************************************************
01033  *             RpcImpersonateClient (RPCRT4.@)
01034  *
01035  * Impersonates the client connected via a binding handle so that security
01036  * checks are done in the context of the client.
01037  *
01038  * PARAMS
01039  *  BindingHandle [I] Handle to the binding to the client.
01040  *
01041  * RETURNS
01042  *  Success: RPS_S_OK.
01043  *  Failure: RPC_STATUS value.
01044  *
01045  * NOTES
01046  *
01047  * If BindingHandle is NULL then the function impersonates the client
01048  * connected to the binding handle of the current thread.
01049  */
01050 RPC_STATUS WINAPI RpcImpersonateClient(RPC_BINDING_HANDLE BindingHandle)
01051 {
01052     RpcBinding *bind;
01053 
01054     TRACE("(%p)\n", BindingHandle);
01055 
01056     if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
01057     if (!BindingHandle) return RPC_S_INVALID_BINDING;
01058 
01059     bind = BindingHandle;
01060     if (bind->FromConn)
01061         return rpcrt4_conn_impersonate_client(bind->FromConn);
01062     return RPC_S_WRONG_KIND_OF_BINDING;
01063 }
01064 
01065 /***********************************************************************
01066  *             RpcRevertToSelfEx (RPCRT4.@)
01067  *
01068  * Stops impersonating the client connected to the binding handle so that security
01069  * checks are no longer done in the context of the client.
01070  *
01071  * PARAMS
01072  *  BindingHandle [I] Handle to the binding to the client.
01073  *
01074  * RETURNS
01075  *  Success: RPS_S_OK.
01076  *  Failure: RPC_STATUS value.
01077  *
01078  * NOTES
01079  *
01080  * If BindingHandle is NULL then the function stops impersonating the client
01081  * connected to the binding handle of the current thread.
01082  */
01083 RPC_STATUS WINAPI RpcRevertToSelfEx(RPC_BINDING_HANDLE BindingHandle)
01084 {
01085     RpcBinding *bind;
01086 
01087     TRACE("(%p)\n", BindingHandle);
01088 
01089     if (!BindingHandle) BindingHandle = I_RpcGetCurrentCallHandle();
01090     if (!BindingHandle) return RPC_S_INVALID_BINDING;
01091 
01092     bind = BindingHandle;
01093     if (bind->FromConn)
01094         return rpcrt4_conn_revert_to_self(bind->FromConn);
01095     return RPC_S_WRONG_KIND_OF_BINDING;
01096 }
01097 
01098 static inline BOOL has_nt_auth_identity(ULONG AuthnLevel)
01099 {
01100     switch (AuthnLevel)
01101     {
01102     case RPC_C_AUTHN_GSS_NEGOTIATE:
01103     case RPC_C_AUTHN_WINNT:
01104     case RPC_C_AUTHN_GSS_KERBEROS:
01105         return TRUE;
01106     default:
01107         return FALSE;
01108     }
01109 }
01110 
01111 RPC_STATUS RpcAuthInfo_Create(ULONG AuthnLevel, ULONG AuthnSvc,
01112                               CredHandle cred, TimeStamp exp,
01113                               ULONG cbMaxToken,
01114                               RPC_AUTH_IDENTITY_HANDLE identity,
01115                               RpcAuthInfo **ret)
01116 {
01117     RpcAuthInfo *AuthInfo = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo));
01118     if (!AuthInfo)
01119         return ERROR_OUTOFMEMORY;
01120 
01121     AuthInfo->refs = 1;
01122     AuthInfo->AuthnLevel = AuthnLevel;
01123     AuthInfo->AuthnSvc = AuthnSvc;
01124     AuthInfo->cred = cred;
01125     AuthInfo->exp = exp;
01126     AuthInfo->cbMaxToken = cbMaxToken;
01127     AuthInfo->identity = identity;
01128     AuthInfo->server_principal_name = NULL;
01129 
01130     /* duplicate the SEC_WINNT_AUTH_IDENTITY structure, if applicable, to
01131      * enable better matching in RpcAuthInfo_IsEqual */
01132     if (identity && has_nt_auth_identity(AuthnSvc))
01133     {
01134         const SEC_WINNT_AUTH_IDENTITY_W *nt_identity = identity;
01135         AuthInfo->nt_identity = HeapAlloc(GetProcessHeap(), 0, sizeof(*AuthInfo->nt_identity));
01136         if (!AuthInfo->nt_identity)
01137         {
01138             HeapFree(GetProcessHeap(), 0, AuthInfo);
01139             return ERROR_OUTOFMEMORY;
01140         }
01141 
01142         AuthInfo->nt_identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
01143         if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
01144             AuthInfo->nt_identity->User = RPCRT4_strndupW(nt_identity->User, nt_identity->UserLength);
01145         else
01146             AuthInfo->nt_identity->User = RPCRT4_strndupAtoW((const char *)nt_identity->User, nt_identity->UserLength);
01147         AuthInfo->nt_identity->UserLength = nt_identity->UserLength;
01148         if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
01149             AuthInfo->nt_identity->Domain = RPCRT4_strndupW(nt_identity->Domain, nt_identity->DomainLength);
01150         else
01151             AuthInfo->nt_identity->Domain = RPCRT4_strndupAtoW((const char *)nt_identity->Domain, nt_identity->DomainLength);
01152         AuthInfo->nt_identity->DomainLength = nt_identity->DomainLength;
01153         if (nt_identity->Flags & SEC_WINNT_AUTH_IDENTITY_UNICODE)
01154             AuthInfo->nt_identity->Password = RPCRT4_strndupW(nt_identity->Password, nt_identity->PasswordLength);
01155         else
01156             AuthInfo->nt_identity->Password = RPCRT4_strndupAtoW((const char *)nt_identity->Password, nt_identity->PasswordLength);
01157         AuthInfo->nt_identity->PasswordLength = nt_identity->PasswordLength;
01158 
01159         if ((nt_identity->User && !AuthInfo->nt_identity->User) ||
01160             (nt_identity->Domain && !AuthInfo->nt_identity->Domain) ||
01161             (nt_identity->Password && !AuthInfo->nt_identity->Password))
01162         {
01163             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
01164             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
01165             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
01166             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
01167             HeapFree(GetProcessHeap(), 0, AuthInfo);
01168             return ERROR_OUTOFMEMORY;
01169         }
01170     }
01171     else
01172         AuthInfo->nt_identity = NULL;
01173     *ret = AuthInfo;
01174     return RPC_S_OK;
01175 }
01176 
01177 ULONG RpcAuthInfo_AddRef(RpcAuthInfo *AuthInfo)
01178 {
01179     return InterlockedIncrement(&AuthInfo->refs);
01180 }
01181 
01182 ULONG RpcAuthInfo_Release(RpcAuthInfo *AuthInfo)
01183 {
01184     ULONG refs = InterlockedDecrement(&AuthInfo->refs);
01185 
01186     if (!refs)
01187     {
01188         FreeCredentialsHandle(&AuthInfo->cred);
01189         if (AuthInfo->nt_identity)
01190         {
01191             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->User);
01192             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Domain);
01193             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity->Password);
01194             HeapFree(GetProcessHeap(), 0, AuthInfo->nt_identity);
01195         }
01196         HeapFree(GetProcessHeap(), 0, AuthInfo->server_principal_name);
01197         HeapFree(GetProcessHeap(), 0, AuthInfo);
01198     }
01199 
01200     return refs;
01201 }
01202 
01203 BOOL RpcAuthInfo_IsEqual(const RpcAuthInfo *AuthInfo1, const RpcAuthInfo *AuthInfo2)
01204 {
01205     if (AuthInfo1 == AuthInfo2)
01206         return TRUE;
01207 
01208     if (!AuthInfo1 || !AuthInfo2)
01209         return FALSE;
01210 
01211     if ((AuthInfo1->AuthnLevel != AuthInfo2->AuthnLevel) ||
01212         (AuthInfo1->AuthnSvc != AuthInfo2->AuthnSvc))
01213         return FALSE;
01214 
01215     if (AuthInfo1->identity == AuthInfo2->identity)
01216         return TRUE;
01217 
01218     if (!AuthInfo1->identity || !AuthInfo2->identity)
01219         return FALSE;
01220 
01221     if (has_nt_auth_identity(AuthInfo1->AuthnSvc))
01222     {
01223         const SEC_WINNT_AUTH_IDENTITY_W *identity1 = AuthInfo1->nt_identity;
01224         const SEC_WINNT_AUTH_IDENTITY_W *identity2 = AuthInfo2->nt_identity;
01225         /* compare user names */
01226         if (identity1->UserLength != identity2->UserLength ||
01227             memcmp(identity1->User, identity2->User, identity1->UserLength))
01228             return FALSE;
01229         /* compare domain names */
01230         if (identity1->DomainLength != identity2->DomainLength ||
01231             memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
01232             return FALSE;
01233         /* compare passwords */
01234         if (identity1->PasswordLength != identity2->PasswordLength ||
01235             memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
01236             return FALSE;
01237     }
01238     else
01239         return FALSE;
01240 
01241     return TRUE;
01242 }
01243 
01244 static RPC_STATUS RpcQualityOfService_Create(const RPC_SECURITY_QOS *qos_src, BOOL unicode, RpcQualityOfService **qos_dst)
01245 {
01246     RpcQualityOfService *qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos));
01247 
01248     if (!qos)
01249         return RPC_S_OUT_OF_RESOURCES;
01250 
01251     qos->refs = 1;
01252     qos->qos = HeapAlloc(GetProcessHeap(), 0, sizeof(*qos->qos));
01253     if (!qos->qos) goto error;
01254     qos->qos->Version = qos_src->Version;
01255     qos->qos->Capabilities = qos_src->Capabilities;
01256     qos->qos->IdentityTracking = qos_src->IdentityTracking;
01257     qos->qos->ImpersonationType = qos_src->ImpersonationType;
01258     qos->qos->AdditionalSecurityInfoType = 0;
01259 
01260     if (qos_src->Version >= 2)
01261     {
01262         const RPC_SECURITY_QOS_V2_W *qos_src2 = (const RPC_SECURITY_QOS_V2_W *)qos_src;
01263         qos->qos->AdditionalSecurityInfoType = qos_src2->AdditionalSecurityInfoType;
01264         if (qos_src2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
01265         {
01266             const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_src = qos_src2->u.HttpCredentials;
01267             RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials_dst;
01268 
01269             http_credentials_dst = HeapAlloc(GetProcessHeap(), 0, sizeof(*http_credentials_dst));
01270             qos->qos->u.HttpCredentials = http_credentials_dst;
01271             if (!http_credentials_dst) goto error;
01272             http_credentials_dst->TransportCredentials = NULL;
01273             http_credentials_dst->Flags = http_credentials_src->Flags;
01274             http_credentials_dst->AuthenticationTarget = http_credentials_src->AuthenticationTarget;
01275             http_credentials_dst->NumberOfAuthnSchemes = http_credentials_src->NumberOfAuthnSchemes;
01276             http_credentials_dst->AuthnSchemes = NULL;
01277             http_credentials_dst->ServerCertificateSubject = NULL;
01278             if (http_credentials_src->TransportCredentials)
01279             {
01280                 SEC_WINNT_AUTH_IDENTITY_W *cred_dst;
01281                 cred_dst = http_credentials_dst->TransportCredentials = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*cred_dst));
01282                 if (!cred_dst) goto error;
01283                 cred_dst->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
01284                 if (unicode)
01285                 {
01286                     const SEC_WINNT_AUTH_IDENTITY_W *cred_src = http_credentials_src->TransportCredentials;
01287                     cred_dst->UserLength = cred_src->UserLength;
01288                     cred_dst->PasswordLength = cred_src->PasswordLength;
01289                     cred_dst->DomainLength = cred_src->DomainLength;
01290                     cred_dst->User = RPCRT4_strndupW(cred_src->User, cred_src->UserLength);
01291                     cred_dst->Password = RPCRT4_strndupW(cred_src->Password, cred_src->PasswordLength);
01292                     cred_dst->Domain = RPCRT4_strndupW(cred_src->Domain, cred_src->DomainLength);
01293                 }
01294                 else
01295                 {
01296                     const SEC_WINNT_AUTH_IDENTITY_A *cred_src = (const SEC_WINNT_AUTH_IDENTITY_A *)http_credentials_src->TransportCredentials;
01297                     cred_dst->UserLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, NULL, 0);
01298                     cred_dst->DomainLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, NULL, 0);
01299                     cred_dst->PasswordLength = MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, NULL, 0);
01300                     cred_dst->User = HeapAlloc(GetProcessHeap(), 0, cred_dst->UserLength * sizeof(WCHAR));
01301                     cred_dst->Password = HeapAlloc(GetProcessHeap(), 0, cred_dst->PasswordLength * sizeof(WCHAR));
01302                     cred_dst->Domain = HeapAlloc(GetProcessHeap(), 0, cred_dst->DomainLength * sizeof(WCHAR));
01303                     if (!cred_dst->Password || !cred_dst->Domain) goto error;
01304                     MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->User, cred_src->UserLength, cred_dst->User, cred_dst->UserLength);
01305                     MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Domain, cred_src->DomainLength, cred_dst->Domain, cred_dst->DomainLength);
01306                     MultiByteToWideChar(CP_ACP, 0, (char *)cred_src->Password, cred_src->PasswordLength, cred_dst->Password, cred_dst->PasswordLength);
01307                 }
01308             }
01309             if (http_credentials_src->NumberOfAuthnSchemes)
01310             {
01311                 http_credentials_dst->AuthnSchemes = HeapAlloc(GetProcessHeap(), 0, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
01312                 if (!http_credentials_dst->AuthnSchemes) goto error;
01313                 memcpy(http_credentials_dst->AuthnSchemes, http_credentials_src->AuthnSchemes, http_credentials_src->NumberOfAuthnSchemes * sizeof(*http_credentials_dst->AuthnSchemes));
01314             }
01315             if (http_credentials_src->ServerCertificateSubject)
01316             {
01317                 if (unicode)
01318                     http_credentials_dst->ServerCertificateSubject =
01319                         RPCRT4_strndupW(http_credentials_src->ServerCertificateSubject,
01320                                         strlenW(http_credentials_src->ServerCertificateSubject));
01321                 else
01322                     http_credentials_dst->ServerCertificateSubject =
01323                         RPCRT4_strdupAtoW((char *)http_credentials_src->ServerCertificateSubject);
01324                 if (!http_credentials_dst->ServerCertificateSubject) goto error;
01325             }
01326         }
01327     }
01328     *qos_dst = qos;
01329     return RPC_S_OK;
01330 
01331 error:
01332     if (qos->qos)
01333     {
01334         if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP &&
01335             qos->qos->u.HttpCredentials)
01336         {
01337             if (qos->qos->u.HttpCredentials->TransportCredentials)
01338             {
01339                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
01340                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
01341                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
01342                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
01343             }
01344             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
01345             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
01346             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
01347         }
01348         HeapFree(GetProcessHeap(), 0, qos->qos);
01349     }
01350     HeapFree(GetProcessHeap(), 0, qos);
01351     return RPC_S_OUT_OF_RESOURCES;
01352 }
01353 
01354 ULONG RpcQualityOfService_AddRef(RpcQualityOfService *qos)
01355 {
01356     return InterlockedIncrement(&qos->refs);
01357 }
01358 
01359 ULONG RpcQualityOfService_Release(RpcQualityOfService *qos)
01360 {
01361     ULONG refs = InterlockedDecrement(&qos->refs);
01362 
01363     if (!refs)
01364     {
01365         if (qos->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
01366         {
01367             if (qos->qos->u.HttpCredentials->TransportCredentials)
01368             {
01369                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->User);
01370                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Domain);
01371                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials->Password);
01372                 HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->TransportCredentials);
01373             }
01374             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->AuthnSchemes);
01375             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials->ServerCertificateSubject);
01376             HeapFree(GetProcessHeap(), 0, qos->qos->u.HttpCredentials);
01377         }
01378         HeapFree(GetProcessHeap(), 0, qos->qos);
01379         HeapFree(GetProcessHeap(), 0, qos);
01380     }
01381     return refs;
01382 }
01383 
01384 BOOL RpcQualityOfService_IsEqual(const RpcQualityOfService *qos1, const RpcQualityOfService *qos2)
01385 {
01386     if (qos1 == qos2)
01387         return TRUE;
01388 
01389     if (!qos1 || !qos2)
01390         return FALSE;
01391 
01392     TRACE("qos1 = { %d %d %d %d }, qos2 = { %d %d %d %d }\n",
01393         qos1->qos->Capabilities, qos1->qos->IdentityTracking,
01394         qos1->qos->ImpersonationType, qos1->qos->AdditionalSecurityInfoType,
01395         qos2->qos->Capabilities, qos2->qos->IdentityTracking,
01396         qos2->qos->ImpersonationType, qos2->qos->AdditionalSecurityInfoType);
01397 
01398     if ((qos1->qos->Capabilities != qos2->qos->Capabilities) ||
01399         (qos1->qos->IdentityTracking != qos2->qos->IdentityTracking) ||
01400         (qos1->qos->ImpersonationType != qos2->qos->ImpersonationType) ||
01401         (qos1->qos->AdditionalSecurityInfoType != qos2->qos->AdditionalSecurityInfoType))
01402         return FALSE;
01403 
01404     if (qos1->qos->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
01405     {
01406         const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials1 = qos1->qos->u.HttpCredentials;
01407         const RPC_HTTP_TRANSPORT_CREDENTIALS_W *http_credentials2 = qos2->qos->u.HttpCredentials;
01408 
01409         if (http_credentials1->Flags != http_credentials2->Flags)
01410             return FALSE;
01411 
01412         if (http_credentials1->AuthenticationTarget != http_credentials2->AuthenticationTarget)
01413             return FALSE;
01414 
01415         /* authentication schemes and server certificate subject not currently used */
01416 
01417         if (http_credentials1->TransportCredentials != http_credentials2->TransportCredentials)
01418         {
01419             const SEC_WINNT_AUTH_IDENTITY_W *identity1 = http_credentials1->TransportCredentials;
01420             const SEC_WINNT_AUTH_IDENTITY_W *identity2 = http_credentials2->TransportCredentials;
01421 
01422             if (!identity1 || !identity2)
01423                 return FALSE;
01424 
01425             /* compare user names */
01426             if (identity1->UserLength != identity2->UserLength ||
01427                 memcmp(identity1->User, identity2->User, identity1->UserLength))
01428                 return FALSE;
01429             /* compare domain names */
01430             if (identity1->DomainLength != identity2->DomainLength ||
01431                 memcmp(identity1->Domain, identity2->Domain, identity1->DomainLength))
01432                 return FALSE;
01433             /* compare passwords */
01434             if (identity1->PasswordLength != identity2->PasswordLength ||
01435                 memcmp(identity1->Password, identity2->Password, identity1->PasswordLength))
01436                 return FALSE;
01437         }
01438     }
01439 
01440     return TRUE;
01441 }
01442 
01443 /***********************************************************************
01444  *             RpcRevertToSelf (RPCRT4.@)
01445  */
01446 RPC_STATUS WINAPI RpcRevertToSelf(void)
01447 {
01448     TRACE("\n");
01449     return RpcRevertToSelfEx(NULL);
01450 }
01451 
01452 /***********************************************************************
01453  *             RpcMgmtSetComTimeout (RPCRT4.@)
01454  */
01455 RPC_STATUS WINAPI RpcMgmtSetComTimeout(RPC_BINDING_HANDLE BindingHandle, unsigned int Timeout)
01456 {
01457     FIXME("(%p, %d): stub\n", BindingHandle, Timeout);
01458     return RPC_S_OK;
01459 }
01460 
01461 /***********************************************************************
01462  *             RpcBindingInqAuthInfoExA (RPCRT4.@)
01463  */
01464 RPCRTAPI RPC_STATUS RPC_ENTRY
01465 RpcBindingInqAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
01466                           ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
01467                           ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
01468 {
01469     RPC_STATUS status;
01470     RPC_WSTR principal;
01471 
01472     TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
01473           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
01474 
01475     status = RpcBindingInqAuthInfoExW(Binding, ServerPrincName ? &principal : NULL, AuthnLevel,
01476                                       AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
01477     if (status == RPC_S_OK && ServerPrincName)
01478     {
01479         *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
01480         RpcStringFreeW(&principal);
01481         if (!*ServerPrincName) return ERROR_OUTOFMEMORY;
01482     }
01483 
01484     return status;
01485 }
01486 
01487 /***********************************************************************
01488  *             RpcBindingInqAuthInfoExW (RPCRT4.@)
01489  */
01490 RPCRTAPI RPC_STATUS RPC_ENTRY
01491 RpcBindingInqAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
01492                           ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc,
01493                           ULONG RpcQosVersion, RPC_SECURITY_QOS *SecurityQOS )
01494 {
01495     RpcBinding *bind = Binding;
01496 
01497     TRACE("%p %p %p %p %p %p %u %p\n", Binding, ServerPrincName, AuthnLevel,
01498           AuthnSvc, AuthIdentity, AuthzSvc, RpcQosVersion, SecurityQOS);
01499 
01500     if (!bind->AuthInfo) return RPC_S_BINDING_HAS_NO_AUTH;
01501 
01502     if (SecurityQOS)
01503     {
01504         FIXME("QOS not implemented\n");
01505         return RPC_S_INVALID_BINDING;
01506     }
01507 
01508     if (ServerPrincName)
01509     {
01510         if (bind->AuthInfo->server_principal_name)
01511         {
01512             *ServerPrincName = RPCRT4_strdupW(bind->AuthInfo->server_principal_name);
01513             if (!*ServerPrincName) return ERROR_OUTOFMEMORY;
01514         }
01515         else *ServerPrincName = NULL;
01516     }
01517     if (AuthnLevel) *AuthnLevel = bind->AuthInfo->AuthnLevel;
01518     if (AuthnSvc) *AuthnSvc = bind->AuthInfo->AuthnSvc;
01519     if (AuthIdentity) *AuthIdentity = bind->AuthInfo->identity;
01520     if (AuthzSvc)
01521     {
01522         FIXME("authorization service not implemented\n");
01523         *AuthzSvc = RPC_C_AUTHZ_NONE;
01524     }
01525 
01526     return RPC_S_OK;
01527 }
01528 
01529 /***********************************************************************
01530  *             RpcBindingInqAuthInfoA (RPCRT4.@)
01531  */
01532 RPCRTAPI RPC_STATUS RPC_ENTRY
01533 RpcBindingInqAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR *ServerPrincName, ULONG *AuthnLevel,
01534                         ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
01535 {
01536     return RpcBindingInqAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
01537                                     AuthzSvc, 0, NULL);
01538 }
01539 
01540 /***********************************************************************
01541  *             RpcBindingInqAuthInfoW (RPCRT4.@)
01542  */
01543 RPCRTAPI RPC_STATUS RPC_ENTRY
01544 RpcBindingInqAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR *ServerPrincName, ULONG *AuthnLevel,
01545                         ULONG *AuthnSvc, RPC_AUTH_IDENTITY_HANDLE *AuthIdentity, ULONG *AuthzSvc )
01546 {
01547     return RpcBindingInqAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity,
01548                                     AuthzSvc, 0, NULL);
01549 }
01550 
01551 /***********************************************************************
01552  *             RpcBindingInqAuthClientA (RPCRT4.@)
01553  */
01554 RPCRTAPI RPC_STATUS RPC_ENTRY
01555 RpcBindingInqAuthClientA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
01556                           RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
01557                           ULONG *AuthzSvc )
01558 {
01559     return RpcBindingInqAuthClientExA(ClientBinding, Privs, ServerPrincName, AuthnLevel,
01560                                       AuthnSvc, AuthzSvc, 0);
01561 }
01562 
01563 /***********************************************************************
01564  *             RpcBindingInqAuthClientW (RPCRT4.@)
01565  */
01566 RPCRTAPI RPC_STATUS RPC_ENTRY
01567 RpcBindingInqAuthClientW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
01568                           RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
01569                           ULONG *AuthzSvc )
01570 {
01571     return RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName, AuthnLevel,
01572                                       AuthnSvc, AuthzSvc, 0);
01573 }
01574 
01575 /***********************************************************************
01576  *             RpcBindingInqAuthClientExA (RPCRT4.@)
01577  */
01578 RPCRTAPI RPC_STATUS RPC_ENTRY
01579 RpcBindingInqAuthClientExA( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
01580                             RPC_CSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
01581                             ULONG *AuthzSvc, ULONG Flags )
01582 {
01583     RPC_STATUS status;
01584     RPC_WSTR principal;
01585 
01586     TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
01587           AuthnSvc, AuthzSvc, Flags);
01588 
01589     status = RpcBindingInqAuthClientExW(ClientBinding, Privs, ServerPrincName ? &principal : NULL,
01590                                         AuthnLevel, AuthnSvc, AuthzSvc, Flags);
01591     if (status == RPC_S_OK && ServerPrincName)
01592     {
01593         *ServerPrincName = (RPC_CSTR)RPCRT4_strdupWtoA(principal);
01594         if (!*ServerPrincName && principal) status = ERROR_OUTOFMEMORY;
01595         RpcStringFreeW(&principal);
01596     }
01597 
01598     return status;
01599 }
01600 
01601 /***********************************************************************
01602  *             RpcBindingInqAuthClientExW (RPCRT4.@)
01603  */
01604 RPCRTAPI RPC_STATUS RPC_ENTRY
01605 RpcBindingInqAuthClientExW( RPC_BINDING_HANDLE ClientBinding, RPC_AUTHZ_HANDLE *Privs,
01606                             RPC_WSTR *ServerPrincName, ULONG *AuthnLevel, ULONG *AuthnSvc,
01607                             ULONG *AuthzSvc, ULONG Flags )
01608 {
01609     RpcBinding *bind = ClientBinding;
01610 
01611     TRACE("%p %p %p %p %p %p 0x%x\n", ClientBinding, Privs, ServerPrincName, AuthnLevel,
01612           AuthnSvc, AuthzSvc, Flags);
01613 
01614     if (!bind->FromConn) return RPC_S_INVALID_BINDING;
01615 
01616     return rpcrt4_conn_inquire_auth_client(bind->FromConn, Privs,
01617                                            ServerPrincName, AuthnLevel,
01618                                            AuthnSvc, AuthzSvc, Flags);
01619 }
01620 
01621 /***********************************************************************
01622  *             RpcBindingSetAuthInfoExA (RPCRT4.@)
01623  */
01624 RPCRTAPI RPC_STATUS RPC_ENTRY
01625 RpcBindingSetAuthInfoExA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName,
01626                           ULONG AuthnLevel, ULONG AuthnSvc,
01627                           RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
01628                           RPC_SECURITY_QOS *SecurityQos )
01629 {
01630   RpcBinding* bind = Binding;
01631   SECURITY_STATUS r;
01632   CredHandle cred;
01633   TimeStamp exp;
01634   ULONG package_count;
01635   ULONG i;
01636   PSecPkgInfoA packages;
01637   ULONG cbMaxToken;
01638 
01639   TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_a((const char*)ServerPrincName),
01640         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
01641 
01642   if (SecurityQos)
01643   {
01644       RPC_STATUS status;
01645 
01646       TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
01647             SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
01648       if (SecurityQos->Version >= 2)
01649       {
01650           const RPC_SECURITY_QOS_V2_A *SecurityQos2 = (const RPC_SECURITY_QOS_V2_A *)SecurityQos;
01651           TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType);
01652           if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
01653               TRACE(", { %p, 0x%x, %d, %d, %p, %s }",
01654                     SecurityQos2->u.HttpCredentials->TransportCredentials,
01655                     SecurityQos2->u.HttpCredentials->Flags,
01656                     SecurityQos2->u.HttpCredentials->AuthenticationTarget,
01657                     SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
01658                     SecurityQos2->u.HttpCredentials->AuthnSchemes,
01659                     SecurityQos2->u.HttpCredentials->ServerCertificateSubject);
01660       }
01661       TRACE("}\n");
01662       status = RpcQualityOfService_Create(SecurityQos, FALSE, &bind->QOS);
01663       if (status != RPC_S_OK)
01664           return status;
01665   }
01666   else
01667   {
01668       if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
01669       bind->QOS = NULL;
01670   }
01671 
01672   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
01673     AuthnSvc = RPC_C_AUTHN_WINNT;
01674 
01675   /* FIXME: the mapping should probably be retrieved using SSPI somehow */
01676   if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
01677     AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
01678 
01679   if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
01680   {
01681     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
01682     bind->AuthInfo = NULL;
01683     return RPC_S_OK;
01684   }
01685 
01686   if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
01687   {
01688     FIXME("unknown AuthnLevel %u\n", AuthnLevel);
01689     return RPC_S_UNKNOWN_AUTHN_LEVEL;
01690   }
01691 
01692   /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
01693   if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
01694   {
01695     FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
01696     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
01697   }
01698 
01699   r = EnumerateSecurityPackagesA(&package_count, &packages);
01700   if (r != SEC_E_OK)
01701   {
01702     ERR("EnumerateSecurityPackagesA failed with error 0x%08x\n", r);
01703     return RPC_S_SEC_PKG_ERROR;
01704   }
01705 
01706   for (i = 0; i < package_count; i++)
01707     if (packages[i].wRPCID == AuthnSvc)
01708         break;
01709 
01710   if (i == package_count)
01711   {
01712     FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
01713     FreeContextBuffer(packages);
01714     return RPC_S_UNKNOWN_AUTHN_SERVICE;
01715   }
01716 
01717   TRACE("found package %s for service %u\n", packages[i].Name, AuthnSvc);
01718   r = AcquireCredentialsHandleA(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
01719                                 AuthIdentity, NULL, NULL, &cred, &exp);
01720   cbMaxToken = packages[i].cbMaxToken;
01721   FreeContextBuffer(packages);
01722   if (r == ERROR_SUCCESS)
01723   {
01724     RpcAuthInfo *new_auth_info;
01725     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
01726                            AuthIdentity, &new_auth_info);
01727     if (r == RPC_S_OK)
01728     {
01729       new_auth_info->server_principal_name = RPCRT4_strdupAtoW((char *)ServerPrincName);
01730       if (new_auth_info->server_principal_name)
01731       {
01732         if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
01733         bind->AuthInfo = new_auth_info;
01734       }
01735       else
01736       {
01737         RpcAuthInfo_Release(new_auth_info);
01738         r = ERROR_OUTOFMEMORY;
01739       }
01740     }
01741     else
01742       FreeCredentialsHandle(&cred);
01743     return r;
01744   }
01745   else
01746   {
01747     ERR("AcquireCredentialsHandleA failed with error 0x%08x\n", r);
01748     return RPC_S_SEC_PKG_ERROR;
01749   }
01750 }
01751 
01752 /***********************************************************************
01753  *             RpcBindingSetAuthInfoExW (RPCRT4.@)
01754  */
01755 RPCRTAPI RPC_STATUS RPC_ENTRY
01756 RpcBindingSetAuthInfoExW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
01757                           ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr,
01758                           RPC_SECURITY_QOS *SecurityQos )
01759 {
01760   RpcBinding* bind = Binding;
01761   SECURITY_STATUS r;
01762   CredHandle cred;
01763   TimeStamp exp;
01764   ULONG package_count;
01765   ULONG i;
01766   PSecPkgInfoW packages;
01767   ULONG cbMaxToken;
01768 
01769   TRACE("%p %s %u %u %p %u %p\n", Binding, debugstr_w(ServerPrincName),
01770         AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, SecurityQos);
01771 
01772   if (SecurityQos)
01773   {
01774       RPC_STATUS status;
01775 
01776       TRACE("SecurityQos { Version=%d, Capabilities=0x%x, IdentityTracking=%d, ImpersonationLevel=%d",
01777             SecurityQos->Version, SecurityQos->Capabilities, SecurityQos->IdentityTracking, SecurityQos->ImpersonationType);
01778       if (SecurityQos->Version >= 2)
01779       {
01780           const RPC_SECURITY_QOS_V2_W *SecurityQos2 = (const RPC_SECURITY_QOS_V2_W *)SecurityQos;
01781           TRACE(", AdditionalSecurityInfoType=%d", SecurityQos2->AdditionalSecurityInfoType);
01782           if (SecurityQos2->AdditionalSecurityInfoType == RPC_C_AUTHN_INFO_TYPE_HTTP)
01783               TRACE(", { %p, 0x%x, %d, %d, %p, %s }",
01784                     SecurityQos2->u.HttpCredentials->TransportCredentials,
01785                     SecurityQos2->u.HttpCredentials->Flags,
01786                     SecurityQos2->u.HttpCredentials->AuthenticationTarget,
01787                     SecurityQos2->u.HttpCredentials->NumberOfAuthnSchemes,
01788                     SecurityQos2->u.HttpCredentials->AuthnSchemes,
01789                     debugstr_w(SecurityQos2->u.HttpCredentials->ServerCertificateSubject));
01790       }
01791       TRACE("}\n");
01792       status = RpcQualityOfService_Create(SecurityQos, TRUE, &bind->QOS);
01793       if (status != RPC_S_OK)
01794           return status;
01795   }
01796   else
01797   {
01798       if (bind->QOS) RpcQualityOfService_Release(bind->QOS);
01799       bind->QOS = NULL;
01800   }
01801 
01802   if (AuthnSvc == RPC_C_AUTHN_DEFAULT)
01803     AuthnSvc = RPC_C_AUTHN_WINNT;
01804 
01805   /* FIXME: the mapping should probably be retrieved using SSPI somehow */
01806   if (AuthnLevel == RPC_C_AUTHN_LEVEL_DEFAULT)
01807     AuthnLevel = RPC_C_AUTHN_LEVEL_NONE;
01808 
01809   if ((AuthnLevel == RPC_C_AUTHN_LEVEL_NONE) || (AuthnSvc == RPC_C_AUTHN_NONE))
01810   {
01811     if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
01812     bind->AuthInfo = NULL;
01813     return RPC_S_OK;
01814   }
01815 
01816   if (AuthnLevel > RPC_C_AUTHN_LEVEL_PKT_PRIVACY)
01817   {
01818     FIXME("unknown AuthnLevel %u\n", AuthnLevel);
01819     return RPC_S_UNKNOWN_AUTHN_LEVEL;
01820   }
01821 
01822   /* RPC_C_AUTHN_WINNT ignores the AuthzSvr parameter */
01823   if (AuthzSvr && AuthnSvc != RPC_C_AUTHN_WINNT)
01824   {
01825     FIXME("unsupported AuthzSvr %u\n", AuthzSvr);
01826     return RPC_S_UNKNOWN_AUTHZ_SERVICE;
01827   }
01828 
01829   r = EnumerateSecurityPackagesW(&package_count, &packages);
01830   if (r != SEC_E_OK)
01831   {
01832     ERR("EnumerateSecurityPackagesW failed with error 0x%08x\n", r);
01833     return RPC_S_SEC_PKG_ERROR;
01834   }
01835 
01836   for (i = 0; i < package_count; i++)
01837     if (packages[i].wRPCID == AuthnSvc)
01838         break;
01839 
01840   if (i == package_count)
01841   {
01842     FIXME("unsupported AuthnSvc %u\n", AuthnSvc);
01843     FreeContextBuffer(packages);
01844     return RPC_S_UNKNOWN_AUTHN_SERVICE;
01845   }
01846 
01847   TRACE("found package %s for service %u\n", debugstr_w(packages[i].Name), AuthnSvc);
01848   r = AcquireCredentialsHandleW(NULL, packages[i].Name, SECPKG_CRED_OUTBOUND, NULL,
01849                                 AuthIdentity, NULL, NULL, &cred, &exp);
01850   cbMaxToken = packages[i].cbMaxToken;
01851   FreeContextBuffer(packages);
01852   if (r == ERROR_SUCCESS)
01853   {
01854     RpcAuthInfo *new_auth_info;
01855     r = RpcAuthInfo_Create(AuthnLevel, AuthnSvc, cred, exp, cbMaxToken,
01856                            AuthIdentity, &new_auth_info);
01857     if (r == RPC_S_OK)
01858     {
01859       new_auth_info->server_principal_name = RPCRT4_strdupW(ServerPrincName);
01860       if (!ServerPrincName || new_auth_info->server_principal_name)
01861       {
01862         if (bind->AuthInfo) RpcAuthInfo_Release(bind->AuthInfo);
01863         bind->AuthInfo = new_auth_info;
01864       }
01865       else
01866       {
01867         RpcAuthInfo_Release(new_auth_info);
01868         r = ERROR_OUTOFMEMORY;
01869       }
01870     }
01871     else
01872       FreeCredentialsHandle(&cred);
01873     return r;
01874   }
01875   else
01876   {
01877     ERR("AcquireCredentialsHandleW failed with error 0x%08x\n", r);
01878     return RPC_S_SEC_PKG_ERROR;
01879   }
01880 }
01881 
01882 /***********************************************************************
01883  *             RpcBindingSetAuthInfoA (RPCRT4.@)
01884  */
01885 RPCRTAPI RPC_STATUS RPC_ENTRY
01886 RpcBindingSetAuthInfoA( RPC_BINDING_HANDLE Binding, RPC_CSTR ServerPrincName, ULONG AuthnLevel,
01887                         ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
01888 {
01889     TRACE("%p %s %u %u %p %u\n", Binding, debugstr_a((const char*)ServerPrincName),
01890           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
01891     return RpcBindingSetAuthInfoExA(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
01892 }
01893 
01894 /***********************************************************************
01895  *             RpcBindingSetAuthInfoW (RPCRT4.@)
01896  */
01897 RPCRTAPI RPC_STATUS RPC_ENTRY
01898 RpcBindingSetAuthInfoW( RPC_BINDING_HANDLE Binding, RPC_WSTR ServerPrincName, ULONG AuthnLevel,
01899                         ULONG AuthnSvc, RPC_AUTH_IDENTITY_HANDLE AuthIdentity, ULONG AuthzSvr )
01900 {
01901     TRACE("%p %s %u %u %p %u\n", Binding, debugstr_w(ServerPrincName),
01902           AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr);
01903     return RpcBindingSetAuthInfoExW(Binding, ServerPrincName, AuthnLevel, AuthnSvc, AuthIdentity, AuthzSvr, NULL);
01904 }
01905 
01906 /***********************************************************************
01907  *             RpcBindingSetOption (RPCRT4.@)
01908  */
01909 RPC_STATUS WINAPI RpcBindingSetOption(RPC_BINDING_HANDLE BindingHandle, ULONG Option, ULONG_PTR OptionValue)
01910 {
01911     FIXME("(%p, %d, %ld): stub\n", BindingHandle, Option, OptionValue);
01912     return RPC_S_OK;
01913 }

Generated on Sun May 27 2012 04:26:04 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.