1 /* 2 * OLEAUT32 3 * 4 * Copyright 1999, 2000 Marcus Meissner 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "config.h" 22 23 #include <stdarg.h> 24 #include <string.h> 25 #include <limits.h> 26 27 #define COBJMACROS 28 29 #include "windef.h" 30 #include "winbase.h" 31 #include "wingdi.h" 32 #include "winuser.h" 33 #include "winerror.h" 34 35 #include "ole2.h" 36 #include "olectl.h" 37 #include "oleauto.h" 38 #include "initguid.h" 39 #include "typelib.h" 40 #include "oleaut32_oaidl.h" 41 42 #include "wine/debug.h" 43 #include "wine/unicode.h" 44 45 WINE_DEFAULT_DEBUG_CHANNEL(ole); 46 WINE_DECLARE_DEBUG_CHANNEL(heap); 47 48 /****************************************************************************** 49 * BSTR {OLEAUT32} 50 * 51 * NOTES 52 * BSTR is a simple typedef for a wide-character string used as the principle 53 * string type in ole automation. When encapsulated in a Variant type they are 54 * automatically copied and destroyed as the variant is processed. 55 * 56 * The low level BSTR API allows manipulation of these strings and is used by 57 * higher level API calls to manage the strings transparently to the caller. 58 * 59 * Internally the BSTR type is allocated with space for a DWORD byte count before 60 * the string data begins. This is undocumented and non-system code should not 61 * access the count directly. Use SysStringLen() or SysStringByteLen() 62 * instead. Note that the byte count does not include the terminating NUL. 63 * 64 * To create a new BSTR, use SysAllocString(), SysAllocStringLen() or 65 * SysAllocStringByteLen(). To change the size of an existing BSTR, use SysReAllocString() 66 * or SysReAllocStringLen(). Finally to destroy a string use SysFreeString(). 67 * 68 * BSTR's are cached by Ole Automation by default. To override this behaviour 69 * either set the environment variable 'OANOCACHE', or call SetOaNoCache(). 70 * 71 * SEE ALSO 72 * 'Inside OLE, second edition' by Kraig Brockshmidt. 73 */ 74 75 static BOOL bstr_cache_enabled; 76 77 static CRITICAL_SECTION cs_bstr_cache; 78 static CRITICAL_SECTION_DEBUG cs_bstr_cache_dbg = 79 { 80 0, 0, &cs_bstr_cache, 81 { &cs_bstr_cache_dbg.ProcessLocksList, &cs_bstr_cache_dbg.ProcessLocksList }, 82 0, 0, { (DWORD_PTR)(__FILE__ ": bstr_cache") } 83 }; 84 static CRITICAL_SECTION cs_bstr_cache = { &cs_bstr_cache_dbg, -1, 0, 0, 0, 0 }; 85 86 typedef struct { 87 #ifdef _WIN64 88 DWORD pad; 89 #endif 90 DWORD size; 91 union { 92 char ptr[1]; 93 WCHAR str[1]; 94 DWORD dwptr[1]; 95 } u; 96 } bstr_t; 97 98 #define BUCKET_SIZE 16 99 #define BUCKET_BUFFER_SIZE 6 100 101 typedef struct { 102 unsigned short head; 103 unsigned short cnt; 104 bstr_t *buf[BUCKET_BUFFER_SIZE]; 105 } bstr_cache_entry_t; 106 107 #define ARENA_INUSE_FILLER 0x55 108 #define ARENA_TAIL_FILLER 0xab 109 #define ARENA_FREE_FILLER 0xfeeefeee 110 111 static bstr_cache_entry_t bstr_cache[0x10000/BUCKET_SIZE]; 112 113 static inline size_t bstr_alloc_size(size_t size) 114 { 115 return (FIELD_OFFSET(bstr_t, u.ptr[size]) + sizeof(WCHAR) + BUCKET_SIZE-1) & ~(BUCKET_SIZE-1); 116 } 117 118 static inline bstr_t *bstr_from_str(BSTR str) 119 { 120 return CONTAINING_RECORD((void *)str, bstr_t, u.str); 121 } 122 123 static inline bstr_cache_entry_t *get_cache_entry_from_idx(unsigned cache_idx) 124 { 125 return bstr_cache_enabled && cache_idx < sizeof(bstr_cache)/sizeof(*bstr_cache) 126 ? bstr_cache + cache_idx 127 : NULL; 128 } 129 130 static inline bstr_cache_entry_t *get_cache_entry(size_t size) 131 { 132 unsigned cache_idx = FIELD_OFFSET(bstr_t, u.ptr[size+sizeof(WCHAR)-1])/BUCKET_SIZE; 133 return get_cache_entry_from_idx(cache_idx); 134 } 135 136 static inline bstr_cache_entry_t *get_cache_entry_from_alloc_size(SIZE_T alloc_size) 137 { 138 unsigned cache_idx; 139 if (alloc_size < BUCKET_SIZE) return NULL; 140 cache_idx = (alloc_size - BUCKET_SIZE) / BUCKET_SIZE; 141 return get_cache_entry_from_idx(cache_idx); 142 } 143 144 static bstr_t *alloc_bstr(size_t size) 145 { 146 bstr_cache_entry_t *cache_entry = get_cache_entry(size); 147 bstr_t *ret; 148 149 if(cache_entry) { 150 EnterCriticalSection(&cs_bstr_cache); 151 152 if(!cache_entry->cnt) { 153 cache_entry = get_cache_entry(size+BUCKET_SIZE); 154 if(cache_entry && !cache_entry->cnt) 155 cache_entry = NULL; 156 } 157 158 if(cache_entry) { 159 ret = cache_entry->buf[cache_entry->head++]; 160 cache_entry->head %= BUCKET_BUFFER_SIZE; 161 cache_entry->cnt--; 162 } 163 164 LeaveCriticalSection(&cs_bstr_cache); 165 166 if(cache_entry) { 167 if(WARN_ON(heap)) { 168 size_t fill_size = (FIELD_OFFSET(bstr_t, u.ptr[size])+2*sizeof(WCHAR)-1) & ~(sizeof(WCHAR)-1); 169 memset(ret, ARENA_INUSE_FILLER, fill_size); 170 memset((char *)ret+fill_size, ARENA_TAIL_FILLER, bstr_alloc_size(size)-fill_size); 171 } 172 ret->size = size; 173 return ret; 174 } 175 } 176 177 ret = CoTaskMemAlloc(bstr_alloc_size(size)); 178 if(ret) 179 ret->size = size; 180 return ret; 181 } 182 183 /****************************************************************************** 184 * SysStringLen [OLEAUT32.7] 185 * 186 * Get the allocated length of a BSTR in wide characters. 187 * 188 * PARAMS 189 * str [I] BSTR to find the length of 190 * 191 * RETURNS 192 * The allocated length of str, or 0 if str is NULL. 193 * 194 * NOTES 195 * See BSTR. 196 * The returned length may be different from the length of the string as 197 * calculated by lstrlenW(), since it returns the length that was used to 198 * allocate the string by SysAllocStringLen(). 199 */ 200 UINT WINAPI SysStringLen(BSTR str) 201 { 202 return str ? bstr_from_str(str)->size/sizeof(WCHAR) : 0; 203 } 204 205 /****************************************************************************** 206 * SysStringByteLen [OLEAUT32.149] 207 * 208 * Get the allocated length of a BSTR in bytes. 209 * 210 * PARAMS 211 * str [I] BSTR to find the length of 212 * 213 * RETURNS 214 * The allocated length of str, or 0 if str is NULL. 215 * 216 * NOTES 217 * See SysStringLen(), BSTR(). 218 */ 219 UINT WINAPI SysStringByteLen(BSTR str) 220 { 221 return str ? bstr_from_str(str)->size : 0; 222 } 223 224 /****************************************************************************** 225 * SysAllocString [OLEAUT32.2] 226 * 227 * Create a BSTR from an OLESTR. 228 * 229 * PARAMS 230 * str [I] Source to create BSTR from 231 * 232 * RETURNS 233 * Success: A BSTR allocated with SysAllocStringLen(). 234 * Failure: NULL, if oleStr is NULL. 235 * 236 * NOTES 237 * See BSTR. 238 * MSDN (October 2001) incorrectly states that NULL is returned if oleStr has 239 * a length of 0. Native Win32 and this implementation both return a valid 240 * empty BSTR in this case. 241 */ 242 BSTR WINAPI SysAllocString(LPCOLESTR str) 243 { 244 if (!str) return 0; 245 246 /* Delegate this to the SysAllocStringLen32 method. */ 247 return SysAllocStringLen(str, lstrlenW(str)); 248 } 249 250 static inline IMalloc *get_malloc(void) 251 { 252 static IMalloc *malloc; 253 254 if (!malloc) 255 CoGetMalloc(1, &malloc); 256 257 return malloc; 258 } 259 260 /****************************************************************************** 261 * SysFreeString [OLEAUT32.6] 262 * 263 * Free a BSTR. 264 * 265 * PARAMS 266 * str [I] BSTR to free. 267 * 268 * RETURNS 269 * Nothing. 270 * 271 * NOTES 272 * See BSTR. 273 * str may be NULL, in which case this function does nothing. 274 */ 275 void WINAPI SysFreeString(BSTR str) 276 { 277 bstr_cache_entry_t *cache_entry; 278 bstr_t *bstr; 279 IMalloc *malloc = get_malloc(); 280 SIZE_T alloc_size; 281 282 if(!str) 283 return; 284 285 bstr = bstr_from_str(str); 286 287 alloc_size = IMalloc_GetSize(malloc, bstr); 288 if (alloc_size == ~0UL) 289 return; 290 291 cache_entry = get_cache_entry_from_alloc_size(alloc_size); 292 if(cache_entry) { 293 unsigned i; 294 295 EnterCriticalSection(&cs_bstr_cache); 296 297 /* According to tests, freeing a string that's already in cache doesn't corrupt anything. 298 * For that to work we need to search the cache. */ 299 for(i=0; i < cache_entry->cnt; i++) { 300 if(cache_entry->buf[(cache_entry->head+i) % BUCKET_BUFFER_SIZE] == bstr) { 301 WARN_(heap)("String already is in cache!\n"); 302 LeaveCriticalSection(&cs_bstr_cache); 303 return; 304 } 305 } 306 307 if(cache_entry->cnt < sizeof(cache_entry->buf)/sizeof(*cache_entry->buf)) { 308 cache_entry->buf[(cache_entry->head+cache_entry->cnt) % BUCKET_BUFFER_SIZE] = bstr; 309 cache_entry->cnt++; 310 311 if(WARN_ON(heap)) { 312 unsigned n = (alloc_size-FIELD_OFFSET(bstr_t, u.ptr))/sizeof(DWORD); 313 for(i=0; i<n; i++) 314 bstr->u.dwptr[i] = ARENA_FREE_FILLER; 315 } 316 317 LeaveCriticalSection(&cs_bstr_cache); 318 return; 319 } 320 321 LeaveCriticalSection(&cs_bstr_cache); 322 } 323 324 CoTaskMemFree(bstr); 325 } 326 327 /****************************************************************************** 328 * SysAllocStringLen [OLEAUT32.4] 329 * 330 * Create a BSTR from an OLESTR of a given wide character length. 331 * 332 * PARAMS 333 * str [I] Source to create BSTR from 334 * len [I] Length of oleStr in wide characters 335 * 336 * RETURNS 337 * Success: A newly allocated BSTR from SysAllocStringByteLen() 338 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails. 339 * 340 * NOTES 341 * See BSTR(), SysAllocStringByteLen(). 342 */ 343 BSTR WINAPI SysAllocStringLen(const OLECHAR *str, unsigned int len) 344 { 345 bstr_t *bstr; 346 DWORD size; 347 348 /* Detect integer overflow. */ 349 if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR))) 350 return NULL; 351 352 TRACE("%s\n", debugstr_wn(str, len)); 353 354 size = len*sizeof(WCHAR); 355 bstr = alloc_bstr(size); 356 if(!bstr) 357 return NULL; 358 359 if(str) { 360 memcpy(bstr->u.str, str, size); 361 bstr->u.str[len] = 0; 362 }else { 363 memset(bstr->u.str, 0, size+sizeof(WCHAR)); 364 } 365 366 return bstr->u.str; 367 } 368 369 /****************************************************************************** 370 * SysReAllocStringLen [OLEAUT32.5] 371 * 372 * Change the length of a previously created BSTR. 373 * 374 * PARAMS 375 * old [O] BSTR to change the length of 376 * str [I] New source for pbstr 377 * len [I] Length of oleStr in wide characters 378 * 379 * RETURNS 380 * Success: 1. The size of pbstr is updated. 381 * Failure: 0, if len >= 0x80000000 or memory allocation fails. 382 * 383 * NOTES 384 * See BSTR(), SysAllocStringByteLen(). 385 * *old may be changed by this function. 386 */ 387 int WINAPI SysReAllocStringLen(BSTR* old, const OLECHAR* str, unsigned int len) 388 { 389 /* Detect integer overflow. */ 390 if (len >= ((UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))/sizeof(WCHAR))) 391 return FALSE; 392 393 if (*old!=NULL) { 394 DWORD newbytelen = len*sizeof(WCHAR); 395 bstr_t *old_bstr = bstr_from_str(*old); 396 bstr_t *bstr = CoTaskMemRealloc(old_bstr, bstr_alloc_size(newbytelen)); 397 398 if (!bstr) return FALSE; 399 400 *old = bstr->u.str; 401 bstr->size = newbytelen; 402 /* The old string data is still there when str is NULL */ 403 if (str && old_bstr->u.str != str) memmove(bstr->u.str, str, newbytelen); 404 bstr->u.str[len] = 0; 405 } else { 406 *old = SysAllocStringLen(str, len); 407 } 408 409 return TRUE; 410 } 411 412 /****************************************************************************** 413 * SysAllocStringByteLen [OLEAUT32.150] 414 * 415 * Create a BSTR from an OLESTR of a given byte length. 416 * 417 * PARAMS 418 * str [I] Source to create BSTR from 419 * len [I] Length of oleStr in bytes 420 * 421 * RETURNS 422 * Success: A newly allocated BSTR 423 * Failure: NULL, if len is >= 0x80000000, or memory allocation fails. 424 * 425 * NOTES 426 * -If len is 0 or oleStr is NULL the resulting string is empty (""). 427 * -This function always NUL terminates the resulting BSTR. 428 * -oleStr may be either an LPCSTR or LPCOLESTR, since it is copied 429 * without checking for a terminating NUL. 430 * See BSTR. 431 */ 432 BSTR WINAPI SysAllocStringByteLen(LPCSTR str, UINT len) 433 { 434 bstr_t *bstr; 435 436 /* Detect integer overflow. */ 437 if (len >= (UINT_MAX-sizeof(WCHAR)-sizeof(DWORD))) 438 return NULL; 439 440 bstr = alloc_bstr(len); 441 if(!bstr) 442 return NULL; 443 444 if(str) { 445 memcpy(bstr->u.ptr, str, len); 446 bstr->u.ptr[len] = 0; 447 }else { 448 memset(bstr->u.ptr, 0, len+1); 449 } 450 bstr->u.str[(len+sizeof(WCHAR)-1)/sizeof(WCHAR)] = 0; 451 452 return bstr->u.str; 453 } 454 455 /****************************************************************************** 456 * SysReAllocString [OLEAUT32.3] 457 * 458 * Change the length of a previously created BSTR. 459 * 460 * PARAMS 461 * old [I/O] BSTR to change the length of 462 * str [I] New source for pbstr 463 * 464 * RETURNS 465 * Success: 1 466 * Failure: 0. 467 * 468 * NOTES 469 * See BSTR(), SysAllocStringStringLen(). 470 */ 471 INT WINAPI SysReAllocString(LPBSTR old,LPCOLESTR str) 472 { 473 /* 474 * Sanity check 475 */ 476 if (old==NULL) 477 return 0; 478 479 /* 480 * Make sure we free the old string. 481 */ 482 SysFreeString(*old); 483 484 /* 485 * Allocate the new string 486 */ 487 *old = SysAllocString(str); 488 489 return 1; 490 } 491 492 /****************************************************************************** 493 * SetOaNoCache (OLEAUT32.327) 494 * 495 * Instruct Ole Automation not to cache BSTR allocations. 496 * 497 * PARAMS 498 * None. 499 * 500 * RETURNS 501 * Nothing. 502 * 503 * NOTES 504 * SetOaNoCache does not release cached strings, so it leaks by design. 505 */ 506 void WINAPI SetOaNoCache(void) 507 { 508 TRACE("\n"); 509 bstr_cache_enabled = FALSE; 510 } 511 512 static const WCHAR _delimiter[] = {'!',0}; /* default delimiter apparently */ 513 static const WCHAR *pdelimiter = &_delimiter[0]; 514 515 /*********************************************************************** 516 * RegisterActiveObject (OLEAUT32.33) 517 * 518 * Registers an object in the global item table. 519 * 520 * PARAMS 521 * punk [I] Object to register. 522 * rcid [I] CLSID of the object. 523 * dwFlags [I] Flags. 524 * pdwRegister [O] Address to store cookie of object registration in. 525 * 526 * RETURNS 527 * Success: S_OK. 528 * Failure: HRESULT code. 529 */ 530 HRESULT WINAPI DECLSPEC_HOTPATCH RegisterActiveObject( 531 LPUNKNOWN punk,REFCLSID rcid,DWORD dwFlags,LPDWORD pdwRegister 532 ) { 533 WCHAR guidbuf[80]; 534 HRESULT ret; 535 LPRUNNINGOBJECTTABLE runobtable; 536 LPMONIKER moniker; 537 DWORD rot_flags = ROTFLAGS_REGISTRATIONKEEPSALIVE; /* default registration is strong */ 538 539 StringFromGUID2(rcid,guidbuf,39); 540 ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker); 541 if (FAILED(ret)) 542 return ret; 543 ret = GetRunningObjectTable(0,&runobtable); 544 if (FAILED(ret)) { 545 IMoniker_Release(moniker); 546 return ret; 547 } 548 if(dwFlags == ACTIVEOBJECT_WEAK) 549 rot_flags = 0; 550 ret = IRunningObjectTable_Register(runobtable,rot_flags,punk,moniker,pdwRegister); 551 IRunningObjectTable_Release(runobtable); 552 IMoniker_Release(moniker); 553 return ret; 554 } 555 556 /*********************************************************************** 557 * RevokeActiveObject (OLEAUT32.34) 558 * 559 * Revokes an object from the global item table. 560 * 561 * PARAMS 562 * xregister [I] Registration cookie. 563 * reserved [I] Reserved. Set to NULL. 564 * 565 * RETURNS 566 * Success: S_OK. 567 * Failure: HRESULT code. 568 */ 569 HRESULT WINAPI DECLSPEC_HOTPATCH RevokeActiveObject(DWORD xregister,LPVOID reserved) 570 { 571 LPRUNNINGOBJECTTABLE runobtable; 572 HRESULT ret; 573 574 ret = GetRunningObjectTable(0,&runobtable); 575 if (FAILED(ret)) return ret; 576 ret = IRunningObjectTable_Revoke(runobtable,xregister); 577 if (SUCCEEDED(ret)) ret = S_OK; 578 IRunningObjectTable_Release(runobtable); 579 return ret; 580 } 581 582 /*********************************************************************** 583 * GetActiveObject (OLEAUT32.35) 584 * 585 * Gets an object from the global item table. 586 * 587 * PARAMS 588 * rcid [I] CLSID of the object. 589 * preserved [I] Reserved. Set to NULL. 590 * ppunk [O] Address to store object into. 591 * 592 * RETURNS 593 * Success: S_OK. 594 * Failure: HRESULT code. 595 */ 596 HRESULT WINAPI DECLSPEC_HOTPATCH GetActiveObject(REFCLSID rcid,LPVOID preserved,LPUNKNOWN *ppunk) 597 { 598 WCHAR guidbuf[80]; 599 HRESULT ret; 600 LPRUNNINGOBJECTTABLE runobtable; 601 LPMONIKER moniker; 602 603 StringFromGUID2(rcid,guidbuf,39); 604 ret = CreateItemMoniker(pdelimiter,guidbuf,&moniker); 605 if (FAILED(ret)) 606 return ret; 607 ret = GetRunningObjectTable(0,&runobtable); 608 if (FAILED(ret)) { 609 IMoniker_Release(moniker); 610 return ret; 611 } 612 ret = IRunningObjectTable_GetObject(runobtable,moniker,ppunk); 613 IRunningObjectTable_Release(runobtable); 614 IMoniker_Release(moniker); 615 return ret; 616 } 617 618 619 /*********************************************************************** 620 * OaBuildVersion [OLEAUT32.170] 621 * 622 * Get the Ole Automation build version. 623 * 624 * PARAMS 625 * None 626 * 627 * RETURNS 628 * The build version. 629 * 630 * NOTES 631 * Known oleaut32.dll versions: 632 *| OLE Ver. Comments Date Build Ver. 633 *| -------- ------------------------- ---- --------- 634 *| OLE 2.1 NT 1993-95 10 3023 635 *| OLE 2.1 10 3027 636 *| Win32s Ver 1.1e 20 4049 637 *| OLE 2.20 W95/NT 1993-96 20 4112 638 *| OLE 2.20 W95/NT 1993-96 20 4118 639 *| OLE 2.20 W95/NT 1993-96 20 4122 640 *| OLE 2.30 W95/NT 1993-98 30 4265 641 *| OLE 2.40 NT?? 1993-98 40 4267 642 *| OLE 2.40 W98 SE orig. file 1993-98 40 4275 643 *| OLE 2.40 W2K orig. file 1993-XX 40 4514 644 * 645 * Currently the versions returned are 2.20 for Win3.1, 2.30 for Win95 & NT 3.51, 646 * and 2.40 for all later versions. The build number is maximum, i.e. 0xffff. 647 */ 648 ULONG WINAPI OaBuildVersion(void) 649 { 650 switch(GetVersion() & 0x8000ffff) /* mask off build number */ 651 { 652 case 0x80000a03: /* WIN31 */ 653 return MAKELONG(0xffff, 20); 654 case 0x00003303: /* NT351 */ 655 return MAKELONG(0xffff, 30); 656 case 0x80000004: /* WIN95; I'd like to use the "standard" w95 minor 657 version here (30), but as we still use w95 658 as default winver (which is good IMHO), I better 659 play safe and use the latest value for w95 for now. 660 Change this as soon as default winver gets changed 661 to something more recent */ 662 case 0x80000a04: /* WIN98 */ 663 case 0x00000004: /* NT40 */ 664 case 0x00000005: /* W2K */ 665 return MAKELONG(0xffff, 40); 666 case 0x00000105: /* WinXP */ 667 case 0x00000006: /* Vista */ 668 case 0x00000106: /* Win7 */ 669 return MAKELONG(0xffff, 50); 670 default: 671 FIXME("Version value not known yet. Please investigate it !\n"); 672 return MAKELONG(0xffff, 40); /* for now return the same value as for w2k */ 673 } 674 } 675 676 /****************************************************************************** 677 * OleTranslateColor [OLEAUT32.421] 678 * 679 * Convert an OLE_COLOR to a COLORREF. 680 * 681 * PARAMS 682 * clr [I] Color to convert 683 * hpal [I] Handle to a palette for the conversion 684 * pColorRef [O] Destination for converted color, or NULL to test if the conversion is ok 685 * 686 * RETURNS 687 * Success: S_OK. The conversion is ok, and pColorRef contains the converted color if non-NULL. 688 * Failure: E_INVALIDARG, if any argument is invalid. 689 * 690 * FIXME 691 * Document the conversion rules. 692 */ 693 HRESULT WINAPI OleTranslateColor( 694 OLE_COLOR clr, 695 HPALETTE hpal, 696 COLORREF* pColorRef) 697 { 698 COLORREF colorref; 699 BYTE b = HIBYTE(HIWORD(clr)); 700 701 TRACE("(%08x, %p, %p)\n", clr, hpal, pColorRef); 702 703 /* 704 * In case pColorRef is NULL, provide our own to simplify the code. 705 */ 706 if (pColorRef == NULL) 707 pColorRef = &colorref; 708 709 switch (b) 710 { 711 case 0x00: 712 { 713 if (hpal != 0) 714 *pColorRef = PALETTERGB(GetRValue(clr), 715 GetGValue(clr), 716 GetBValue(clr)); 717 else 718 *pColorRef = clr; 719 720 break; 721 } 722 723 case 0x01: 724 { 725 if (hpal != 0) 726 { 727 PALETTEENTRY pe; 728 /* 729 * Validate the palette index. 730 */ 731 if (GetPaletteEntries(hpal, LOWORD(clr), 1, &pe) == 0) 732 return E_INVALIDARG; 733 } 734 735 *pColorRef = clr; 736 737 break; 738 } 739 740 case 0x02: 741 *pColorRef = clr; 742 break; 743 744 case 0x80: 745 { 746 int index = LOBYTE(LOWORD(clr)); 747 748 /* 749 * Validate GetSysColor index. 750 */ 751 if ((index < COLOR_SCROLLBAR) || (index > COLOR_MENUBAR)) 752 return E_INVALIDARG; 753 754 *pColorRef = GetSysColor(index); 755 756 break; 757 } 758 759 default: 760 return E_INVALIDARG; 761 } 762 763 return S_OK; 764 } 765 766 extern HRESULT WINAPI OLEAUTPS_DllGetClassObject(REFCLSID, REFIID, LPVOID *) DECLSPEC_HIDDEN; 767 extern BOOL WINAPI OLEAUTPS_DllMain(HINSTANCE, DWORD, LPVOID) DECLSPEC_HIDDEN; 768 extern HRESULT WINAPI OLEAUTPS_DllRegisterServer(void) DECLSPEC_HIDDEN; 769 extern HRESULT WINAPI OLEAUTPS_DllUnregisterServer(void) DECLSPEC_HIDDEN; 770 771 extern void _get_STDFONT_CF(LPVOID *); 772 extern void _get_STDPIC_CF(LPVOID *); 773 774 static HRESULT WINAPI PSDispatchFacBuf_QueryInterface(IPSFactoryBuffer *iface, REFIID riid, void **ppv) 775 { 776 if (IsEqualIID(riid, &IID_IUnknown) || 777 IsEqualIID(riid, &IID_IPSFactoryBuffer)) 778 { 779 IPSFactoryBuffer_AddRef(iface); 780 *ppv = iface; 781 return S_OK; 782 } 783 return E_NOINTERFACE; 784 } 785 786 static ULONG WINAPI PSDispatchFacBuf_AddRef(IPSFactoryBuffer *iface) 787 { 788 return 2; 789 } 790 791 static ULONG WINAPI PSDispatchFacBuf_Release(IPSFactoryBuffer *iface) 792 { 793 return 1; 794 } 795 796 static HRESULT WINAPI PSDispatchFacBuf_CreateProxy(IPSFactoryBuffer *iface, IUnknown *pUnkOuter, REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv) 797 { 798 IPSFactoryBuffer *pPSFB; 799 HRESULT hr; 800 801 if (IsEqualIID(riid, &IID_IDispatch)) 802 hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB); 803 else 804 hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB); 805 806 if (FAILED(hr)) return hr; 807 808 hr = IPSFactoryBuffer_CreateProxy(pPSFB, pUnkOuter, riid, ppProxy, ppv); 809 810 IPSFactoryBuffer_Release(pPSFB); 811 return hr; 812 } 813 814 static HRESULT WINAPI PSDispatchFacBuf_CreateStub(IPSFactoryBuffer *iface, REFIID riid, IUnknown *pUnkOuter, IRpcStubBuffer **ppStub) 815 { 816 IPSFactoryBuffer *pPSFB; 817 HRESULT hr; 818 819 if (IsEqualIID(riid, &IID_IDispatch)) 820 hr = OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, &IID_IPSFactoryBuffer, (void **)&pPSFB); 821 else 822 hr = TMARSHAL_DllGetClassObject(&CLSID_PSOAInterface, &IID_IPSFactoryBuffer, (void **)&pPSFB); 823 824 if (FAILED(hr)) return hr; 825 826 hr = IPSFactoryBuffer_CreateStub(pPSFB, riid, pUnkOuter, ppStub); 827 828 IPSFactoryBuffer_Release(pPSFB); 829 return hr; 830 } 831 832 static const IPSFactoryBufferVtbl PSDispatchFacBuf_Vtbl = 833 { 834 PSDispatchFacBuf_QueryInterface, 835 PSDispatchFacBuf_AddRef, 836 PSDispatchFacBuf_Release, 837 PSDispatchFacBuf_CreateProxy, 838 PSDispatchFacBuf_CreateStub 839 }; 840 841 /* This is the whole PSFactoryBuffer object, just the vtableptr */ 842 static const IPSFactoryBufferVtbl *pPSDispatchFacBuf = &PSDispatchFacBuf_Vtbl; 843 844 /*********************************************************************** 845 * DllGetClassObject (OLEAUT32.@) 846 */ 847 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv) 848 { 849 *ppv = NULL; 850 if (IsEqualGUID(rclsid,&CLSID_StdFont)) { 851 if (IsEqualGUID(iid,&IID_IClassFactory)) { 852 _get_STDFONT_CF(ppv); 853 IClassFactory_AddRef((IClassFactory*)*ppv); 854 return S_OK; 855 } 856 } 857 if (IsEqualGUID(rclsid,&CLSID_StdPicture)) { 858 if (IsEqualGUID(iid,&IID_IClassFactory)) { 859 _get_STDPIC_CF(ppv); 860 IClassFactory_AddRef((IClassFactory*)*ppv); 861 return S_OK; 862 } 863 } 864 if (IsEqualCLSID(rclsid, &CLSID_PSDispatch) && IsEqualIID(iid, &IID_IPSFactoryBuffer)) { 865 *ppv = &pPSDispatchFacBuf; 866 IPSFactoryBuffer_AddRef((IPSFactoryBuffer *)*ppv); 867 return S_OK; 868 } 869 if (IsEqualGUID(rclsid,&CLSID_PSOAInterface)) { 870 if (S_OK==TMARSHAL_DllGetClassObject(rclsid,iid,ppv)) 871 return S_OK; 872 /*FALLTHROUGH*/ 873 } 874 if (IsEqualCLSID(rclsid, &CLSID_PSTypeComp) || 875 IsEqualCLSID(rclsid, &CLSID_PSTypeInfo) || 876 IsEqualCLSID(rclsid, &CLSID_PSTypeLib) || 877 IsEqualCLSID(rclsid, &CLSID_PSDispatch) || 878 IsEqualCLSID(rclsid, &CLSID_PSEnumVariant)) 879 return OLEAUTPS_DllGetClassObject(&CLSID_PSFactoryBuffer, iid, ppv); 880 881 return OLEAUTPS_DllGetClassObject(rclsid, iid, ppv); 882 } 883 884 /*********************************************************************** 885 * DllCanUnloadNow (OLEAUT32.@) 886 * 887 * Determine if this dll can be unloaded from the callers address space. 888 * 889 * PARAMS 890 * None. 891 * 892 * RETURNS 893 * Always returns S_FALSE. This dll cannot be unloaded. 894 */ 895 HRESULT WINAPI DllCanUnloadNow(void) 896 { 897 return S_FALSE; 898 } 899 900 /***************************************************************************** 901 * DllMain [OLEAUT32.@] 902 */ 903 BOOL WINAPI DllMain(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved) 904 { 905 static const WCHAR oanocacheW[] = {'o','a','n','o','c','a','c','h','e',0}; 906 907 if(fdwReason == DLL_PROCESS_ATTACH) 908 bstr_cache_enabled = !GetEnvironmentVariableW(oanocacheW, NULL, 0); 909 910 return OLEAUTPS_DllMain( hInstDll, fdwReason, lpvReserved ); 911 } 912 913 /*********************************************************************** 914 * DllRegisterServer (OLEAUT32.@) 915 */ 916 HRESULT WINAPI DllRegisterServer(void) 917 { 918 return OLEAUTPS_DllRegisterServer(); 919 } 920 921 /*********************************************************************** 922 * DllUnregisterServer (OLEAUT32.@) 923 */ 924 HRESULT WINAPI DllUnregisterServer(void) 925 { 926 return OLEAUTPS_DllUnregisterServer(); 927 } 928 929 /*********************************************************************** 930 * OleIconToCursor (OLEAUT32.415) 931 */ 932 HCURSOR WINAPI OleIconToCursor( HINSTANCE hinstExe, HICON hIcon) 933 { 934 FIXME("(%p,%p), partially implemented.\n",hinstExe,hIcon); 935 /* FIXME: make an extended conversation from HICON to HCURSOR */ 936 return CopyCursor(hIcon); 937 } 938 939 /*********************************************************************** 940 * GetAltMonthNames (OLEAUT32.@) 941 */ 942 HRESULT WINAPI GetAltMonthNames(LCID lcid, LPOLESTR **str) 943 { 944 static const WCHAR ar_month1W[] = {0x645,0x62d,0x631,0x645,0}; 945 static const WCHAR ar_month2W[] = {0x635,0x641,0x631,0}; 946 static const WCHAR ar_month3W[] = {0x631,0x628,0x64a,0x639,' ',0x627,0x644,0x627,0x648,0x644,0}; 947 static const WCHAR ar_month4W[] = {0x631,0x628,0x64a,0x639,' ',0x627,0x644,0x62b,0x627,0x646,0x64a,0}; 948 static const WCHAR ar_month5W[] = {0x62c,0x645,0x627,0x62f,0x649,' ',0x627,0x644,0x627,0x648,0x644,0x649,0}; 949 static const WCHAR ar_month6W[] = {0x62c,0x645,0x627,0x62f,0x649,' ',0x627,0x644,0x62b,0x627,0x646,0x64a,0x629,0}; 950 static const WCHAR ar_month7W[] = {0x631,0x62c,0x628,0}; 951 static const WCHAR ar_month8W[] = {0x634,0x639,0x628,0x627,0x646,0}; 952 static const WCHAR ar_month9W[] = {0x631,0x645,0x636,0x627,0x646,0}; 953 static const WCHAR ar_month10W[] = {0x634,0x648,0x627,0x643,0}; 954 static const WCHAR ar_month11W[] = {0x630,0x648,' ',0x627,0x644,0x642,0x639,0x62f,0x629,0}; 955 static const WCHAR ar_month12W[] = {0x630,0x648,' ',0x627,0x644,0x62d,0x62c,0x629,0}; 956 957 static const WCHAR *arabic_hijri[] = 958 { 959 ar_month1W, 960 ar_month2W, 961 ar_month3W, 962 ar_month4W, 963 ar_month5W, 964 ar_month6W, 965 ar_month7W, 966 ar_month8W, 967 ar_month9W, 968 ar_month10W, 969 ar_month11W, 970 ar_month12W, 971 NULL 972 }; 973 974 static const WCHAR pl_month1W[] = {'s','t','y','c','z','n','i','a',0}; 975 static const WCHAR pl_month2W[] = {'l','u','t','e','g','o',0}; 976 static const WCHAR pl_month3W[] = {'m','a','r','c','a',0}; 977 static const WCHAR pl_month4W[] = {'k','w','i','e','t','n','i','a',0}; 978 static const WCHAR pl_month5W[] = {'m','a','j','a',0}; 979 static const WCHAR pl_month6W[] = {'c','z','e','r','w','c','a',0}; 980 static const WCHAR pl_month7W[] = {'l','i','p','c','a',0}; 981 static const WCHAR pl_month8W[] = {'s','i','e','r','p','n','i','a',0}; 982 static const WCHAR pl_month9W[] = {'w','r','z','e',0x15b,'n','i','a',0}; 983 static const WCHAR pl_month10W[] = {'p','a',0x17a,'d','z','i','e','r','n','i','k','a',0}; 984 static const WCHAR pl_month11W[] = {'l','i','s','t','o','p','a','d','a',0}; 985 static const WCHAR pl_month12W[] = {'g','r','u','d','n','i','a',0}; 986 987 static const WCHAR *polish_genitive_names[] = 988 { 989 pl_month1W, 990 pl_month2W, 991 pl_month3W, 992 pl_month4W, 993 pl_month5W, 994 pl_month6W, 995 pl_month7W, 996 pl_month8W, 997 pl_month9W, 998 pl_month10W, 999 pl_month11W, 1000 pl_month12W, 1001 NULL 1002 }; 1003 1004 static const WCHAR ru_month1W[] = {0x44f,0x43d,0x432,0x430,0x440,0x44f,0}; 1005 static const WCHAR ru_month2W[] = {0x444,0x435,0x432,0x440,0x430,0x43b,0x44f,0}; 1006 static const WCHAR ru_month3W[] = {0x43c,0x430,0x440,0x442,0x430,0}; 1007 static const WCHAR ru_month4W[] = {0x430,0x43f,0x440,0x435,0x43b,0x44f,0}; 1008 static const WCHAR ru_month5W[] = {0x43c,0x430,0x44f,0}; 1009 static const WCHAR ru_month6W[] = {0x438,0x44e,0x43d,0x44f,0}; 1010 static const WCHAR ru_month7W[] = {0x438,0x44e,0x43b,0x44f,0}; 1011 static const WCHAR ru_month8W[] = {0x430,0x432,0x433,0x443,0x441,0x442,0x430,0}; 1012 static const WCHAR ru_month9W[] = {0x441,0x435,0x43d,0x442,0x44f,0x431,0x440,0x44f,0}; 1013 static const WCHAR ru_month10W[] = {0x43e,0x43a,0x442,0x44f,0x431,0x440,0x44f,0}; 1014 static const WCHAR ru_month11W[] = {0x43d,0x43e,0x44f,0x431,0x440,0x44f,0}; 1015 static const WCHAR ru_month12W[] = {0x434,0x435,0x43a,0x430,0x431,0x440,0x44f,0}; 1016 1017 static const WCHAR *russian_genitive_names[] = 1018 { 1019 ru_month1W, 1020 ru_month2W, 1021 ru_month3W, 1022 ru_month4W, 1023 ru_month5W, 1024 ru_month6W, 1025 ru_month7W, 1026 ru_month8W, 1027 ru_month9W, 1028 ru_month10W, 1029 ru_month11W, 1030 ru_month12W, 1031 NULL 1032 }; 1033 1034 TRACE("%#x, %p\n", lcid, str); 1035 1036 if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_ARABIC) 1037 *str = (LPOLESTR *)arabic_hijri; 1038 else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_POLISH) 1039 *str = (LPOLESTR *)polish_genitive_names; 1040 else if (PRIMARYLANGID(LANGIDFROMLCID(lcid)) == LANG_RUSSIAN) 1041 *str = (LPOLESTR *)russian_genitive_names; 1042 else 1043 *str = NULL; 1044 1045 return S_OK; 1046 } 1047