2 * Copyright 2005 Juan Lang
3 * Copyright 2005-2006 Robert Shearman (for CodeWeavers)
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define NONAMELESSUNION
24 #define WIN32_NO_STATUS
25 #define USE_COM_CONTEXT_DEF
30 #include "wine/debug.h"
31 #include "wine/heap.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
35 #define CHARS_IN_GUID 39
37 struct comclassredirect_data
53 DWORD miscstatuscontent
;
54 DWORD miscstatusthumbnail
;
56 DWORD miscstatusdocprint
;
59 struct progidredirect_data
66 static NTSTATUS
create_key(HKEY
*retkey
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
)
68 NTSTATUS status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
70 if (status
== STATUS_OBJECT_NAME_NOT_FOUND
)
72 HANDLE subkey
, root
= attr
->RootDirectory
;
73 WCHAR
*buffer
= attr
->ObjectName
->Buffer
;
74 DWORD attrs
, pos
= 0, i
= 0, len
= attr
->ObjectName
->Length
/ sizeof(WCHAR
);
77 while (i
< len
&& buffer
[i
] != '\\') i
++;
78 if (i
== len
) return status
;
80 attrs
= attr
->Attributes
;
81 attr
->ObjectName
= &str
;
85 str
.Buffer
= buffer
+ pos
;
86 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
87 status
= NtCreateKey(&subkey
, access
, attr
, 0, NULL
, 0, NULL
);
88 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
89 if (status
) return status
;
90 attr
->RootDirectory
= subkey
;
91 while (i
< len
&& buffer
[i
] == '\\') i
++;
93 while (i
< len
&& buffer
[i
] != '\\') i
++;
95 str
.Buffer
= buffer
+ pos
;
96 str
.Length
= (i
- pos
) * sizeof(WCHAR
);
97 attr
->Attributes
= attrs
;
98 status
= NtCreateKey((HANDLE
*)retkey
, access
, attr
, 0, NULL
, 0, NULL
);
99 if (attr
->RootDirectory
!= root
) NtClose(attr
->RootDirectory
);
104 static HKEY classes_root_hkey
;
106 static HKEY
create_classes_root_hkey(DWORD access
)
109 OBJECT_ATTRIBUTES attr
;
112 attr
.Length
= sizeof(attr
);
113 attr
.RootDirectory
= 0;
114 attr
.ObjectName
= &name
;
116 attr
.SecurityDescriptor
= NULL
;
117 attr
.SecurityQualityOfService
= NULL
;
118 RtlInitUnicodeString(&name
, L
"\\Registry\\Machine\\Software\\Classes");
120 if (create_key( &hkey
, access
, &attr
)) return 0;
121 TRACE( "%s -> %p\n", debugstr_w(attr
.ObjectName
->Buffer
), hkey
);
123 if (!(access
& KEY_WOW64_64KEY
))
125 if (!(ret
= InterlockedCompareExchangePointer( (void **)&classes_root_hkey
, hkey
, 0 )))
128 NtClose( hkey
); /* somebody beat us to it */
135 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
);
137 static LSTATUS
create_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
139 OBJECT_ATTRIBUTES attr
;
140 UNICODE_STRING nameW
;
142 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
143 return ERROR_INVALID_HANDLE
;
145 attr
.Length
= sizeof(attr
);
146 attr
.RootDirectory
= hkey
;
147 attr
.ObjectName
= &nameW
;
149 attr
.SecurityDescriptor
= NULL
;
150 attr
.SecurityQualityOfService
= NULL
;
151 RtlInitUnicodeString( &nameW
, name
);
153 return RtlNtStatusToDosError(create_key(retkey
, access
, &attr
));
156 static HKEY
get_classes_root_hkey(HKEY hkey
, REGSAM access
)
159 const BOOL is_win64
= sizeof(void*) > sizeof(int);
160 const BOOL force_wow32
= is_win64
&& (access
& KEY_WOW64_32KEY
);
162 if (hkey
== HKEY_CLASSES_ROOT
&&
163 ((access
& KEY_WOW64_64KEY
) || !(ret
= classes_root_hkey
)))
164 ret
= create_classes_root_hkey(MAXIMUM_ALLOWED
| (access
& KEY_WOW64_64KEY
));
165 if (force_wow32
&& ret
&& ret
== classes_root_hkey
)
167 access
&= ~KEY_WOW64_32KEY
;
168 if (create_classes_key(classes_root_hkey
, L
"Wow6432Node", access
, &hkey
))
176 static LSTATUS
open_classes_key(HKEY hkey
, const WCHAR
*name
, REGSAM access
, HKEY
*retkey
)
178 OBJECT_ATTRIBUTES attr
;
179 UNICODE_STRING nameW
;
181 if (!(hkey
= get_classes_root_hkey(hkey
, access
)))
182 return ERROR_INVALID_HANDLE
;
184 attr
.Length
= sizeof(attr
);
185 attr
.RootDirectory
= hkey
;
186 attr
.ObjectName
= &nameW
;
188 attr
.SecurityDescriptor
= NULL
;
189 attr
.SecurityQualityOfService
= NULL
;
190 RtlInitUnicodeString( &nameW
, name
);
192 return RtlNtStatusToDosError(NtOpenKey((HANDLE
*)retkey
, access
, &attr
));
195 static HRESULT
open_key_for_clsid(REFCLSID clsid
, const WCHAR
*keyname
, REGSAM access
, HKEY
*subkey
)
197 static const WCHAR clsidW
[] = L
"CLSID\\";
198 WCHAR path
[CHARS_IN_GUID
+ ARRAY_SIZE(clsidW
) - 1];
202 lstrcpyW(path
, clsidW
);
203 StringFromGUID2(clsid
, path
+ lstrlenW(clsidW
), CHARS_IN_GUID
);
204 res
= open_classes_key(HKEY_CLASSES_ROOT
, path
, keyname
? KEY_READ
: access
, &key
);
205 if (res
== ERROR_FILE_NOT_FOUND
)
206 return REGDB_E_CLASSNOTREG
;
207 else if (res
!= ERROR_SUCCESS
)
208 return REGDB_E_READREGDB
;
216 res
= open_classes_key(key
, keyname
, access
, subkey
);
218 if (res
== ERROR_FILE_NOT_FOUND
)
219 return REGDB_E_KEYMISSING
;
220 else if (res
!= ERROR_SUCCESS
)
221 return REGDB_E_READREGDB
;
226 /***********************************************************************
227 * FreePropVariantArray (combase.@)
229 HRESULT WINAPI
FreePropVariantArray(ULONG count
, PROPVARIANT
*rgvars
)
233 TRACE("%u, %p.\n", count
, rgvars
);
238 for (i
= 0; i
< count
; ++i
)
239 PropVariantClear(&rgvars
[i
]);
244 static HRESULT
propvar_validatetype(VARTYPE vt
)
276 case VT_STREAMED_OBJECT
:
277 case VT_STORED_OBJECT
:
281 case VT_I1
|VT_VECTOR
:
282 case VT_I2
|VT_VECTOR
:
283 case VT_I4
|VT_VECTOR
:
284 case VT_I8
|VT_VECTOR
:
285 case VT_R4
|VT_VECTOR
:
286 case VT_R8
|VT_VECTOR
:
287 case VT_CY
|VT_VECTOR
:
288 case VT_DATE
|VT_VECTOR
:
289 case VT_BSTR
|VT_VECTOR
:
290 case VT_ERROR
|VT_VECTOR
:
291 case VT_BOOL
|VT_VECTOR
:
292 case VT_VARIANT
|VT_VECTOR
:
293 case VT_UI1
|VT_VECTOR
:
294 case VT_UI2
|VT_VECTOR
:
295 case VT_UI4
|VT_VECTOR
:
296 case VT_UI8
|VT_VECTOR
:
297 case VT_LPSTR
|VT_VECTOR
:
298 case VT_LPWSTR
|VT_VECTOR
:
299 case VT_FILETIME
|VT_VECTOR
:
300 case VT_CF
|VT_VECTOR
:
301 case VT_CLSID
|VT_VECTOR
:
303 case VT_ARRAY
|VT_UI1
:
305 case VT_ARRAY
|VT_UI2
:
307 case VT_ARRAY
|VT_UI4
:
308 case VT_ARRAY
|VT_INT
:
309 case VT_ARRAY
|VT_UINT
:
313 case VT_ARRAY
|VT_DATE
:
314 case VT_ARRAY
|VT_BSTR
:
315 case VT_ARRAY
|VT_BOOL
:
316 case VT_ARRAY
|VT_DECIMAL
:
317 case VT_ARRAY
|VT_DISPATCH
:
318 case VT_ARRAY
|VT_UNKNOWN
:
319 case VT_ARRAY
|VT_ERROR
:
320 case VT_ARRAY
|VT_VARIANT
:
323 WARN("Bad type %d\n", vt
);
324 return STG_E_INVALIDPARAMETER
;
327 static void propvar_free_cf_array(ULONG count
, CLIPDATA
*data
)
330 for (i
= 0; i
< count
; ++i
)
331 CoTaskMemFree(data
[i
].pClipData
);
334 /***********************************************************************
335 * PropVariantClear (combase.@)
337 HRESULT WINAPI
PropVariantClear(PROPVARIANT
*pvar
)
341 TRACE("%p.\n", pvar
);
346 hr
= propvar_validatetype(pvar
->vt
);
349 memset(pvar
, 0, sizeof(*pvar
));
379 case VT_STREAMED_OBJECT
:
381 case VT_STORED_OBJECT
:
383 IStream_Release(pvar
->u
.pStream
);
388 /* pick an arbitrary typed pointer - we don't care about the type
389 * as we are just freeing it */
390 CoTaskMemFree(pvar
->u
.puuid
);
394 CoTaskMemFree(pvar
->u
.blob
.pBlobData
);
397 SysFreeString(pvar
->u
.bstrVal
);
400 if (pvar
->u
.pclipdata
)
402 propvar_free_cf_array(1, pvar
->u
.pclipdata
);
403 CoTaskMemFree(pvar
->u
.pclipdata
);
407 if (pvar
->vt
& VT_VECTOR
)
411 switch (pvar
->vt
& ~VT_VECTOR
)
414 FreePropVariantArray(pvar
->u
.capropvar
.cElems
, pvar
->u
.capropvar
.pElems
);
417 propvar_free_cf_array(pvar
->u
.caclipdata
.cElems
, pvar
->u
.caclipdata
.pElems
);
420 for (i
= 0; i
< pvar
->u
.cabstr
.cElems
; i
++)
421 SysFreeString(pvar
->u
.cabstr
.pElems
[i
]);
424 for (i
= 0; i
< pvar
->u
.calpstr
.cElems
; i
++)
425 CoTaskMemFree(pvar
->u
.calpstr
.pElems
[i
]);
428 for (i
= 0; i
< pvar
->u
.calpwstr
.cElems
; i
++)
429 CoTaskMemFree(pvar
->u
.calpwstr
.pElems
[i
]);
432 if (pvar
->vt
& ~VT_VECTOR
)
434 /* pick an arbitrary VT_VECTOR structure - they all have the same
436 CoTaskMemFree(pvar
->u
.capropvar
.pElems
);
439 else if (pvar
->vt
& VT_ARRAY
)
440 hr
= SafeArrayDestroy(pvar
->u
.parray
);
443 WARN("Invalid/unsupported type %d\n", pvar
->vt
);
444 hr
= STG_E_INVALIDPARAMETER
;
448 memset(pvar
, 0, sizeof(*pvar
));
452 /***********************************************************************
453 * PropVariantCopy (combase.@)
455 HRESULT WINAPI
PropVariantCopy(PROPVARIANT
*pvarDest
, const PROPVARIANT
*pvarSrc
)
460 TRACE("%p, %p vt %04x.\n", pvarDest
, pvarSrc
, pvarSrc
->vt
);
462 hr
= propvar_validatetype(pvarSrc
->vt
);
464 return DISP_E_BADVARTYPE
;
466 /* this will deal with most cases */
467 *pvarDest
= *pvarSrc
;
495 case VT_STREAMED_OBJECT
:
497 case VT_STORED_OBJECT
:
498 if (pvarDest
->u
.pStream
)
499 IStream_AddRef(pvarDest
->u
.pStream
);
502 pvarDest
->u
.puuid
= CoTaskMemAlloc(sizeof(CLSID
));
503 *pvarDest
->u
.puuid
= *pvarSrc
->u
.puuid
;
506 if (pvarSrc
->u
.pszVal
)
508 len
= strlen(pvarSrc
->u
.pszVal
);
509 pvarDest
->u
.pszVal
= CoTaskMemAlloc((len
+1)*sizeof(CHAR
));
510 CopyMemory(pvarDest
->u
.pszVal
, pvarSrc
->u
.pszVal
, (len
+1)*sizeof(CHAR
));
514 if (pvarSrc
->u
.pwszVal
)
516 len
= lstrlenW(pvarSrc
->u
.pwszVal
);
517 pvarDest
->u
.pwszVal
= CoTaskMemAlloc((len
+1)*sizeof(WCHAR
));
518 CopyMemory(pvarDest
->u
.pwszVal
, pvarSrc
->u
.pwszVal
, (len
+1)*sizeof(WCHAR
));
523 if (pvarSrc
->u
.blob
.pBlobData
)
525 len
= pvarSrc
->u
.blob
.cbSize
;
526 pvarDest
->u
.blob
.pBlobData
= CoTaskMemAlloc(len
);
527 CopyMemory(pvarDest
->u
.blob
.pBlobData
, pvarSrc
->u
.blob
.pBlobData
, len
);
531 pvarDest
->u
.bstrVal
= SysAllocString(pvarSrc
->u
.bstrVal
);
534 if (pvarSrc
->u
.pclipdata
)
536 len
= pvarSrc
->u
.pclipdata
->cbSize
- sizeof(pvarSrc
->u
.pclipdata
->ulClipFmt
);
537 pvarDest
->u
.pclipdata
= CoTaskMemAlloc(sizeof (CLIPDATA
));
538 pvarDest
->u
.pclipdata
->cbSize
= pvarSrc
->u
.pclipdata
->cbSize
;
539 pvarDest
->u
.pclipdata
->ulClipFmt
= pvarSrc
->u
.pclipdata
->ulClipFmt
;
540 pvarDest
->u
.pclipdata
->pClipData
= CoTaskMemAlloc(len
);
541 CopyMemory(pvarDest
->u
.pclipdata
->pClipData
, pvarSrc
->u
.pclipdata
->pClipData
, len
);
545 if (pvarSrc
->vt
& VT_VECTOR
)
550 switch (pvarSrc
->vt
& ~VT_VECTOR
)
552 case VT_I1
: elemSize
= sizeof(pvarSrc
->u
.cVal
); break;
553 case VT_UI1
: elemSize
= sizeof(pvarSrc
->u
.bVal
); break;
554 case VT_I2
: elemSize
= sizeof(pvarSrc
->u
.iVal
); break;
555 case VT_UI2
: elemSize
= sizeof(pvarSrc
->u
.uiVal
); break;
556 case VT_BOOL
: elemSize
= sizeof(pvarSrc
->u
.boolVal
); break;
557 case VT_I4
: elemSize
= sizeof(pvarSrc
->u
.lVal
); break;
558 case VT_UI4
: elemSize
= sizeof(pvarSrc
->u
.ulVal
); break;
559 case VT_R4
: elemSize
= sizeof(pvarSrc
->u
.fltVal
); break;
560 case VT_R8
: elemSize
= sizeof(pvarSrc
->u
.dblVal
); break;
561 case VT_ERROR
: elemSize
= sizeof(pvarSrc
->u
.scode
); break;
562 case VT_I8
: elemSize
= sizeof(pvarSrc
->u
.hVal
); break;
563 case VT_UI8
: elemSize
= sizeof(pvarSrc
->u
.uhVal
); break;
564 case VT_CY
: elemSize
= sizeof(pvarSrc
->u
.cyVal
); break;
565 case VT_DATE
: elemSize
= sizeof(pvarSrc
->u
.date
); break;
566 case VT_FILETIME
: elemSize
= sizeof(pvarSrc
->u
.filetime
); break;
567 case VT_CLSID
: elemSize
= sizeof(*pvarSrc
->u
.puuid
); break;
568 case VT_CF
: elemSize
= sizeof(*pvarSrc
->u
.pclipdata
); break;
569 case VT_BSTR
: elemSize
= sizeof(pvarSrc
->u
.bstrVal
); break;
570 case VT_LPSTR
: elemSize
= sizeof(pvarSrc
->u
.pszVal
); break;
571 case VT_LPWSTR
: elemSize
= sizeof(pvarSrc
->u
.pwszVal
); break;
572 case VT_VARIANT
: elemSize
= sizeof(*pvarSrc
->u
.pvarVal
); break;
575 FIXME("Invalid element type: %ul\n", pvarSrc
->vt
& ~VT_VECTOR
);
578 len
= pvarSrc
->u
.capropvar
.cElems
;
579 pvarDest
->u
.capropvar
.pElems
= len
? CoTaskMemAlloc(len
* elemSize
) : NULL
;
580 if (pvarSrc
->vt
== (VT_VECTOR
| VT_VARIANT
))
582 for (i
= 0; i
< len
; i
++)
583 PropVariantCopy(&pvarDest
->u
.capropvar
.pElems
[i
], &pvarSrc
->u
.capropvar
.pElems
[i
]);
585 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_CF
))
587 FIXME("Copy clipformats\n");
589 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_BSTR
))
591 for (i
= 0; i
< len
; i
++)
592 pvarDest
->u
.cabstr
.pElems
[i
] = SysAllocString(pvarSrc
->u
.cabstr
.pElems
[i
]);
594 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPSTR
))
597 for (i
= 0; i
< len
; i
++)
599 strLen
= lstrlenA(pvarSrc
->u
.calpstr
.pElems
[i
]) + 1;
600 pvarDest
->u
.calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
601 memcpy(pvarDest
->u
.calpstr
.pElems
[i
],
602 pvarSrc
->u
.calpstr
.pElems
[i
], strLen
);
605 else if (pvarSrc
->vt
== (VT_VECTOR
| VT_LPWSTR
))
608 for (i
= 0; i
< len
; i
++)
610 strLen
= (lstrlenW(pvarSrc
->u
.calpwstr
.pElems
[i
]) + 1) *
612 pvarDest
->u
.calpstr
.pElems
[i
] = CoTaskMemAlloc(strLen
);
613 memcpy(pvarDest
->u
.calpstr
.pElems
[i
],
614 pvarSrc
->u
.calpstr
.pElems
[i
], strLen
);
618 CopyMemory(pvarDest
->u
.capropvar
.pElems
, pvarSrc
->u
.capropvar
.pElems
, len
* elemSize
);
620 else if (pvarSrc
->vt
& VT_ARRAY
)
622 pvarDest
->u
.uhVal
.QuadPart
= 0;
623 return SafeArrayCopy(pvarSrc
->u
.parray
, &pvarDest
->u
.parray
);
626 WARN("Invalid/unsupported type %d\n", pvarSrc
->vt
);
632 /***********************************************************************
633 * CoFileTimeNow (combase.@)
635 HRESULT WINAPI
CoFileTimeNow(FILETIME
*filetime
)
637 GetSystemTimeAsFileTime(filetime
);
641 /******************************************************************************
642 * CoCreateGuid (combase.@)
644 HRESULT WINAPI
CoCreateGuid(GUID
*guid
)
648 if (!guid
) return E_INVALIDARG
;
650 status
= UuidCreate(guid
);
651 if (status
== RPC_S_OK
|| status
== RPC_S_UUID_LOCAL_ONLY
) return S_OK
;
652 return HRESULT_FROM_WIN32(status
);
655 /******************************************************************************
656 * CoQueryProxyBlanket (combase.@)
658 HRESULT WINAPI
CoQueryProxyBlanket(IUnknown
*proxy
, DWORD
*authn_service
,
659 DWORD
*authz_service
, OLECHAR
**servername
, DWORD
*authn_level
,
660 DWORD
*imp_level
, void **auth_info
, DWORD
*capabilities
)
662 IClientSecurity
*client_security
;
665 TRACE("%p, %p, %p, %p, %p, %p, %p, %p.\n", proxy
, authn_service
, authz_service
, servername
, authn_level
, imp_level
,
666 auth_info
, capabilities
);
668 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
671 hr
= IClientSecurity_QueryBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
,
672 authn_level
, imp_level
, auth_info
, capabilities
);
673 IClientSecurity_Release(client_security
);
676 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
680 /******************************************************************************
681 * CoSetProxyBlanket (combase.@)
683 HRESULT WINAPI
CoSetProxyBlanket(IUnknown
*proxy
, DWORD authn_service
, DWORD authz_service
,
684 OLECHAR
*servername
, DWORD authn_level
, DWORD imp_level
, void *auth_info
, DWORD capabilities
)
686 IClientSecurity
*client_security
;
689 TRACE("%p, %u, %u, %p, %u, %u, %p, %#x.\n", proxy
, authn_service
, authz_service
, servername
,
690 authn_level
, imp_level
, auth_info
, capabilities
);
692 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
695 hr
= IClientSecurity_SetBlanket(client_security
, proxy
, authn_service
, authz_service
, servername
, authn_level
,
696 imp_level
, auth_info
, capabilities
);
697 IClientSecurity_Release(client_security
);
700 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
704 /***********************************************************************
705 * CoCopyProxy (combase.@)
707 HRESULT WINAPI
CoCopyProxy(IUnknown
*proxy
, IUnknown
**proxy_copy
)
709 IClientSecurity
*client_security
;
712 TRACE("%p, %p.\n", proxy
, proxy_copy
);
714 hr
= IUnknown_QueryInterface(proxy
, &IID_IClientSecurity
, (void **)&client_security
);
717 hr
= IClientSecurity_CopyProxy(client_security
, proxy
, proxy_copy
);
718 IClientSecurity_Release(client_security
);
721 if (FAILED(hr
)) ERR("-- failed with %#x.\n", hr
);
725 /***********************************************************************
726 * CoQueryClientBlanket (combase.@)
728 HRESULT WINAPI
CoQueryClientBlanket(DWORD
*authn_service
, DWORD
*authz_service
, OLECHAR
**servername
,
729 DWORD
*authn_level
, DWORD
*imp_level
, RPC_AUTHZ_HANDLE
*privs
, DWORD
*capabilities
)
731 IServerSecurity
*server_security
;
734 TRACE("%p, %p, %p, %p, %p, %p, %p.\n", authn_service
, authz_service
, servername
, authn_level
, imp_level
,
735 privs
, capabilities
);
737 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
740 hr
= IServerSecurity_QueryBlanket(server_security
, authn_service
, authz_service
, servername
, authn_level
,
741 imp_level
, privs
, capabilities
);
742 IServerSecurity_Release(server_security
);
748 /***********************************************************************
749 * CoImpersonateClient (combase.@)
751 HRESULT WINAPI
CoImpersonateClient(void)
753 IServerSecurity
*server_security
;
758 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
761 hr
= IServerSecurity_ImpersonateClient(server_security
);
762 IServerSecurity_Release(server_security
);
768 /***********************************************************************
769 * CoRevertToSelf (combase.@)
771 HRESULT WINAPI
CoRevertToSelf(void)
773 IServerSecurity
*server_security
;
778 hr
= CoGetCallContext(&IID_IServerSecurity
, (void **)&server_security
);
781 hr
= IServerSecurity_RevertToSelf(server_security
);
782 IServerSecurity_Release(server_security
);
788 /***********************************************************************
789 * CoGetObjectContext (combase.@)
791 HRESULT WINAPI
CoGetObjectContext(REFIID riid
, void **ppv
)
793 IObjContext
*context
;
796 TRACE("%s, %p.\n", debugstr_guid(riid
), ppv
);
799 hr
= CoGetContextToken((ULONG_PTR
*)&context
);
803 return IObjContext_QueryInterface(context
, riid
, ppv
);
806 /***********************************************************************
807 * CoGetDefaultContext (combase.@)
809 HRESULT WINAPI
CoGetDefaultContext(APTTYPE type
, REFIID riid
, void **obj
)
811 FIXME("%d, %s, %p stub\n", type
, debugstr_guid(riid
), obj
);
813 return E_NOINTERFACE
;
816 /***********************************************************************
817 * CoGetCallState (combase.@)
819 HRESULT WINAPI
CoGetCallState(int arg1
, ULONG
*arg2
)
821 FIXME("%d, %p.\n", arg1
, arg2
);
826 /***********************************************************************
827 * CoGetActivationState (combase.@)
829 HRESULT WINAPI
CoGetActivationState(GUID guid
, DWORD arg2
, DWORD
*arg3
)
831 FIXME("%s, %x, %p.\n", debugstr_guid(&guid
), arg2
, arg3
);
836 /******************************************************************************
837 * CoGetTreatAsClass (combase.@)
839 HRESULT WINAPI
CoGetTreatAsClass(REFCLSID clsidOld
, CLSID
*clsidNew
)
841 WCHAR buffW
[CHARS_IN_GUID
];
842 LONG len
= sizeof(buffW
);
846 TRACE("%s, %p.\n", debugstr_guid(clsidOld
), clsidNew
);
848 if (!clsidOld
|| !clsidNew
)
851 *clsidNew
= *clsidOld
;
853 hr
= open_key_for_clsid(clsidOld
, L
"TreatAs", KEY_READ
, &hkey
);
860 if (RegQueryValueW(hkey
, NULL
, buffW
, &len
))
866 hr
= CLSIDFromString(buffW
, clsidNew
);
868 ERR("Failed to get CLSID from string %s, hr %#x.\n", debugstr_w(buffW
), hr
);
870 if (hkey
) RegCloseKey(hkey
);
874 /******************************************************************************
875 * ProgIDFromCLSID (combase.@)
877 HRESULT WINAPI DECLSPEC_HOTPATCH
ProgIDFromCLSID(REFCLSID clsid
, LPOLESTR
*progid
)
879 ACTCTX_SECTION_KEYED_DATA data
;
889 data
.cbSize
= sizeof(data
);
890 if (FindActCtxSectionGuid(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION
,
893 struct comclassredirect_data
*comclass
= (struct comclassredirect_data
*)data
.lpData
;
894 if (comclass
->progid_len
)
898 *progid
= CoTaskMemAlloc(comclass
->progid_len
+ sizeof(WCHAR
));
899 if (!*progid
) return E_OUTOFMEMORY
;
901 ptrW
= (WCHAR
*)((BYTE
*)comclass
+ comclass
->progid_offset
);
902 memcpy(*progid
, ptrW
, comclass
->progid_len
+ sizeof(WCHAR
));
906 return REGDB_E_CLASSNOTREG
;
909 hr
= open_key_for_clsid(clsid
, L
"ProgID", KEY_READ
, &hkey
);
913 if (RegQueryValueW(hkey
, NULL
, NULL
, &progidlen
))
914 hr
= REGDB_E_CLASSNOTREG
;
918 *progid
= CoTaskMemAlloc(progidlen
* sizeof(WCHAR
));
921 if (RegQueryValueW(hkey
, NULL
, *progid
, &progidlen
))
923 hr
= REGDB_E_CLASSNOTREG
;
924 CoTaskMemFree(*progid
);
936 static inline BOOL
is_valid_hex(WCHAR c
)
938 if (!(((c
>= '0') && (c
<= '9')) ||
939 ((c
>= 'a') && (c
<= 'f')) ||
940 ((c
>= 'A') && (c
<= 'F'))))
945 static const BYTE guid_conv_table
[256] =
947 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
948 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
949 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
950 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, /* 0x30 */
951 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
952 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
953 0, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf /* 0x60 */
956 static BOOL
guid_from_string(LPCWSTR s
, GUID
*id
)
960 if (!s
|| s
[0] != '{')
962 memset(id
, 0, sizeof(*id
));
967 TRACE("%s -> %p\n", debugstr_w(s
), id
);
969 /* In form {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX} */
972 for (i
= 1; i
< 9; ++i
)
974 if (!is_valid_hex(s
[i
])) return FALSE
;
975 id
->Data1
= (id
->Data1
<< 4) | guid_conv_table
[s
[i
]];
977 if (s
[9] != '-') return FALSE
;
980 for (i
= 10; i
< 14; ++i
)
982 if (!is_valid_hex(s
[i
])) return FALSE
;
983 id
->Data2
= (id
->Data2
<< 4) | guid_conv_table
[s
[i
]];
985 if (s
[14] != '-') return FALSE
;
988 for (i
= 15; i
< 19; ++i
)
990 if (!is_valid_hex(s
[i
])) return FALSE
;
991 id
->Data3
= (id
->Data3
<< 4) | guid_conv_table
[s
[i
]];
993 if (s
[19] != '-') return FALSE
;
995 for (i
= 20; i
< 37; i
+= 2)
999 if (s
[i
] != '-') return FALSE
;
1002 if (!is_valid_hex(s
[i
]) || !is_valid_hex(s
[i
+ 1])) return FALSE
;
1003 id
->Data4
[(i
- 20) / 2] = guid_conv_table
[s
[i
]] << 4 | guid_conv_table
[s
[i
+ 1]];
1006 if (s
[37] == '}' && s
[38] == '\0')
1012 static HRESULT
clsid_from_string_reg(LPCOLESTR progid
, CLSID
*clsid
)
1014 WCHAR buf2
[CHARS_IN_GUID
];
1015 LONG buf2len
= sizeof(buf2
);
1019 memset(clsid
, 0, sizeof(*clsid
));
1020 buf
= heap_alloc((lstrlenW(progid
) + 8) * sizeof(WCHAR
));
1021 if (!buf
) return E_OUTOFMEMORY
;
1023 lstrcpyW(buf
, progid
);
1024 lstrcatW(buf
, L
"\\CLSID");
1025 if (open_classes_key(HKEY_CLASSES_ROOT
, buf
, MAXIMUM_ALLOWED
, &xhkey
))
1028 WARN("couldn't open key for ProgID %s\n", debugstr_w(progid
));
1029 return CO_E_CLASSSTRING
;
1033 if (RegQueryValueW(xhkey
, NULL
, buf2
, &buf2len
))
1036 WARN("couldn't query clsid value for ProgID %s\n", debugstr_w(progid
));
1037 return CO_E_CLASSSTRING
;
1040 return guid_from_string(buf2
, clsid
) ? S_OK
: CO_E_CLASSSTRING
;
1043 /******************************************************************************
1044 * CLSIDFromProgID (combase.@)
1046 HRESULT WINAPI DECLSPEC_HOTPATCH
CLSIDFromProgID(LPCOLESTR progid
, CLSID
*clsid
)
1048 ACTCTX_SECTION_KEYED_DATA data
;
1050 if (!progid
|| !clsid
)
1051 return E_INVALIDARG
;
1053 data
.cbSize
= sizeof(data
);
1054 if (FindActCtxSectionStringW(0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION
,
1057 struct progidredirect_data
*progiddata
= (struct progidredirect_data
*)data
.lpData
;
1058 CLSID
*alias
= (CLSID
*)((BYTE
*)data
.lpSectionBase
+ progiddata
->clsid_offset
);
1063 return clsid_from_string_reg(progid
, clsid
);
1066 /******************************************************************************
1067 * CLSIDFromProgIDEx (combase.@)
1069 HRESULT WINAPI
CLSIDFromProgIDEx(LPCOLESTR progid
, CLSID
*clsid
)
1071 FIXME("%s, %p: semi-stub\n", debugstr_w(progid
), clsid
);
1073 return CLSIDFromProgID(progid
, clsid
);
1076 /******************************************************************************
1077 * CLSIDFromString (combase.@)
1079 HRESULT WINAPI
CLSIDFromString(LPCOLESTR str
, LPCLSID clsid
)
1085 return E_INVALIDARG
;
1087 if (guid_from_string(str
, clsid
))
1090 /* It appears a ProgID is also valid */
1091 hr
= clsid_from_string_reg(str
, &tmp_id
);
1098 /******************************************************************************
1099 * IIDFromString (combase.@)
1101 HRESULT WINAPI
IIDFromString(LPCOLESTR str
, IID
*iid
)
1103 TRACE("%s, %p\n", debugstr_w(str
), iid
);
1107 memset(iid
, 0, sizeof(*iid
));
1111 /* length mismatch is a special case */
1112 if (lstrlenW(str
) + 1 != CHARS_IN_GUID
)
1113 return E_INVALIDARG
;
1116 return CO_E_IIDSTRING
;
1118 return guid_from_string(str
, iid
) ? S_OK
: CO_E_IIDSTRING
;
1121 /******************************************************************************
1122 * StringFromCLSID (combase.@)
1124 HRESULT WINAPI
StringFromCLSID(REFCLSID clsid
, LPOLESTR
*str
)
1126 if (!(*str
= CoTaskMemAlloc(CHARS_IN_GUID
* sizeof(WCHAR
)))) return E_OUTOFMEMORY
;
1127 StringFromGUID2(clsid
, *str
, CHARS_IN_GUID
);
1131 /******************************************************************************
1132 * StringFromGUID2 (combase.@)
1134 INT WINAPI
StringFromGUID2(REFGUID guid
, LPOLESTR str
, INT cmax
)
1136 if (!guid
|| cmax
< CHARS_IN_GUID
) return 0;
1137 swprintf(str
, CHARS_IN_GUID
, L
"{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", guid
->Data1
,
1138 guid
->Data2
, guid
->Data3
, guid
->Data4
[0], guid
->Data4
[1], guid
->Data4
[2], guid
->Data4
[3],
1139 guid
->Data4
[4], guid
->Data4
[5], guid
->Data4
[6], guid
->Data4
[7]);
1140 return CHARS_IN_GUID
;
1143 static void init_multi_qi(DWORD count
, MULTI_QI
*mqi
, HRESULT hr
)
1147 for (i
= 0; i
< count
; i
++)
1154 static HRESULT
return_multi_qi(IUnknown
*unk
, DWORD count
, MULTI_QI
*mqi
, BOOL include_unk
)
1156 ULONG index
= 0, fetched
= 0;
1162 index
= fetched
= 1;
1165 for (; index
< count
; index
++)
1167 mqi
[index
].hr
= IUnknown_QueryInterface(unk
, mqi
[index
].pIID
, (void **)&mqi
[index
].pItf
);
1168 if (mqi
[index
].hr
== S_OK
)
1173 IUnknown_Release(unk
);
1176 return E_NOINTERFACE
;
1178 return fetched
== count
? S_OK
: CO_S_NOTALLINTERFACES
;
1181 /***********************************************************************
1182 * CoGetInstanceFromFile (combase.@)
1184 HRESULT WINAPI DECLSPEC_HOTPATCH
CoGetInstanceFromFile(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1185 IUnknown
*outer
, DWORD cls_context
, DWORD grfmode
, OLECHAR
*filename
, DWORD count
,
1188 IPersistFile
*pf
= NULL
;
1189 IUnknown
*obj
= NULL
;
1193 if (!count
|| !results
)
1194 return E_INVALIDARG
;
1197 FIXME("() non-NULL server_info not supported\n");
1199 init_multi_qi(count
, results
, E_NOINTERFACE
);
1203 hr
= GetClassFile(filename
, &clsid
);
1206 ERR("Failed to get CLSID from a file.\n");
1213 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1216 init_multi_qi(count
, results
, hr
);
1220 /* Init from file */
1221 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistFile
, (void **)&pf
);
1224 init_multi_qi(count
, results
, hr
);
1225 IUnknown_Release(obj
);
1229 hr
= IPersistFile_Load(pf
, filename
, grfmode
);
1230 IPersistFile_Release(pf
);
1232 return return_multi_qi(obj
, count
, results
, FALSE
);
1235 init_multi_qi(count
, results
, hr
);
1236 IUnknown_Release(obj
);
1241 /***********************************************************************
1242 * CoGetInstanceFromIStorage (combase.@)
1244 HRESULT WINAPI
CoGetInstanceFromIStorage(COSERVERINFO
*server_info
, CLSID
*rclsid
,
1245 IUnknown
*outer
, DWORD cls_context
, IStorage
*storage
, DWORD count
, MULTI_QI
*results
)
1247 IPersistStorage
*ps
= NULL
;
1248 IUnknown
*obj
= NULL
;
1252 if (!count
|| !results
|| !storage
)
1253 return E_INVALIDARG
;
1256 FIXME("() non-NULL server_info not supported\n");
1258 init_multi_qi(count
, results
, E_NOINTERFACE
);
1262 memset(&stat
.clsid
, 0, sizeof(stat
.clsid
));
1263 hr
= IStorage_Stat(storage
, &stat
, STATFLAG_NONAME
);
1266 ERR("Failed to get CLSID from a storage.\n");
1270 rclsid
= &stat
.clsid
;
1273 hr
= CoCreateInstance(rclsid
, outer
, cls_context
, &IID_IUnknown
, (void **)&obj
);
1277 /* Init from IStorage */
1278 hr
= IUnknown_QueryInterface(obj
, &IID_IPersistStorage
, (void **)&ps
);
1280 ERR("failed to get IPersistStorage\n");
1284 IPersistStorage_Load(ps
, storage
);
1285 IPersistStorage_Release(ps
);
1288 return return_multi_qi(obj
, count
, results
, FALSE
);
1291 /***********************************************************************
1292 * CoCreateInstance (combase.@)
1294 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstance(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1295 REFIID riid
, void **obj
)
1297 MULTI_QI multi_qi
= { .pIID
= riid
};
1300 TRACE("%s, %p, %#x, %s, %p.\n", debugstr_guid(rclsid
), outer
, cls_context
, debugstr_guid(riid
), obj
);
1305 hr
= CoCreateInstanceEx(rclsid
, outer
, cls_context
, NULL
, 1, &multi_qi
);
1306 *obj
= multi_qi
.pItf
;
1310 /***********************************************************************
1311 * CoCreateInstanceEx (combase.@)
1313 HRESULT WINAPI DECLSPEC_HOTPATCH
CoCreateInstanceEx(REFCLSID rclsid
, IUnknown
*outer
, DWORD cls_context
,
1314 COSERVERINFO
*server_info
, ULONG count
, MULTI_QI
*results
)
1316 IClassFactory
*factory
;
1317 IUnknown
*unk
= NULL
;
1321 TRACE("%s, %p, %#x, %p, %u, %p\n", debugstr_guid(rclsid
), outer
, cls_context
, server_info
, count
, results
);
1323 if (!count
|| !results
)
1324 return E_INVALIDARG
;
1327 FIXME("Server info is not supported.\n");
1329 init_multi_qi(count
, results
, E_NOINTERFACE
);
1331 hr
= CoGetTreatAsClass(rclsid
, &clsid
);
1335 hr
= CoGetClassObject(&clsid
, cls_context
, NULL
, &IID_IClassFactory
, (void **)&factory
);
1339 hr
= IClassFactory_CreateInstance(factory
, outer
, results
[0].pIID
, (void **)&unk
);
1340 IClassFactory_Release(factory
);
1343 if (hr
== CLASS_E_NOAGGREGATION
&& outer
)
1344 FIXME("Class %s does not support aggregation\n", debugstr_guid(&clsid
));
1346 FIXME("no instance created for interface %s of class %s, hr %#x.\n",
1347 debugstr_guid(results
[0].pIID
), debugstr_guid(&clsid
), hr
);
1351 return return_multi_qi(unk
, count
, results
, TRUE
);
1354 /***********************************************************************
1355 * CoFreeUnusedLibraries (combase.@)
1357 void WINAPI DECLSPEC_HOTPATCH
CoFreeUnusedLibraries(void)
1359 CoFreeUnusedLibrariesEx(INFINITE
, 0);