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