1 /* 2 * Copyright 2011 Hans Leidekker for CodeWeavers 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #include <stdarg.h> 20 #define COBJMACROS 21 #include "windef.h" 22 #include "winbase.h" 23 #include "transact.h" 24 #include "initguid.h" 25 #include "txdtc.h" 26 #include "wine/unicode.h" 27 #include "wine/debug.h" 28 29 WINE_DEFAULT_DEBUG_CHANNEL(xolehlp); 30 31 /* Resource manager start */ 32 33 typedef struct { 34 IResourceManager IResourceManager_iface; 35 LONG ref; 36 } ResourceManager; 37 38 static inline ResourceManager *impl_from_IResourceManager(IResourceManager *iface) 39 { 40 return CONTAINING_RECORD(iface, ResourceManager, IResourceManager_iface); 41 } 42 43 static HRESULT WINAPI ResourceManager_QueryInterface(IResourceManager *iface, REFIID iid, 44 void **ppv) 45 { 46 ResourceManager *This = impl_from_IResourceManager(iface); 47 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 48 49 if (!ppv) return E_INVALIDARG; 50 51 if (IsEqualIID(&IID_IUnknown, iid) || 52 IsEqualIID(&IID_IResourceManager, iid)) 53 { 54 *ppv = &This->IResourceManager_iface; 55 } 56 else 57 { 58 FIXME("(%s): not implemented\n", debugstr_guid(iid)); 59 *ppv = NULL; 60 return E_NOINTERFACE; 61 } 62 63 IUnknown_AddRef((IUnknown*)*ppv); 64 return S_OK; 65 } 66 67 static ULONG WINAPI ResourceManager_AddRef(IResourceManager *iface) 68 { 69 ResourceManager *This = impl_from_IResourceManager(iface); 70 ULONG ref = InterlockedIncrement(&This->ref); 71 72 TRACE("(%p) refcount=%u\n", iface, ref); 73 74 return ref; 75 } 76 77 static ULONG WINAPI ResourceManager_Release(IResourceManager *iface) 78 { 79 ResourceManager *This = impl_from_IResourceManager(iface); 80 ULONG ref = InterlockedDecrement(&This->ref); 81 82 TRACE("(%p) refcount=%u\n", iface, ref); 83 84 if (ref == 0) 85 { 86 HeapFree(GetProcessHeap(), 0, This); 87 } 88 89 return ref; 90 } 91 static HRESULT WINAPI ResourceManager_Enlist(IResourceManager *iface, 92 ITransaction *pTransaction,ITransactionResourceAsync *pRes,XACTUOW *pUOW, 93 LONG *pisoLevel,ITransactionEnlistmentAsync **ppEnlist) 94 { 95 FIXME("(%p, %p, %p, %p, %p, %p): stub\n", iface, pTransaction,pRes,pUOW, 96 pisoLevel,ppEnlist); 97 return E_NOTIMPL; 98 } 99 static HRESULT WINAPI ResourceManager_Reenlist(IResourceManager *iface, 100 byte *pPrepInfo,ULONG cbPrepInfo,DWORD lTimeout,XACTSTAT *pXactStat) 101 { 102 FIXME("(%p, %p, %u, %u, %p): stub\n", iface, pPrepInfo, cbPrepInfo, lTimeout, pXactStat); 103 return E_NOTIMPL; 104 } 105 static HRESULT WINAPI ResourceManager_ReenlistmentComplete(IResourceManager *iface) 106 { 107 FIXME("(%p): stub\n", iface); 108 return S_OK; 109 } 110 static HRESULT WINAPI ResourceManager_GetDistributedTransactionManager(IResourceManager *iface, 111 REFIID iid,void **ppvObject) 112 { 113 FIXME("(%p, %s, %p): stub\n", iface, debugstr_guid(iid), ppvObject); 114 return E_NOTIMPL; 115 } 116 117 static const IResourceManagerVtbl ResourceManager_Vtbl = { 118 ResourceManager_QueryInterface, 119 ResourceManager_AddRef, 120 ResourceManager_Release, 121 ResourceManager_Enlist, 122 ResourceManager_Reenlist, 123 ResourceManager_ReenlistmentComplete, 124 ResourceManager_GetDistributedTransactionManager 125 }; 126 127 static HRESULT ResourceManager_Create(REFIID riid, void **ppv) 128 { 129 ResourceManager *This; 130 HRESULT ret; 131 132 if (!ppv) return E_INVALIDARG; 133 134 This = HeapAlloc(GetProcessHeap(), 0, sizeof(ResourceManager)); 135 if (!This) return E_OUTOFMEMORY; 136 137 This->IResourceManager_iface.lpVtbl = &ResourceManager_Vtbl; 138 This->ref = 1; 139 140 ret = IResourceManager_QueryInterface(&This->IResourceManager_iface, riid, ppv); 141 IResourceManager_Release(&This->IResourceManager_iface); 142 143 return ret; 144 } 145 146 /* Resource manager end */ 147 148 /* Transaction options start */ 149 150 typedef struct { 151 ITransactionOptions ITransactionOptions_iface; 152 LONG ref; 153 XACTOPT opts; 154 } TransactionOptions; 155 156 static inline TransactionOptions *impl_from_ITransactionOptions(ITransactionOptions *iface) 157 { 158 return CONTAINING_RECORD(iface, TransactionOptions, ITransactionOptions_iface); 159 } 160 161 static HRESULT WINAPI TransactionOptions_QueryInterface(ITransactionOptions *iface, REFIID iid, 162 void **ppv) 163 { 164 TransactionOptions *This = impl_from_ITransactionOptions(iface); 165 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 166 167 if (!ppv) return E_INVALIDARG; 168 169 if (IsEqualIID(&IID_IUnknown, iid) || 170 IsEqualIID(&IID_ITransactionOptions, iid)) 171 { 172 *ppv = &This->ITransactionOptions_iface; 173 } 174 else 175 { 176 FIXME("(%s): not implemented\n", debugstr_guid(iid)); 177 *ppv = NULL; 178 return E_NOINTERFACE; 179 } 180 181 IUnknown_AddRef((IUnknown*)*ppv); 182 return S_OK; 183 } 184 185 static ULONG WINAPI TransactionOptions_AddRef(ITransactionOptions *iface) 186 { 187 TransactionOptions *This = impl_from_ITransactionOptions(iface); 188 ULONG ref = InterlockedIncrement(&This->ref); 189 190 TRACE("(%p) refcount=%u\n", iface, ref); 191 192 return ref; 193 } 194 195 static ULONG WINAPI TransactionOptions_Release(ITransactionOptions *iface) 196 { 197 TransactionOptions *This = impl_from_ITransactionOptions(iface); 198 ULONG ref = InterlockedDecrement(&This->ref); 199 200 TRACE("(%p) refcount=%u\n", iface, ref); 201 202 if (ref == 0) 203 { 204 HeapFree(GetProcessHeap(), 0, This); 205 } 206 207 return ref; 208 } 209 static HRESULT WINAPI TransactionOptions_SetOptions(ITransactionOptions *iface, 210 XACTOPT *pOptions) 211 { 212 TransactionOptions *This = impl_from_ITransactionOptions(iface); 213 214 if (!pOptions) return E_INVALIDARG; 215 TRACE("(%p, %u, %s)\n", iface, pOptions->ulTimeout, debugstr_a(pOptions->szDescription)); 216 This->opts = *pOptions; 217 return S_OK; 218 } 219 static HRESULT WINAPI TransactionOptions_GetOptions(ITransactionOptions *iface, 220 XACTOPT *pOptions) 221 { 222 TransactionOptions *This = impl_from_ITransactionOptions(iface); 223 224 TRACE("(%p, %p)\n", iface, pOptions); 225 if (!pOptions) return E_INVALIDARG; 226 *pOptions = This->opts; 227 return S_OK; 228 } 229 230 static const ITransactionOptionsVtbl TransactionOptions_Vtbl = { 231 TransactionOptions_QueryInterface, 232 TransactionOptions_AddRef, 233 TransactionOptions_Release, 234 TransactionOptions_SetOptions, 235 TransactionOptions_GetOptions 236 }; 237 238 static HRESULT TransactionOptions_Create(ITransactionOptions **ppv) 239 { 240 TransactionOptions *This; 241 242 if (!ppv) return E_INVALIDARG; 243 244 This = HeapAlloc(GetProcessHeap(), 0, sizeof(TransactionOptions)); 245 if (!This) return E_OUTOFMEMORY; 246 247 This->ITransactionOptions_iface.lpVtbl = &TransactionOptions_Vtbl; 248 This->ref = 1; 249 250 *ppv = &This->ITransactionOptions_iface; 251 252 return S_OK; 253 } 254 255 /* Transaction options end */ 256 257 /* Transaction start */ 258 259 typedef struct { 260 ITransaction ITransaction_iface; 261 LONG ref; 262 XACTTRANSINFO info; 263 } Transaction; 264 265 static inline Transaction *impl_from_ITransaction(ITransaction *iface) 266 { 267 return CONTAINING_RECORD(iface, Transaction, ITransaction_iface); 268 } 269 270 static HRESULT WINAPI Transaction_QueryInterface(ITransaction *iface, REFIID iid, 271 void **ppv) 272 { 273 Transaction *This = impl_from_ITransaction(iface); 274 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 275 276 if (!ppv) return E_INVALIDARG; 277 278 if (IsEqualIID(&IID_IUnknown, iid) || 279 IsEqualIID(&IID_ITransaction, iid)) 280 { 281 *ppv = &This->ITransaction_iface; 282 } 283 else 284 { 285 FIXME("(%s): not implemented\n", debugstr_guid(iid)); 286 *ppv = NULL; 287 return E_NOINTERFACE; 288 } 289 290 IUnknown_AddRef((IUnknown*)*ppv); 291 return S_OK; 292 } 293 294 static ULONG WINAPI Transaction_AddRef(ITransaction *iface) 295 { 296 Transaction *This = impl_from_ITransaction(iface); 297 ULONG ref = InterlockedIncrement(&This->ref); 298 299 TRACE("(%p) refcount=%u\n", iface, ref); 300 301 return ref; 302 } 303 304 static ULONG WINAPI Transaction_Release(ITransaction *iface) 305 { 306 Transaction *This = impl_from_ITransaction(iface); 307 ULONG ref = InterlockedDecrement(&This->ref); 308 309 TRACE("(%p) refcount=%u\n", iface, ref); 310 311 if (ref == 0) 312 { 313 HeapFree(GetProcessHeap(), 0, This); 314 } 315 316 return ref; 317 } 318 static HRESULT WINAPI Transaction_Commit(ITransaction *iface, 319 BOOL fRetaining, DWORD grfTC, DWORD grfRM) 320 { 321 FIXME("(%p, %d, %08x, %08x): stub\n", iface, fRetaining, grfTC, grfRM); 322 return E_NOTIMPL; 323 } 324 static HRESULT WINAPI Transaction_Abort(ITransaction *iface, 325 BOID *pboidReason, BOOL fRetaining, BOOL fAsync) 326 { 327 FIXME("(%p, %p, %d, %d): stub\n", iface, pboidReason, fRetaining, fAsync); 328 return E_NOTIMPL; 329 } 330 static HRESULT WINAPI Transaction_GetTransactionInfo(ITransaction *iface, 331 XACTTRANSINFO *pinfo) 332 { 333 Transaction *This = impl_from_ITransaction(iface); 334 TRACE("(%p, %p)\n", iface, pinfo); 335 if (!pinfo) return E_INVALIDARG; 336 *pinfo = This->info; 337 return S_OK; 338 } 339 340 static const ITransactionVtbl Transaction_Vtbl = { 341 Transaction_QueryInterface, 342 Transaction_AddRef, 343 Transaction_Release, 344 Transaction_Commit, 345 Transaction_Abort, 346 Transaction_GetTransactionInfo 347 }; 348 349 static HRESULT Transaction_Create(ISOLEVEL isoLevel, ULONG isoFlags, 350 ITransactionOptions *pOptions, ITransaction **ppv) 351 { 352 Transaction *This; 353 354 if (!ppv) return E_INVALIDARG; 355 356 This = HeapAlloc(GetProcessHeap(), 0, sizeof(Transaction)); 357 if (!This) return E_OUTOFMEMORY; 358 ZeroMemory(&This->info, sizeof(This->info)); 359 360 This->ITransaction_iface.lpVtbl = &Transaction_Vtbl; 361 This->ref = 1; 362 This->info.isoLevel = isoLevel; 363 This->info.isoFlags = isoFlags; 364 365 *ppv = &This->ITransaction_iface; 366 367 return S_OK; 368 } 369 370 /* Transaction end */ 371 372 /* DTC Proxy Core Object start */ 373 374 typedef struct { 375 ITransactionDispenser ITransactionDispenser_iface; 376 LONG ref; 377 IResourceManagerFactory2 IResourceManagerFactory2_iface; 378 ITransactionImportWhereabouts ITransactionImportWhereabouts_iface; 379 ITransactionImport ITransactionImport_iface; 380 } TransactionManager; 381 382 static inline TransactionManager *impl_from_ITransactionDispenser(ITransactionDispenser *iface) 383 { 384 return CONTAINING_RECORD(iface, TransactionManager, ITransactionDispenser_iface); 385 } 386 387 static HRESULT WINAPI TransactionDispenser_QueryInterface(ITransactionDispenser *iface, REFIID iid, 388 void **ppv) 389 { 390 TransactionManager *This = impl_from_ITransactionDispenser(iface); 391 TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); 392 393 if (!ppv) return E_INVALIDARG; 394 395 if (IsEqualIID(&IID_IUnknown, iid) || 396 IsEqualIID(&IID_ITransactionDispenser, iid)) 397 { 398 *ppv = &This->ITransactionDispenser_iface; 399 } 400 else if (IsEqualIID(&IID_IResourceManagerFactory, iid) || 401 IsEqualIID(&IID_IResourceManagerFactory2, iid)) 402 { 403 *ppv = &This->IResourceManagerFactory2_iface; 404 } 405 else if (IsEqualIID(&IID_ITransactionImportWhereabouts, iid)) 406 { 407 *ppv = &This->ITransactionImportWhereabouts_iface; 408 } 409 else if (IsEqualIID(&IID_ITransactionImport, iid)) 410 { 411 *ppv = &This->ITransactionImport_iface; 412 } 413 else 414 { 415 FIXME("(%s): not implemented\n", debugstr_guid(iid)); 416 *ppv = NULL; 417 return E_NOINTERFACE; 418 } 419 420 IUnknown_AddRef((IUnknown*)*ppv); 421 return S_OK; 422 } 423 424 static ULONG WINAPI TransactionDispenser_AddRef(ITransactionDispenser *iface) 425 { 426 TransactionManager *This = impl_from_ITransactionDispenser(iface); 427 ULONG ref = InterlockedIncrement(&This->ref); 428 429 TRACE("(%p) refcount=%u\n", iface, ref); 430 431 return ref; 432 } 433 434 static ULONG WINAPI TransactionDispenser_Release(ITransactionDispenser *iface) 435 { 436 TransactionManager *This = impl_from_ITransactionDispenser(iface); 437 ULONG ref = InterlockedDecrement(&This->ref); 438 439 TRACE("(%p) refcount=%u\n", iface, ref); 440 441 if (ref == 0) 442 { 443 HeapFree(GetProcessHeap(), 0, This); 444 } 445 446 return ref; 447 } 448 449 static HRESULT WINAPI TransactionDispenser_GetOptionsObject(ITransactionDispenser *iface, 450 ITransactionOptions **ppOptions) 451 { 452 TRACE("(%p, %p)\n", iface, ppOptions); 453 454 if (!ppOptions) return E_INVALIDARG; 455 return TransactionOptions_Create(ppOptions); 456 } 457 static HRESULT WINAPI TransactionDispenser_BeginTransaction(ITransactionDispenser *iface, 458 IUnknown *punkOuter, 459 ISOLEVEL isoLevel, 460 ULONG isoFlags, 461 ITransactionOptions *pOptions, 462 ITransaction **ppTransaction) 463 { 464 FIXME("(%p, %p, %08x, %08x, %p, %p): semi-stub\n", iface, punkOuter, 465 isoLevel, isoFlags, pOptions, ppTransaction); 466 467 if (!ppTransaction) return E_INVALIDARG; 468 if (punkOuter) return CLASS_E_NOAGGREGATION; 469 return Transaction_Create(isoLevel, isoFlags, pOptions, ppTransaction); 470 } 471 static const ITransactionDispenserVtbl TransactionDispenser_Vtbl = { 472 TransactionDispenser_QueryInterface, 473 TransactionDispenser_AddRef, 474 TransactionDispenser_Release, 475 TransactionDispenser_GetOptionsObject, 476 TransactionDispenser_BeginTransaction 477 }; 478 479 static inline TransactionManager *impl_from_IResourceManagerFactory2(IResourceManagerFactory2 *iface) 480 { 481 return CONTAINING_RECORD(iface, TransactionManager, IResourceManagerFactory2_iface); 482 } 483 484 static HRESULT WINAPI ResourceManagerFactory2_QueryInterface(IResourceManagerFactory2 *iface, REFIID iid, 485 void **ppv) 486 { 487 TransactionManager *This = impl_from_IResourceManagerFactory2(iface); 488 return TransactionDispenser_QueryInterface(&This->ITransactionDispenser_iface, iid, ppv); 489 } 490 491 static ULONG WINAPI ResourceManagerFactory2_AddRef(IResourceManagerFactory2 *iface) 492 { 493 TransactionManager *This = impl_from_IResourceManagerFactory2(iface); 494 return TransactionDispenser_AddRef(&This->ITransactionDispenser_iface); 495 } 496 497 static ULONG WINAPI ResourceManagerFactory2_Release(IResourceManagerFactory2 *iface) 498 { 499 TransactionManager *This = impl_from_IResourceManagerFactory2(iface); 500 return TransactionDispenser_Release(&This->ITransactionDispenser_iface); 501 } 502 static HRESULT WINAPI ResourceManagerFactory2_Create(IResourceManagerFactory2 *iface, 503 GUID *pguidRM, CHAR *pszRMName, IResourceManagerSink *pIResMgrSink, IResourceManager **ppResMgr) 504 { 505 FIXME("(%p, %s, %s, %p, %p): semi-stub\n", iface, debugstr_guid(pguidRM), 506 debugstr_a(pszRMName), pIResMgrSink, ppResMgr); 507 return ResourceManager_Create(&IID_IResourceManager, (void**)ppResMgr); 508 } 509 static HRESULT WINAPI ResourceManagerFactory2_CreateEx(IResourceManagerFactory2 *iface, 510 GUID *pguidRM, CHAR *pszRMName, IResourceManagerSink *pIResMgrSink, REFIID riidRequested, void **ppResMgr) 511 { 512 FIXME("(%p, %s, %s, %p, %s, %p): semi-stub\n", iface, debugstr_guid(pguidRM), 513 debugstr_a(pszRMName), pIResMgrSink, debugstr_guid(riidRequested), ppResMgr); 514 515 return ResourceManager_Create(riidRequested, ppResMgr); 516 } 517 static const IResourceManagerFactory2Vtbl ResourceManagerFactory2_Vtbl = { 518 ResourceManagerFactory2_QueryInterface, 519 ResourceManagerFactory2_AddRef, 520 ResourceManagerFactory2_Release, 521 ResourceManagerFactory2_Create, 522 ResourceManagerFactory2_CreateEx 523 }; 524 525 static inline TransactionManager *impl_from_ITransactionImportWhereabouts(ITransactionImportWhereabouts *iface) 526 { 527 return CONTAINING_RECORD(iface, TransactionManager, ITransactionImportWhereabouts_iface); 528 } 529 530 static HRESULT WINAPI TransactionImportWhereabouts_QueryInterface(ITransactionImportWhereabouts *iface, REFIID iid, 531 void **ppv) 532 { 533 TransactionManager *This = impl_from_ITransactionImportWhereabouts(iface); 534 return TransactionDispenser_QueryInterface(&This->ITransactionDispenser_iface, iid, ppv); 535 } 536 537 static ULONG WINAPI TransactionImportWhereabouts_AddRef(ITransactionImportWhereabouts *iface) 538 { 539 TransactionManager *This = impl_from_ITransactionImportWhereabouts(iface); 540 return TransactionDispenser_AddRef(&This->ITransactionDispenser_iface); 541 } 542 543 static ULONG WINAPI TransactionImportWhereabouts_Release(ITransactionImportWhereabouts *iface) 544 { 545 TransactionManager *This = impl_from_ITransactionImportWhereabouts(iface); 546 return TransactionDispenser_Release(&This->ITransactionDispenser_iface); 547 } 548 static HRESULT WINAPI TransactionImportWhereabouts_GetWhereaboutsSize(ITransactionImportWhereabouts *iface, 549 ULONG *pcbWhereabouts) 550 { 551 FIXME("(%p, %p): stub returning fake value\n", iface, pcbWhereabouts); 552 553 if (!pcbWhereabouts) return E_INVALIDARG; 554 *pcbWhereabouts = 1; 555 return S_OK; 556 } 557 static HRESULT WINAPI TransactionImportWhereabouts_GetWhereabouts(ITransactionImportWhereabouts *iface, 558 ULONG cbWhereabouts, BYTE *rgbWhereabouts,ULONG *pcbUsed) 559 { 560 FIXME("(%p, %u, %p, %p): stub returning fake value\n", iface, cbWhereabouts, rgbWhereabouts, pcbUsed); 561 562 if (!rgbWhereabouts || !pcbUsed) return E_INVALIDARG; 563 *rgbWhereabouts = 0; 564 *pcbUsed = 1; 565 return S_OK; 566 } 567 static const ITransactionImportWhereaboutsVtbl TransactionImportWhereabouts_Vtbl = { 568 TransactionImportWhereabouts_QueryInterface, 569 TransactionImportWhereabouts_AddRef, 570 TransactionImportWhereabouts_Release, 571 TransactionImportWhereabouts_GetWhereaboutsSize, 572 TransactionImportWhereabouts_GetWhereabouts 573 }; 574 575 static inline TransactionManager *impl_from_ITransactionImport(ITransactionImport *iface) 576 { 577 return CONTAINING_RECORD(iface, TransactionManager, ITransactionImport_iface); 578 } 579 580 static HRESULT WINAPI TransactionImport_QueryInterface(ITransactionImport *iface, REFIID iid, 581 void **ppv) 582 { 583 TransactionManager *This = impl_from_ITransactionImport(iface); 584 return TransactionDispenser_QueryInterface(&This->ITransactionDispenser_iface, iid, ppv); 585 } 586 587 static ULONG WINAPI TransactionImport_AddRef(ITransactionImport *iface) 588 { 589 TransactionManager *This = impl_from_ITransactionImport(iface); 590 return TransactionDispenser_AddRef(&This->ITransactionDispenser_iface); 591 } 592 593 static ULONG WINAPI TransactionImport_Release(ITransactionImport *iface) 594 { 595 TransactionManager *This = impl_from_ITransactionImport(iface); 596 return TransactionDispenser_Release(&This->ITransactionDispenser_iface); 597 } 598 static HRESULT WINAPI TransactionImport_Import(ITransactionImport *iface, 599 ULONG cbTransactionCookie, byte *rgbTransactionCookie, IID *piid, void **ppvTransaction) 600 { 601 FIXME("(%p, %u, %p, %s, %p): stub\n", iface, cbTransactionCookie, rgbTransactionCookie, debugstr_guid(piid), ppvTransaction); 602 603 if (!rgbTransactionCookie || !piid || !ppvTransaction) return E_INVALIDARG; 604 return E_NOTIMPL; 605 } 606 static const ITransactionImportVtbl TransactionImport_Vtbl = { 607 TransactionImport_QueryInterface, 608 TransactionImport_AddRef, 609 TransactionImport_Release, 610 TransactionImport_Import 611 }; 612 613 static HRESULT TransactionManager_Create(REFIID riid, void **ppv) 614 { 615 TransactionManager *This; 616 HRESULT ret; 617 618 This = HeapAlloc(GetProcessHeap(), 0, sizeof(TransactionManager)); 619 if (!This) return E_OUTOFMEMORY; 620 621 This->ITransactionDispenser_iface.lpVtbl = &TransactionDispenser_Vtbl; 622 This->IResourceManagerFactory2_iface.lpVtbl = &ResourceManagerFactory2_Vtbl; 623 This->ITransactionImportWhereabouts_iface.lpVtbl = &TransactionImportWhereabouts_Vtbl; 624 This->ITransactionImport_iface.lpVtbl = &TransactionImport_Vtbl; 625 This->ref = 1; 626 627 ret = ITransactionDispenser_QueryInterface(&This->ITransactionDispenser_iface, riid, ppv); 628 ITransactionDispenser_Release(&This->ITransactionDispenser_iface); 629 630 return ret; 631 } 632 /* DTC Proxy Core Object end */ 633 634 BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) 635 { 636 TRACE("%p, %u, %p\n", hinst, reason, reserved); 637 638 switch (reason) 639 { 640 case DLL_WINE_PREATTACH: 641 return FALSE; /* prefer native version */ 642 case DLL_PROCESS_ATTACH: 643 DisableThreadLibraryCalls( hinst ); 644 break; 645 } 646 return TRUE; 647 } 648 649 static BOOL is_local_machineA( const CHAR *server ) 650 { 651 static const CHAR dot[] = "."; 652 CHAR buffer[MAX_COMPUTERNAME_LENGTH + 1]; 653 DWORD len = ARRAY_SIZE( buffer ); 654 655 if (!server || !strcmp( server, dot )) return TRUE; 656 if (GetComputerNameA( buffer, &len ) && !lstrcmpiA( server, buffer )) return TRUE; 657 return FALSE; 658 } 659 static BOOL is_local_machineW( const WCHAR *server ) 660 { 661 static const WCHAR dotW[] = {'.',0}; 662 WCHAR buffer[MAX_COMPUTERNAME_LENGTH + 1]; 663 DWORD len = ARRAY_SIZE( buffer ); 664 665 if (!server || !strcmpW( server, dotW )) return TRUE; 666 if (GetComputerNameW( buffer, &len ) && !strcmpiW( server, buffer )) return TRUE; 667 return FALSE; 668 } 669 670 HRESULT CDECL DtcGetTransactionManager(char *host, char *tm_name, REFIID riid, 671 DWORD dwReserved1, WORD wcbReserved2, void *pvReserved2, void **ppv) 672 { 673 TRACE("(%s, %s, %s, %d, %d, %p, %p)\n", debugstr_a(host), debugstr_a(tm_name), 674 debugstr_guid(riid), dwReserved1, wcbReserved2, pvReserved2, ppv); 675 676 if (!is_local_machineA(host)) 677 { 678 FIXME("remote computer not supported\n"); 679 return E_NOTIMPL; 680 } 681 return TransactionManager_Create(riid, ppv); 682 } 683 684 HRESULT CDECL DtcGetTransactionManagerExA(CHAR *host, CHAR *tm_name, REFIID riid, 685 DWORD options, void *config, void **ppv) 686 { 687 TRACE("(%s, %s, %s, %d, %p, %p)\n", debugstr_a(host), debugstr_a(tm_name), 688 debugstr_guid(riid), options, config, ppv); 689 690 if (!is_local_machineA(host)) 691 { 692 FIXME("remote computer not supported\n"); 693 return E_NOTIMPL; 694 } 695 return TransactionManager_Create(riid, ppv); 696 } 697 698 HRESULT CDECL DtcGetTransactionManagerExW(WCHAR *host, WCHAR *tm_name, REFIID riid, 699 DWORD options, void *config, void **ppv) 700 { 701 TRACE("(%s, %s, %s, %d, %p, %p)\n", debugstr_w(host), debugstr_w(tm_name), 702 debugstr_guid(riid), options, config, ppv); 703 704 if (!is_local_machineW(host)) 705 { 706 FIXME("remote computer not supported\n"); 707 return E_NOTIMPL; 708 } 709 return TransactionManager_Create(riid, ppv); 710 } 711