From 9f16d9b33acd6d7615c90fcce7c2a9e7cadc5065 Mon Sep 17 00:00:00 2001 From: Alemarius Nexus Date: Thu, 1 Jul 2021 06:48:38 +0200 Subject: [PATCH] Add limited, experimental support for MinGW and Clang --- README.md | 1 + README_MINGW_CLANG.md | 21 + src/3rd_party/reactos-atl/LICENSE-GPL.txt | 348 +++ src/3rd_party/reactos-atl/LICENSE-LGPL.txt | 504 +++++ src/3rd_party/reactos-atl/README.txt | 6 + src/3rd_party/reactos-atl/atl/CMakeLists.txt | 13 + src/3rd_party/reactos-atl/atl/atlalloc.h | 194 ++ src/3rd_party/reactos-atl/atl/atlbase.h | 1864 ++++++++++++++++ src/3rd_party/reactos-atl/atl/atlcoll.h | 900 ++++++++ src/3rd_party/reactos-atl/atl/atlcom.h | 1527 +++++++++++++ src/3rd_party/reactos-atl/atl/atlcomcli.h | 573 +++++ src/3rd_party/reactos-atl/atl/atlcore.h | 310 +++ src/3rd_party/reactos-atl/atl/atldef.h | 63 + src/3rd_party/reactos-atl/atl/atlexcept.h | 50 + src/3rd_party/reactos-atl/atl/atlfile.h | 281 +++ src/3rd_party/reactos-atl/atl/atlimage.h | 1219 ++++++++++ src/3rd_party/reactos-atl/atl/atlmem.h | 105 + src/3rd_party/reactos-atl/atl/atlpath.h | 389 ++++ src/3rd_party/reactos-atl/atl/atlsimpcoll.h | 454 ++++ src/3rd_party/reactos-atl/atl/atlsimpstr.h | 630 ++++++ src/3rd_party/reactos-atl/atl/atlstr.h | 145 ++ src/3rd_party/reactos-atl/atl/atltime.h | 662 ++++++ src/3rd_party/reactos-atl/atl/atltypes.h | 569 +++++ src/3rd_party/reactos-atl/atl/atlwin.h | 1978 +++++++++++++++++ src/3rd_party/reactos-atl/atl/cstringt.h | 998 +++++++++ src/3rd_party/reactos-atl/atl/statreg.h | 765 +++++++ .../rewolf-wow64ext/src/wow64ext.cpp | 2 + src/BlackBone/Asm/AsmHelper32.cpp | 1 + src/BlackBone/CMakeLists.txt | 5 + src/BlackBone/Include/CallResult.h | 1 + src/BlackBone/Include/Macro.h | 2 +- src/BlackBone/Misc/NameResolve.cpp | 2 +- src/BlackBone/PE/PEImage.cpp | 8 +- src/BlackBone/PE/PEImage.h | 4 +- src/BlackBone/Process/MemBlock.cpp | 2 +- src/BlackBone/Process/Process.h | 2 +- src/BlackBone/Process/ProcessModules.cpp | 7 +- src/BlackBone/Process/RPC/RemoteExec.cpp | 3 + src/BlackBone/Process/Threads/Thread.h | 39 +- src/BlackBone/Process/Threads/Threads.h | 3 +- src/BlackBone/Subsystem/Wow64Subsystem.cpp | 2 +- src/BlackBone/Symbols/PDBHelper.cpp | 10 + src/BlackBone/Symbols/SymbolData.cpp | 1 - src/BlackBone/Syscalls/Syscall.h | 4 + src/CMakeLists.txt | 8 + src/Samples/Main.cpp | 7 +- 46 files changed, 14661 insertions(+), 21 deletions(-) create mode 100644 README_MINGW_CLANG.md create mode 100644 src/3rd_party/reactos-atl/LICENSE-GPL.txt create mode 100644 src/3rd_party/reactos-atl/LICENSE-LGPL.txt create mode 100644 src/3rd_party/reactos-atl/README.txt create mode 100644 src/3rd_party/reactos-atl/atl/CMakeLists.txt create mode 100644 src/3rd_party/reactos-atl/atl/atlalloc.h create mode 100644 src/3rd_party/reactos-atl/atl/atlbase.h create mode 100644 src/3rd_party/reactos-atl/atl/atlcoll.h create mode 100644 src/3rd_party/reactos-atl/atl/atlcom.h create mode 100644 src/3rd_party/reactos-atl/atl/atlcomcli.h create mode 100644 src/3rd_party/reactos-atl/atl/atlcore.h create mode 100644 src/3rd_party/reactos-atl/atl/atldef.h create mode 100644 src/3rd_party/reactos-atl/atl/atlexcept.h create mode 100644 src/3rd_party/reactos-atl/atl/atlfile.h create mode 100644 src/3rd_party/reactos-atl/atl/atlimage.h create mode 100644 src/3rd_party/reactos-atl/atl/atlmem.h create mode 100644 src/3rd_party/reactos-atl/atl/atlpath.h create mode 100644 src/3rd_party/reactos-atl/atl/atlsimpcoll.h create mode 100644 src/3rd_party/reactos-atl/atl/atlsimpstr.h create mode 100644 src/3rd_party/reactos-atl/atl/atlstr.h create mode 100644 src/3rd_party/reactos-atl/atl/atltime.h create mode 100644 src/3rd_party/reactos-atl/atl/atltypes.h create mode 100644 src/3rd_party/reactos-atl/atl/atlwin.h create mode 100644 src/3rd_party/reactos-atl/atl/cstringt.h create mode 100644 src/3rd_party/reactos-atl/atl/statreg.h diff --git a/README.md b/README.md index a8d58f85..1f747bc7 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ ## Requirements - Visual Studio 2017 15.7 or higher + - There is limited support for MinGW and Clang. See [README_MINGW_CLANG.md](README_MINGW_CLANG.md) - Windows SDK 10.0.17134 or higher - WDK 10.0.17134 or higher (driver only) - VC++ 2017 Libs for Spectre (x86 and x64) diff --git a/README_MINGW_CLANG.md b/README_MINGW_CLANG.md new file mode 100644 index 00000000..8ad35aff --- /dev/null +++ b/README_MINGW_CLANG.md @@ -0,0 +1,21 @@ +# Support for MinGW/Clang + +There is limited, experimental support for building BlackBone with MinGW (GCC) and Clang on Windows. Read the following hints carefully before attempting to use it. + + +## General + +* You must **build with CMake**, by using the directory with the top-level CMakeLists.txt as source directory. +* **Only the library and Samples** work with MinGW/Clang. I have not attempted to make the driver or the unit tests compile. I have not even tried if the library works with an MSVC-compiled driver. +* **Only 64-bit builds** are supported. Even if it compiles under 32-bit, it may crash at runtime. This is because BlackBone uses the Rewolf-WOW64Ext library when running under Wow64, and that contains inline ASM code that only works in MSVC right now. No idea about 32-bit builds on 32-bit Windows. +* **Syscall support is disabled.** This means anything in the *Blackbone/Syscalls* directory won't work. That's because syscalls in BlackBone require ASM code that was written in MASM syntax, which neither MinGW nor Clang support. + + +## MinGW (GCC) Specifics + +* It was tested with **MinGW GCC 10.0.3 from MSYS2**. GCC 8.1.0 did also work at some point, but YMMV. + + +## Clang Specifics + +* It was tested with **Clang 12.0.0 from MSYS2**. Earlier versions may or may not work. diff --git a/src/3rd_party/reactos-atl/LICENSE-GPL.txt b/src/3rd_party/reactos-atl/LICENSE-GPL.txt new file mode 100644 index 00000000..513a9494 --- /dev/null +++ b/src/3rd_party/reactos-atl/LICENSE-GPL.txt @@ -0,0 +1,348 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. + + +ReactOS may be used, runtime linked, and distributed with non-free software +(meaning that such software has no obligations to open-source, or render +free, their non-free code) such as commercial device drivers and commercial +applications. This exception does not alter any other responsibilities of +the licensee under the GPL (meaning that such software must still obey +the GPL for the free ("open-sourced") code that has been integrated into +the said software). \ No newline at end of file diff --git a/src/3rd_party/reactos-atl/LICENSE-LGPL.txt b/src/3rd_party/reactos-atl/LICENSE-LGPL.txt new file mode 100644 index 00000000..67870f65 --- /dev/null +++ b/src/3rd_party/reactos-atl/LICENSE-LGPL.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/src/3rd_party/reactos-atl/README.txt b/src/3rd_party/reactos-atl/README.txt new file mode 100644 index 00000000..4ee0cb0e --- /dev/null +++ b/src/3rd_party/reactos-atl/README.txt @@ -0,0 +1,6 @@ +These headers are taken from ReactOS: + + https://github.com/reactos/reactos/tree/master/sdk/lib/atl + +They are only used when compiling with MinGW/Clang, because the standard ATL +headers are only compatible with MSVC. diff --git a/src/3rd_party/reactos-atl/atl/CMakeLists.txt b/src/3rd_party/reactos-atl/atl/CMakeLists.txt new file mode 100644 index 00000000..9fb5d548 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/CMakeLists.txt @@ -0,0 +1,13 @@ + +add_library(atl_classes INTERFACE) +if(DBG) + #target_compile_definitions(atl_classes INTERFACE _DEBUG) # HACK & FIXME: CORE-17505 +endif() + +target_include_directories(atl_classes INTERFACE + $<$:${CMAKE_CURRENT_SOURCE_DIR}>) + +target_compile_definitions(atl_classes INTERFACE + "$<$,$>>>:_ATL_NO_EXCEPTIONS>") + +target_link_libraries(atl_classes INTERFACE pseh) diff --git a/src/3rd_party/reactos-atl/atl/atlalloc.h b/src/3rd_party/reactos-atl/atl/atlalloc.h new file mode 100644 index 00000000..757b822b --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlalloc.h @@ -0,0 +1,194 @@ +/* + * ReactOS ATL + * + * Copyright 2009 Andrew Hill + * Copyright 2016 Mark Jansen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +class CCRTAllocator +{ +public: + static void* Allocate(_In_ size_t size) + { + return malloc(size); + } + + static void* Reallocate(_In_opt_ void* ptr, _In_ size_t size) + { + return realloc(ptr, size); + } + + static void Free(_In_opt_ void* ptr) + { + free(ptr); + } +}; + +class CLocalAllocator +{ +public: + static void* Allocate(_In_ size_t size) + { + return ::LocalAlloc(LMEM_FIXED, size); + } + + static void* Reallocate(_In_opt_ void* ptr, _In_ size_t size) + { + if (!ptr) + return Allocate(size); + if (size == 0) + { + Free(ptr); + return NULL; + } + return ::LocalReAlloc(ptr, size, 0); + } + + static void Free(_In_opt_ void* ptr) + { + ::LocalFree(ptr); + } +}; + +class CGlobalAllocator +{ +public: + static void* Allocate(_In_ size_t size) + { + return ::GlobalAlloc(GMEM_FIXED, size); + } + + static void* Reallocate(_In_opt_ void* ptr, _In_ size_t size) + { + if (!ptr) + return Allocate(size); + if (size == 0) + { + Free(ptr); + return NULL; + } + return ::GlobalReAlloc(ptr, size, 0); + } + + static void Free(_In_opt_ void* ptr) + { + GlobalFree(ptr); + } +}; + + +template +class CHeapPtr +{ +public: + CHeapPtr() : + m_pData(NULL) + { + } + + explicit CHeapPtr(T *lp) : + m_pData(lp) + { + } + + explicit CHeapPtr(CHeapPtr &lp) + { + m_pData = lp.Detach(); + } + + ~CHeapPtr() + { + Free(); + } + + CHeapPtr& operator = (CHeapPtr &lp) + { + if (lp.m_pData != m_pData) + Attach(lp.Detach()); + return *this; + } + + bool AllocateBytes(_In_ size_t nBytes) + { + ATLASSERT(m_pData == NULL); + m_pData = static_cast(Allocator::Allocate(nBytes)); + return m_pData != NULL; + } + + bool ReallocateBytes(_In_ size_t nBytes) + { + T* newData = static_cast(Allocator::Reallocate(m_pData, nBytes)); + if (newData == NULL) + return false; + m_pData = newData; + return true; + } + + bool Allocate(_In_ size_t nElements = 1) + { + return AllocateBytes(nElements * sizeof(T)); + } + + bool Reallocate(_In_ size_t nElements) + { + return ReallocateBytes(nElements * sizeof(T)); + } + + void Free() + { + if (m_pData) + { + Allocator::Free(m_pData); + m_pData = NULL; + } + } + + void Attach(T *lp) + { + Allocator::Free(m_pData); + m_pData = lp; + } + + T *Detach() + { + T *saveP = m_pData; + m_pData = NULL; + return saveP; + } + + T **operator &() + { + ATLASSERT(m_pData == NULL); + return &m_pData; + } + + operator T* () const + { + return m_pData; + } + + T* operator->() const + { + return m_pData; + } + +public: + T *m_pData; +}; + diff --git a/src/3rd_party/reactos-atl/atl/atlbase.h b/src/3rd_party/reactos-atl/atl/atlbase.h new file mode 100644 index 00000000..502d7b1a --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlbase.h @@ -0,0 +1,1864 @@ +/* + * ReactOS ATL + * + * Copyright 2009 Andrew Hill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "atldef.h" +#include "atlcore.h" +#include "statreg.h" +#include "atlcomcli.h" +#include "atlalloc.h" +#include "atlexcept.h" +#include "comcat.h" +#include "tchar.h" + +#ifdef _MSC_VER +// It is common to use this in ATL constructors. They only store this for later use, so the usage is safe. +#pragma warning(disable:4355) +#endif + +#ifndef ATLTRY +#define ATLTRY(x) x; +#endif + +#ifdef _ATL_DISABLE_NO_VTABLE +#define ATL_NO_VTABLE +#else +#define ATL_NO_VTABLE __declspec(novtable) +#endif + +#ifndef ATL_DEPRECATED +#define ATL_DEPRECATED __declspec(deprecated) +#endif + + +namespace ATL +{ + +class CAtlModule; +class CComModule; +class CAtlComModule; +__declspec(selectany) CAtlModule *_pAtlModule = NULL; +__declspec(selectany) CComModule *_pModule = NULL; + + +struct _ATL_CATMAP_ENTRY +{ + int iType; + const GUID* pcatid; +}; + +#define _ATL_CATMAP_ENTRY_END 0 +#define _ATL_CATMAP_ENTRY_IMPLEMENTED 1 +#define _ATL_CATMAP_ENTRY_REQUIRED 2 + + +typedef HRESULT (WINAPI _ATL_CREATORFUNC)(void *pv, REFIID riid, LPVOID *ppv); +typedef LPCTSTR (WINAPI _ATL_DESCRIPTIONFUNC)(); +typedef const struct _ATL_CATMAP_ENTRY * (_ATL_CATMAPFUNC)(); + +struct _ATL_OBJMAP_ENTRY30 +{ + const CLSID *pclsid; + HRESULT (WINAPI *pfnUpdateRegistry)(BOOL bRegister); + _ATL_CREATORFUNC *pfnGetClassObject; + _ATL_CREATORFUNC *pfnCreateInstance; + IUnknown *pCF; + DWORD dwRegister; + _ATL_DESCRIPTIONFUNC *pfnGetObjectDescription; + _ATL_CATMAPFUNC *pfnGetCategoryMap; + void (WINAPI *pfnObjectMain)(bool bStarting); + + HRESULT WINAPI RevokeClassObject() + { + if (dwRegister == 0) + return S_OK; + return CoRevokeClassObject(dwRegister); + } + + HRESULT WINAPI RegisterClassObject(DWORD dwClsContext, DWORD dwFlags) + { + IUnknown *p; + HRESULT hResult; + + p = NULL; + if (pfnGetClassObject == NULL) + return S_OK; + + hResult = pfnGetClassObject(reinterpret_cast(pfnCreateInstance), IID_IUnknown, reinterpret_cast(&p)); + if (SUCCEEDED(hResult)) + hResult = CoRegisterClassObject(*pclsid, p, dwClsContext, dwFlags, &dwRegister); + + if (p != NULL) + p->Release(); + + return hResult; + } +}; + +typedef _ATL_OBJMAP_ENTRY30 _ATL_OBJMAP_ENTRY; + +typedef void (__stdcall _ATL_TERMFUNC)(DWORD_PTR dw); + +struct _ATL_TERMFUNC_ELEM +{ + _ATL_TERMFUNC *pFunc; + DWORD_PTR dw; + _ATL_TERMFUNC_ELEM *pNext; +}; + +struct _ATL_MODULE70 +{ + UINT cbSize; + LONG m_nLockCnt; + _ATL_TERMFUNC_ELEM *m_pTermFuncs; + CComCriticalSection m_csStaticDataInitAndTypeInfo; +}; +typedef _ATL_MODULE70 _ATL_MODULE; + +typedef HRESULT (WINAPI _ATL_CREATORARGFUNC)(void *pv, REFIID riid, LPVOID *ppv, DWORD_PTR dw); + +#define _ATL_SIMPLEMAPENTRY ((ATL::_ATL_CREATORARGFUNC *)1) + +struct _ATL_INTMAP_ENTRY +{ + const IID *piid; + DWORD_PTR dw; + _ATL_CREATORARGFUNC *pFunc; +}; + +struct _AtlCreateWndData +{ + void *m_pThis; + DWORD m_dwThreadID; + _AtlCreateWndData *m_pNext; +}; + +struct _ATL_COM_MODULE70 +{ + UINT cbSize; + HINSTANCE m_hInstTypeLib; + _ATL_OBJMAP_ENTRY **m_ppAutoObjMapFirst; + _ATL_OBJMAP_ENTRY **m_ppAutoObjMapLast; + CComCriticalSection m_csObjMap; +}; +typedef _ATL_COM_MODULE70 _ATL_COM_MODULE; + +struct _ATL_WIN_MODULE70 +{ + UINT cbSize; + CComCriticalSection m_csWindowCreate; + _AtlCreateWndData *m_pCreateWndList; +#ifdef NOTYET + CSimpleArray m_rgWindowClassAtoms; +#endif +}; +typedef _ATL_WIN_MODULE70 _ATL_WIN_MODULE; + +struct _ATL_REGMAP_ENTRY +{ + LPCOLESTR szKey; + LPCOLESTR szData; +}; + +HRESULT WINAPI AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule); +HRESULT WINAPI AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst); +HRESULT WINAPI AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject); +void WINAPI AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject); +void *WINAPI AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule); +HRESULT WINAPI AtlComModuleGetClassObject(_ATL_COM_MODULE *pComModule, REFCLSID rclsid, REFIID riid, LPVOID *ppv); + +HRESULT WINAPI AtlComModuleRegisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid); +HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid); + +HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags); +HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module); + + +template +class CComCritSecLock +{ +private: + bool m_bLocked; + TLock &m_cs; +public: + CComCritSecLock(TLock &cs, bool bInitialLock = true) : m_cs(cs) + { + HRESULT hResult; + + m_bLocked = false; + if (bInitialLock) + { + hResult = Lock(); + if (FAILED(hResult)) + { + ATLASSERT(false); + } + } + } + + ~CComCritSecLock() + { + if (m_bLocked) + Unlock(); + } + + HRESULT Lock() + { + HRESULT hResult; + + ATLASSERT(!m_bLocked); + hResult = m_cs.Lock(); + if (FAILED(hResult)) + return hResult; + m_bLocked = true; + + return S_OK; + } + + void Unlock() + { + HRESULT hResult; + + ATLASSERT(m_bLocked); + hResult = m_cs.Unlock(); + if (FAILED(hResult)) + { + ATLASSERT(false); + } + m_bLocked = false; + } +}; + + +class CHandle +{ +public: + HANDLE m_handle; + +public: + CHandle() : + m_handle(NULL) + { + } + + CHandle(_Inout_ CHandle& handle) : + m_handle(NULL) + { + Attach(handle.Detach()); + } + + explicit CHandle(_In_ HANDLE handle) : + m_handle(handle) + { + } + + ~CHandle() + { + if (m_handle) + { + Close(); + } + } + + CHandle& operator=(_Inout_ CHandle& handle) + { + if (this != &handle) + { + if (m_handle) + { + Close(); + } + Attach(handle.Detach()); + } + + return *this; + } + + operator HANDLE() const + { + return m_handle; + } + + void Attach(_In_ HANDLE handle) + { + ATLASSERT(m_handle == NULL); + m_handle = handle; + } + + HANDLE Detach() + { + HANDLE handle = m_handle; + m_handle = NULL; + return handle; + } + + void Close() + { + if (m_handle) + { + ::CloseHandle(m_handle); + m_handle = NULL; + } + } +}; + + +inline BOOL WINAPI InlineIsEqualUnknown(REFGUID rguid1) +{ + return ( + ((unsigned long *)&rguid1)[0] == 0 && + ((unsigned long *)&rguid1)[1] == 0 && + ((unsigned long *)&rguid1)[2] == 0x000000C0 && + ((unsigned long *)&rguid1)[3] == 0x46000000); +} + +class CComMultiThreadModelNoCS +{ +public: + typedef CComFakeCriticalSection AutoCriticalSection; + typedef CComFakeCriticalSection CriticalSection; + typedef CComMultiThreadModelNoCS ThreadModelNoCS; + typedef CComFakeCriticalSection AutoDeleteCriticalSection; + + static ULONG WINAPI Increment(LPLONG p) + { + return InterlockedIncrement(p); + } + + static ULONG WINAPI Decrement(LPLONG p) + { + return InterlockedDecrement(p); + } +}; + +class CComMultiThreadModel +{ +public: + typedef CComAutoCriticalSection AutoCriticalSection; + typedef CComCriticalSection CriticalSection; + typedef CComMultiThreadModelNoCS ThreadModelNoCS; + typedef CComAutoDeleteCriticalSection AutoDeleteCriticalSection; + + static ULONG WINAPI Increment(LPLONG p) + { + return InterlockedIncrement(p); + } + + static ULONG WINAPI Decrement(LPLONG p) + { + return InterlockedDecrement(p); + } +}; + +class CComSingleThreadModel +{ +public: + typedef CComFakeCriticalSection AutoCriticalSection; + typedef CComFakeCriticalSection CriticalSection; + typedef CComSingleThreadModel ThreadModelNoCS; + typedef CComFakeCriticalSection AutoDeleteCriticalSection; + + static ULONG WINAPI Increment(LPLONG p) + { + return ++*p; + } + + static ULONG WINAPI Decrement(LPLONG p) + { + return --*p; + } +}; + +#if defined(_ATL_FREE_THREADED) + + typedef CComMultiThreadModel CComObjectThreadModel; + typedef CComMultiThreadModel CComGlobalsThreadModel; + +#elif defined(_ATL_APARTMENT_THREADED) + + typedef CComSingleThreadModel CComObjectThreadModel; + typedef CComMultiThreadModel CComGlobalsThreadModel; + +#elif defined(_ATL_SINGLE_THREADED) + + typedef CComSingleThreadModel CComObjectThreadModel; + typedef CComSingleThreadModel CComGlobalsThreadModel; + +#else +#error No threading model +#endif + +class CAtlModule : public _ATL_MODULE +{ +public: + static GUID m_libid; + + CAtlModule() + { + ATLASSERT(_pAtlModule == NULL); + _pAtlModule = this; + cbSize = sizeof(_ATL_MODULE); + m_nLockCnt = 0; + } + + virtual LONG GetLockCount() + { + return m_nLockCnt; + } + + virtual LONG Lock() + { + return CComGlobalsThreadModel::Increment(&m_nLockCnt); + } + + virtual LONG Unlock() + { + return CComGlobalsThreadModel::Decrement(&m_nLockCnt); + } + + virtual HRESULT AddCommonRGSReplacements(IRegistrarBase* /*pRegistrar*/) = 0; + + HRESULT WINAPI UpdateRegistryFromResource(LPCTSTR lpszRes, BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries = NULL) + { + CRegObject registrar; + WCHAR modulePath[MAX_PATH]; + HRESULT hResult; + PCWSTR lpwszRes; + + hResult = CommonInitRegistrar(registrar, modulePath, sizeof(modulePath) / sizeof(modulePath[0]), pMapEntries); + if (FAILED(hResult)) + return hResult; +#ifdef UNICODE + lpwszRes = lpszRes; +#else + /* FIXME: this is a bit of a hack, need to re-evaluate */ + WCHAR resid[MAX_PATH]; + MultiByteToWideChar(CP_ACP, 0, lpszRes, -1, resid, MAX_PATH); + lpwszRes = resid; +#endif + if (bRegister != FALSE) + hResult = registrar.ResourceRegisterSz(modulePath, lpwszRes, L"REGISTRY"); + else + hResult = registrar.ResourceUnregisterSz(modulePath, lpwszRes, L"REGISTRY"); + + return hResult; + } + + HRESULT WINAPI UpdateRegistryFromResource(UINT nResID, BOOL bRegister, struct _ATL_REGMAP_ENTRY *pMapEntries = NULL) + { + CRegObject registrar; + WCHAR modulePath[MAX_PATH]; + HRESULT hResult; + + hResult = CommonInitRegistrar(registrar, modulePath, sizeof(modulePath) / sizeof(modulePath[0]), pMapEntries); + if (FAILED(hResult)) + return hResult; + + if (bRegister != FALSE) + hResult = registrar.ResourceRegister(modulePath, nResID, L"REGISTRY"); + else + hResult = registrar.ResourceUnregister(modulePath, nResID, L"REGISTRY"); + + return hResult; + } + +private: + HRESULT CommonInitRegistrar(CRegObject ®istrar, WCHAR *modulePath, DWORD modulePathCount, struct _ATL_REGMAP_ENTRY *pMapEntries) + { + HINSTANCE hInstance; + DWORD dwFLen; + HRESULT hResult; + + hInstance = _AtlBaseModule.GetModuleInstance(); + dwFLen = GetModuleFileNameW(hInstance, modulePath, modulePathCount); + if (dwFLen == modulePathCount) + return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); + else if (dwFLen == 0) + return HRESULT_FROM_WIN32(GetLastError()); + + if (pMapEntries != NULL) + { + while (pMapEntries->szKey != NULL) + { + ATLASSERT(pMapEntries->szData != NULL); + hResult = registrar.AddReplacement(pMapEntries->szKey, pMapEntries->szData); + if (FAILED(hResult)) + return hResult; + pMapEntries++; + } + } + + hResult = AddCommonRGSReplacements(®istrar); + if (FAILED(hResult)) + return hResult; + + hResult = registrar.AddReplacement(L"Module", modulePath); + if (FAILED(hResult)) + return hResult; + + hResult = registrar.AddReplacement(L"Module_Raw", modulePath); + if (FAILED(hResult)) + return hResult; + + return S_OK; + } +}; + +__declspec(selectany) GUID CAtlModule::m_libid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} }; + +template +class CAtlModuleT : public CAtlModule +{ +public: + + HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL); + HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL); + + + virtual HRESULT AddCommonRGSReplacements(IRegistrarBase *pRegistrar) + { + return pRegistrar->AddReplacement(L"APPID", T::GetAppId()); + } + + static LPCOLESTR GetAppId() + { + return L""; + } +}; + +class CAtlComModule : public _ATL_COM_MODULE +{ +public: + CAtlComModule() + { + GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)this, &m_hInstTypeLib); + m_ppAutoObjMapFirst = NULL; + m_ppAutoObjMapLast = NULL; + if (FAILED(m_csObjMap.Init())) + { + ATLASSERT(0); + CAtlBaseModule::m_bInitFailed = true; + return; + } + cbSize = sizeof(_ATL_COM_MODULE); + } + + ~CAtlComModule() + { + Term(); + } + + HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL) + { + return AtlComModuleRegisterServer(this, bRegTypeLib, pCLSID); + } + + HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL) + { + return AtlComModuleUnregisterServer(this, bUnRegTypeLib, pCLSID); + } + + + void Term() + { + if (cbSize != 0) + { + ATLASSERT(m_ppAutoObjMapFirst == NULL); + ATLASSERT(m_ppAutoObjMapLast == NULL); + m_csObjMap.Term(); + cbSize = 0; + } + } +}; + +__declspec(selectany) CAtlComModule _AtlComModule; + + +template +HRESULT CAtlModuleT::RegisterServer(BOOL bRegTypeLib, const CLSID *pCLSID) +{ + return _AtlComModule.RegisterServer(bRegTypeLib, pCLSID); +} + +template +HRESULT CAtlModuleT::UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID) +{ + return _AtlComModule.UnregisterServer(bUnRegTypeLib, pCLSID); +} + +template +class CAtlDllModuleT : public CAtlModuleT +{ +public: + CAtlDllModuleT() + { + } + + HRESULT DllCanUnloadNow() + { + T *pThis; + + pThis = static_cast(this); + if (pThis->GetLockCount() == 0) + return S_OK; + return S_FALSE; + } + + HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) + { + T *pThis; + + pThis = static_cast(this); + return pThis->GetClassObject(rclsid, riid, ppv); + } + + HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) + { + T *pThis; + HRESULT hResult; + + pThis = static_cast(this); + hResult = pThis->RegisterServer(bRegTypeLib); + return hResult; + } + + HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) + { + T *pThis; + HRESULT hResult; + + pThis = static_cast(this); + hResult = pThis->UnregisterServer(bUnRegTypeLib); + return hResult; + } + + HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) + { + return AtlComModuleGetClassObject(&_AtlComModule, rclsid, riid, ppv); + } +}; + + +template +class CAtlExeModuleT : public CAtlModuleT +{ +public: + DWORD m_dwMainThreadID; + //DWORD m_dwTimeOut; + //DWORD m_dwPause; + //bool m_bDelayShutdown; + + CAtlExeModuleT() + :m_dwMainThreadID(::GetCurrentThreadId()) + { + } + + ~CAtlExeModuleT() + { + } + + int WinMain(int nShowCmd) + { + HRESULT hr = T::InitializeCom(); + if (FAILED(hr)) + return hr; + + T* pThis = static_cast(this); + + LPCTSTR lpCommandLine = GetCommandLine(); + if (pThis->ParseCommandLine(lpCommandLine, &hr)) + { + hr = pThis->Run(nShowCmd); + } + + T::UninitializeCom(); + return hr; + } + + + HRESULT Run(int nShowCmd = SW_HIDE) + { + HRESULT hr = S_OK; + + T* pThis = static_cast(this); + hr = pThis->PreMessageLoop(nShowCmd); + + if (hr == S_OK) + { + pThis->RunMessageLoop(); + hr = pThis->PostMessageLoop(); + } + + return hr; + } + + LONG Lock() + { + return CoAddRefServerProcess(); + } + + LONG Unlock() + { + LONG lRet = CoReleaseServerProcess(); + if (lRet == 0) + { + ::PostThreadMessage(m_dwMainThreadID, WM_QUIT, 0, 0); + } + return lRet; + } + + bool ParseCommandLine(LPCTSTR lpCmdLine, HRESULT* pnRetCode) + { + // unimplemented! + return true; + } + + HRESULT PreMessageLoop(int nShowCmd) + { + T* pThis = static_cast(this); + return pThis->RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE); + } + + void RunMessageLoop() + { + MSG msg; + while (GetMessage(&msg, 0, 0, 0) > 0) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } + + HRESULT PostMessageLoop() + { + T* pThis = static_cast(this); + return pThis->RevokeClassObjects(); + } + + HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) + { + return AtlComModuleRegisterClassObjects(&_AtlComModule, dwClsContext, dwFlags); + } + + HRESULT RevokeClassObjects() + { + return AtlComModuleRevokeClassObjects(&_AtlComModule); + } + + static HRESULT InitializeCom() + { + return ::CoInitializeEx(NULL, COINIT_MULTITHREADED); + } + + static void UninitializeCom() + { + ::CoUninitialize(); + } + +}; + + + +class CComModule : public CAtlModuleT +{ +public: + _ATL_OBJMAP_ENTRY *m_pObjMap; +public: + CComModule() + { + ATLASSERT(_pModule == NULL); + _pModule = this; + _pModule->m_pObjMap = NULL; + } + + ~CComModule() + { + _pModule = NULL; + } + + HRESULT Init(_ATL_OBJMAP_ENTRY *p, HINSTANCE /* h */, const GUID *plibid) + { + _ATL_OBJMAP_ENTRY *objectMapEntry; + + if (plibid != NULL) + m_libid = *plibid; + + if (p != reinterpret_cast<_ATL_OBJMAP_ENTRY *>(-1)) + { + m_pObjMap = p; + if (p != NULL) + { + objectMapEntry = p; + while (objectMapEntry->pclsid != NULL) + { + objectMapEntry->pfnObjectMain(true); + objectMapEntry++; + } + } + } + return S_OK; + } + + void Term() + { + _ATL_OBJMAP_ENTRY *objectMapEntry; + + if (m_pObjMap != NULL) + { + objectMapEntry = m_pObjMap; + while (objectMapEntry->pclsid != NULL) + { + if (objectMapEntry->pCF != NULL) + objectMapEntry->pCF->Release(); + objectMapEntry->pCF = NULL; + objectMapEntry->pfnObjectMain(false); + objectMapEntry++; + } + } + } + + HRESULT GetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) + { + _ATL_OBJMAP_ENTRY *objectMapEntry; + HRESULT hResult; + + ATLASSERT(ppv != NULL); + if (ppv == NULL) + return E_POINTER; + *ppv = NULL; + hResult = S_OK; + if (m_pObjMap != NULL) + { + objectMapEntry = m_pObjMap; + while (objectMapEntry->pclsid != NULL) + { + if (objectMapEntry->pfnGetClassObject != NULL && InlineIsEqualGUID(rclsid, *objectMapEntry->pclsid) != FALSE) + { + if (objectMapEntry->pCF == NULL) + { + CComCritSecLock lock(_AtlComModule.m_csObjMap, true); + + if (objectMapEntry->pCF == NULL) + hResult = objectMapEntry->pfnGetClassObject(reinterpret_cast(objectMapEntry->pfnCreateInstance), IID_IUnknown, reinterpret_cast(&objectMapEntry->pCF)); + } + if (objectMapEntry->pCF != NULL) + hResult = objectMapEntry->pCF->QueryInterface(riid, ppv); + break; + } + objectMapEntry++; + } + } + if (hResult == S_OK && *ppv == NULL) + { + // FIXME: call AtlComModuleGetClassObject + hResult = CLASS_E_CLASSNOTAVAILABLE; + } + return hResult; + } + + HRESULT RegisterServer(BOOL bRegTypeLib = FALSE, const CLSID *pCLSID = NULL) + { + _ATL_OBJMAP_ENTRY *objectMapEntry; + HRESULT hResult; + + hResult = S_OK; + objectMapEntry = m_pObjMap; + if (objectMapEntry != NULL) + { + while (objectMapEntry->pclsid != NULL) + { + if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE) + { + hResult = objectMapEntry->pfnUpdateRegistry(TRUE); + if (FAILED(hResult)) + break; + } + objectMapEntry++; + } + } + if (SUCCEEDED(hResult)) + hResult = CAtlModuleT::RegisterServer(bRegTypeLib, pCLSID); + return hResult; + } + + HRESULT UnregisterServer(BOOL bUnRegTypeLib, const CLSID *pCLSID = NULL) + { + _ATL_OBJMAP_ENTRY *objectMapEntry; + HRESULT hResult; + + hResult = S_OK; + objectMapEntry = m_pObjMap; + if (objectMapEntry != NULL) + { + while (objectMapEntry->pclsid != NULL) + { + if (pCLSID == NULL || IsEqualGUID(*pCLSID, *objectMapEntry->pclsid) != FALSE) + { + hResult = objectMapEntry->pfnUpdateRegistry(FALSE); //unregister + if (FAILED(hResult)) + break; + } + objectMapEntry++; + } + } + if (SUCCEEDED(hResult)) + hResult = CAtlModuleT::UnregisterServer(bUnRegTypeLib, pCLSID); + + return hResult; + } + + HRESULT DllCanUnloadNow() + { + if (GetLockCount() == 0) + return S_OK; + return S_FALSE; + } + + HRESULT DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) + { + return GetClassObject(rclsid, riid, ppv); + } + + HRESULT DllRegisterServer(BOOL bRegTypeLib = TRUE) + { + return RegisterServer(bRegTypeLib); + } + + HRESULT DllUnregisterServer(BOOL bUnRegTypeLib = TRUE) + { + return UnregisterServer(bUnRegTypeLib); + } + +}; + +class CAtlWinModule : public _ATL_WIN_MODULE +{ +public: + CAtlWinModule() + { + HRESULT hResult; + + hResult = AtlWinModuleInit(this); + if (FAILED(hResult)) + { + CAtlBaseModule::m_bInitFailed = true; + ATLASSERT(0); + } + } + + ~CAtlWinModule() + { + Term(); + } + + void Term() + { + AtlWinModuleTerm(this, _AtlBaseModule.GetModuleInstance()); + } + + void AddCreateWndData(_AtlCreateWndData *pData, void *pObject) + { + AtlWinModuleAddCreateWndData(this, pData, pObject); + } + + void *ExtractCreateWndData() + { + return AtlWinModuleExtractCreateWndData(this); + } +}; + +__declspec(selectany) CAtlWinModule _AtlWinModule; + + +class CComAllocator +{ +public: + static void* Allocate(_In_ size_t size) + { + return ::CoTaskMemAlloc(size); + } + + static void* Reallocate(_In_opt_ void* ptr, _In_ size_t size) + { + return ::CoTaskMemRealloc(ptr, size); + } + + static void Free(_In_opt_ void* ptr) + { + ::CoTaskMemFree(ptr); + } +}; + +class CRegKey +{ +public: + HKEY m_hKey; +#if 0 + // FIXME & TODO: + CAtlTransactionManager* m_pTM; +#endif + +public: + + CRegKey() throw() + : m_hKey(NULL) + { + } + + CRegKey(CRegKey& key) throw() + : m_hKey(key.Detach()) + { + } + + explicit CRegKey(HKEY hKey) throw() + : m_hKey(hKey) + { + } + +#if 0 + // FIXME & TODO: + CRegKey(CAtlTransactionManager* pTM) throw() + { + ... + } +#endif + + ~CRegKey() throw() + { + Close(); + } + + void Attach(HKEY hKey) throw() + { + m_hKey = hKey; + } + + LONG Close() throw() + { + if (m_hKey) + { + HKEY hKey = Detach(); + return ::RegCloseKey(hKey); + } + return ERROR_SUCCESS; + } + + HKEY Detach() throw() + { + HKEY hKey = m_hKey; + m_hKey = NULL; + return hKey; + } + + LONG Open(HKEY hKeyParent, LPCTSTR lpszKeyName, + REGSAM samDesired = KEY_READ | KEY_WRITE) throw() + { + ATLASSERT(hKeyParent); + ATLASSERT(lpszKeyName); + + HKEY hKey = NULL; + LONG lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); + if (lRes != ERROR_SUCCESS) + { + samDesired |= KEY_WOW64_64KEY; + lRes = ::RegOpenKeyEx(hKeyParent, lpszKeyName, 0, samDesired, &hKey); + } + if (lRes == ERROR_SUCCESS) + { + Close(); + m_hKey = hKey; + } + return lRes; + } + + LONG Create(HKEY hKeyParent, LPCTSTR lpszKeyName, + LPTSTR lpszClass = REG_NONE, + DWORD dwOptions = REG_OPTION_NON_VOLATILE, + REGSAM samDesired = KEY_READ | KEY_WRITE, + LPSECURITY_ATTRIBUTES lpSecAttr = NULL, + LPDWORD lpdwDisposition = NULL) throw() + { + ATLASSERT(hKeyParent); + ATLASSERT(lpszKeyName); + + HKEY hKey = NULL; + LONG lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, + dwOptions, samDesired, lpSecAttr, &hKey, + lpdwDisposition); + if (lRes != ERROR_SUCCESS) + { + samDesired |= KEY_WOW64_64KEY; + lRes = ::RegCreateKeyEx(hKeyParent, lpszKeyName, 0, lpszClass, + dwOptions, samDesired, lpSecAttr, &hKey, + lpdwDisposition); + } + if (lRes == ERROR_SUCCESS) + { + Close(); + m_hKey = hKey; + } + return lRes; + } + + LONG QueryValue(LPCTSTR pszValueName, DWORD* pdwType, void* pData, ULONG* pnBytes) throw() + { + ATLASSERT(m_hKey); + return ::RegQueryValueEx(m_hKey, pszValueName, NULL, pdwType, (LPBYTE)pData, pnBytes); + } + + LONG QueryDWORDValue(LPCTSTR pszValueName, DWORD& dwValue) throw() + { + ULONG size = sizeof(DWORD); + DWORD type = 0; + LONG lRet = QueryValue(pszValueName, &type, &dwValue, &size); + + if (lRet == ERROR_SUCCESS && type != REG_DWORD) + lRet = ERROR_INVALID_DATA; + + return lRet; + } + + LONG QueryBinaryValue(LPCTSTR pszValueName, void* pValue, ULONG* pnBytes) throw() + { + DWORD type = 0; + LONG lRet = QueryValue(pszValueName, &type, pValue, pnBytes); + + if (lRet == ERROR_SUCCESS && type != REG_BINARY) + lRet = ERROR_INVALID_DATA; + + return lRet; + } + + LONG QueryStringValue(LPCTSTR pszValueName, LPTSTR pszValue, ULONG* pnChars) throw() + { + ULONG size = (*pnChars) * sizeof(TCHAR); + DWORD type = 0; + LONG lRet = QueryValue(pszValueName, &type, pszValue, &size); + + if (lRet == ERROR_SUCCESS && type != REG_SZ && type != REG_EXPAND_SZ) + lRet = ERROR_INVALID_DATA; + + *pnChars = size / sizeof(TCHAR); + return lRet; + } + + LONG QueryGUIDValue(LPCTSTR pszValueName, GUID& guidValue) throw() + { + OLECHAR buf[40] = {0}; + ULONG nChars = 39; + LONG lRet; + +#ifdef UNICODE + lRet = QueryStringValue(pszValueName, buf, &nChars); +#else + CHAR bufA[40] = {0}; + lRet = QueryStringValue(pszValueName, bufA, &nChars); + if (lRet != ERROR_SUCCESS) + return lRet; + if (!::MultiByteToWideChar(CP_THREAD_ACP, 0, bufA, -1, buf, 39)) + lRet = ERROR_INVALID_DATA; +#endif + if (lRet != ERROR_SUCCESS) + return lRet; + + if (!SUCCEEDED(::CLSIDFromString(buf, &guidValue))) + return ERROR_INVALID_DATA; + + return lRet; + } + + LONG QueryQWORDValue(LPCTSTR pszValueName, ULONGLONG& qwValue) throw() + { + ULONG size = sizeof(ULONGLONG); + DWORD type = 0; + LONG lRet = QueryValue(pszValueName, &type, &qwValue, &size); + + if (lRet == ERROR_SUCCESS && type != REG_QWORD) + lRet = ERROR_INVALID_DATA; + + return lRet; + } + + LONG QueryMultiStringValue(LPCTSTR pszValueName, LPTSTR pszValue, + ULONG* pnChars) throw() + { + ULONG size = (*pnChars) * sizeof(TCHAR); + DWORD type; + LONG lRet = QueryValue(pszValueName, &type, pszValue, &size); + + if (lRet == ERROR_SUCCESS && type != REG_MULTI_SZ) + lRet = ERROR_INVALID_DATA; + + *pnChars = size / sizeof(TCHAR); + return lRet; + } + + LONG SetValue(LPCTSTR pszValueName, DWORD dwType, const void* pValue, ULONG nBytes) throw() + { + ATLASSERT(m_hKey); + return ::RegSetValueEx(m_hKey, pszValueName, 0, dwType, (const BYTE*)pValue, nBytes); + } + + LONG SetDWORDValue(LPCTSTR pszValueName, DWORD dwValue) throw() + { + return SetValue(pszValueName, REG_DWORD, &dwValue, sizeof(DWORD)); + } + + LONG SetStringValue(LPCTSTR pszValueName, LPCTSTR pszValue, DWORD dwType = REG_SZ) throw() + { + SIZE_T length; + switch (dwType) + { + case REG_SZ: + case REG_EXPAND_SZ: + length = (_tcslen(pszValue) + 1) * sizeof(TCHAR); + return SetValue(pszValueName, dwType, pszValue, length); + case REG_MULTI_SZ: + return SetMultiStringValue(pszValueName, pszValue); + default: + return ERROR_INVALID_DATA; + } + } + + LONG SetGUIDValue(LPCTSTR pszValueName, REFGUID guidValue) throw() + { + OLECHAR buf[40] = {0}; + ::StringFromGUID2(guidValue, buf, 39); +#ifdef UNICODE + return SetStringValue(pszValueName, buf); +#else + CHAR bufA[40] = {0}; + ::WideCharToMultiByte(CP_THREAD_ACP, 0, buf, -1, bufA, 40, NULL, NULL); + return SetStringValue(pszValueName, bufA); +#endif + } + + LONG SetBinaryValue(LPCTSTR pszValueName, const void* pValue, ULONG nBytes) throw() + { + return SetValue(pszValueName, REG_BINARY, pValue, nBytes); + } + + LONG SetMultiStringValue(LPCTSTR pszValueName, LPCTSTR pszValue) throw() + { + ULONG dwSize = CRegKey::_GetMultiStringSize(pszValue); + return SetValue(pszValueName, REG_MULTI_SZ, pszValue, dwSize); + } + + LONG SetQWORDValue(LPCTSTR pszValueName, ULONGLONG qwValue) throw() + { + ULONG dwSize = sizeof(ULONGLONG); + return SetValue(pszValueName, REG_QWORD, &qwValue, dwSize); + } + + LONG NotifyChangeKeyValue(BOOL bWatchSubtree, DWORD dwNotifyFilter, + HANDLE hEvent, BOOL bAsync = TRUE) throw() + { + ATLASSERT(m_hKey); + LONG ret = ::RegNotifyChangeKeyValue(m_hKey, bWatchSubtree, + dwNotifyFilter, hEvent, bAsync); + return ret; + } + + LONG Flush() throw() + { + ATLASSERT(m_hKey); + LONG ret = ::RegFlushKey(m_hKey); + return ret; + } + + static LONG WINAPI SetValue(HKEY hKeyParent, LPCTSTR lpszKeyName, + LPCTSTR lpszValue, LPCTSTR lpszValueName = NULL) + { + CRegKey key; + LONG lRet = key.Create(hKeyParent, lpszKeyName); + if (lRet == ERROR_SUCCESS) + { + lRet = key.SetStringValue(lpszValueName, lpszValue); + } + return lRet; + } + + LONG SetKeyValue(LPCTSTR lpszKeyName, LPCTSTR lpszValue, + LPCTSTR lpszValueName = NULL) throw() + { + CRegKey key; + LONG lRet = key.Create(m_hKey, lpszKeyName); + if (lRet == ERROR_SUCCESS) + { + lRet = key.SetStringValue(lpszValueName, lpszValue); + } + return lRet; + } + + LONG DeleteValue(LPCTSTR lpszValue) throw() + { + ATLASSERT(m_hKey); + return ::RegDeleteValue(m_hKey, lpszValue); + } + + LONG DeleteSubKey(LPCTSTR lpszSubKey) throw() + { + ATLASSERT(m_hKey); + ATLASSERT(lpszSubKey); + return ::RegDeleteKey(m_hKey, lpszSubKey); + } + + LONG RecurseDeleteKey(LPCTSTR lpszKey) throw() + { + ATLASSERT(m_hKey); + ATLASSERT(lpszKey); + return CRegKey::_DoDeleteKeyTree(m_hKey, lpszKey); + } + + LONG EnumKey(DWORD iIndex, LPTSTR pszName, LPDWORD pnNameLength, + FILETIME* pftLastWriteTime = NULL) throw() + { + ATLASSERT(m_hKey); + LONG ret = ::RegEnumKeyEx(m_hKey, iIndex, pszName, pnNameLength, NULL, + NULL, NULL, pftLastWriteTime); + return ret; + } + + LONG GetKeySecurity(SECURITY_INFORMATION si, PSECURITY_DESCRIPTOR psd, + LPDWORD pnBytes) throw() + { + ATLASSERT(m_hKey); + LONG ret = ::RegGetKeySecurity(m_hKey, si, psd, pnBytes); + return ret; + } + + LONG SetKeySecurity(SECURITY_INFORMATION si, + PSECURITY_DESCRIPTOR psd) throw() + { + ATLASSERT(m_hKey); + LONG ret = ::RegSetKeySecurity(m_hKey, si, psd); + return ret; + } + + operator HKEY() const throw() + { + return m_hKey; + } + + CRegKey& operator=(CRegKey& key) throw() + { + if (m_hKey != key.m_hKey) + { + Close(); + Attach(key.Detach()); + } + return *this; + } + +protected: + // get the total size of a multistring + static ULONG _GetMultiStringSize(LPCTSTR pszz) + { + size_t count = 0; + do + { + size_t len = _tcslen(pszz); + count += len + 1; + pszz += len + 1; + } while (*pszz != TEXT('\0')); + ++count; + ATLASSERT(count * sizeof(TCHAR) <= ULONG_MAX); + return (ULONG)count * sizeof(TCHAR); + } + + // delete key recursively + static LONG _DoDeleteKeyTree(HKEY hParentKey, LPCTSTR lpszKey) + { + ATLASSERT(hParentKey); + ATLASSERT(lpszKey); + + // open the key + CRegKey key; + LONG ret = key.Open(hParentKey, lpszKey); + if (ret != ERROR_SUCCESS) + { + return ret; // failure + } + + // get the longest length of subkey names + DWORD NameMax; + ret = ::RegQueryInfoKey(key, NULL, NULL, NULL, NULL, &NameMax, NULL, + NULL, NULL, NULL, NULL, NULL); + if (ret != ERROR_SUCCESS) + { + return ret; // failure + } + ++NameMax; // for NUL + + // allocate the string buffer for names if necessary + TCHAR szNameBuf[MAX_PATH], *pszName; + if (NameMax > MAX_PATH) + { + pszName = (TCHAR *)malloc(NameMax * sizeof(TCHAR)); + ATLASSERT(pszName); + if (pszName == NULL) + { + return ERROR_OUTOFMEMORY; // failure + } + } + else + { + NameMax = MAX_PATH; + pszName = szNameBuf; + } + + // enumerate every subkey and delete + for (;;) + { + DWORD Count = NameMax; + ret = key.EnumKey(0, pszName, &Count); + if (ret != ERROR_SUCCESS) + { + if (ret == ERROR_NO_MORE_ITEMS) + ret = ERROR_SUCCESS; + break; + } + + ret = CRegKey::_DoDeleteKeyTree(key, pszName); + if (ret != ERROR_SUCCESS) + break; + } + + // close key + key.Close(); + + // delete the subkey + if (ret == ERROR_SUCCESS) + ret = ::RegDeleteKey(hParentKey, lpszKey); + + // delete the buffer if any + if (pszName != szNameBuf) + free(pszName); + + return ret; + } +}; + +template +class CComHeapPtr : public CHeapPtr +{ +public: + CComHeapPtr() + { + } + + explicit CComHeapPtr(T *lp) : + CHeapPtr(lp) + { + } +}; + + +inline HRESULT __stdcall AtlAdvise(IUnknown *pUnkCP, IUnknown *pUnk, const IID &iid, LPDWORD pdw) +{ + CComPtr container; + CComPtr connectionPoint; + HRESULT hResult; + + if (pUnkCP == NULL) + return E_INVALIDARG; + hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container); + if (FAILED(hResult)) + return hResult; + hResult = container->FindConnectionPoint(iid, &connectionPoint); + if (FAILED(hResult)) + return hResult; + return connectionPoint->Advise(pUnk, pdw); +} + +inline HRESULT __stdcall AtlUnadvise(IUnknown *pUnkCP, const IID &iid, DWORD dw) +{ + CComPtr container; + CComPtr connectionPoint; + HRESULT hResult; + + if (pUnkCP == NULL) + return E_INVALIDARG; + hResult = pUnkCP->QueryInterface(IID_IConnectionPointContainer, (void **)&container); + if (FAILED(hResult)) + return hResult; + hResult = container->FindConnectionPoint(iid, &connectionPoint); + if (FAILED(hResult)) + return hResult; + return connectionPoint->Unadvise(dw); +} + +inline HRESULT __stdcall AtlInternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject) +{ + int i; + IUnknown *resultInterface; + HRESULT hResult; + + ATLASSERT(pThis != NULL && pEntries != NULL); + if (pThis == NULL || pEntries == NULL) + return E_INVALIDARG; + ATLASSERT(ppvObject != NULL); + if (ppvObject == NULL) + return E_POINTER; + + if (InlineIsEqualUnknown(iid)) + { + resultInterface = reinterpret_cast(reinterpret_cast(pThis) + pEntries[0].dw); + *ppvObject = resultInterface; + resultInterface->AddRef(); + return S_OK; + } + + i = 0; + while (pEntries[i].pFunc != 0) + { + if (pEntries[i].piid == NULL || InlineIsEqualGUID(iid, *pEntries[i].piid)) + { + if (pEntries[i].pFunc == reinterpret_cast<_ATL_CREATORARGFUNC *>(1)) + { + ATLASSERT(pEntries[i].piid != NULL); + resultInterface = reinterpret_cast(reinterpret_cast(pThis) + pEntries[i].dw); + *ppvObject = resultInterface; + resultInterface->AddRef(); + return S_OK; + } + else + { + hResult = pEntries[i].pFunc(pThis, iid, ppvObject, 0); + if (hResult == S_OK) + return hResult; + if (FAILED(hResult) && pEntries[i].piid != NULL) + break; + } + } + i++; + } + *ppvObject = NULL; + return E_NOINTERFACE; +} + +inline HRESULT __stdcall AtlWinModuleInit(_ATL_WIN_MODULE *pWinModule) +{ + if (pWinModule == NULL) + return E_INVALIDARG; + pWinModule->m_pCreateWndList = NULL; + return pWinModule->m_csWindowCreate.Init(); +} + +inline HRESULT __stdcall AtlWinModuleTerm(_ATL_WIN_MODULE *pWinModule, HINSTANCE hInst) +{ + if (pWinModule == NULL) + return E_INVALIDARG; + pWinModule->m_csWindowCreate.Term(); + return S_OK; +} + +inline void __stdcall AtlWinModuleAddCreateWndData(_ATL_WIN_MODULE *pWinModule, _AtlCreateWndData *pData, void *pObject) +{ + CComCritSecLock lock(pWinModule->m_csWindowCreate, true); + + ATLASSERT(pWinModule != NULL); + ATLASSERT(pObject != NULL); + + pData->m_pThis = pObject; + pData->m_dwThreadID = ::GetCurrentThreadId(); + pData->m_pNext = pWinModule->m_pCreateWndList; + pWinModule->m_pCreateWndList = pData; +} + +inline void *__stdcall AtlWinModuleExtractCreateWndData(_ATL_WIN_MODULE *pWinModule) +{ + CComCritSecLock lock(pWinModule->m_csWindowCreate, true); + void *result; + _AtlCreateWndData *currentEntry; + _AtlCreateWndData **previousLink; + DWORD threadID; + + ATLASSERT(pWinModule != NULL); + + result = NULL; + threadID = GetCurrentThreadId(); + currentEntry = pWinModule->m_pCreateWndList; + previousLink = &pWinModule->m_pCreateWndList; + while (currentEntry != NULL) + { + if (currentEntry->m_dwThreadID == threadID) + { + *previousLink = currentEntry->m_pNext; + result = currentEntry->m_pThis; + break; + } + previousLink = ¤tEntry->m_pNext; + currentEntry = currentEntry->m_pNext; + } + return result; +} + +// Adapted from dll/win32/atl/atl.c +inline HRESULT WINAPI AtlLoadTypeLib(HINSTANCE inst, LPCOLESTR lpszIndex, + BSTR *pbstrPath, ITypeLib **ppTypeLib) +{ + size_t index_len = lpszIndex ? wcslen(lpszIndex) : 0; + CComHeapPtr path; + path.Allocate(MAX_PATH + index_len + wcslen(L".tlb")); + + if (!path) + return E_OUTOFMEMORY; + + size_t path_len = GetModuleFileNameW(inst, path, MAX_PATH); + if (!path_len) + return HRESULT_FROM_WIN32(GetLastError()); + + if (index_len) + wcscat(path, lpszIndex); + + CComPtr typelib; + HRESULT hResult = LoadTypeLib(path, &typelib); + if (FAILED(hResult)) + { + WCHAR *ptr; + for (ptr = path+path_len-1; ptr > path && *ptr != '\\' && *ptr != '.'; ptr--) + ; + if (*ptr != '.') + ptr = (WCHAR*)path + path_len; + wcscpy(ptr, L".tlb"); + + hResult = LoadTypeLib(path, &typelib); + } + + if (SUCCEEDED(hResult)) + { + *pbstrPath = SysAllocString(path); + if (!*pbstrPath) + { + typelib.Release(); + hResult = E_OUTOFMEMORY; + } + } + + if (FAILED(hResult)) + return hResult; + + *ppTypeLib = typelib.Detach(); + return S_OK; +} + +// Adapted from dll/win32/atl/atl.c +inline HRESULT WINAPI AtlRegisterTypeLib(HINSTANCE inst, const WCHAR *index) +{ + CComBSTR path; + CComPtr typelib; + HRESULT hResult = AtlLoadTypeLib(inst, index, &path, &typelib); + if (FAILED(hResult)) + return hResult; + + return RegisterTypeLib(typelib, path, NULL); /* FIXME: pass help directory */ +} + +// Adapted from dll/win32/atl/atl.c +inline HRESULT WINAPI AtlRegisterClassCategoriesHelper(REFCLSID clsid, const _ATL_CATMAP_ENTRY *catmap, BOOL reg) +{ + if (!catmap) + return S_OK; + + CComPtr catreg; + + HRESULT hResult = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&catreg); + if (FAILED(hResult)) + return hResult; + + for (const _ATL_CATMAP_ENTRY *iter = catmap; iter->iType != _ATL_CATMAP_ENTRY_END; iter++) + { + CATID catid = *iter->pcatid; + + if (iter->iType == _ATL_CATMAP_ENTRY_IMPLEMENTED) + { + if (reg) + hResult = catreg->RegisterClassImplCategories(clsid, 1, &catid); + else + hResult = catreg->UnRegisterClassImplCategories(clsid, 1, &catid); + } + else + { + if (reg) + hResult = catreg->RegisterClassReqCategories(clsid, 1, &catid); + else + hResult = catreg->UnRegisterClassReqCategories(clsid, 1, &catid); + } + if (FAILED(hResult)) + return hResult; + } + + if (!reg) + { + WCHAR reg_path[256] = L"CLSID\\"; + + StringFromGUID2(clsid, reg_path + wcslen(reg_path), 64); + wcscat(reg_path, L"\\"); + WCHAR* ptr = reg_path + wcslen(reg_path); + + wcscpy(ptr, L"Implemented Categories"); + RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); + + wcscpy(ptr, L"Required Categories"); + RegDeleteKeyW(HKEY_CLASSES_ROOT, reg_path); + } + + return hResult; +} + + +// Adapted from dll/win32/atl80/atl80.c +inline HRESULT __stdcall AtlComModuleRegisterServer(_ATL_COM_MODULE *mod, BOOL bRegTypeLib, const CLSID *clsid) +{ + HRESULT hResult = S_OK; + + for (_ATL_OBJMAP_ENTRY ** iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) + { + if (!*iter) + continue; + _ATL_OBJMAP_ENTRY* entry = *iter; + if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid)) + continue; + + hResult = entry->pfnUpdateRegistry(TRUE); + if (FAILED(hResult)) + return hResult; + + const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap(); + if (catmap) + { + hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, TRUE); + if (FAILED(hResult)) + return hResult; + } + } + + if (bRegTypeLib) + { + hResult = AtlRegisterTypeLib(mod->m_hInstTypeLib, NULL); + } + + return hResult; +} + +// Adapted from dll/win32/atl/atl.c +inline HRESULT WINAPI AtlComModuleUnregisterServer(_ATL_COM_MODULE *mod, BOOL bUnRegTypeLib, const CLSID *clsid) +{ + HRESULT hResult = S_OK; + + for (_ATL_OBJMAP_ENTRY **iter = mod->m_ppAutoObjMapFirst; iter < mod->m_ppAutoObjMapLast; iter++) + { + if (!*iter) + continue; + _ATL_OBJMAP_ENTRY* entry = *iter; + if (clsid && !IsEqualCLSID(*entry->pclsid, *clsid)) + continue; + + const _ATL_CATMAP_ENTRY *catmap = entry->pfnGetCategoryMap(); + if (catmap) + { + hResult = AtlRegisterClassCategoriesHelper(*entry->pclsid, catmap, FALSE); + if (FAILED(hResult)) + return hResult; + } + + hResult = entry->pfnUpdateRegistry(FALSE); + if (FAILED(hResult)) + return hResult; + } + + if (bUnRegTypeLib) + { + CComPtr typelib; + TLIBATTR *attr; + CComBSTR path; + + hResult = AtlLoadTypeLib(mod->m_hInstTypeLib, NULL, &path, &typelib); + if (FAILED(hResult)) + return hResult; + + hResult = typelib->GetLibAttr(&attr); + if (SUCCEEDED(hResult)) + { + hResult = UnRegisterTypeLib(attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, attr->lcid, attr->syskind); + typelib->ReleaseTLibAttr(attr); + } + } + + return hResult; +} + + +// Adapted from dll/win32/atl/atl.c +inline HRESULT WINAPI AtlComModuleRegisterClassObjects(_ATL_COM_MODULE *module, DWORD context, DWORD flags) +{ + _ATL_OBJMAP_ENTRY **iter; + IUnknown* unk = NULL; + HRESULT hr; + + if (!module) + return E_INVALIDARG; + + for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) + { + if (!(*iter)->pfnGetClassObject) + continue; + + hr = (*iter)->pfnGetClassObject((void*)(*iter)->pfnCreateInstance, IID_IUnknown, (void**)&unk); + if (FAILED(hr)) + return hr; + + hr = CoRegisterClassObject(*(*iter)->pclsid, unk, context, flags, &(*iter)->dwRegister); + unk->Release(); + if (FAILED(hr)) + return hr; + } + + return S_OK; +} + + +// Adapted from dll/win32/atl/atl.c +inline HRESULT WINAPI AtlComModuleRevokeClassObjects(_ATL_COM_MODULE *module) +{ + _ATL_OBJMAP_ENTRY **iter; + HRESULT hr; + + if (!module) + return E_INVALIDARG; + + for (iter = module->m_ppAutoObjMapFirst; iter < module->m_ppAutoObjMapLast; iter++) + { + hr = CoRevokeClassObject((*iter)->dwRegister); + if (FAILED(hr)) + return hr; + } + + return S_OK; +} + + +}; // namespace ATL + +#ifndef _ATL_NO_AUTOMATIC_NAMESPACE +using namespace ATL; +#endif //!_ATL_NO_AUTOMATIC_NAMESPACE diff --git a/src/3rd_party/reactos-atl/atl/atlcoll.h b/src/3rd_party/reactos-atl/atl/atlcoll.h new file mode 100644 index 00000000..f41fee71 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlcoll.h @@ -0,0 +1,900 @@ +#ifndef __ATLCOLL_H__ +#define __ATLCOLL_H__ + +#pragma once +#include "atlbase.h" +#include "atlexcept.h" + +// FIXME: We need to include for placement new, but that would mean everyone using atl +// would also need to set the option 'WITH_STL'.. +// For now we just copy the definition here, under a guard.. +#ifndef _NEW +inline void* operator new (size_t size, void* ptr) throw() { return ptr; } +inline void operator delete (void* ptr, void* voidptr2) throw() { } +#endif + + +struct __POSITION +{ +}; +typedef __POSITION* POSITION; + + +namespace ATL +{ + +class CAtlPlex +{ +public: + CAtlPlex* m_Next; + +#if (_AFX_PACKING >= 8) + DWORD dwReserved[1]; +#endif + + static inline CAtlPlex* Create( + _Inout_ CAtlPlex*& Entry, + _In_ size_t MaxElements, + _In_ size_t ElementSize + ) + { + CAtlPlex* Block; + + ATLASSERT(MaxElements > 0); + ATLASSERT(ElementSize > 0); + + size_t BufferSize = sizeof(CAtlPlex) + (MaxElements * ElementSize); + + void *Buffer = HeapAlloc(GetProcessHeap(), 0, BufferSize); + if (Buffer == NULL) return NULL; + + Block = static_cast< CAtlPlex* >(Buffer); + Block->m_Next = Entry; + Entry = Block; + + return Block; + } + + void* GetData() + { + return (this + 1); + } + + inline void Destroy() + { + CAtlPlex* Block; + CAtlPlex* Next; + + Block = this; + while (Block != NULL) + { + Next = Block->m_Next; + HeapFree(GetProcessHeap(), 0, Block); + Block = Next; + } + } +}; + + +template +class CElementTraitsBase +{ +public: + typedef const T& INARGTYPE; + typedef T& OUTARGTYPE; + + static void CopyElements( + _Out_writes_all_(NumElements) T* Dest, + _In_reads_(NumElements) const T* Source, + _In_ size_t NumElements) + { + for (size_t i = 0; i < NumElements; i++) + { + Dest[i] = Source[i]; + } + } + + static void RelocateElements( + _Out_writes_all_(NumElements) T* Dest, + _In_reads_(NumElements) T* Source, + _In_ size_t NumElements) + { + // A simple memmove works for most of the types. + // You'll have to override this for types that have pointers to their + // own members. + +#if defined(__GNUC__) && __GNUC__ >= 8 + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wclass-memaccess" +#endif + memmove(Dest, Source, NumElements * sizeof(T)); +#if defined(__GNUC__) && __GNUC__ >= 8 + #pragma GCC diagnostic pop +#endif + } +}; + +template +class CDefaultCompareTraits +{ +public: + static bool CompareElements( + _In_ const T& Val1, + _In_ const T& Val2) + { + return (Val1 == Val2); + } + + static int CompareElementsOrdered( + _In_ const T& Val1, + _In_ const T& Val2) + { + if (Val1 < Val2) + { + return -1; + } + else if (Val1 > Val2) + { + return 1; + } + + return 0; // equal + } +}; + +template +class CDefaultElementTraits : + public CElementTraitsBase, + public CDefaultCompareTraits +{ +}; + + +template +class CElementTraits : + public CDefaultElementTraits +{ +}; + + +template +class CHeapPtrElementTraits : + public CDefaultElementTraits< CHeapPtr > +{ +public: + typedef CHeapPtr& INARGTYPE; + typedef T*& OUTARGTYPE; +}; + + + +template > +class CAtlArray +{ +public: + typedef typename ETraits::INARGTYPE INARGTYPE; + typedef typename ETraits::OUTARGTYPE OUTARGTYPE; + +private: + E* m_pData; + size_t m_Size; + size_t m_AllocatedSize; + size_t m_GrowBy; + + +#pragma push_macro("new") +#undef new + + void CreateItems(E* pData, size_t Size) + { + for (size_t n = 0; n < Size; ++n) + { + ::new (pData + n) E; + } + } + +#pragma pop_macro("new") + + void DestructItems(E* pData, size_t Size) + { + for (size_t n = 0; n < Size; ++n) + { + pData[n].~E(); + } + } + + bool GrowAllocatedData(size_t nNewSize) + { + if (m_pData) + { + size_t addSize = m_GrowBy > 0 ? m_GrowBy : m_AllocatedSize / 2; + size_t allocSize = m_AllocatedSize + addSize; + if (allocSize < nNewSize) + allocSize = nNewSize; + + E* pData = (E*)malloc(nNewSize * sizeof(E)); + + if (pData == NULL) + { + return false; + } + + // Copy the objects over (default implementation will just move them without calling anything + ETraits::RelocateElements(pData, m_pData, m_Size); + + free(m_pData); + m_pData = pData; + m_AllocatedSize = nNewSize; + } + else + { + // We need to allocate a new buffer + size_t allocSize = m_GrowBy > nNewSize ? m_GrowBy : nNewSize; + m_pData = (E*)malloc(allocSize * sizeof(E)); + if (m_pData == NULL) + { + return false; + } + m_AllocatedSize = allocSize; + } + return true; + } + + /* The CAtlArray class does not support construction by copy */ +private: + CAtlArray(_In_ const CAtlArray&); + CAtlArray& operator=(_In_ const CAtlArray&); + +public: + CAtlArray(); + ~CAtlArray(); + + size_t Add(INARGTYPE element); + size_t Add(); + + bool SetCount(size_t nNewSize, int nGrowBy = - 1); + size_t GetCount() const; + + E& operator[](size_t ielement); + const E& operator[](size_t ielement) const; + + E& GetAt(size_t iElement); + const E& GetAt(size_t iElement) const; + + E* GetData(); + const E* GetData() const; + + + //FIXME: Most of this class is missing! +}; + +// +// CAtlArray public methods +// + +template +CAtlArray< E, ETraits >::CAtlArray() + : m_pData(NULL) + , m_Size(0) + , m_AllocatedSize(0) + , m_GrowBy(0) +{ +} + +template +CAtlArray< E, ETraits >::~CAtlArray() +{ + // Destroy all items + SetCount(0, -1); +} + +#pragma push_macro("new") +#undef new + +template +size_t CAtlArray::Add(INARGTYPE element) +{ + if (m_Size >= m_AllocatedSize) + { + if (!GrowAllocatedData(m_Size + 1)) + { + AtlThrow(E_OUTOFMEMORY); + } + } + + ::new (m_pData + m_Size) E(element); + m_Size++; + + return m_Size - 1; +} + +#pragma pop_macro("new") + +template +size_t CAtlArray::Add() +{ + if (!SetCount(m_Size + 1)) + { + AtlThrow(E_OUTOFMEMORY); + } + + return m_Size - 1; +} + +template +bool CAtlArray::SetCount(size_t nNewSize, int nGrowBy /*= -1*/) +{ + + if (nGrowBy > -1) + { + m_GrowBy = (size_t)nGrowBy; + } + + if (nNewSize == m_Size) + { + // Do nothing + } + else if (nNewSize == 0) + { + if (m_pData) + { + DestructItems(m_pData, m_Size); + m_pData = NULL; + } + m_Size = m_AllocatedSize = NULL; + } + else if (nNewSize < m_AllocatedSize) + { + if (nNewSize > m_Size) + { + CreateItems(m_pData + m_Size, nNewSize - m_Size); + } + else + { + DestructItems(m_pData + nNewSize, m_Size - nNewSize); + } + m_Size = nNewSize; + } + else + { + if (!GrowAllocatedData(nNewSize)) + { + return false; + } + + CreateItems(m_pData + m_Size, nNewSize - m_Size); + m_Size = nNewSize; + } + + return true; +} + +template +size_t CAtlArray::GetCount() const +{ + return m_Size; +} + +template +E& CAtlArray::operator[](size_t iElement) +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +const E& CAtlArray::operator[](size_t iElement) const +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +E& CAtlArray::GetAt(size_t iElement) +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +const E& CAtlArray::GetAt(size_t iElement) const +{ + ATLASSERT(iElement < m_Size); + + return m_pData[iElement]; +} + +template +E* CAtlArray::GetData() +{ + return m_pData; +} + +template +const E* CAtlArray::GetData() const +{ + return m_pData; +} + + +template > +class CAtlList +{ +private: + typedef typename ETraits::INARGTYPE INARGTYPE; + +private: + class CNode : public __POSITION + { + public: + CNode* m_Next; + CNode* m_Prev; + E m_Element; + + public: + CNode(INARGTYPE Element) : + m_Element(Element) + { + } + + /* The CNode class does not support construction by copy */ + private: + CNode(_In_ const CNode&); + CNode& operator=(_In_ const CNode&); + }; + +private: + CAtlPlex* m_Blocks; + UINT m_BlockSize; + CNode* m_HeadNode; + CNode* m_TailNode; + CNode* m_FreeNode; + size_t m_NumElements; + +/* The CAtlList class does not support construction by copy */ +private: + CAtlList(_In_ const CAtlList&); + CAtlList& operator=(_In_ const CAtlList&); + +public: + CAtlList(_In_ UINT nBlockSize = 10); + ~CAtlList(); + + size_t GetCount() const; + bool IsEmpty() const; + + POSITION GetHeadPosition() const; + POSITION GetTailPosition() const; + + E& GetNext(_Inout_ POSITION& pos); + const E& GetNext(_Inout_ POSITION& pos) const; + E& GetPrev(_Inout_ POSITION& pos); + const E& GetPrev(_Inout_ POSITION& pos) const; + + E& GetAt(_In_ POSITION pos); + const E& GetAt(_In_ POSITION pos) const; + + POSITION AddHead(INARGTYPE element); + POSITION AddTail(INARGTYPE element); + + E RemoveHead(); + E RemoveTail(); + + POSITION InsertBefore(_In_ POSITION pos, INARGTYPE element); + POSITION InsertAfter(_In_ POSITION pos, INARGTYPE element); + + void RemoveAll(); + void RemoveAt(_In_ POSITION pos); + + POSITION Find( + INARGTYPE element, + _In_opt_ POSITION posStartAfter = NULL) const; + POSITION FindIndex(_In_ size_t iElement) const; + +private: + CNode* CreateNode( + INARGTYPE element, + _In_opt_ CNode* pPrev, + _In_opt_ CNode* pNext + ); + + void FreeNode( + _Inout_ CNode* pNode + ); + + CNode* GetFreeNode( + ); + +}; + + +// +// CAtlist public methods +// + +template +CAtlList< E, ETraits >::CAtlList(_In_ UINT nBlockSize) : + m_Blocks(NULL), + m_BlockSize(nBlockSize), + m_HeadNode(NULL), + m_TailNode(NULL), + m_FreeNode(NULL), + m_NumElements(0) +{ + ATLASSERT(nBlockSize > 0); +} + +template +CAtlList::~CAtlList(void) +{ + RemoveAll(); +} + +template +inline size_t CAtlList< E, ETraits >::GetCount() const +{ + return m_NumElements; +} + +template +inline bool CAtlList< E, ETraits >::IsEmpty() const +{ + return (m_NumElements == 0); +} + +template +inline POSITION CAtlList::GetHeadPosition() const +{ + return (POSITION)m_HeadNode; +} + +template +inline POSITION CAtlList::GetTailPosition() const +{ + return (POSITION)m_TailNode; +} + +template +inline E& CAtlList< E, ETraits >::GetNext(_Inout_ POSITION& pos) +{ + CNode* Node = (CNode*)pos; + pos = (POSITION)Node->m_Next; + return Node->m_Element; +} + +template +inline const E& CAtlList< E, ETraits >::GetNext(_Inout_ POSITION& pos) const +{ + CNode* Node = (CNode*)pos; + pos = (POSITION)Node->m_Next; + return Node->m_Element; +} + +template +inline E& CAtlList< E, ETraits >::GetPrev(_Inout_ POSITION& pos) +{ + CNode* Node = (CNode*)pos; + pos = (POSITION)Node->m_Prev; + return Node->m_Element; +} + +template +inline const E& CAtlList< E, ETraits >::GetPrev(_Inout_ POSITION& pos) const +{ + CNode* Node = (CNode*)pos; + pos = (POSITION)Node->m_Prev; + return Node->m_Element; +} + +template +inline E& CAtlList< E, ETraits >::GetAt(_In_ POSITION pos) +{ + CNode* Node = (CNode*)pos; + return Node->m_Element; +} + +template +inline const E& CAtlList< E, ETraits >::GetAt(_In_ POSITION pos) const +{ + CNode* Node = (CNode*)pos; + return Node->m_Element; +} + +template +POSITION CAtlList::AddHead(INARGTYPE element) +{ + CNode* Node = CreateNode(element, NULL, m_HeadNode); + if (m_HeadNode) + { + m_HeadNode->m_Prev = Node; + } + else + { + m_TailNode = Node; + } + m_HeadNode = Node; + + return (POSITION)Node; +} + +template +POSITION CAtlList::AddTail(INARGTYPE element) +{ + CNode* Node = CreateNode(element, m_TailNode, NULL); + if (m_TailNode) + { + m_TailNode->m_Next = Node; + } + else + { + m_HeadNode = Node; + } + m_TailNode = Node; + + return (POSITION)Node; +} + +template +E CAtlList::RemoveHead() +{ + CNode* Node = m_HeadNode; + E Element(Node->m_Element); + + m_HeadNode = Node->m_Next; + if (m_HeadNode) + { + m_HeadNode->m_Prev = NULL; + } + else + { + m_TailNode = NULL; + } + FreeNode(Node); + + return Element; +} + +template +E CAtlList::RemoveTail() +{ + CNode* Node = m_TailNode; + E Element(Node->m_Element); + + m_TailNode = Node->m_Prev; + if (m_TailNode) + { + m_TailNode->m_Next = NULL; + } + else + { + m_HeadNode = NULL; + } + FreeNode(Node); + + return Element; +} + +template +POSITION CAtlList::InsertBefore(_In_ POSITION pos, _In_ INARGTYPE element) +{ + if (pos == NULL) + return AddHead(element); + + CNode* OldNode = (CNode*)pos; + CNode* Node = CreateNode(element, OldNode->m_Prev, OldNode); + + if (OldNode->m_Prev != NULL) + { + OldNode->m_Prev->m_Next = Node; + } + else + { + m_HeadNode = Node; + } + OldNode->m_Prev = Node; + + return (POSITION)Node; +} + +template +POSITION CAtlList::InsertAfter(_In_ POSITION pos, _In_ INARGTYPE element) +{ + if (pos == NULL) + return AddTail(element); + + CNode* OldNode = (CNode*)pos; + CNode* Node = CreateNode(element, OldNode, OldNode->m_Next); + + if (OldNode->m_Next != NULL) + { + OldNode->m_Next->m_Prev = Node; + } + else + { + m_TailNode = Node; + } + OldNode->m_Next = Node; + + return (POSITION)Node; +} + +template +void CAtlList::RemoveAll() +{ + while (m_NumElements > 0) + { + CNode* Node = m_HeadNode; + m_HeadNode = m_HeadNode->m_Next; + FreeNode(Node); + } + + m_HeadNode = NULL; + m_TailNode = NULL; + m_FreeNode = NULL; + + if (m_Blocks) + { + m_Blocks->Destroy(); + m_Blocks = NULL; + } +} + +template +void CAtlList::RemoveAt(_In_ POSITION pos) +{ + ATLASSERT(pos != NULL); + + CNode* OldNode = (CNode*)pos; + if (OldNode == m_HeadNode) + { + m_HeadNode = OldNode->m_Next; + } + else + { + OldNode->m_Prev->m_Next = OldNode->m_Next; + } + if (OldNode == m_TailNode) + { + m_TailNode = OldNode->m_Prev; + } + else + { + OldNode->m_Next->m_Prev = OldNode->m_Prev; + } + FreeNode(OldNode); +} + +template +POSITION CAtlList< E, ETraits >::Find( + INARGTYPE element, + _In_opt_ POSITION posStartAfter) const +{ + CNode* Node = (CNode*)posStartAfter; + if (Node == NULL) + { + Node = m_HeadNode; + } + else + { + Node = Node->m_Next; + } + + for (; Node != NULL; Node = Node->m_Next) + { + if (ETraits::CompareElements(Node->m_Element, element)) + return (POSITION)Node; + } + + return NULL; +} + +template +POSITION CAtlList< E, ETraits >::FindIndex(_In_ size_t iElement) const +{ + if (iElement >= m_NumElements) + return NULL; + + if (m_HeadNode == NULL) + return NULL; + + CNode* Node = m_HeadNode; + for (size_t i = 0; i < iElement; i++) + { + Node = Node->m_Next; + } + + return (POSITION)Node; +} + + +// +// CAtlist private methods +// + +template +typename CAtlList::CNode* CAtlList::CreateNode( + INARGTYPE element, + _In_opt_ CNode* Prev, + _In_opt_ CNode* Next + ) +{ + GetFreeNode(); + + CNode* NewNode = m_FreeNode; + CNode* NextFree = m_FreeNode->m_Next; + + NewNode = new CNode(element); + + m_FreeNode = NextFree; + NewNode->m_Prev = Prev; + NewNode->m_Next = Next; + m_NumElements++; + + return NewNode; +} + +template +void CAtlList::FreeNode( + _Inout_ CNode* pNode + ) +{ + pNode->~CNode(); + pNode->m_Next = m_FreeNode; + m_FreeNode = pNode; + + m_NumElements--; + if (m_NumElements == 0) + { + RemoveAll(); + } +} + +template +typename CAtlList::CNode* CAtlList< E, ETraits>::GetFreeNode() +{ + if (m_FreeNode) + { + return m_FreeNode; + } + + CAtlPlex* Block = CAtlPlex::Create(m_Blocks, m_BlockSize, sizeof(CNode)); + if (Block == NULL) + { + AtlThrowImp(E_OUTOFMEMORY); + } + + CNode* Node = (CNode*)Block->GetData(); + Node += (m_BlockSize - 1); + for (int i = m_BlockSize - 1; i >= 0; i--) + { + Node->m_Next = m_FreeNode; + m_FreeNode = Node; + Node--; + } + + return m_FreeNode; +} + + +template +class CHeapPtrList : + public CAtlList, CHeapPtrElementTraits > +{ +public: + CHeapPtrList(_In_ UINT nBlockSize = 10) : + CAtlList, CHeapPtrElementTraits >(nBlockSize) + { + } + +private: + CHeapPtrList(const CHeapPtrList&); + CHeapPtrList& operator=(const CHeapPtrList*); +}; + + +} + +#endif \ No newline at end of file diff --git a/src/3rd_party/reactos-atl/atl/atlcom.h b/src/3rd_party/reactos-atl/atl/atlcom.h new file mode 100644 index 00000000..c9d92edb --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlcom.h @@ -0,0 +1,1527 @@ +/* + * ReactOS ATL + * + * Copyright 2009 Andrew Hill + * Copyright 2013 Katayama Hirofumi MZ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include // for GUID_NULL +#include + +namespace ATL +{ + +template +class CComEnum; + +#define DECLARE_CLASSFACTORY_EX(cf) typedef ATL::CComCreator > _ClassFactoryCreatorClass; +#define DECLARE_CLASSFACTORY() DECLARE_CLASSFACTORY_EX(ATL::CComClassFactory) +#define DECLARE_CLASSFACTORY_SINGLETON(obj) DECLARE_CLASSFACTORY_EX(ATL::CComClassFactorySingleton) + +class CComObjectRootBase +{ +public: + LONG m_dwRef; +public: + CComObjectRootBase() + { + m_dwRef = 0; + } + + ~CComObjectRootBase() + { + } + + void SetVoid(void *) + { + } + + HRESULT _AtlFinalConstruct() + { + return S_OK; + } + + HRESULT FinalConstruct() + { + return S_OK; + } + + void InternalFinalConstructAddRef() + { + } + + void InternalFinalConstructRelease() + { + } + + void FinalRelease() + { + } + + static void WINAPI ObjectMain(bool) + { + } + + static const struct _ATL_CATMAP_ENTRY *GetCategoryMap() + { + return NULL; + } + + static HRESULT WINAPI InternalQueryInterface(void *pThis, const _ATL_INTMAP_ENTRY *pEntries, REFIID iid, void **ppvObject) + { + return AtlInternalQueryInterface(pThis, pEntries, iid, ppvObject); + } + +}; + +template +class CComObjectRootEx : public CComObjectRootBase +{ +private: + typename ThreadModel::AutoDeleteCriticalSection m_critsec; +public: + ~CComObjectRootEx() + { + } + + ULONG InternalAddRef() + { + ATLASSERT(m_dwRef >= 0); + return ThreadModel::Increment(&m_dwRef); + } + + ULONG InternalRelease() + { + ATLASSERT(m_dwRef > 0); + return ThreadModel::Decrement(&m_dwRef); + } + + void Lock() + { + m_critsec.Lock(); + } + + void Unlock() + { + m_critsec.Unlock(); + } + + HRESULT _AtlInitialConstruct() + { + return m_critsec.Init(); + } +}; + +template +class CComObject : public Base +{ +public: + CComObject(void * = NULL) + { + _pAtlModule->Lock(); + } + + virtual ~CComObject() + { + this->FinalRelease(); + _pAtlModule->Unlock(); + } + + STDMETHOD_(ULONG, AddRef)() + { + return this->InternalAddRef(); + } + + STDMETHOD_(ULONG, Release)() + { + ULONG newRefCount; + + newRefCount = this->InternalRelease(); + if (newRefCount == 0) + delete this; + return newRefCount; + } + + STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) + { + return this->_InternalQueryInterface(iid, ppvObject); + } + + static HRESULT WINAPI CreateInstance(CComObject **pp) + { + CComObject *newInstance; + HRESULT hResult; + + ATLASSERT(pp != NULL); + if (pp == NULL) + return E_POINTER; + + hResult = E_OUTOFMEMORY; + newInstance = NULL; + ATLTRY(newInstance = new CComObject()) + if (newInstance != NULL) + { + newInstance->SetVoid(NULL); + newInstance->InternalFinalConstructAddRef(); + hResult = newInstance->_AtlInitialConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->FinalConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->_AtlFinalConstruct(); + newInstance->InternalFinalConstructRelease(); + if (hResult != S_OK) + { + delete newInstance; + newInstance = NULL; + } + } + *pp = newInstance; + return hResult; + } + + +}; + +template +class CComContainedObject : public Base +{ +public: + IUnknown* m_pUnkOuter; + CComContainedObject(void * pv = NULL) : m_pUnkOuter(static_cast(pv)) + { + } + + STDMETHOD_(ULONG, AddRef)() + { + return m_pUnkOuter->AddRef(); + } + + STDMETHOD_(ULONG, Release)() + { + return m_pUnkOuter->Release(); + } + + STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) + { + return m_pUnkOuter->QueryInterface(iid, ppvObject); + } + + IUnknown* GetControllingUnknown() + { + return m_pUnkOuter; + } +}; + +template +class CComAggObject : public contained +{ +public: + CComContainedObject m_contained; + + CComAggObject(void * pv = NULL) : m_contained(static_cast(pv)) + { + _pAtlModule->Lock(); + } + + virtual ~CComAggObject() + { + this->FinalRelease(); + _pAtlModule->Unlock(); + } + + HRESULT FinalConstruct() + { + return m_contained.FinalConstruct(); + } + void FinalRelease() + { + m_contained.FinalRelease(); + } + + STDMETHOD_(ULONG, AddRef)() + { + return this->InternalAddRef(); + } + + STDMETHOD_(ULONG, Release)() + { + ULONG newRefCount; + newRefCount = this->InternalRelease(); + if (newRefCount == 0) + delete this; + return newRefCount; + } + + STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) + { + if (ppvObject == NULL) + return E_POINTER; + if (iid == IID_IUnknown) + *ppvObject = reinterpret_cast(this); + else + return m_contained._InternalQueryInterface(iid, ppvObject); + return S_OK; + } + + static HRESULT WINAPI CreateInstance(IUnknown * punkOuter, CComAggObject **pp) + { + CComAggObject *newInstance; + HRESULT hResult; + + ATLASSERT(pp != NULL); + if (pp == NULL) + return E_POINTER; + + hResult = E_OUTOFMEMORY; + newInstance = NULL; + ATLTRY(newInstance = new CComAggObject(punkOuter)) + if (newInstance != NULL) + { + newInstance->SetVoid(NULL); + newInstance->InternalFinalConstructAddRef(); + hResult = newInstance->_AtlInitialConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->FinalConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->_AtlFinalConstruct(); + newInstance->InternalFinalConstructRelease(); + if (hResult != S_OK) + { + delete newInstance; + newInstance = NULL; + } + } + *pp = newInstance; + return hResult; + } +}; + +template +class CComPolyObject : public contained +{ +public: + CComContainedObject m_contained; + + CComPolyObject(void * pv = NULL) + : m_contained(pv ? static_cast(pv) : this) + { + _pAtlModule->Lock(); + } + + virtual ~CComPolyObject() + { + this->FinalRelease(); + _pAtlModule->Unlock(); + } + + HRESULT FinalConstruct() + { + return m_contained.FinalConstruct(); + } + void FinalRelease() + { + m_contained.FinalRelease(); + } + + STDMETHOD_(ULONG, AddRef)() + { + return this->InternalAddRef(); + } + + STDMETHOD_(ULONG, Release)() + { + ULONG newRefCount; + newRefCount = this->InternalRelease(); + if (newRefCount == 0) + delete this; + return newRefCount; + } + + STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) + { + if (ppvObject == NULL) + return E_POINTER; + if (iid == IID_IUnknown) + *ppvObject = reinterpret_cast(this); + else + return m_contained._InternalQueryInterface(iid, ppvObject); + return S_OK; + } + + static HRESULT WINAPI CreateInstance(IUnknown * punkOuter, CComPolyObject **pp) + { + CComPolyObject *newInstance; + HRESULT hResult; + + ATLASSERT(pp != NULL); + if (pp == NULL) + return E_POINTER; + + hResult = E_OUTOFMEMORY; + newInstance = NULL; + ATLTRY(newInstance = new CComPolyObject(punkOuter)) + if (newInstance != NULL) + { + newInstance->SetVoid(NULL); + newInstance->InternalFinalConstructAddRef(); + hResult = newInstance->_AtlInitialConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->FinalConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->_AtlFinalConstruct(); + newInstance->InternalFinalConstructRelease(); + if (hResult != S_OK) + { + delete newInstance; + newInstance = NULL; + } + } + *pp = newInstance; + return hResult; + } +}; + +template +class CComFailCreator +{ +public: + static HRESULT WINAPI CreateInstance(void *, REFIID, LPVOID *ppv) + { + ATLASSERT(ppv != NULL); + if (ppv == NULL) + return E_POINTER; + *ppv = NULL; + + return hResult; + } +}; + +template +class CComCreator +{ +public: + static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv) + { + T1 *newInstance; + HRESULT hResult; + + ATLASSERT(ppv != NULL); + if (ppv == NULL) + return E_POINTER; + *ppv = NULL; + + hResult = E_OUTOFMEMORY; + newInstance = NULL; + ATLTRY(newInstance = new T1(pv)) + if (newInstance != NULL) + { + newInstance->SetVoid(pv); + newInstance->InternalFinalConstructAddRef(); + hResult = newInstance->_AtlInitialConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->FinalConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->_AtlFinalConstruct(); + newInstance->InternalFinalConstructRelease(); + if (SUCCEEDED(hResult)) + hResult = newInstance->QueryInterface(riid, ppv); + if (FAILED(hResult)) + { + delete newInstance; + newInstance = NULL; + } + } + return hResult; + } +}; + +template +class CComCreator2 +{ +public: + static HRESULT WINAPI CreateInstance(void *pv, REFIID riid, LPVOID *ppv) + { + ATLASSERT(ppv != NULL); + + if (pv == NULL) + return T1::CreateInstance(NULL, riid, ppv); + else + return T2::CreateInstance(pv, riid, ppv); + } +}; + +template +class CComObjectCached : public Base +{ +public: + CComObjectCached(void * = NULL) + { + } + + virtual ~CComObjectCached() + { + this->FinalRelease(); + } + + STDMETHOD_(ULONG, AddRef)() + { + ULONG newRefCount; + + newRefCount = this->InternalAddRef(); + if (newRefCount == 2) + _pAtlModule->Lock(); + return newRefCount; + } + + STDMETHOD_(ULONG, Release)() + { + ULONG newRefCount; + + newRefCount = this->InternalRelease(); + if (newRefCount == 0) + delete this; + else if (newRefCount == 1) + _pAtlModule->Unlock(); + return newRefCount; + } + + STDMETHOD(QueryInterface)(REFIID iid, void **ppvObject) + { + return this->_InternalQueryInterface(iid, ppvObject); + } + + static HRESULT WINAPI CreateInstance(CComObjectCached **pp) + { + CComObjectCached *newInstance; + HRESULT hResult; + + ATLASSERT(pp != NULL); + if (pp == NULL) + return E_POINTER; + + hResult = E_OUTOFMEMORY; + newInstance = NULL; + ATLTRY(newInstance = new CComObjectCached()) + if (newInstance != NULL) + { + newInstance->SetVoid(NULL); + newInstance->InternalFinalConstructAddRef(); + hResult = newInstance->_AtlInitialConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->FinalConstruct(); + if (SUCCEEDED(hResult)) + hResult = newInstance->_AtlFinalConstruct(); + newInstance->InternalFinalConstructRelease(); + if (hResult != S_OK) + { + delete newInstance; + newInstance = NULL; + } + } + *pp = newInstance; + return hResult; + } +}; + +#define BEGIN_COM_MAP(x) \ +public: \ + typedef x _ComMapClass; \ + HRESULT _InternalQueryInterface(REFIID iid, void **ppvObject) \ + { \ + return this->InternalQueryInterface(this, _GetEntries(), iid, ppvObject); \ + } \ + const static ATL::_ATL_INTMAP_ENTRY *WINAPI _GetEntries() \ + { \ + static const ATL::_ATL_INTMAP_ENTRY _entries[] = { + +#define END_COM_MAP() \ + {NULL, 0, 0} \ + }; \ + return _entries; \ + } \ + virtual ULONG STDMETHODCALLTYPE AddRef() = 0; \ + virtual ULONG STDMETHODCALLTYPE Release() = 0; \ + STDMETHOD(QueryInterface)(REFIID, void **) = 0; + +#define COM_INTERFACE_ENTRY_IID(iid, x) \ + {&iid, offsetofclass(x, _ComMapClass), _ATL_SIMPLEMAPENTRY}, + +#define COM_INTERFACE_ENTRY(x) \ + {&_ATL_IIDOF(x), \ + offsetofclass(x, _ComMapClass), \ + _ATL_SIMPLEMAPENTRY}, + +#define COM_INTERFACE_ENTRY2_IID(iid, x, x2) \ + {&iid, \ + reinterpret_cast(static_cast(static_cast(reinterpret_cast<_ComMapClass *>(_ATL_PACKING)))) - _ATL_PACKING, \ + _ATL_SIMPLEMAPENTRY}, + +#define COM_INTERFACE_ENTRY_BREAK(x) \ + {&_ATL_IIDOF(x), \ + NULL, \ + _Break}, // Break is a function that issues int 3. + +#define COM_INTERFACE_ENTRY_NOINTERFACE(x) \ + {&_ATL_IIDOF(x), \ + NULL, \ + _NoInterface}, // NoInterface returns E_NOINTERFACE. + +#define COM_INTERFACE_ENTRY_FUNC(iid, dw, func) \ + {&iid, \ + dw, \ + func}, + +#define COM_INTERFACE_ENTRY_FUNC_BLIND(dw, func) \ + {NULL, \ + dw, \ + func}, + +#define COM_INTERFACE_ENTRY_CHAIN(classname) \ + {NULL, \ + reinterpret_cast(&_CComChainData::data), \ + _Chain}, + +#define DECLARE_NO_REGISTRY()\ + static HRESULT WINAPI UpdateRegistry(BOOL /*bRegister*/) \ + { \ + return S_OK; \ + } + +#define DECLARE_REGISTRY_RESOURCEID(x) \ + static HRESULT WINAPI UpdateRegistry(BOOL bRegister) \ + { \ + return ATL::_pAtlModule->UpdateRegistryFromResource(x, bRegister); \ + } + +#define DECLARE_NOT_AGGREGATABLE(x) \ +public: \ + typedef ATL::CComCreator2 >, ATL::CComFailCreator > _CreatorClass; + +#define DECLARE_AGGREGATABLE(x) \ +public: \ + typedef ATL::CComCreator2 >, ATL::CComCreator > > _CreatorClass; + +#define DECLARE_ONLY_AGGREGATABLE(x) \ +public: \ + typedef ATL::CComCreator2, ATL::CComCreator > > _CreatorClass; + +#define DECLARE_POLY_AGGREGATABLE(x) \ +public: \ + typedef ATL::CComCreator > _CreatorClass; + +#define COM_INTERFACE_ENTRY_AGGREGATE(iid, punk) \ + {&iid, \ + (DWORD_PTR)offsetof(_ComMapClass, punk), \ + _Delegate}, + +#define DECLARE_GET_CONTROLLING_UNKNOWN() \ +public: \ + virtual IUnknown *GetControllingUnknown() \ + { \ + return GetUnknown(); \ + } + +#define DECLARE_PROTECT_FINAL_CONSTRUCT() \ + void InternalFinalConstructAddRef() \ + { \ + InternalAddRef(); \ + } \ + void InternalFinalConstructRelease() \ + { \ + InternalRelease(); \ + } + +#define BEGIN_OBJECT_MAP(x) static ATL::_ATL_OBJMAP_ENTRY x[] = { + +#define END_OBJECT_MAP() {NULL, NULL, NULL, NULL, NULL, 0, NULL, NULL, NULL}}; + +#define OBJECT_ENTRY(clsid, class) \ +{ \ + &clsid, \ + class::UpdateRegistry, \ + class::_ClassFactoryCreatorClass::CreateInstance, \ + class::_CreatorClass::CreateInstance, \ + NULL, \ + 0, \ + class::GetObjectDescription, \ + class::GetCategoryMap, \ + class::ObjectMain }, + +class CComClassFactory : + public IClassFactory, + public CComObjectRootEx +{ +public: + _ATL_CREATORFUNC *m_pfnCreateInstance; + + virtual ~CComClassFactory() + { + } + +public: + STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj) + { + HRESULT hResult; + + ATLASSERT(m_pfnCreateInstance != NULL); + + if (ppvObj == NULL) + return E_POINTER; + *ppvObj = NULL; + + if (pUnkOuter != NULL && InlineIsEqualUnknown(riid) == FALSE) + hResult = CLASS_E_NOAGGREGATION; + else + hResult = m_pfnCreateInstance(pUnkOuter, riid, ppvObj); + return hResult; + } + + STDMETHOD(LockServer)(BOOL fLock) + { + if (fLock) + _pAtlModule->Lock(); + else + _pAtlModule->Unlock(); + return S_OK; + } + + void SetVoid(void *pv) + { + m_pfnCreateInstance = (_ATL_CREATORFUNC *)pv; + } + + BEGIN_COM_MAP(CComClassFactory) + COM_INTERFACE_ENTRY_IID(IID_IClassFactory, IClassFactory) + END_COM_MAP() +}; + +template +class CComClassFactorySingleton : + public CComClassFactory +{ +public: + HRESULT m_hrCreate; + IUnknown *m_spObj; + +public: + CComClassFactorySingleton() : + m_hrCreate(S_OK), + m_spObj(NULL) + { + } + + STDMETHOD(CreateInstance)(LPUNKNOWN pUnkOuter, REFIID riid, void **ppvObj) + { + HRESULT hResult; + + if (ppvObj == NULL) + return E_POINTER; + *ppvObj = NULL; + + if (pUnkOuter != NULL) + hResult = CLASS_E_NOAGGREGATION; + else if (m_hrCreate == S_OK && m_spObj == NULL) + { + _SEH2_TRY + { + Lock(); + if (m_hrCreate == S_OK && m_spObj == NULL) + { + CComObjectCached *pObj; + m_hrCreate = CComObjectCached::CreateInstance(&pObj); + if (SUCCEEDED(m_hrCreate)) + { + m_hrCreate = pObj->QueryInterface(IID_IUnknown, reinterpret_cast(&m_spObj)); + if (FAILED(m_hrCreate)) + delete pObj; + } + } + } + _SEH2_FINALLY + { + Unlock(); + } + _SEH2_END; + } + if (m_hrCreate == S_OK) + hResult = m_spObj->QueryInterface(riid, ppvObj); + else + hResult = m_hrCreate; + return hResult; + } +}; + +template +class CComCoClass +{ +public: + DECLARE_CLASSFACTORY() + + static LPCTSTR WINAPI GetObjectDescription() + { + return NULL; + } +}; + +template +class _Copy +{ +public: + static HRESULT copy(T *pTo, const T *pFrom) + { + memcpy(pTo, pFrom, sizeof(T)); + return S_OK; + } + + static void init(T *) + { + } + + static void destroy(T *) + { + } +}; + +template<> +class _Copy +{ +public: + static HRESULT copy(CONNECTDATA *pTo, const CONNECTDATA *pFrom) + { + *pTo = *pFrom; + if (pTo->pUnk) + pTo->pUnk->AddRef(); + return S_OK; + } + + static void init(CONNECTDATA *) + { + } + + static void destroy(CONNECTDATA *p) + { + if (p->pUnk) + p->pUnk->Release(); + } +}; + +template +class _CopyInterface +{ +public: + static HRESULT copy(T **pTo, T **pFrom) + { + *pTo = *pFrom; + if (*pTo) + (*pTo)->AddRef(); + return S_OK; + } + + static void init(T **) + { + } + + static void destroy(T **p) + { + if (*p) + (*p)->Release(); + } +}; + +enum CComEnumFlags +{ + AtlFlagNoCopy = 0, + AtlFlagTakeOwnership = 2, // BitOwn + AtlFlagCopy = 3 // BitOwn | BitCopy +}; + +template +class CComEnumImpl : public Base +{ +private: + typedef CComObject > enumeratorClass; +public: + CComPtr m_spUnk; + DWORD m_dwFlags; + T *m_begin; + T *m_end; + T *m_iter; +public: + CComEnumImpl() + { + m_dwFlags = 0; + m_begin = NULL; + m_end = NULL; + m_iter = NULL; + } + + virtual ~CComEnumImpl() + { + T *x; + + if ((m_dwFlags & BitOwn) != 0) + { + for (x = m_begin; x != m_end; x++) + Copy::destroy(x); + delete [] m_begin; + } + } + + HRESULT Init(T *begin, T *end, IUnknown *pUnk, CComEnumFlags flags = AtlFlagNoCopy) + { + T *newBuffer; + T *sourcePtr; + T *destPtr; + T *cleanupPtr; + HRESULT hResult; + + if (flags == AtlFlagCopy) + { + ATLTRY(newBuffer = new T[end - begin]) + if (newBuffer == NULL) + return E_OUTOFMEMORY; + destPtr = newBuffer; + for (sourcePtr = begin; sourcePtr != end; sourcePtr++) + { + Copy::init(destPtr); + hResult = Copy::copy(destPtr, sourcePtr); + if (FAILED(hResult)) + { + cleanupPtr = m_begin; + while (cleanupPtr < destPtr) + Copy::destroy(cleanupPtr++); + delete [] newBuffer; + return hResult; + } + destPtr++; + } + m_begin = newBuffer; + m_end = m_begin + (end - begin); + } + else + { + m_begin = begin; + m_end = end; + } + m_spUnk = pUnk; + m_dwFlags = flags; + m_iter = m_begin; + return S_OK; + } + + STDMETHOD(Next)(ULONG celt, T *rgelt, ULONG *pceltFetched) + { + ULONG numAvailable; + ULONG numToFetch; + T *rgeltTemp; + HRESULT hResult; + + if (pceltFetched != NULL) + *pceltFetched = 0; + if (celt == 0) + return E_INVALIDARG; + if (rgelt == NULL || (celt != 1 && pceltFetched == NULL)) + return E_POINTER; + if (m_begin == NULL || m_end == NULL || m_iter == NULL) + return E_FAIL; + + numAvailable = static_cast(m_end - m_iter); + if (celt < numAvailable) + numToFetch = celt; + else + numToFetch = numAvailable; + if (pceltFetched != NULL) + *pceltFetched = numToFetch; + rgeltTemp = rgelt; + while (numToFetch != 0) + { + hResult = Copy::copy(rgeltTemp, m_iter); + if (FAILED(hResult)) + { + while (rgelt < rgeltTemp) + Copy::destroy(rgelt++); + if (pceltFetched != NULL) + *pceltFetched = 0; + return hResult; + } + rgeltTemp++; + m_iter++; + numToFetch--; + } + if (numAvailable < celt) + return S_FALSE; + return S_OK; + } + + STDMETHOD(Skip)(ULONG celt) + { + ULONG numAvailable; + ULONG numToSkip; + + if (celt == 0) + return E_INVALIDARG; + + numAvailable = static_cast(m_end - m_iter); + if (celt < numAvailable) + numToSkip = celt; + else + numToSkip = numAvailable; + m_iter += numToSkip; + if (numAvailable < celt) + return S_FALSE; + return S_OK; + } + + STDMETHOD(Reset)() + { + m_iter = m_begin; + return S_OK; + } + + STDMETHOD(Clone)(Base **ppEnum) + { + enumeratorClass *newInstance; + HRESULT hResult; + + hResult = E_POINTER; + if (ppEnum != NULL) + { + *ppEnum = NULL; + hResult = enumeratorClass::CreateInstance(&newInstance); + if (SUCCEEDED(hResult)) + { + hResult = newInstance->Init(m_begin, m_end, (m_dwFlags & BitOwn) ? this : m_spUnk); + if (SUCCEEDED(hResult)) + { + newInstance->m_iter = m_iter; + hResult = newInstance->_InternalQueryInterface(*piid, (void **)ppEnum); + } + if (FAILED(hResult)) + delete newInstance; + } + } + return hResult; + } + +protected: + enum FlagBits + { + BitCopy = 1, + BitOwn = 2 + }; +}; + +template +class CComEnum : + public CComEnumImpl, + public CComObjectRootEx +{ +public: + typedef CComEnum _CComEnum; + typedef CComEnumImpl _CComEnumBase; + + BEGIN_COM_MAP(_CComEnum) + COM_INTERFACE_ENTRY_IID(*piid, _CComEnumBase) + END_COM_MAP() +}; + +#ifndef _DEFAULT_VECTORLENGTH +#define _DEFAULT_VECTORLENGTH 4 +#endif + +class CComDynamicUnkArray +{ +public: + int m_nSize; + IUnknown **m_ppUnk; +public: + CComDynamicUnkArray() + { + m_nSize = 0; + m_ppUnk = NULL; + } + + ~CComDynamicUnkArray() + { + free(m_ppUnk); + } + + IUnknown **begin() + { + return m_ppUnk; + } + + IUnknown **end() + { + return &m_ppUnk[m_nSize]; + } + + IUnknown *GetAt(int nIndex) + { + ATLASSERT(nIndex >= 0 && nIndex < m_nSize); + if (nIndex >= 0 && nIndex < m_nSize) + return m_ppUnk[nIndex]; + else + return NULL; + } + + IUnknown *WINAPI GetUnknown(DWORD dwCookie) + { + ATLASSERT(dwCookie != 0 && dwCookie <= static_cast(m_nSize)); + if (dwCookie != 0 && dwCookie <= static_cast(m_nSize)) + return GetAt(dwCookie - 1); + else + return NULL; + } + + DWORD WINAPI GetCookie(IUnknown **ppFind) + { + IUnknown **x; + DWORD curCookie; + + ATLASSERT(ppFind != NULL && *ppFind != NULL); + if (ppFind != NULL && *ppFind != NULL) + { + curCookie = 1; + for (x = begin(); x < end(); x++) + { + if (*x == *ppFind) + return curCookie; + curCookie++; + } + } + return 0; + } + + DWORD Add(IUnknown *pUnk) + { + IUnknown **x; + IUnknown **newArray; + int newSize; + DWORD curCookie; + + ATLASSERT(pUnk != NULL); + if (m_nSize == 0) + { + newSize = _DEFAULT_VECTORLENGTH * sizeof(IUnknown *); + ATLTRY(newArray = reinterpret_cast(malloc(newSize))); + if (newArray == NULL) + return 0; + memset(newArray, 0, newSize); + m_ppUnk = newArray; + m_nSize = _DEFAULT_VECTORLENGTH; + } + curCookie = 1; + for (x = begin(); x < end(); x++) + { + if (*x == NULL) + { + *x = pUnk; + return curCookie; + } + curCookie++; + } + newSize = m_nSize * 2; + newArray = reinterpret_cast(realloc(m_ppUnk, newSize * sizeof(IUnknown *))); + if (newArray == NULL) + return 0; + m_ppUnk = newArray; + memset(&m_ppUnk[m_nSize], 0, (newSize - m_nSize) * sizeof(IUnknown *)); + curCookie = m_nSize + 1; + m_nSize = newSize; + m_ppUnk[curCookie - 1] = pUnk; + return curCookie; + } + + BOOL Remove(DWORD dwCookie) + { + DWORD index; + + index = dwCookie - 1; + ATLASSERT(index < dwCookie && index < static_cast(m_nSize)); + if (index < dwCookie && index < static_cast(m_nSize) && m_ppUnk[index] != NULL) + { + m_ppUnk[index] = NULL; + return TRUE; + } + return FALSE; + } + +private: + CComDynamicUnkArray &operator = (const CComDynamicUnkArray &) + { + return *this; + } + + CComDynamicUnkArray(const CComDynamicUnkArray &) + { + } +}; + +struct _ATL_CONNMAP_ENTRY +{ + DWORD_PTR dwOffset; +}; + +template +class _ICPLocator +{ +public: + STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject) = 0; + virtual ULONG STDMETHODCALLTYPE AddRef() = 0; + virtual ULONG STDMETHODCALLTYPE Release() = 0; +}; + +template +class IConnectionPointImpl : public _ICPLocator +{ + typedef CComEnum > CComEnumConnections; +public: + CDV m_vec; +public: + ~IConnectionPointImpl() + { + IUnknown **x; + + for (x = m_vec.begin(); x < m_vec.end(); x++) + if (*x != NULL) + (*x)->Release(); + } + + STDMETHOD(_LocCPQueryInterface)(REFIID riid, void **ppvObject) + { + IConnectionPointImpl *pThis; + + pThis = reinterpret_cast*>(this); + + ATLASSERT(ppvObject != NULL); + if (ppvObject == NULL) + return E_POINTER; + + if (InlineIsEqualGUID(riid, IID_IConnectionPoint) || InlineIsEqualUnknown(riid)) + { + *ppvObject = this; + pThis->AddRef(); + return S_OK; + } + else + { + *ppvObject = NULL; + return E_NOINTERFACE; + } + } + + STDMETHOD(GetConnectionInterface)(IID *piid2) + { + if (piid2 == NULL) + return E_POINTER; + *piid2 = *piid; + return S_OK; + } + + STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer **ppCPC) + { + T *pThis; + + pThis = static_cast(this); + return pThis->QueryInterface(IID_IConnectionPointContainer, reinterpret_cast(ppCPC)); + } + + STDMETHOD(Advise)(IUnknown *pUnkSink, DWORD *pdwCookie) + { + IUnknown *adviseTarget; + IID interfaceID; + HRESULT hResult; + + if (pdwCookie != NULL) + *pdwCookie = 0; + if (pUnkSink == NULL || pdwCookie == NULL) + return E_POINTER; + GetConnectionInterface(&interfaceID); // can't fail + hResult = pUnkSink->QueryInterface(interfaceID, reinterpret_cast(&adviseTarget)); + if (SUCCEEDED(hResult)) + { + *pdwCookie = m_vec.Add(adviseTarget); + if (*pdwCookie != 0) + hResult = S_OK; + else + { + adviseTarget->Release(); + hResult = CONNECT_E_ADVISELIMIT; + } + } + else if (hResult == E_NOINTERFACE) + hResult = CONNECT_E_CANNOTCONNECT; + return hResult; + } + + STDMETHOD(Unadvise)(DWORD dwCookie) + { + IUnknown *adviseTarget; + HRESULT hResult; + + adviseTarget = m_vec.GetUnknown(dwCookie); + if (m_vec.Remove(dwCookie)) + { + if (adviseTarget != NULL) + adviseTarget->Release(); + hResult = S_OK; + } + else + hResult = CONNECT_E_NOCONNECTION; + return hResult; + } + + STDMETHOD(EnumConnections)(IEnumConnections **ppEnum) + { + CComObject *newEnumerator; + CONNECTDATA *itemBuffer; + CONNECTDATA *itemBufferEnd; + IUnknown **x; + HRESULT hResult; + + ATLASSERT(ppEnum != NULL); + if (ppEnum == NULL) + return E_POINTER; + *ppEnum = NULL; + + ATLTRY(itemBuffer = new CONNECTDATA[m_vec.end() - m_vec.begin()]) + if (itemBuffer == NULL) + return E_OUTOFMEMORY; + itemBufferEnd = itemBuffer; + for (x = m_vec.begin(); x < m_vec.end(); x++) + { + if (*x != NULL) + { + (*x)->AddRef(); + itemBufferEnd->pUnk = *x; + itemBufferEnd->dwCookie = m_vec.GetCookie(x); + itemBufferEnd++; + } + } + ATLTRY(newEnumerator = new CComObject) + if (newEnumerator == NULL) + return E_OUTOFMEMORY; + newEnumerator->Init(itemBuffer, itemBufferEnd, NULL, AtlFlagTakeOwnership); // can't fail + hResult = newEnumerator->_InternalQueryInterface(IID_IEnumConnections, (void **)ppEnum); + if (FAILED(hResult)) + delete newEnumerator; + return hResult; + } +}; + +template +class IConnectionPointContainerImpl : public IConnectionPointContainer +{ + typedef const _ATL_CONNMAP_ENTRY * (*handlerFunctionType)(int *); + typedef CComEnum > + CComEnumConnectionPoints; + +public: + STDMETHOD(EnumConnectionPoints)(IEnumConnectionPoints **ppEnum) + { + const _ATL_CONNMAP_ENTRY *entryPtr; + int connectionPointCount; + IConnectionPoint **itemBuffer; + int destIndex; + handlerFunctionType handlerFunction; + CComEnumConnectionPoints *newEnumerator; + HRESULT hResult; + + ATLASSERT(ppEnum != NULL); + if (ppEnum == NULL) + return E_POINTER; + *ppEnum = NULL; + + entryPtr = T::GetConnMap(&connectionPointCount); + ATLTRY(itemBuffer = new IConnectionPoint * [connectionPointCount]) + if (itemBuffer == NULL) + return E_OUTOFMEMORY; + + destIndex = 0; + while (entryPtr->dwOffset != static_cast(-1)) + { + if (entryPtr->dwOffset == static_cast(-2)) + { + entryPtr++; + handlerFunction = reinterpret_cast(entryPtr->dwOffset); + entryPtr = handlerFunction(NULL); + } + else + { + itemBuffer[destIndex++] = reinterpret_cast((char *)this + entryPtr->dwOffset); + entryPtr++; + } + } + + ATLTRY(newEnumerator = new CComObject) + if (newEnumerator == NULL) + { + delete [] itemBuffer; + return E_OUTOFMEMORY; + } + + newEnumerator->Init(&itemBuffer[0], &itemBuffer[destIndex], NULL, AtlFlagTakeOwnership); // can't fail + hResult = newEnumerator->QueryInterface(IID_IEnumConnectionPoints, (void**)ppEnum); + if (FAILED(hResult)) + delete newEnumerator; + return hResult; + } + + STDMETHOD(FindConnectionPoint)(REFIID riid, IConnectionPoint **ppCP) + { + IID interfaceID; + const _ATL_CONNMAP_ENTRY *entryPtr; + handlerFunctionType handlerFunction; + IConnectionPoint *connectionPoint; + HRESULT hResult; + + if (ppCP == NULL) + return E_POINTER; + *ppCP = NULL; + hResult = CONNECT_E_NOCONNECTION; + entryPtr = T::GetConnMap(NULL); + while (entryPtr->dwOffset != static_cast(-1)) + { + if (entryPtr->dwOffset == static_cast(-2)) + { + entryPtr++; + handlerFunction = reinterpret_cast(entryPtr->dwOffset); + entryPtr = handlerFunction(NULL); + } + else + { + connectionPoint = reinterpret_cast(reinterpret_cast(this) + entryPtr->dwOffset); + if (SUCCEEDED(connectionPoint->GetConnectionInterface(&interfaceID)) && InlineIsEqualGUID(riid, interfaceID)) + { + *ppCP = connectionPoint; + connectionPoint->AddRef(); + hResult = S_OK; + break; + } + entryPtr++; + } + } + return hResult; + } +}; + +#define BEGIN_CONNECTION_POINT_MAP(x) \ + typedef x _atl_conn_classtype; \ + static const ATL::_ATL_CONNMAP_ENTRY *GetConnMap(int *pnEntries) { \ + static const ATL::_ATL_CONNMAP_ENTRY _entries[] = { + +#define END_CONNECTION_POINT_MAP() \ + {(DWORD_PTR)-1} }; \ + if (pnEntries) \ + *pnEntries = sizeof(_entries) / sizeof(ATL::_ATL_CONNMAP_ENTRY) - 1; \ + return _entries;} + +#define CONNECTION_POINT_ENTRY(iid) \ + {offsetofclass(ATL::_ICPLocator<&iid>, _atl_conn_classtype) - \ + offsetofclass(ATL::IConnectionPointContainerImpl<_atl_conn_classtype>, _atl_conn_classtype)}, + + + +/* TODO: + - IDispatchImpl contains a static member of type CComTypeInfoHolder that manages the type information for the dual interface. + If you have multiple objects that implement the same dual interface, only one instance of CComTypeInfoHolder is used. + - By default, the IDispatchImpl class looks up the type information for T in the registry. + To implement an unregistered interface, you can use the IDispatchImpl class without accessing the registry by using a predefined version number. + If you create an IDispatchImpl object that has 0xFFFF as the value for wMajor and 0xFFFF as the value for wMinor, + the IDispatchImpl class retrieves the type library from the .dll file instead of the registry. +*/ +template +class IDispatchImpl : + public T +{ +private: + CComPtr m_pTypeInfo; + + STDMETHOD(EnsureTILoaded)(LCID lcid) + { + HRESULT hr = S_OK; + if (m_pTypeInfo != NULL) + return hr; + + if (IsEqualCLSID(CLSID_NULL, *plibid)) + OutputDebugStringA("IDispatchImpl: plibid is CLSID_NULL!\r\n"); + + // Should we assert here? + if (wMajor == 0xffff && wMinor == 0xffff) + OutputDebugStringA("IDispatchImpl: not fully implemented, missing functionality to load TLB from file!\r\n"); + + CComPtr spTypeLib; + hr = LoadRegTypeLib(*plibid, wMajor, wMinor, lcid, &spTypeLib); + if (SUCCEEDED(hr)) + { + hr = spTypeLib->GetTypeInfoOfGuid(*piid, &m_pTypeInfo); + } + return hr; + } + +public: + IDispatchImpl() + { + } + + + // *** IDispatch methods *** + STDMETHOD(GetTypeInfoCount)(UINT *pctinfo) + { + if (pctinfo == NULL) + return E_POINTER; + + *pctinfo = 1; + return S_OK; + } + + STDMETHOD(GetTypeInfo)(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) + { + if (iTInfo != 0) + return DISP_E_BADINDEX; + if (ppTInfo == NULL) + return E_POINTER; + + HRESULT hr = EnsureTILoaded(lcid); + *ppTInfo = m_pTypeInfo; + if (*ppTInfo) + (*ppTInfo)->AddRef(); + + return hr; + } + + STDMETHOD(GetIDsOfNames)(REFIID /*riid*/, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId) + { + HRESULT hr = EnsureTILoaded(lcid); + if (SUCCEEDED(hr)) + hr = m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId); + return hr; + } + + STDMETHOD(Invoke)(DISPID dispIdMember, REFIID /*riid*/, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr) + { + HRESULT hr = EnsureTILoaded(lcid); + if (SUCCEEDED(hr)) + hr = m_pTypeInfo->Invoke(this, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr); + return hr; + } +}; + +}; // namespace ATL diff --git a/src/3rd_party/reactos-atl/atl/atlcomcli.h b/src/3rd_party/reactos-atl/atl/atlcomcli.h new file mode 100644 index 00000000..cba78101 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlcomcli.h @@ -0,0 +1,573 @@ +/* + * ReactOS ATL + * + * Copyright 2009 Andrew Hill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include "atlcore.h" + + +#ifdef _MSC_VER +// It is common to use this in ATL constructors. They only store this for later use, so the usage is safe. +#pragma warning(disable:4355) +#endif + +#ifndef _ATL_PACKING +#define _ATL_PACKING 8 +#endif + +#ifndef _ATL_FREE_THREADED +#ifndef _ATL_APARTMENT_THREADED +#ifndef _ATL_SINGLE_THREADED +#define _ATL_FREE_THREADED +#endif +#endif +#endif + +#ifndef ATLTRY +#define ATLTRY(x) x; +#endif + +#ifdef _ATL_DISABLE_NO_VTABLE +#define ATL_NO_VTABLE +#else +#define ATL_NO_VTABLE __declspec(novtable) +#endif + +namespace ATL +{ + +inline HRESULT AtlHresultFromLastError() throw() +{ + DWORD dwError = ::GetLastError(); + return HRESULT_FROM_WIN32(dwError); +} + + +template +class CComPtr +{ +public: + T *p; +public: + CComPtr() + { + p = NULL; + } + + CComPtr(T *lp) + { + p = lp; + if (p != NULL) + p->AddRef(); + } + + CComPtr(const CComPtr &lp) + { + p = lp.p; + if (p != NULL) + p->AddRef(); + } + + ~CComPtr() + { + if (p != NULL) + p->Release(); + } + + T *operator = (T *lp) + { + T* pOld = p; + + p = lp; + if (p != NULL) + p->AddRef(); + + if (pOld != NULL) + pOld->Release(); + + return *this; + } + + T *operator = (const CComPtr &lp) + { + T* pOld = p; + + p = lp.p; + if (p != NULL) + p->AddRef(); + + if (pOld != NULL) + pOld->Release(); + + return *this; + } + + // We cannot enable this until gcc starts supporting __uuidof + // See CORE-12710 +#if 0 + template + T* operator=(const CComPtr& lp) + { + T* pOld = p; + + if (!lp.p || FAILED(lp.p->QueryInterface(__uuidof(T), (void**)(IUnknown**)&p))) + p = NULL; + + if (pOld != NULL) + pOld->Release(); + + return *this; + } +#endif + + void Release() + { + if (p != NULL) + { + p->Release(); + p = NULL; + } + } + + void Attach(T *lp) + { + if (p != NULL) + p->Release(); + p = lp; + } + + T *Detach() + { + T *saveP; + + saveP = p; + p = NULL; + return saveP; + } + + T **operator & () + { + ATLASSERT(p == NULL); + return &p; + } + + operator T * () + { + return p; + } + + T *operator -> () + { + ATLASSERT(p != NULL); + return p; + } +}; + + +//CComQIIDPtr is the gcc compatible version of CComQIPtr +#define I_ID(Itype) Itype,&IID_##Itype + +template +class CComQIIDPtr : + public CComPtr +{ +public: + // Let's tell GCC how to find a symbol. + using CComPtr::p; + + CComQIIDPtr() + { + } + CComQIIDPtr(_Inout_opt_ T* lp) : + CComPtr(lp) + { + } + CComQIIDPtr(_Inout_ const CComQIIDPtr& lp): + CComPtr(lp.p) + { + } + CComQIIDPtr(_Inout_opt_ IUnknown* lp) + { + if (lp != NULL) + { + if (FAILED(lp->QueryInterface(*piid, (void**)(IUnknown**)&p))) + p = NULL; + } + } + T *operator = (T *lp) + { + T* pOld = p; + + p = lp; + if (p != NULL) + p->AddRef(); + + if (pOld != NULL) + pOld->Release(); + + return *this; + } + + T *operator = (const CComQIIDPtr &lp) + { + T* pOld = p; + + p = lp.p; + if (p != NULL) + p->AddRef(); + + if (pOld != NULL) + pOld->Release(); + + return *this; + } + + T * operator=(IUnknown* lp) + { + T* pOld = p; + + if (!lp || FAILED(lp->QueryInterface(*piid, (void**)(IUnknown**)&p))) + p = NULL; + + if (pOld != NULL) + pOld->Release(); + + return *this; + } +}; + + +class CComBSTR +{ +public: + BSTR m_str; +public: + CComBSTR() : + m_str(NULL) + { + } + + CComBSTR(LPCOLESTR pSrc) + { + if (pSrc == NULL) + m_str = NULL; + else + m_str = ::SysAllocString(pSrc); + } + + CComBSTR(int length) + { + if (length == 0) + m_str = NULL; + else + m_str = ::SysAllocStringLen(NULL, length); + } + + CComBSTR(int length, LPCOLESTR pSrc) + { + if (length == 0) + m_str = NULL; + else + m_str = ::SysAllocStringLen(pSrc, length); + } + + CComBSTR(PCSTR pSrc) + { + if (pSrc) + { + int len = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, NULL, 0); + m_str = ::SysAllocStringLen(NULL, len - 1); + if (m_str) + { + int res = MultiByteToWideChar(CP_THREAD_ACP, 0, pSrc, -1, m_str, len); + ATLASSERT(res == len); + if (res != len) + { + ::SysFreeString(m_str); + m_str = NULL; + } + } + } + else + { + m_str = NULL; + } + } + + CComBSTR(const CComBSTR &other) + { + m_str = other.Copy(); + } + + CComBSTR(REFGUID guid) + { + OLECHAR szGuid[40]; + ::StringFromGUID2(guid, szGuid, 40); + m_str = ::SysAllocString(szGuid); + } + + ~CComBSTR() + { + ::SysFreeString(m_str); + m_str = NULL; + } + + operator BSTR () const + { + return m_str; + } + + BSTR *operator & () + { + return &m_str; + } + + CComBSTR &operator = (const CComBSTR &other) + { + ::SysFreeString(m_str); + m_str = other.Copy(); + return *this; + } + + void Attach(BSTR bstr) + { + ::SysFreeString(m_str); + m_str = bstr; + } + + BSTR Detach() + { + BSTR str = m_str; + m_str = NULL; + return str; + } + + BSTR Copy() const + { + if (!m_str) + return NULL; + return ::SysAllocStringLen(m_str, ::SysStringLen(m_str)); + } + + HRESULT CopyTo(BSTR *other) const + { + if (!other) + return E_POINTER; + *other = Copy(); + return S_OK; + } + + bool LoadString(HMODULE module, DWORD uID) + { + ::SysFreeString(m_str); + m_str = NULL; + const wchar_t *ptr = NULL; + int len = ::LoadStringW(module, uID, (PWSTR)&ptr, 0); + if (len) + m_str = ::SysAllocStringLen(ptr, len); + return m_str != NULL; + } + + unsigned int Length() const + { + return ::SysStringLen(m_str); + } + + unsigned int ByteLength() const + { + return ::SysStringByteLen(m_str); + } +}; + + +class CComVariant : public tagVARIANT +{ +public: + CComVariant() + { + ::VariantInit(this); + } + + CComVariant(const CComVariant& other) + { + V_VT(this) = VT_EMPTY; + Copy(&other); + } + + ~CComVariant() + { + Clear(); + } + + CComVariant(LPCOLESTR lpStr) + { + V_VT(this) = VT_BSTR; + V_BSTR(this) = ::SysAllocString(lpStr); + } + + CComVariant(LPCSTR lpStr) + { + V_VT(this) = VT_BSTR; + CComBSTR str(lpStr); + V_BSTR(this) = str.Detach(); + } + + CComVariant(bool value) + { + V_VT(this) = VT_BOOL; + V_BOOL(this) = value ? VARIANT_TRUE : VARIANT_FALSE; + } + + CComVariant(char value) + { + V_VT(this) = VT_I1; + V_I1(this) = value; + } + + CComVariant(BYTE value) + { + V_VT(this) = VT_UI1; + V_UI1(this) = value; + } + + CComVariant(short value) + { + V_VT(this) = VT_I2; + V_I2(this) = value; + } + + CComVariant(unsigned short value) + { + V_VT(this) = VT_UI2; + V_UI2(this) = value; + } + + CComVariant(int value, VARENUM type = VT_I4) + { + if (type == VT_I4 || type == VT_INT) + { + V_VT(this) = type; + V_I4(this) = value; + } + else + { + V_VT(this) = VT_ERROR; + V_ERROR(this) = E_INVALIDARG; + } + } + + CComVariant(unsigned int value, VARENUM type = VT_UI4) + { + if (type == VT_UI4 || type == VT_UINT) + { + V_VT(this) = type; + V_UI4(this) = value; + } + else + { + V_VT(this) = VT_ERROR; + V_ERROR(this) = E_INVALIDARG; + } + } + + CComVariant(long value, VARENUM type = VT_I4) + { + if (type == VT_I4 || type == VT_ERROR) + { + V_VT(this) = type; + V_I4(this) = value; + } + else + { + V_VT(this) = VT_ERROR; + V_ERROR(this) = E_INVALIDARG; + } + } + + CComVariant(unsigned long value) + { + V_VT(this) = VT_UI4; + V_UI4(this) = value; + } + + CComVariant(float value) + { + V_VT(this) = VT_R4; + V_R4(this) = value; + } + + CComVariant(double value, VARENUM type = VT_R8) + { + if (type == VT_R8 || type == VT_DATE) + { + V_VT(this) = type; + V_R8(this) = value; + } + else + { + V_VT(this) = VT_ERROR; + V_ERROR(this) = E_INVALIDARG; + } + } + + CComVariant(const LONGLONG& value) + { + V_VT(this) = VT_I8; + V_I8(this) = value; + } + + CComVariant(const ULONGLONG& value) + { + V_VT(this) = VT_UI8; + V_UI8(this) = value; + } + + CComVariant(const CY& value) + { + V_VT(this) = VT_CY; + V_I8(this) = value.int64; + } + + + HRESULT Clear() + { + return ::VariantClear(this); + } + + HRESULT Copy(_In_ const VARIANT* src) + { + return ::VariantCopy(this, const_cast(src)); + } + + HRESULT ChangeType(_In_ VARTYPE newType, _In_opt_ const LPVARIANT src = NULL) + { + const LPVARIANT lpSrc = src ? src : this; + return ::VariantChangeType(this, lpSrc, 0, newType); + } +}; + + + +}; // namespace ATL + +#ifndef _ATL_NO_AUTOMATIC_NAMESPACE +using namespace ATL; +#endif //!_ATL_NO_AUTOMATIC_NAMESPACE + diff --git a/src/3rd_party/reactos-atl/atl/atlcore.h b/src/3rd_party/reactos-atl/atl/atlcore.h new file mode 100644 index 00000000..26f3cedc --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlcore.h @@ -0,0 +1,310 @@ +/* + * ReactOS ATL + * + * Copyright 2009 Andrew Hill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#include + +#ifdef __REACTOS__ + #define WIN32_NO_STATUS + #define _INC_WINDOWS + #define COM_NO_WINDOWS_H + #include + #include + #include + #include + #include +#else + #include +#endif +#include +#include +#include + +#ifndef ATLASSERT +#define ATLASSERT(expr) _ASSERTE(expr) +#endif // ATLASSERT + +namespace ATL +{ + +class CComCriticalSection +{ +public: + CRITICAL_SECTION m_sec; +public: + CComCriticalSection() + { + memset(&m_sec, 0, sizeof(CRITICAL_SECTION)); + } + + virtual ~CComCriticalSection() + { + } + + HRESULT Lock() + { + EnterCriticalSection(&m_sec); + return S_OK; + } + + HRESULT Unlock() + { + LeaveCriticalSection(&m_sec); + return S_OK; + } + + HRESULT Init() + { + InitializeCriticalSection(&m_sec); + return S_OK; + } + + HRESULT Term() + { + DeleteCriticalSection(&m_sec); + return S_OK; + } +}; + +class CComFakeCriticalSection +{ +public: + HRESULT Lock() + { + return S_OK; + } + + HRESULT Unlock() + { + return S_OK; + } + + HRESULT Init() + { + return S_OK; + } + + HRESULT Term() + { + return S_OK; + } +}; + +class CComAutoCriticalSection : public CComCriticalSection +{ +public: + CComAutoCriticalSection() + { + HRESULT hResult __MINGW_ATTRIB_UNUSED; + + hResult = CComCriticalSection::Init(); + ATLASSERT(SUCCEEDED(hResult)); + } + ~CComAutoCriticalSection() + { + CComCriticalSection::Term(); + } +}; + +class CComSafeDeleteCriticalSection : public CComCriticalSection +{ +private: + bool m_bInitialized; +public: + CComSafeDeleteCriticalSection() + { + m_bInitialized = false; + } + + ~CComSafeDeleteCriticalSection() + { + Term(); + } + + HRESULT Lock() + { + ATLASSERT(m_bInitialized); + return CComCriticalSection::Lock(); + } + + HRESULT Init() + { + HRESULT hResult; + + ATLASSERT(!m_bInitialized); + hResult = CComCriticalSection::Init(); + if (SUCCEEDED(hResult)) + m_bInitialized = true; + return hResult; + } + + HRESULT Term() + { + if (!m_bInitialized) + return S_OK; + m_bInitialized = false; + return CComCriticalSection::Term(); + } +}; + +class CComAutoDeleteCriticalSection : public CComSafeDeleteCriticalSection +{ +private: + // CComAutoDeleteCriticalSection::Term should never be called + HRESULT Term(); +}; + +struct _ATL_BASE_MODULE70 +{ + UINT cbSize; + HINSTANCE m_hInst; + HINSTANCE m_hInstResource; + bool m_bNT5orWin98; + DWORD dwAtlBuildVer; + GUID *pguidVer; + CRITICAL_SECTION m_csResource; +#ifdef NOTYET + CSimpleArray m_rgResourceInstance; +#endif +}; +typedef _ATL_BASE_MODULE70 _ATL_BASE_MODULE; + +class CAtlBaseModule : public _ATL_BASE_MODULE +{ +public : + static bool m_bInitFailed; +public: + CAtlBaseModule() + { + cbSize = sizeof(_ATL_BASE_MODULE); + GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)this, &m_hInst); + m_hInstResource = m_hInst; + } + + HINSTANCE GetModuleInstance() + { + return m_hInst; + } + + HINSTANCE GetResourceInstance() + { + return m_hInstResource; + } + + HINSTANCE SetResourceInstance(HINSTANCE hInst) + { + return static_cast< HINSTANCE >(InterlockedExchangePointer((void**)&m_hInstResource, hInst)); + } + + HINSTANCE GetHInstanceAt(int i); +}; + +__declspec(selectany) CAtlBaseModule _AtlBaseModule; +__declspec(selectany) bool CAtlBaseModule::m_bInitFailed = false; + + +/// +// String Resource helper functions +// +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) +#endif +struct ATLSTRINGRESOURCEIMAGE +{ + WORD nLength; + WCHAR achString[]; +}; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +inline const ATLSTRINGRESOURCEIMAGE* _AtlGetStringResourceImage( + _In_ HINSTANCE hInstance, + _In_ HRSRC hResource, + _In_ UINT id) +{ + const ATLSTRINGRESOURCEIMAGE* pImage; + const ATLSTRINGRESOURCEIMAGE* pImageEnd; + ULONG nResourceSize; + HGLOBAL hGlobal; + UINT iIndex; + + hGlobal = ::LoadResource(hInstance, hResource); + if (hGlobal == NULL) return NULL; + + pImage = (const ATLSTRINGRESOURCEIMAGE*)::LockResource(hGlobal); + if (pImage == NULL) return NULL; + + nResourceSize = ::SizeofResource(hInstance, hResource); + pImageEnd = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE(pImage) + nResourceSize); + iIndex = id & 0x000f; + + while ((iIndex > 0) && (pImage < pImageEnd)) + { + pImage = (const ATLSTRINGRESOURCEIMAGE*)(LPBYTE(pImage) + (sizeof(ATLSTRINGRESOURCEIMAGE) + (pImage->nLength * sizeof(WCHAR)))); + iIndex--; + } + + if (pImage >= pImageEnd) return NULL; + if (pImage->nLength == 0) return NULL; + + return pImage; +} + +inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( + _In_ HINSTANCE hInstance, + _In_ UINT id) throw() +{ + HRSRC hResource; + hResource = ::FindResourceW(hInstance, MAKEINTRESOURCEW((((id >> 4) + 1) & static_cast(~0))), (LPWSTR)RT_STRING); + if (hResource == NULL) return NULL; + return _AtlGetStringResourceImage(hInstance, hResource, id); +} + +inline const ATLSTRINGRESOURCEIMAGE* AtlGetStringResourceImage( + _In_ HINSTANCE hInstance, + _In_ UINT id, + _In_ WORD wLanguage) +{ + HRSRC hResource; + hResource = ::FindResourceExW(hInstance, (LPWSTR)RT_STRING, MAKEINTRESOURCEW((((id >> 4) + 1) & static_cast(~0))), wLanguage); + if (hResource == NULL) return NULL; + return _AtlGetStringResourceImage(hInstance, hResource, id); +} + +inline HINSTANCE AtlFindStringResourceInstance( + UINT nID, + WORD wLanguage = 0) +{ + const ATLSTRINGRESOURCEIMAGE* strRes = NULL; + HINSTANCE hInst = _AtlBaseModule.GetHInstanceAt(0); + + for (int i = 1; hInst != NULL && strRes == NULL; hInst = _AtlBaseModule.GetHInstanceAt(i++)) + { + strRes = AtlGetStringResourceImage(hInst, nID, wLanguage); + if (strRes != NULL) return hInst; + } + + return NULL; +} + +}; // namespace ATL diff --git a/src/3rd_party/reactos-atl/atl/atldef.h b/src/3rd_party/reactos-atl/atl/atldef.h new file mode 100644 index 00000000..a7898709 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atldef.h @@ -0,0 +1,63 @@ +/* +* PROJECT: ReactOS ATL +* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) +* PURPOSE: ATL Base definitions +* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) +*/ + +#pragma once + +#ifndef __REACTOS__ + #include + #include +#endif + +#define _ATL_PACKING 8 + + +#ifndef AtlThrow +#ifndef _ATL_CUSTOM_THROW +#define AtlThrow(x) ATL::AtlThrowImp(x) +#endif +#endif + + +#ifndef ATLASSERT +#define ATLASSERT(expr) _ASSERTE(expr) +#endif + + +// ATLASSUME, ATLENSURE, ATLVERIFY, ... + + + + + +#ifdef _ATL_DISABLE_NO_VTABLE +#define ATL_NO_VTABLE +#else +#define ATL_NO_VTABLE __declspec(novtable) +#endif + +#ifndef ATL_DEPRECATED +#define ATL_DEPRECATED __declspec(deprecated) +#endif + +// ATL_NOTHROW, ATL_FORCEINLINE, ATL_NOINLINE + +// _ATL, ATL_VER, ATL_FILENAME_VER, ATL_FILENAME_VERNUM, ... + + + +#define offsetofclass(base, derived) (reinterpret_cast(static_cast(reinterpret_cast(_ATL_PACKING))) - _ATL_PACKING) + + + +#ifndef _ATL_FREE_THREADED +#ifndef _ATL_APARTMENT_THREADED +#ifndef _ATL_SINGLE_THREADED +#define _ATL_FREE_THREADED +#endif +#endif +#endif + diff --git a/src/3rd_party/reactos-atl/atl/atlexcept.h b/src/3rd_party/reactos-atl/atl/atlexcept.h new file mode 100644 index 00000000..a71b4430 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlexcept.h @@ -0,0 +1,50 @@ + +#ifndef __ATLEXCEPT_H__ +#define __ATLEXCEPT_H__ + + +#ifdef _ATL_NO_EXCEPTIONS +#if !defined(STATUS_NO_MEMORY) && defined(WIN32_NO_STATUS) +#define STATUS_NO_MEMORY ((DWORD)0xC0000017) +#endif +#endif + +namespace ATL +{ + + +//FIXME: Enable when RaiseException is marked as NORETURN +//DECLSPEC_NORETURN +inline void AtlThrowImp(HRESULT hr) +{ +#ifdef ATLTRACE + ATLTRACE(hr); +#endif + +#ifdef _ATL_NO_EXCEPTIONS + + ATLASSERT(false); + + RaiseException( + hr == E_OUTOFMEMORY ? STATUS_NO_MEMORY : EXCEPTION_ILLEGAL_INSTRUCTION, + EXCEPTION_NONCONTINUABLE, 0, NULL + ); + +#else + + // FIXME: This is horribly wrong, we should implement CException! + throw; + +#endif + +} + + +#ifndef AtlThrow +#define AtlThrow(x) AtlThrowImp(x) +#endif + + +}; // namespace ATL + +#endif diff --git a/src/3rd_party/reactos-atl/atl/atlfile.h b/src/3rd_party/reactos-atl/atl/atlfile.h new file mode 100644 index 00000000..d204cce5 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlfile.h @@ -0,0 +1,281 @@ +/* +* PROJECT: ReactOS ATL +* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) +* PURPOSE: ATL File implementation +* COPYRIGHT: Copyright 2019 Mark Jansen (mark.jansen@reactos.org) +*/ + +#pragma once + +#include + +namespace ATL +{ + +//class CAtlFile: TODO +// public CHandle +//{ +//}; + + +//class CAtlTemporaryFile TODO +//{ +//}; + + + +class CAtlFileMappingBase +{ +private: + void* m_pData; + SIZE_T m_nMappingSize; + HANDLE m_hMapping; + ULARGE_INTEGER m_nOffset; + DWORD m_dwViewDesiredAccess; + +public: + CAtlFileMappingBase() throw() + :m_pData(NULL) + ,m_nMappingSize(0) + ,m_hMapping(NULL) + ,m_dwViewDesiredAccess(0) + { + m_nOffset.QuadPart = 0; + } + + ~CAtlFileMappingBase() throw() + { + Unmap(); + } + + CAtlFileMappingBase(CAtlFileMappingBase& orig) + { + HRESULT hr; + + m_pData = NULL; + m_nMappingSize = 0; + m_hMapping = NULL; + m_dwViewDesiredAccess = 0; + m_nOffset.QuadPart = 0; + + hr = CopyFrom(orig); + if (FAILED(hr)) + AtlThrow(hr); + } + + CAtlFileMappingBase& operator=(CAtlFileMappingBase& orig) + { + HRESULT hr; + + hr = CopyFrom(orig); + if (FAILED(hr)) + AtlThrow(hr); + + return *this; + } + + HRESULT CopyFrom(CAtlFileMappingBase& orig) throw() + { + HRESULT hr = S_OK; + + if (&orig == this) + return S_OK; + + ATLASSERT(m_pData == NULL); + ATLASSERT(m_hMapping == NULL); + ATLASSERT(orig.m_pData != NULL); + + m_nMappingSize = orig.m_nMappingSize; + m_nOffset.QuadPart = orig.m_nOffset.QuadPart; + m_dwViewDesiredAccess = orig.m_dwViewDesiredAccess; + + if (::DuplicateHandle(GetCurrentProcess(), orig.m_hMapping, GetCurrentProcess(), &m_hMapping, 0, TRUE, DUPLICATE_SAME_ACCESS)) + { + m_pData = ::MapViewOfFile(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize); + if (!m_pData) + { + hr = AtlHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + } + } + else + { + hr = AtlHresultFromLastError(); + } + + return hr; + } + + HRESULT MapFile( + HANDLE hFile, + SIZE_T nMappingSize = 0, + ULONGLONG nOffset = 0, + DWORD dwMappingProtection = PAGE_READONLY, + DWORD dwViewDesiredAccess = FILE_MAP_READ) throw() + { + HRESULT hr = S_OK; + ULARGE_INTEGER FileSize; + + ATLASSERT(hFile != INVALID_HANDLE_VALUE); + ATLASSERT(m_pData == NULL); + ATLASSERT(m_hMapping == NULL); + + FileSize.LowPart = ::GetFileSize(hFile, &FileSize.HighPart); + FileSize.QuadPart = nMappingSize > FileSize.QuadPart ? nMappingSize : FileSize.QuadPart; + + m_hMapping = ::CreateFileMapping(hFile, NULL, dwMappingProtection, FileSize.HighPart, FileSize.LowPart, 0); + if (m_hMapping) + { + m_nMappingSize = nMappingSize == 0 ? (SIZE_T)(FileSize.QuadPart - nOffset) : nMappingSize; + m_nOffset.QuadPart = nOffset; + m_dwViewDesiredAccess = dwViewDesiredAccess; + + m_pData = ::MapViewOfFile(m_hMapping, m_dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize); + if (!m_pData) + { + hr = AtlHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + } + } + else + { + hr = AtlHresultFromLastError(); + } + + return hr; + } + + HRESULT MapSharedMem( + SIZE_T nMappingSize, + LPCTSTR szName, + BOOL* pbAlreadyExisted = NULL, + LPSECURITY_ATTRIBUTES lpsa = NULL, + DWORD dwMappingProtection = PAGE_READWRITE, + DWORD dwViewDesiredAccess = FILE_MAP_ALL_ACCESS) throw() + { + HRESULT hr = S_OK; + ULARGE_INTEGER Size; + + ATLASSERT(nMappingSize > 0); + ATLASSERT(szName != NULL); + ATLASSERT(m_pData == NULL); + ATLASSERT(m_hMapping == NULL); + + m_nMappingSize = nMappingSize; + m_dwViewDesiredAccess = dwViewDesiredAccess; + m_nOffset.QuadPart = 0; + Size.QuadPart = nMappingSize; + + m_hMapping = ::CreateFileMapping(NULL, lpsa, dwMappingProtection, Size.HighPart, Size.LowPart, szName); + if (m_hMapping != NULL) + { + if (pbAlreadyExisted) + *pbAlreadyExisted = GetLastError() == ERROR_ALREADY_EXISTS; + + m_pData = ::MapViewOfFile(m_hMapping, dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize); + if (!m_pData) + { + hr = AtlHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + } + } + else + { + hr = AtlHresultFromLastError(); + } + + return hr; + } + + HRESULT OpenMapping( + LPCTSTR szName, + SIZE_T nMappingSize, + ULONGLONG nOffset = 0, + DWORD dwViewDesiredAccess = FILE_MAP_ALL_ACCESS) throw() + { + HRESULT hr = S_OK; + + ATLASSERT(szName != NULL); + ATLASSERT(m_pData == NULL); + ATLASSERT(m_hMapping == NULL); + + m_nMappingSize = nMappingSize; + m_dwViewDesiredAccess = dwViewDesiredAccess; + m_nOffset.QuadPart = nOffset; + + m_hMapping = ::OpenFileMapping(m_dwViewDesiredAccess, FALSE, szName); + if (m_hMapping) + { + m_pData = ::MapViewOfFile(m_hMapping, dwViewDesiredAccess, m_nOffset.HighPart, m_nOffset.LowPart, m_nMappingSize); + if (!m_pData) + { + hr = AtlHresultFromLastError(); + ::CloseHandle(m_hMapping); + m_hMapping = NULL; + } + } + else + { + hr = AtlHresultFromLastError(); + } + + return hr; + } + + HRESULT Unmap() throw() + { + HRESULT hr = S_OK; + + if (m_pData) + { + if (!::UnmapViewOfFile(m_pData)) + hr = AtlHresultFromLastError(); + + m_pData = NULL; + } + if (m_hMapping) + { + // If we already had an error, do not overwrite it + if (!::CloseHandle(m_hMapping) && SUCCEEDED(hr)) + hr = AtlHresultFromLastError(); + + m_hMapping = NULL; + } + + return hr; + } + + void* GetData() const throw() + { + return m_pData; + } + + HANDLE GetHandle() throw () + { + return m_hMapping; + } + + SIZE_T GetMappingSize() throw() + { + return m_nMappingSize; + } + +}; + + +template +class CAtlFileMapping: + public CAtlFileMappingBase +{ +public: + operator T*() const throw() + { + return reinterpret_cast(GetData()); + } +}; + + +} diff --git a/src/3rd_party/reactos-atl/atl/atlimage.h b/src/3rd_party/reactos-atl/atl/atlimage.h new file mode 100644 index 00000000..f124c9a1 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlimage.h @@ -0,0 +1,1219 @@ +// PROJECT: ReactOS ATL CImage +// LICENSE: Public Domain +// PURPOSE: Provides compatibility to Microsoft ATL +// PROGRAMMERS: Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + +#ifndef __ATLIMAGE_H__ +#define __ATLIMAGE_H__ + +// !!!! +// TODO: The backend (gdi+) that this class relies on is not yet complete! +// Before that is finished, this class will not be a perfect replacement. +// See rostest/apitests/atl/CImage_WIP.txt for test results. +// !!!! + +// TODO: CImage::Load, CImage::Save +// TODO: make CImage thread-safe + +#pragma once + +#include // for ATL Core +#include // for CAtlStringMgr +#include // for CSimpleString +#include // for CSimpleArray + +#include +#include // for GUID_NULL +#include // GDI+ + +namespace ATL +{ + +class CImage +{ +public: + // flags for CImage::Create/CreateEx + enum + { + createAlphaChannel = 1 // enable alpha + }; + + // orientation of DIB + enum DIBOrientation + { + DIBOR_DEFAULT, // default + DIBOR_BOTTOMUP, // bottom-up DIB + DIBOR_TOPDOWN // top-down DIB + }; + + CImage() throw() + { + m_hbm = NULL; + m_hbmOld = NULL; + m_hDC = NULL; + + m_eOrientation = DIBOR_DEFAULT; + m_bHasAlphaCh = false; + m_bIsDIBSec = false; + m_rgbTransColor = CLR_INVALID; + ZeroMemory(&m_ds, sizeof(m_ds)); + + if (GetCommon().AddRef() == 1) + { + GetCommon().LoadLib(); + } + } + + ~CImage() + { + Destroy(); + ReleaseGDIPlus(); + } + + operator HBITMAP() + { + return m_hbm; + } + +public: + void Attach(HBITMAP hBitmap, DIBOrientation eOrientation = DIBOR_DEFAULT) + { + AttachInternal(hBitmap, eOrientation, -1); + } + + HBITMAP Detach() throw() + { + m_eOrientation = DIBOR_DEFAULT; + m_bHasAlphaCh = false; + m_rgbTransColor = CLR_INVALID; + ZeroMemory(&m_ds, sizeof(m_ds)); + + HBITMAP hBitmap = m_hbm; + m_hbm = NULL; + return hBitmap; + } + + HDC GetDC() const throw() + { + if (m_hDC) + return m_hDC; + + m_hDC = ::CreateCompatibleDC(NULL); + m_hbmOld = ::SelectObject(m_hDC, m_hbm); + return m_hDC; + } + + void ReleaseDC() const throw() + { + ATLASSERT(m_hDC); + + if (m_hDC == NULL) + return; + + if (m_hbmOld) + { + ::SelectObject(m_hDC, m_hbmOld); + m_hbmOld = NULL; + } + ::DeleteDC(m_hDC); + m_hDC = NULL; + } + +public: + BOOL AlphaBlend(HDC hDestDC, + int xDest, int yDest, int nDestWidth, int nDestHeight, + int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, + BYTE bSrcAlpha = 0xFF, BYTE bBlendOp = AC_SRC_OVER) const + { + ATLASSERT(IsTransparencySupported()); + + BLENDFUNCTION bf; + bf.BlendOp = bBlendOp; + bf.BlendFlags = 0; + bf.SourceConstantAlpha = bSrcAlpha; + bf.AlphaFormat = AC_SRC_ALPHA; + + GetDC(); + BOOL ret = ::AlphaBlend(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + m_hDC, xSrc, ySrc, nSrcWidth, nSrcHeight, bf); + ReleaseDC(); + return ret; + } + BOOL AlphaBlend(HDC hDestDC, int xDest, int yDest, + BYTE bSrcAlpha = 0xFF, BYTE bBlendOp = AC_SRC_OVER) const + { + int width = GetWidth(); + int height = GetHeight(); + return AlphaBlend(hDestDC, xDest, yDest, width, height, 0, 0, + width, height, bSrcAlpha, bBlendOp); + } + BOOL AlphaBlend(HDC hDestDC, const POINT& pointDest, + BYTE bSrcAlpha = 0xFF, BYTE bBlendOp = AC_SRC_OVER) const + { + return AlphaBlend(hDestDC, pointDest.x, pointDest.y, bSrcAlpha, bBlendOp); + } + BOOL AlphaBlend(HDC hDestDC, const RECT& rectDest, const RECT& rectSrc, + BYTE bSrcAlpha = 0xFF, BYTE bBlendOp = AC_SRC_OVER) const + { + return AlphaBlend(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top, + rectSrc.left, rectSrc.top, + rectSrc.right - rectSrc.left, + rectSrc.bottom - rectSrc.top, + bSrcAlpha, bBlendOp); + } + + BOOL BitBlt(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight, + int xSrc, int ySrc, DWORD dwROP = SRCCOPY) const throw() + { + GetDC(); + BOOL ret = ::BitBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + m_hDC, xSrc, ySrc, dwROP); + ReleaseDC(); + return ret; + } + BOOL BitBlt(HDC hDestDC, int xDest, int yDest, + DWORD dwROP = SRCCOPY) const throw() + { + return BitBlt(hDestDC, xDest, yDest, + GetWidth(), GetHeight(), 0, 0, dwROP); + } + BOOL BitBlt(HDC hDestDC, const POINT& pointDest, + DWORD dwROP = SRCCOPY) const throw() + { + return BitBlt(hDestDC, pointDest.x, pointDest.y, dwROP); + } + BOOL BitBlt(HDC hDestDC, const RECT& rectDest, const POINT& pointSrc, + DWORD dwROP = SRCCOPY) const throw() + { + return BitBlt(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top, + pointSrc.x, pointSrc.y, dwROP); + } + + BOOL Create(int nWidth, int nHeight, int nBPP, DWORD dwFlags = 0) throw() + { + return CreateEx(nWidth, nHeight, nBPP, BI_RGB, NULL, dwFlags); + } + + BOOL CreateEx(int nWidth, int nHeight, int nBPP, DWORD eCompression, + const DWORD* pdwBitmasks = NULL, DWORD dwFlags = 0) throw() + { + return CreateInternal(nWidth, nHeight, nBPP, eCompression, pdwBitmasks, dwFlags); + } + + void Destroy() throw() + { + if (m_hbm) + { + ::DeleteObject(Detach()); + } + } + + BOOL Draw(HDC hDestDC, int xDest, int yDest, int nDestWidth, int nDestHeight, + int xSrc, int ySrc, int nSrcWidth, int nSrcHeight) const throw() + { + ATLASSERT(IsTransparencySupported()); + if (m_bHasAlphaCh) + { + return AlphaBlend(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + xSrc, ySrc, nSrcWidth, nSrcHeight); + } + else if (m_rgbTransColor != CLR_INVALID) + { + COLORREF rgb; + if ((m_rgbTransColor & 0xFF000000) == 0x01000000) + rgb = RGBFromPaletteIndex(m_rgbTransColor & 0xFF); + else + rgb = m_rgbTransColor; + return TransparentBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + xSrc, ySrc, nSrcWidth, nSrcHeight, rgb); + } + else + { + return StretchBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + xSrc, ySrc, nSrcWidth, nSrcHeight); + } + } + BOOL Draw(HDC hDestDC, const RECT& rectDest, const RECT& rectSrc) const throw() + { + return Draw(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top, + rectSrc.left, rectSrc.top, + rectSrc.right - rectSrc.left, + rectSrc.bottom - rectSrc.top); + } + BOOL Draw(HDC hDestDC, int xDest, int yDest) const throw() + { + return Draw(hDestDC, xDest, yDest, GetWidth(), GetHeight()); + } + BOOL Draw(HDC hDestDC, const POINT& pointDest) const throw() + { + return Draw(hDestDC, pointDest.x, pointDest.y); + } + BOOL Draw(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight) const throw() + { + return Draw(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + 0, 0, GetWidth(), GetHeight()); + } + BOOL Draw(HDC hDestDC, const RECT& rectDest) const throw() + { + return Draw(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top); + } + + void *GetBits() throw() + { + ATLASSERT(IsDIBSection()); + BYTE *pb = (BYTE *)m_bm.bmBits; + if (m_eOrientation == DIBOR_BOTTOMUP) + { + pb += m_bm.bmWidthBytes * (m_bm.bmHeight - 1); + } + return pb; + } + + int GetBPP() const throw() + { + ATLASSERT(m_hbm); + return m_bm.bmBitsPixel; + } + + void GetColorTable(UINT iFirstColor, UINT nColors, + RGBQUAD* prgbColors) const throw() + { + ATLASSERT(IsDIBSection()); + GetDC(); + ::GetDIBColorTable(m_hDC, iFirstColor, nColors, prgbColors); + ReleaseDC(); + } + + int GetHeight() const throw() + { + ATLASSERT(m_hbm); + return m_bm.bmHeight; + } + + int GetMaxColorTableEntries() const throw() + { + ATLASSERT(IsDIBSection()); + if (m_ds.dsBmih.biClrUsed && m_ds.dsBmih.biBitCount < 16) + return m_ds.dsBmih.biClrUsed; + switch (m_bm.bmBitsPixel) + { + case 1: return 2; + case 4: return 16; + case 8: return 256; + case 16: case 32: + if (m_ds.dsBmih.biCompression == BI_BITFIELDS) + return 3; + return 0; + case 24: + default: + return 0; + } + } + + int GetPitch() const throw() + { + ATLASSERT(IsDIBSection()); + if (m_eOrientation == DIBOR_BOTTOMUP) + return -m_bm.bmWidthBytes; + else + return m_bm.bmWidthBytes; + } + + COLORREF GetPixel(int x, int y) const throw() + { + GetDC(); + COLORREF ret = ::GetPixel(m_hDC, x, y); + ReleaseDC(); + return ret; + } + + void* GetPixelAddress(int x, int y) throw() + { + ATLASSERT(IsDIBSection()); + BYTE *pb = (BYTE *)GetBits(); + pb += GetPitch() * y; + pb += (GetBPP() * x) / 8; + return pb; + } + + COLORREF GetTransparentColor() const throw() + { + return m_rgbTransColor; + } + + int GetWidth() const throw() + { + ATLASSERT(m_hbm); + return m_bm.bmWidth; + } + + bool IsDIBSection() const throw() + { + ATLASSERT(m_hbm); + return m_bIsDIBSec; + } + + bool IsIndexed() const throw() + { + ATLASSERT(IsDIBSection()); + return GetBPP() <= 8; + } + + bool IsNull() const throw() + { + return m_hbm == NULL; + } + + HRESULT Load(LPCTSTR pszFileName) throw() + { + // convert the file name string into Unicode + CStringW pszNameW(pszFileName); + + // create a GpBitmap object from file + using namespace Gdiplus; + GpBitmap *pBitmap = NULL; + GetCommon().CreateBitmapFromFile(pszNameW, &pBitmap); + ATLASSERT(pBitmap); + + // TODO & FIXME: get parameters (m_rgbTransColor etc.) + + // get bitmap handle + HBITMAP hbm = NULL; + Color color(0xFF, 0xFF, 0xFF); + Gdiplus::Status status; + status = GetCommon().CreateHBITMAPFromBitmap( + pBitmap, &hbm, color.GetValue()); + + // delete GpBitmap + GetCommon().DisposeImage(pBitmap); + + // attach it + if (status == Ok) + Attach(hbm); + return (status == Ok ? S_OK : E_FAIL); + } + HRESULT Load(IStream* pStream) throw() + { + // create GpBitmap from stream + using namespace Gdiplus; + GpBitmap *pBitmap = NULL; + GetCommon().CreateBitmapFromStream(pStream, &pBitmap); + ATLASSERT(pBitmap); + + // TODO & FIXME: get parameters (m_rgbTransColor etc.) + + // get bitmap handle + HBITMAP hbm = NULL; + Color color(0xFF, 0xFF, 0xFF); + Gdiplus::Status status; + status = GetCommon().CreateHBITMAPFromBitmap( + pBitmap, &hbm, color.GetValue()); + + // delete Bitmap + GetCommon().DisposeImage(pBitmap); + + // attach it + if (status == Ok) + Attach(hbm); + return (status == Ok ? S_OK : E_FAIL); + } + + // NOTE: LoadFromResource loads BITMAP resource only + void LoadFromResource(HINSTANCE hInstance, LPCTSTR pszResourceName) throw() + { + HANDLE hHandle = ::LoadImage(hInstance, pszResourceName, + IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION); + Attach(reinterpret_cast(hHandle)); + } + void LoadFromResource(HINSTANCE hInstance, UINT nIDResource) throw() + { + LoadFromResource(hInstance, MAKEINTRESOURCE(nIDResource)); + } + + BOOL MaskBlt(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight, int xSrc, int ySrc, + HBITMAP hbmMask, int xMask, int yMask, + DWORD dwROP = SRCCOPY) const throw() + { + ATLASSERT(IsTransparencySupported()); + GetDC(); + BOOL ret = ::MaskBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + m_hDC, xSrc, ySrc, + hbmMask, xMask, yMask, dwROP); + ReleaseDC(); + return ret; + } + BOOL MaskBlt(HDC hDestDC, const RECT& rectDest, const POINT& pointSrc, + HBITMAP hbmMask, const POINT& pointMask, + DWORD dwROP = SRCCOPY) const throw() + { + return MaskBlt(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, rectDest.bottom - rectDest.top, + pointSrc.x, pointSrc.y, hbmMask, pointMask.x, pointMask.y, dwROP); + } + BOOL MaskBlt(HDC hDestDC, int xDest, int yDest, + HBITMAP hbmMask, DWORD dwROP = SRCCOPY) const throw() + { + return MaskBlt(hDestDC, xDest, yDest, GetWidth(), GetHeight(), + 0, 0, hbmMask, 0, 0, dwROP); + } + BOOL MaskBlt(HDC hDestDC, const POINT& pointDest, + HBITMAP hbmMask, DWORD dwROP = SRCCOPY) const throw() + { + return MaskBlt(hDestDC, pointDest.x, pointDest.y, hbmMask, dwROP); + } + + BOOL PlgBlt(HDC hDestDC, const POINT* pPoints, + int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, + HBITMAP hbmMask = NULL, + int xMask = 0, int yMask = 0) const throw() + { + ATLASSERT(IsTransparencySupported()); + GetDC(); + BOOL ret = ::PlgBlt(hDestDC, pPoints, m_hDC, + xSrc, ySrc, nSrcWidth, nSrcHeight, + hbmMask, xMask, yMask); + ReleaseDC(); + return ret; + } + BOOL PlgBlt(HDC hDestDC, const POINT* pPoints, + HBITMAP hbmMask = NULL) const throw() + { + return PlgBlt(hDestDC, pPoints, 0, 0, GetWidth(), GetHeight(), + hbmMask); + } + BOOL PlgBlt(HDC hDestDC, const POINT* pPoints, const RECT& rectSrc, + HBITMAP hbmMask, const POINT& pointMask) const throw() + { + return PlgBlt(hDestDC, pPoints, rectSrc.left, rectSrc.top, + rectSrc.right - rectSrc.left, rectSrc.bottom - rectSrc.top, + hbmMask, pointMask.x, pointMask.y); + } + BOOL PlgBlt(HDC hDestDC, const POINT* pPoints, const RECT& rectSrc, + HBITMAP hbmMask = NULL) const throw() + { + POINT pointMask = {0, 0}; + return PlgBlt(hDestDC, pPoints, rectSrc, hbmMask, pointMask); + } + + void ReleaseGDIPlus() throw() + { + COMMON*& pCommon = GetCommonPtr(); + if (pCommon && pCommon->Release() == 0) + { + delete pCommon; + pCommon = NULL; + } + } + + HRESULT Save(IStream* pStream, GUID *guidFileType) const throw() + { + using namespace Gdiplus; + ATLASSERT(m_hbm); + + // TODO & FIXME: set parameters (m_rgbTransColor etc.) + CLSID clsid; + if (!GetClsidFromFileType(&clsid, guidFileType)) + return E_FAIL; + + // create a GpBitmap from HBITMAP + GpBitmap *pBitmap = NULL; + GetCommon().CreateBitmapFromHBITMAP(m_hbm, NULL, &pBitmap); + + // save to stream + Status status; + status = GetCommon().SaveImageToStream(pBitmap, pStream, &clsid, NULL); + + // destroy GpBitmap + GetCommon().DisposeImage(pBitmap); + + return (status == Ok ? S_OK : E_FAIL); + } + HRESULT Save(LPCTSTR pszFileName, + REFGUID guidFileType = GUID_NULL) const throw() + { + using namespace Gdiplus; + ATLASSERT(m_hbm); + + // TODO & FIXME: set parameters (m_rgbTransColor etc.) + + // convert the file name string into Unicode + CStringW pszNameW(pszFileName); + + // if the file type is null, get the file type from extension + const GUID *FileType = &guidFileType; + if (IsGuidEqual(guidFileType, GUID_NULL)) + { + LPCWSTR pszExt = GetFileExtension(pszNameW); + FileType = FileTypeFromExtension(pszExt); + } + + // get CLSID from file type + CLSID clsid; + if (!GetClsidFromFileType(&clsid, FileType)) + return E_FAIL; + + // create a GpBitmap from HBITMAP + GpBitmap *pBitmap = NULL; + GetCommon().CreateBitmapFromHBITMAP(m_hbm, NULL, &pBitmap); + + // save to file + Status status; + status = GetCommon().SaveImageToFile(pBitmap, pszNameW, &clsid, NULL); + + // destroy GpBitmap + GetCommon().DisposeImage(pBitmap); + + return (status == Ok ? S_OK : E_FAIL); + } + + void SetColorTable(UINT iFirstColor, UINT nColors, + const RGBQUAD* prgbColors) throw() + { + ATLASSERT(IsDIBSection()); + GetDC(); + ::SetDIBColorTable(m_hDC, iFirstColor, nColors, prgbColors); + ReleaseDC(); + } + + void SetPixel(int x, int y, COLORREF color) throw() + { + GetDC(); + ::SetPixelV(m_hDC, x, y, color); + ReleaseDC(); + } + + void SetPixelIndexed(int x, int y, int iIndex) throw() + { + ATLASSERT(IsIndexed()); + GetDC(); + ::SetPixelV(m_hDC, x, y, PALETTEINDEX(iIndex)); + ReleaseDC(); + } + + void SetPixelRGB(int x, int y, BYTE r, BYTE g, BYTE b) throw() + { + SetPixel(x, y, RGB(r, g, b)); + } + + COLORREF SetTransparentColor(COLORREF rgbTransparent) throw() + { + ATLASSERT(m_hbm); + COLORREF rgbOldColor = m_rgbTransColor; + m_rgbTransColor = rgbTransparent; + return rgbOldColor; + } + + BOOL StretchBlt(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight, + int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, + DWORD dwROP = SRCCOPY) const throw() + { + GetDC(); + BOOL ret = ::StretchBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + m_hDC, xSrc, ySrc, nSrcWidth, nSrcHeight, dwROP); + ReleaseDC(); + return ret; + } + BOOL StretchBlt(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight, + DWORD dwROP = SRCCOPY) const throw() + { + return StretchBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + 0, 0, GetWidth(), GetHeight(), dwROP); + } + BOOL StretchBlt(HDC hDestDC, const RECT& rectDest, + DWORD dwROP = SRCCOPY) const throw() + { + return StretchBlt(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top, dwROP); + } + BOOL StretchBlt(HDC hDestDC, const RECT& rectDest, + const RECT& rectSrc, DWORD dwROP = SRCCOPY) const throw() + { + return StretchBlt(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top, + rectSrc.left, rectSrc.top, + rectSrc.right - rectSrc.left, + rectSrc.bottom - rectSrc.top, dwROP); + } + + BOOL TransparentBlt(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight, + int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, + UINT crTransparent = CLR_INVALID) const throw() + { + ATLASSERT(IsTransparencySupported()); + GetDC(); + BOOL ret = ::TransparentBlt(hDestDC, xDest, yDest, + nDestWidth, nDestHeight, + m_hDC, xSrc, ySrc, + nSrcWidth, nSrcHeight, crTransparent); + ReleaseDC(); + return ret; + } + BOOL TransparentBlt(HDC hDestDC, int xDest, int yDest, + int nDestWidth, int nDestHeight, + UINT crTransparent = CLR_INVALID) const throw() + { + return TransparentBlt(hDestDC, xDest, yDest, nDestWidth, nDestHeight, + 0, 0, GetWidth(), GetHeight(), crTransparent); + } + BOOL TransparentBlt(HDC hDestDC, const RECT& rectDest, + UINT crTransparent = CLR_INVALID) const throw() + { + return TransparentBlt(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, + rectDest.bottom - rectDest.top, crTransparent); + } + BOOL TransparentBlt( + HDC hDestDC, const RECT& rectDest, + const RECT& rectSrc, UINT crTransparent = CLR_INVALID) const throw() + { + return TransparentBlt(hDestDC, rectDest.left, rectDest.top, + rectDest.right - rectDest.left, rectDest.bottom - rectDest.left, + rectSrc.left, rectSrc.top, rectSrc.right - rectSrc.left, + rectSrc.bottom - rectSrc.top, crTransparent); + } + +public: + static BOOL IsTransparencySupported() throw() + { + return TRUE; + } + + enum ExcludeFlags + { + excludeGIF = 0x01, + excludeBMP = 0x02, + excludeEMF = 0x04, + excludeWMF = 0x08, + excludeJPEG = 0x10, + excludePNG = 0x20, + excludeTIFF = 0x40, + excludeIcon = 0x80, + excludeOther = 0x80000000, + excludeDefaultLoad = 0, + excludeDefaultSave = excludeIcon | excludeEMF | excludeWMF + }; + + struct FILTER_DATA { + DWORD dwExclude; + const TCHAR *title; + const TCHAR *extensions; + const GUID *guid; + }; + +protected: + static HRESULT GetCommonFilterString( + CSimpleString& strFilter, + CSimpleArray& aguidFileTypes, + LPCTSTR pszAllFilesDescription, + DWORD dwExclude, + TCHAR chSeparator) + { + static const FILTER_DATA table[] = + { + {excludeBMP, TEXT("BMP"), TEXT("*.BMP;*.DIB;*.RLE"), &Gdiplus::ImageFormatBMP}, + {excludeJPEG, TEXT("JPEG"), TEXT("*.JPG;*.JPEG;*.JPE;*.JFIF"), &Gdiplus::ImageFormatJPEG}, + {excludeGIF, TEXT("GIF"), TEXT("*.GIF"), &Gdiplus::ImageFormatGIF}, + {excludeEMF, TEXT("EMF"), TEXT("*.EMF"), &Gdiplus::ImageFormatEMF}, + {excludeWMF, TEXT("WMF"), TEXT("*.WMF"), &Gdiplus::ImageFormatWMF}, + {excludeTIFF, TEXT("TIFF"), TEXT("*.TIF;*.TIFF"), &Gdiplus::ImageFormatTIFF}, + {excludePNG, TEXT("PNG"), TEXT("*.PNG"), &Gdiplus::ImageFormatPNG}, + {excludeIcon, TEXT("ICO"), TEXT("*.ICO"), &Gdiplus::ImageFormatIcon} + }; + + if (pszAllFilesDescription) + { + strFilter += pszAllFilesDescription; + strFilter += chSeparator; + + BOOL bFirst = TRUE; + for (size_t i = 0; i < _countof(table); ++i) + { + if ((dwExclude & table[i].dwExclude) != 0) + continue; + + if (bFirst) + bFirst = FALSE; + else + strFilter += TEXT(';'); + + strFilter += table[i].extensions; + } + strFilter += chSeparator; + + aguidFileTypes.Add(GUID_NULL); + } + + for (size_t i = 0; i < _countof(table); ++i) + { + if ((dwExclude & table[i].dwExclude) != 0) + continue; + strFilter += table[i].title; + strFilter += TEXT(" ("); + strFilter += table[i].extensions; + strFilter += TEXT(")"); + strFilter += chSeparator; + strFilter += table[i].extensions; + strFilter += chSeparator; + + aguidFileTypes.Add(*table[i].guid); + } + + strFilter += chSeparator; + + return S_OK; + } + +public: + static HRESULT GetImporterFilterString( + CSimpleString& strImporters, + CSimpleArray& aguidFileTypes, + LPCTSTR pszAllFilesDescription = NULL, + DWORD dwExclude = excludeDefaultLoad, + TCHAR chSeparator = TEXT('|')) + { + return GetCommonFilterString(strImporters, + aguidFileTypes, + pszAllFilesDescription, + dwExclude, + chSeparator); + } + + static HRESULT GetExporterFilterString( + CSimpleString& strExporters, + CSimpleArray& aguidFileTypes, + LPCTSTR pszAllFilesDescription = NULL, + DWORD dwExclude = excludeDefaultSave, + TCHAR chSeparator = TEXT('|')) + { + return GetCommonFilterString(strExporters, + aguidFileTypes, + pszAllFilesDescription, + dwExclude, + chSeparator); + } + +protected: + // an extension of BITMAPINFO + struct MYBITMAPINFOEX + { + BITMAPINFOHEADER bmiHeader; + RGBQUAD bmiColors[256]; + BITMAPINFO *get() + { + return reinterpret_cast(this); + } + const BITMAPINFO *get() const + { + return reinterpret_cast(this); + } + }; + + // The common data of atlimage + struct COMMON + { + // abbreviations of GDI+ basic types + typedef Gdiplus::GpStatus St; + typedef Gdiplus::ImageCodecInfo ICI; + typedef Gdiplus::GpBitmap Bm; + typedef Gdiplus::EncoderParameters EncParams; + typedef Gdiplus::GpImage Im; + typedef Gdiplus::ARGB ARGB; + typedef HBITMAP HBM; + typedef Gdiplus::GdiplusStartupInput GSI; + typedef Gdiplus::GdiplusStartupOutput GSO; + + // GDI+ function types +#undef API +#undef CST +#define API WINGDIPAPI +#define CST GDIPCONST + typedef St (WINAPI *STARTUP)(ULONG_PTR *, const GSI *, GSO *); + typedef void (WINAPI *SHUTDOWN)(ULONG_PTR); + typedef St (API *GETIMAGEENCODERSSIZE)(UINT *, UINT *); + typedef St (API *GETIMAGEENCODERS)(UINT, UINT, ICI *); + typedef St (API *CREATEBITMAPFROMFILE)(CST WCHAR*, Bm **); + typedef St (API *CREATEHBITMAPFROMBITMAP)(Bm *, HBM *, ARGB); + typedef St (API *CREATEBITMAPFROMSTREAM)(IStream *, Bm **); + typedef St (API *CREATEBITMAPFROMHBITMAP)(HBM, HPALETTE, Bm **); + typedef St (API *SAVEIMAGETOSTREAM)(Im *, IStream *, CST CLSID *, + CST EncParams *); + typedef St (API *SAVEIMAGETOFILE)(Im *, CST WCHAR *, CST CLSID *, + CST EncParams *); + typedef St (API *DISPOSEIMAGE)(Im*); +#undef API +#undef CST + + // members + int count; + HINSTANCE hinstGdiPlus; + ULONG_PTR gdiplusToken; + + // GDI+ functions + STARTUP Startup; + SHUTDOWN Shutdown; + GETIMAGEENCODERSSIZE GetImageEncodersSize; + GETIMAGEENCODERS GetImageEncoders; + CREATEBITMAPFROMFILE CreateBitmapFromFile; + CREATEHBITMAPFROMBITMAP CreateHBITMAPFromBitmap; + CREATEBITMAPFROMSTREAM CreateBitmapFromStream; + CREATEBITMAPFROMHBITMAP CreateBitmapFromHBITMAP; + SAVEIMAGETOSTREAM SaveImageToStream; + SAVEIMAGETOFILE SaveImageToFile; + DISPOSEIMAGE DisposeImage; + + COMMON() + { + count = 0; + hinstGdiPlus = NULL; + Startup = NULL; + Shutdown = NULL; + GetImageEncodersSize = NULL; + GetImageEncoders = NULL; + CreateBitmapFromFile = NULL; + CreateHBITMAPFromBitmap = NULL; + CreateBitmapFromStream = NULL; + CreateBitmapFromHBITMAP = NULL; + SaveImageToStream = NULL; + SaveImageToFile = NULL; + DisposeImage = NULL; + } + ~COMMON() + { + FreeLib(); + } + + ULONG AddRef() + { + return ++count; + } + ULONG Release() + { + return --count; + } + + // get procedure address of the DLL + template + TYPE AddrOf(const char *name) + { + FARPROC proc = ::GetProcAddress(hinstGdiPlus, name); + return reinterpret_cast(proc); + } + + HINSTANCE LoadLib() + { + if (hinstGdiPlus) + return hinstGdiPlus; + + hinstGdiPlus = ::LoadLibraryA("gdiplus.dll"); + + // get procedure addresses from the DLL + Startup = AddrOf("GdiplusStartup"); + Shutdown = AddrOf("GdiplusShutdown"); + GetImageEncodersSize = + AddrOf("GdipGetImageEncodersSize"); + GetImageEncoders = AddrOf("GdipGetImageEncoders"); + CreateBitmapFromFile = + AddrOf("GdipCreateBitmapFromFile"); + CreateHBITMAPFromBitmap = + AddrOf("GdipCreateHBITMAPFromBitmap"); + CreateBitmapFromStream = + AddrOf("GdipCreateBitmapFromStream"); + CreateBitmapFromHBITMAP = + AddrOf("GdipCreateBitmapFromHBITMAP"); + SaveImageToStream = + AddrOf("GdipSaveImageToStream"); + SaveImageToFile = AddrOf("GdipSaveImageToFile"); + DisposeImage = AddrOf("GdipDisposeImage"); + + if (hinstGdiPlus && Startup) + { + Gdiplus::GdiplusStartupInput gdiplusStartupInput; + Startup(&gdiplusToken, &gdiplusStartupInput, NULL); + } + + return hinstGdiPlus; + } + void FreeLib() + { + if (hinstGdiPlus) + { + Shutdown(gdiplusToken); + + Startup = NULL; + Shutdown = NULL; + GetImageEncodersSize = NULL; + GetImageEncoders = NULL; + CreateBitmapFromFile = NULL; + CreateHBITMAPFromBitmap = NULL; + CreateBitmapFromStream = NULL; + CreateBitmapFromHBITMAP = NULL; + SaveImageToStream = NULL; + SaveImageToFile = NULL; + DisposeImage = NULL; + ::FreeLibrary(hinstGdiPlus); + hinstGdiPlus = NULL; + } + } + }; // struct COMMON + + static COMMON*& GetCommonPtr() + { + static COMMON *s_pCommon = NULL; + return s_pCommon; + } + + static COMMON& GetCommon() + { + COMMON*& pCommon = GetCommonPtr(); + if (pCommon == NULL) + pCommon = new COMMON; + return *pCommon; + } + +protected: + HBITMAP m_hbm; + mutable HGDIOBJ m_hbmOld; + mutable HDC m_hDC; + DIBOrientation m_eOrientation; + bool m_bHasAlphaCh; + bool m_bIsDIBSec; + COLORREF m_rgbTransColor; + union + { + BITMAP m_bm; + DIBSECTION m_ds; + }; + + LPCWSTR GetFileExtension(LPCWSTR pszFileName) const + { + LPCWSTR pch = wcsrchr(pszFileName, L'\\'); + if (pch == NULL) + pch = wcsrchr(pszFileName, L'/'); + pch = (pch ? wcsrchr(pch, L'.') : wcsrchr(pszFileName, L'.')); + return (pch ? pch : (pszFileName + ::lstrlenW(pszFileName))); + } + + COLORREF RGBFromPaletteIndex(int iIndex) const + { + RGBQUAD table[256]; + GetColorTable(0, 256, table); + RGBQUAD& quad = table[iIndex]; + return RGB(quad.rgbRed, quad.rgbGreen, quad.rgbBlue); + } + + struct EXTENSION_ENTRY + { + LPCWSTR pszExt; + GUID guid; + }; + + const GUID *FileTypeFromExtension(LPCWSTR pszExt) const + { + static const EXTENSION_ENTRY table[] = + { + {L".jpg", Gdiplus::ImageFormatJPEG}, + {L".png", Gdiplus::ImageFormatPNG}, + {L".bmp", Gdiplus::ImageFormatBMP}, + {L".gif", Gdiplus::ImageFormatGIF}, + {L".tif", Gdiplus::ImageFormatTIFF}, + {L".jpeg", Gdiplus::ImageFormatJPEG}, + {L".jpe", Gdiplus::ImageFormatJPEG}, + {L".jfif", Gdiplus::ImageFormatJPEG}, + {L".dib", Gdiplus::ImageFormatBMP}, + {L".rle", Gdiplus::ImageFormatBMP}, + {L".tiff", Gdiplus::ImageFormatTIFF} + }; + const size_t count = _countof(table); + for (size_t i = 0; i < count; ++i) + { + if (::lstrcmpiW(table[i].pszExt, pszExt) == 0) + return &table[i].guid; + } + return NULL; + } + + struct FORMAT_ENTRY + { + GUID guid; + LPCWSTR mime; + }; + + bool GetClsidFromFileType(CLSID *clsid, const GUID *guid) const + { + static const FORMAT_ENTRY table[] = + { + {Gdiplus::ImageFormatJPEG, L"image/jpeg"}, + {Gdiplus::ImageFormatPNG, L"image/png"}, + {Gdiplus::ImageFormatBMP, L"image/bmp"}, + {Gdiplus::ImageFormatGIF, L"image/gif"}, + {Gdiplus::ImageFormatTIFF, L"image/tiff"} + }; + const size_t count = _countof(table); + for (size_t i = 0; i < count; ++i) + { + if (IsGuidEqual(table[i].guid, *guid)) + { + int num = GetEncoderClsid(table[i].mime, clsid); + if (num >= 0) + { + return true; + } + } + } + return false; + } + + int GetEncoderClsid(LPCWSTR mime, CLSID *clsid) const + { + UINT count = 0, total_size = 0; + GetCommon().GetImageEncodersSize(&count, &total_size); + if (total_size == 0) + return -1; // failure + + Gdiplus::ImageCodecInfo *pInfo; + BYTE *pb = new BYTE[total_size]; + ATLASSERT(pb); + pInfo = reinterpret_cast(pb); + if (pInfo == NULL) + return -1; // failure + + GetCommon().GetImageEncoders(count, total_size, pInfo); + + for (UINT iInfo = 0; iInfo < count; ++iInfo) + { + if (::lstrcmpiW(pInfo[iInfo].MimeType, mime) == 0) + { + *clsid = pInfo[iInfo].Clsid; + delete[] pb; + return iInfo; // success + } + } + + delete[] pb; + return -1; // failure + } + + bool IsGuidEqual(const GUID& guid1, const GUID& guid2) const + { + RPC_STATUS status; + if (::UuidEqual(const_cast(&guid1), + const_cast(&guid2), &status)) + { + if (status == RPC_S_OK) + return true; + } + return false; + } + + void AttachInternal(HBITMAP hBitmap, DIBOrientation eOrientation, + LONG iTransColor) + { + Destroy(); + + const int size = sizeof(DIBSECTION); + m_bIsDIBSec = (::GetObject(hBitmap, size, &m_ds) == size); + + bool bOK = (::GetObject(hBitmap, sizeof(BITMAP), &m_bm) != 0); + + if (bOK) + { + m_hbm = hBitmap; + m_eOrientation = eOrientation; + m_bHasAlphaCh = (m_bm.bmBitsPixel == 32); + m_rgbTransColor = CLR_INVALID; + } + } + + BOOL CreateInternal(int nWidth, int nHeight, int nBPP, + DWORD eCompression, const DWORD* pdwBitmasks = NULL, + DWORD dwFlags = 0) throw() + { + ATLASSERT(nWidth != 0); + ATLASSERT(nHeight != 0); + + // initialize BITMAPINFO extension + MYBITMAPINFOEX bi; + ZeroMemory(&bi, sizeof(bi)); + bi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bi.bmiHeader.biWidth = nWidth; + bi.bmiHeader.biHeight = nHeight; + bi.bmiHeader.biPlanes = 1; + bi.bmiHeader.biBitCount = nBPP; + bi.bmiHeader.biCompression = eCompression; + + // is there alpha channel? + bool bHasAlphaCh; + bHasAlphaCh = (nBPP == 32 && (dwFlags & createAlphaChannel)); + + // get orientation + DIBOrientation eOrientation; + eOrientation = ((nHeight > 0) ? DIBOR_BOTTOMUP : DIBOR_TOPDOWN); + + // does it have bit fields? + if (eCompression == BI_BITFIELDS) + { + if (nBPP == 16 || nBPP == 32) + { + // store the mask data + LPDWORD pdwMask = reinterpret_cast(bi.bmiColors); + pdwMask[0] = pdwBitmasks[0]; + pdwMask[1] = pdwBitmasks[1]; + pdwMask[2] = pdwBitmasks[2]; + } + else + { + return FALSE; + } + } + else + { + ATLASSERT(pdwBitmasks == NULL); + if (pdwBitmasks) + return FALSE; + } + + // create a DIB section + HDC hDC = ::CreateCompatibleDC(NULL); + ATLASSERT(hDC); + LPVOID pvBits; + HBITMAP hbm = ::CreateDIBSection(hDC, bi.get(), DIB_RGB_COLORS, + &pvBits, NULL, 0); + ATLASSERT(hbm); + ::DeleteDC(hDC); + + // attach it + AttachInternal(hbm, eOrientation, -1); + m_bHasAlphaCh = bHasAlphaCh; + + return hbm != NULL; + } + +private: + // NOTE: CImage is not copyable + CImage(const CImage&); + CImage& operator=(const CImage&); +}; + +} + +#endif + +#ifndef _ATL_NO_AUTOMATIC_NAMESPACE +using namespace ATL; +#endif //!_ATL_NO_AUTOMATIC_NAMESPACE diff --git a/src/3rd_party/reactos-atl/atl/atlmem.h b/src/3rd_party/reactos-atl/atl/atlmem.h new file mode 100644 index 00000000..3b3a9986 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlmem.h @@ -0,0 +1,105 @@ +#ifndef __ATLMEM_H__ +#define __ATLMEM_H__ + +#pragma once +#include "atlcore.h" + + +namespace ATL +{ + +//__interface __declspec(uuid("654F7EF5-CFDF-4df9-A450-6C6A13C622C0")) +class IAtlMemMgr +{ +public: + virtual ~IAtlMemMgr() {}; + + virtual _Ret_maybenull_ _Post_writable_byte_size_(SizeBytes) void* Allocate( + _In_ size_t SizeBytes + ) = 0; + + virtual void Free( + _Inout_opt_ void* Buffer + ) = 0; + + virtual _Ret_maybenull_ _Post_writable_byte_size_(SizeBytes) void* Reallocate( + _Inout_updates_bytes_opt_(SizeBytes) void* Buffer, + _In_ size_t SizeBytes + ) = 0; + + virtual size_t GetSize( + _In_ void* Buffer + ) = 0; +}; + +class CWin32Heap : public IAtlMemMgr +{ +public: + HANDLE m_hHeap; + +public: + CWin32Heap() : + m_hHeap(NULL) + { + } + + CWin32Heap(_In_ HANDLE hHeap) : + m_hHeap(hHeap) + { + ATLASSERT(hHeap != NULL); + } + + virtual ~CWin32Heap() + { + } + + + // IAtlMemMgr + _Ret_maybenull_ _Post_writable_byte_size_(SizeBytes) virtual void* Allocate( + _In_ size_t SizeBytes + ) + { + return ::HeapAlloc(m_hHeap, 0, SizeBytes); + } + + virtual void Free( + _In_opt_ void* Buffer + ) + { + if (Buffer) + { + if (!::HeapFree(m_hHeap, 0, Buffer)) + ATLASSERT(FALSE); + } + } + + _Ret_maybenull_ _Post_writable_byte_size_(SizeBytes) virtual void* Reallocate( + _In_opt_ void* Buffer, + _In_ size_t SizeBytes + ) + { + if (SizeBytes == 0) + { + Free(Buffer); + return NULL; + } + + if (Buffer == NULL) + { + return Allocate(SizeBytes); + } + + return ::HeapReAlloc(m_hHeap, 0, Buffer, SizeBytes); + } + + virtual size_t GetSize( + _Inout_ void* Buffer + ) + { + return ::HeapSize(m_hHeap, 0, Buffer); + } +}; + +} + +#endif diff --git a/src/3rd_party/reactos-atl/atl/atlpath.h b/src/3rd_party/reactos-atl/atl/atlpath.h new file mode 100644 index 00000000..942b47f6 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlpath.h @@ -0,0 +1,389 @@ +// PROJECT: ReactOS ATL CPathT +// LICENSE: Public Domain +// PURPOSE: Provides compatibility to Microsoft ATL +// PROGRAMMERS: Benedikt Freisen + +#ifndef __ATLPATH_H__ +#define __ATLPATH_H__ + +// WARNING: Untested code + +#pragma once + +#include +#include +#include + +namespace ATL +{ + +template +class CPathT +{ + // const + inline BOOL PathFileExistsX(LPCSTR pszPath) { return PathFileExistsA(pszPath); } + inline BOOL PathFileExistsX(LPCWSTR pszPath) { return PathFileExistsW(pszPath); } + inline LPCSTR PathFindExtensionX(LPCSTR pszPath) { return PathFindExtensionA(pszPath); } + inline LPCWSTR PathFindExtensionX(LPCWSTR pszPath) { return PathFindExtensionW(pszPath); } + inline LPCSTR PathFindFileNameX(LPCSTR pszPath) { return PathFindFileNameA(pszPath); } + inline LPCWSTR PathFindFileNameX(LPCWSTR pszPath) { return PathFindFileNameW(pszPath); } + inline int PathGetDriveNumberX(LPCSTR pszPath) { return PathGetDriveNumberA(pszPath); } + inline int PathGetDriveNumberX(LPCWSTR pszPath) { return PathGetDriveNumberW(pszPath); } + inline BOOL PathIsDirectoryX(LPCSTR pszPath) { return PathIsDirectoryA(pszPath); } + inline BOOL PathIsDirectoryX(LPCWSTR pszPath) { return PathIsDirectoryW(pszPath); } + inline BOOL PathIsFileSpecX(LPCSTR pszPath) { return PathIsFileSpecA(pszPath); } + inline BOOL PathIsFileSpecX(LPCWSTR pszPath) { return PathIsFileSpecW(pszPath); } + inline BOOL PathIsPrefixX(LPCSTR pszPath, LPCSTR pszPrefix) { return PathIsPrefixA(pszPath, pszPrefix); } + inline BOOL PathIsPrefixX(LPCWSTR pszPath, LPCWSTR pszPrefix) { return PathIsPrefixW(pszPath, pszPrefix); } + inline BOOL PathIsRelativeX(LPCSTR pszPath) { return PathIsRelativeA(pszPath); } + inline BOOL PathIsRelativeX(LPCWSTR pszPath) { return PathIsRelativeW(pszPath); } + inline BOOL PathIsRootX(LPCSTR pszPath) { return PathIsRootA(pszPath); } + inline BOOL PathIsRootX(LPCWSTR pszPath) { return PathIsRootW(pszPath); } + inline BOOL PathIsSameRootX(LPCSTR pszPath, LPCSTR pszOther) { return PathIsSameRootA(pszPath, pszOther); } + inline BOOL PathIsSameRootX(LPCWSTR pszPath, LPCWSTR pszOther) { return PathIsSameRootW(pszPath, pszOther); } + inline BOOL PathIsUNCX(LPCSTR pszPath) { return PathIsUNCA(pszPath); } + inline BOOL PathIsUNCX(LPCWSTR pszPath) { return PathIsUNCW(pszPath); } + inline BOOL PathIsUNCServerX(LPCSTR pszPath) { return PathIsUNCServerA(pszPath); } + inline BOOL PathIsUNCServerX(LPCWSTR pszPath) { return PathIsUNCServerW(pszPath); } + inline BOOL PathIsUNCServerShareX(LPCSTR pszPath) { return PathIsUNCServerShareA(pszPath); } + inline BOOL PathIsUNCServerShareX(LPCWSTR pszPath) { return PathIsUNCServerShareW(pszPath); } + inline BOOL PathMatchSpecX(LPCSTR pszPath, LPCSTR pszSpec) { return PathMatchSpecA(pszPath, pszSpec); } + inline BOOL PathMatchSpecX(LPCWSTR pszPath, LPCWSTR pszSpec) { return PathMatchSpecW(pszPath, pszSpec); } + inline LPCSTR PathSkipRootX(LPCSTR pszPath) { return PathSkipRootA(pszPath); } + inline LPCWSTR PathSkipRootX(LPCWSTR pszPath) { return PathSkipRootW(pszPath); } + + // non-const + inline void PathAddBackslashX(LPSTR pszPath) { PathAddBackslashA(pszPath); } + inline void PathAddBackslashX(LPWSTR pszPath) { PathAddBackslashW(pszPath); } + inline BOOL PathAddExtensionX(LPSTR pszPath, LPCSTR pszExt) { return PathAddExtensionA(pszPath, pszExt); } + inline BOOL PathAddExtensionX(LPWSTR pszPath, LPCWSTR pszExt) { return PathAddExtensionW(pszPath, pszExt); } + inline BOOL PathAppendX(LPSTR pszPath, LPCSTR pszMore) { return PathAppendA(pszPath, pszMore); } + inline BOOL PathAppendX(LPWSTR pszPath, LPCWSTR pszMore) { return PathAppendW(pszPath, pszMore); } + inline void PathBuildRootX(LPSTR pszRoot, int iDrive) { PathBuildRootA(pszRoot, iDrive); } + inline void PathBuildRootX(LPWSTR pszRoot, int iDrive) { PathBuildRootW(pszRoot, iDrive); } + inline void PathCanonicalizeX(LPSTR pszDst, LPCSTR pszSrc) { PathCanonicalizeA(pszDst, pszSrc); } + inline void PathCanonicalizeX(LPWSTR pszDst, LPCWSTR pszSrc) { PathCanonicalizeW(pszDst, pszSrc); } + inline void PathCombineX(LPSTR pszPathOut, LPCSTR pszPathIn, LPCSTR pszMore) { PathCombineA(pszPathOut, pszPathIn, pszMore); } + inline void PathCombineX(LPWSTR pszPathOut, LPCWSTR pszPathIn, LPCWSTR pszMore) { PathCombineW(pszPathOut, pszPathIn, pszMore); } + inline CPathT PathCommonPrefixX(LPCSTR pszFile1, LPCSTR pszFile2, LPSTR pszPath) { return PathCommonPrefixA(pszFile1, pszFile2, pszPath); } + inline CPathT PathCommonPrefixX(LPCWSTR pszFile1, LPCWSTR pszFile2, LPWSTR pszPath) { return PathCommonPrefixW(pszFile1, pszFile2, pszPath); } + inline BOOL PathCompactPathX(HDC hDC, LPSTR pszPath, UINT dx) { return PathCompactPathA(hDC, pszPath, dx); } + inline BOOL PathCompactPathX(HDC hDC, LPWSTR pszPath, UINT dx) { return PathCompactPathW(hDC, pszPath, dx); } + inline BOOL PathCompactPathExX(LPSTR pszOut, LPCSTR pszSrc, UINT cchMax, DWORD dwFlags) { return PathCompactPathExA(pszOut, pszSrc, cchMax, dwFlags); } + inline BOOL PathCompactPathExX(LPWSTR pszOut, LPCWSTR pszSrc, UINT cchMax, DWORD dwFlags) { return PathCompactPathExW(pszOut, pszSrc, cchMax, dwFlags); } + inline BOOL PathMakePrettyX(LPSTR pszPath) { return PathMakePrettyA(pszPath); } + inline BOOL PathMakePrettyX(LPWSTR pszPath) { return PathMakePrettyW(pszPath); } + inline void PathQuoteSpacesX(LPSTR pszPath) { PathQuoteSpacesA(pszPath); } + inline void PathQuoteSpacesX(LPWSTR pszPath) { PathQuoteSpacesW(pszPath); } + inline BOOL PathRelativePathToX(LPSTR pszPath, LPCSTR pszFrom, DWORD dwAttrFrom, LPCSTR pszTo, DWORD dwAttrTo) { return PathRelativePathToA(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo); } + inline BOOL PathRelativePathToX(LPWSTR pszPath, LPCWSTR pszFrom, DWORD dwAttrFrom, LPCWSTR pszTo, DWORD dwAttrTo) { return PathRelativePathToW(pszPath, pszFrom, dwAttrFrom, pszTo, dwAttrTo); } + inline void PathRemoveArgsX(LPSTR pszPath) { PathRemoveArgsA(pszPath); } + inline void PathRemoveArgsX(LPWSTR pszPath) { PathRemoveArgsW(pszPath); } + inline void PathRemoveBackslashX(LPSTR pszPath) { PathRemoveBackslashA(pszPath); } + inline void PathRemoveBackslashX(LPWSTR pszPath) { PathRemoveBackslashW(pszPath); } + inline void PathRemoveBlanksX(LPSTR pszPath) { PathRemoveBlanksA(pszPath); } + inline void PathRemoveBlanksX(LPWSTR pszPath) { PathRemoveBlanksW(pszPath); } + inline void PathRemoveExtensionX(LPSTR pszPath) { PathRemoveExtensionA(pszPath); } + inline void PathRemoveExtensionX(LPWSTR pszPath) { PathRemoveExtensionW(pszPath); } + inline BOOL PathRemoveFileSpecX(LPSTR pszPath) { return PathRemoveFileSpecA(pszPath); } + inline BOOL PathRemoveFileSpecX(LPWSTR pszPath) { return PathRemoveFileSpecW(pszPath); } + inline BOOL PathRenameExtensionX(LPSTR pszPath, LPCSTR pszExt) { return PathRenameExtensionA(pszPath, pszExt); } + inline BOOL PathRenameExtensionX(LPWSTR pszPath, LPCWSTR pszExt) { return PathRenameExtensionW(pszPath, pszExt); } + inline void PathStripPathX(LPSTR pszPath) { PathStripPathA(pszPath); } + inline void PathStripPathX(LPWSTR pszPath) { PathStripPathW(pszPath); } + inline BOOL PathStripToRootX(LPSTR pszPath) { return PathStripToRootA(pszPath); } + inline BOOL PathStripToRootX(LPWSTR pszPath) { return PathStripToRootW(pszPath); } + inline void PathUnquoteSpacesX(LPSTR pszPath) { PathUnquoteSpacesA(pszPath); } + inline void PathUnquoteSpacesX(LPWSTR pszPath) { PathUnquoteSpacesW(pszPath); } + +public: + typedef typename StringType::PCXSTR PCXSTR; + typedef typename StringType::PXSTR PXSTR; + typedef typename StringType::XCHAR XCHAR; + + StringType m_strPath; + + CPathT(PCXSTR pszPath) + { + m_strPath = StringType(pszPath); + } + + CPathT(const CPathT& path) + { + m_strPath = path.m_strPath; + } + + CPathT() throw() + { + // do nothing, m_strPath initializes itself + } + + void AddBackslash() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathAddBackslashX(str); + m_strPath.ReleaseBuffer(); + } + + BOOL AddExtension(PCXSTR pszExtension) + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathAddExtensionX(str, pszExtension); + m_strPath.ReleaseBuffer(); + return result; + } + + BOOL Append(PCXSTR pszMore) + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathAppendX(str, pszMore); + m_strPath.ReleaseBuffer(); + return result; + } + + void BuildRoot(int iDrive) + { + PXSTR str = m_strPath.GetBuffer(4); + PathBuildRootX(str, iDrive); + m_strPath.ReleaseBuffer(); + } + + void Canonicalize() + { + StringType strTemp; + PXSTR str = strTemp.GetBuffer(MAX_PATH); + PathCanonicalizeX(str, m_strPath); + strTemp.ReleaseBuffer(); + m_strPath = strTemp; + } + + void Combine(PCXSTR pszDir, PCXSTR pszFile) + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathCombineX(str, pszDir, pszFile); + m_strPath.ReleaseBuffer(); + } + + CPathT CommonPrefix(PCXSTR pszOther) + { + StringType result; + result.SetString(m_strPath, PathCommonPrefixX(m_strPath, pszOther, NULL)); + return result; + } + + BOOL CompactPath(HDC hDC, UINT nWidth) + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathCompactPathX(hDC, str, nWidth); + m_strPath.ReleaseBuffer(); + return result; + } + + BOOL CompactPathEx(UINT nMaxChars, DWORD dwFlags = 0) + { + StringType strTemp; + PXSTR str = strTemp.GetBuffer(nMaxChars); + BOOL result = PathCompactPathExX(str, m_strPath, nMaxChars, dwFlags); + strTemp.ReleaseBuffer(); + m_strPath = strTemp; + return result; + } + + BOOL FileExists() const + { + return PathFileExistsX(m_strPath); + } + + int FindExtension() const + { + return PathFindExtensionX(m_strPath); + } + + int FindFileName() const + { + return PathFindFileNameX(m_strPath); + } + + int GetDriveNumber() const + { + return PathGetDriveNumberX(m_strPath); + } + + StringType GetExtension() const + { + return StringType(PathFindExtensionX(m_strPath)); + } + + BOOL IsDirectory() const + { + return PathIsDirectoryX(m_strPath); + } + + BOOL IsFileSpec() const + { + return PathIsFileSpecX(m_strPath); + } + + BOOL IsPrefix(PCXSTR pszPrefix) const + { + return PathIsPrefixX(m_strPath); + } + + BOOL IsRelative() const + { + return PathIsRelativeX(m_strPath); + } + + BOOL IsRoot() const + { + return PathIsRootX(m_strPath); + } + + BOOL IsSameRoot(PCXSTR pszOther) const + { + return PathIsSameRootX(m_strPath, pszOther); + } + + BOOL IsUNC() const + { + return PathIsUNCX(m_strPath); + } + + BOOL IsUNCServer() const + { + return PathIsUNCServerX(m_strPath); + } + + BOOL IsUNCServerShare() const + { + return PathIsUNCServerShareX(m_strPath); + } + + BOOL MakePretty() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathMakePrettyX(str); + m_strPath.ReleaseBuffer(); + return result; + } + + BOOL MatchSpec(PCXSTR pszSpec) const + { + return PathMatchSpecX(m_strPath, pszSpec); + } + + void QuoteSpaces() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathQuoteSpacesX(str); + m_strPath.ReleaseBuffer(); + } + + BOOL RelativePathTo(PCXSTR pszFrom, DWORD dwAttrFrom, PCXSTR pszTo, DWORD dwAttrTo) + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathRelativePathToX(str, pszFrom, dwAttrFrom, pszTo, dwAttrTo); + m_strPath.ReleaseBuffer(); + return result; + } + + void RemoveArgs() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathRemoveArgsX(str); + m_strPath.ReleaseBuffer(); + } + + void RemoveBackslash() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathRemoveBackslashX(str); + m_strPath.ReleaseBuffer(); + } + + void RemoveBlanks() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathRemoveBlanksX(str); + m_strPath.ReleaseBuffer(); + } + + void RemoveExtension() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathRemoveExtensionX(str); + m_strPath.ReleaseBuffer(); + } + + BOOL RemoveFileSpec() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathRemoveFileSpecX(str); + m_strPath.ReleaseBuffer(); + return result; + } + + BOOL RenameExtension(PCXSTR pszExtension) + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathRenameExtensionX(str, pszExtension); + m_strPath.ReleaseBuffer(); + return result; + } + + int SkipRoot() const + { + return PathSkipRootX(m_strPath); + } + + void StripPath() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathStripPathX(str); + m_strPath.ReleaseBuffer(); + } + + BOOL StripToRoot() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + BOOL result = PathStripToRootX(str); + m_strPath.ReleaseBuffer(); + return result; + } + + void UnquoteSpaces() + { + PXSTR str = m_strPath.GetBuffer(MAX_PATH); + PathUnquoteSpacesX(str); + m_strPath.ReleaseBuffer(); + } + + operator const StringType&() const throw() + { + return m_strPath; + } + + operator PCXSTR() const throw() + { + return m_strPath; + } + + operator StringType&() throw() + { + return m_strPath; + } + + CPathT& operator+=(PCXSTR pszMore) + { + m_strPath += pszMore; + } + +}; + +typedef CPathT CPath; +typedef CPathT CPathA; +typedef CPathT CPathW; + +} // namespace ATL + +#endif diff --git a/src/3rd_party/reactos-atl/atl/atlsimpcoll.h b/src/3rd_party/reactos-atl/atl/atlsimpcoll.h new file mode 100644 index 00000000..a174378f --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlsimpcoll.h @@ -0,0 +1,454 @@ +// PROJECT: ReactOS ATL Simple Collection +// LICENSE: Public Domain +// PURPOSE: Provides compatibility to Microsoft ATL +// PROGRAMMERS: Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com) + +#ifndef __ATLSIMPCOLL_H__ +#define __ATLSIMPCOLL_H__ + +#pragma once + +#include "atlcore.h" // for ATL Core + +namespace ATL +{ +template +class CSimpleArrayEqualHelper +{ +public: + static bool IsEqual(const T& t1, const T& t2) + { + return t1 == t2; + } +}; + +// This class exists for the element types of no comparison. +template +class CSimpleArrayEqualHelperFalse +{ +public: + static bool IsEqual(const T&, const T&) + { + ATLASSERT(FALSE); + return false; + } +}; + +template > +class CSimpleArray +{ +public: + typedef T _ArrayElementType; + + CSimpleArray() : m_pData(NULL), m_nCount(0), m_nCapacity(0) + { + } + + CSimpleArray(const CSimpleArray& src) : + m_pData(NULL), m_nCount(0), m_nCapacity(0) + { + *this = src; + } + + ~CSimpleArray() + { + RemoveAll(); + } + + BOOL Add(const T& t) + { + // is the capacity enough? + if (m_nCapacity < m_nCount + 1) + { + // allocate extra capacity for optimization + const int nNewCapacity = (m_nCount + 1) + c_nGrow; + T *pNewData = (T *)realloc(static_cast(m_pData), nNewCapacity * sizeof(T)); + if (pNewData == NULL) + return FALSE; // failure + + m_pData = pNewData; + m_nCapacity = nNewCapacity; + } + + // call constructor + ConstructItemInPlace(m_nCount, t); + + // increment + ++m_nCount; + + return TRUE; + } + + int Find(const T& t) const + { + for (int nIndex = 0; nIndex < m_nCount; ++nIndex) + { + if (TEqual::IsEqual(m_pData[nIndex], t)) + { + return nIndex; // success + } + } + return -1; // failure + } + + T* GetData() + { + return m_pData; + } + + const T* GetData() const + { + return m_pData; + } + + int GetSize() const + { + return m_nCount; + } + + BOOL Remove(const T& t) + { + return RemoveAt(Find(t)); + } + + void RemoveAll() + { + if (m_pData) + { + // call destructor + const int nCount = m_nCount; + for (int nIndex = 0; nIndex < nCount; ++nIndex) + { + DestructItem(nIndex); + } + + free(m_pData); + m_pData = NULL; + } + m_nCount = 0; + m_nCapacity = 0; + } + + BOOL RemoveAt(int nIndex) + { + // boundary check + if (nIndex < 0 || m_nCount <= nIndex) + return FALSE; // failure + + // call destructor + DestructItem(nIndex); + + // move range [nIndex + 1, m_nCount) to nIndex + const int nRightCount = m_nCount - (nIndex + 1); + const int nRightSize = nRightCount * sizeof(T); + memmove(static_cast(&m_pData[nIndex]), &m_pData[nIndex + 1], nRightSize); + + // decrement + --m_nCount; + + return TRUE; + } + + BOOL SetAtIndex(int nIndex, const T& t) + { + // boundary check + if (nIndex < 0 || m_nCount <= nIndex) + return FALSE; // failure + + // store it + m_pData[nIndex] = t; + return TRUE; + } + + T& operator[](int nIndex) + { + ATLASSERT(0 <= nIndex && nIndex < m_nCount); + return m_pData[nIndex]; + } + + const T& operator[](int nIndex) const + { + ATLASSERT(0 <= nIndex && nIndex < m_nCount); + return m_pData[nIndex]; + } + + CSimpleArray& operator=(const CSimpleArray& src) + { + // don't copy if two objects are same + if (this == &src) + return *this; + + if (src.GetSize() != GetSize()) + { + RemoveAll(); + + int nNewCount = src.GetSize(); + + T *pNewData = (T *)realloc(static_cast(m_pData), nNewCount * sizeof(T)); + ATLASSERT(pNewData); + if (pNewData == NULL) + return *this; // failure + + // store new + m_pData = pNewData; + m_nCount = nNewCount; + m_nCapacity = nNewCount; + } + else + { + for (int nIndex = 0; nIndex < m_nCount; ++nIndex) + { + DestructItem(nIndex); + } + } + + ATLASSERT(GetSize() == src.GetSize()); + for (int nIndex = 0; nIndex < src.GetSize(); ++nIndex) + { + ConstructItemInPlace(nIndex, src[nIndex]); + } + + return *this; + } + +protected: + T * m_pData; // malloc'ed + int m_nCount; // # of items of type T + int m_nCapacity; // for optimization + static const int c_nGrow = 8; // for optimization + + // NOTE: Range m_pData[0] .. m_pData[m_nCapacity - 1] are accessible. + // NOTE: Range [0, m_nCount) are constructed. + // NOTE: Range [m_nCount, m_nCapacity) are not constructed. + // NOTE: 0 <= m_nCount && m_nCount <= m_nCapacity. + + // call constructor at nIndex + void ConstructItemInPlace(int nIndex, const T& src) + { + new(&m_pData[nIndex]) ConstructImpl(src); + } + + // call destructor at nIndex + void DestructItem(int nIndex) + { + m_pData[nIndex].~T(); + } + +private: + + struct ConstructImpl + { + ConstructImpl(const T& obj) + :m_ConstructHelper(obj) + { + } + + static void *operator new(size_t, void *ptr) + { + return ptr; + } + + static void operator delete(void *p, void* ) + { + } + + T m_ConstructHelper; + }; + +}; + +template +class CSimpleMapEqualHelper +{ +public: + static bool IsEqualKey(const TKey& k1, const TKey& k2) + { + return k1 == k2; + } + + static bool IsEqualValue(const TVal& v1, const TVal& v2) + { + return v1 == v2; + } +}; + +// This class exists for the keys and the values of no comparison. +template +class CSimpleMapEqualHelperFalse +{ +public: + static bool IsEqualKey(const TKey& k1, const TKey& k2) + { + ATLASSERT(FALSE); + return false; + } + + static bool IsEqualValue(const TVal& v1, const TVal& v2) + { + ATLASSERT(FALSE); + return false; + } +}; + +template > +class CSimpleMap +{ +public: + typedef TKey _ArrayKeyType; + typedef TVal _ArrayElementType; + + CSimpleMap() + { + } + + ~CSimpleMap() + { + } + + BOOL Add(const TKey& key, const TVal& val) + { + Pair pair(key, val); + return m_Pairs.Add(pair); + } + + int FindKey(const TKey& key) const + { + const int nCount = GetSize(); + for (int nIndex = 0; nIndex < nCount; ++nIndex) + { + if (TEqual::IsEqualKey(m_Pairs[nIndex].key, key)) + { + return nIndex; // success + } + } + return -1; // failure + } + + int FindVal(const TVal& val) const + { + const int nCount = GetSize(); + for (int nIndex = 0; nIndex < nCount; ++nIndex) + { + if (TEqual::IsEqualValue(m_Pairs[nIndex].val, val)) + { + return nIndex; // success + } + } + return -1; // failure + } + + TKey& GetKeyAt(int nIndex) + { + ATLASSERT(0 <= nIndex && nIndex < GetSize()); + return m_Pairs[nIndex].key; + } + + const TKey& GetKeyAt(int nIndex) const + { + ATLASSERT(0 <= nIndex && nIndex < GetSize()); + return m_Pairs[nIndex].key; + } + + int GetSize() const + { + return m_Pairs.GetSize(); + } + + TVal& GetValueAt(int nIndex) + { + ATLASSERT(0 <= nIndex && nIndex < GetSize()); + return m_Pairs[nIndex].val; + } + + const TVal& GetValueAt(int nIndex) const + { + ATLASSERT(0 <= nIndex && nIndex < GetSize()); + return m_Pairs[nIndex].val; + } + + TVal Lookup(const TKey& key) const + { + int nIndex = FindKey(key); + if (nIndex < 0) + return TVal(); + return m_Pairs[nIndex].val; + } + + BOOL Remove(const TKey& key) + { + int nIndex = FindKey(key); + return RemoveAt(nIndex); + } + + void RemoveAll() + { + m_Pairs.RemoveAll(); + } + + BOOL RemoveAt(int nIndex) + { + return m_Pairs.RemoveAt(nIndex); + } + + TKey ReverseLookup(const TVal& val) const + { + int nIndex = FindVal(val); + if (nIndex < 0) + return TKey(); + return m_Pairs[nIndex].key; + } + + BOOL SetAt(const TKey& key, const TVal& val) + { + int nIndex = FindKey(key); + if (nIndex < 0) + return Add(key, val); + + m_Pairs[nIndex].val = val; + return TRUE; + } + + BOOL SetAtIndex(int nIndex, const TKey& key, const TVal& val) + { + // boundary check + if (nIndex < 0 || GetSize() <= nIndex) + return FALSE; + + m_Pairs[nIndex].key = key; + m_Pairs[nIndex].val = val; + return TRUE; + } + +protected: + struct Pair + { + TKey key; + TVal val; + + Pair() + { + } + + Pair(const TKey& k, const TVal& v) : key(k), val(v) + { + } + + Pair(const Pair& pair) : key(pair.key), val(pair.val) + { + } + + Pair& operator=(const Pair& pair) + { + key = pair.key; + val = pair.val; + return *this; + } + }; + + CSimpleArray > m_Pairs; +}; + +} + +#endif diff --git a/src/3rd_party/reactos-atl/atl/atlsimpstr.h b/src/3rd_party/reactos-atl/atl/atlsimpstr.h new file mode 100644 index 00000000..c06a8e46 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlsimpstr.h @@ -0,0 +1,630 @@ +#ifndef __ATLSIMPSTR_H__ +#define __ATLSIMPSTR_H__ + +#pragma once + +#include +#include + +namespace ATL +{ +struct CStringData; + +// Pure virtual interface +class IAtlStringMgr +{ +public: + + virtual ~IAtlStringMgr() {} + + virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize) + CStringData* Allocate( + _In_ int nAllocLength, + _In_ int nCharSize + ) = 0; + + virtual void Free( + _Inout_ CStringData* pData + ) = 0; + + virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nAllocLength*nCharSize) + CStringData* Reallocate( + _Inout_ CStringData* pData, + _In_ int nAllocLength, + _In_ int nCharSize + ) = 0; + + virtual CStringData* GetNilString(void) = 0; + virtual IAtlStringMgr* Clone(void) = 0; +}; + + +struct CStringData +{ + IAtlStringMgr* pStringMgr; + int nAllocLength; + int nDataLength; + long nRefs; + + void* data() throw() + { + return (this + 1); + } + + void AddRef() throw() + { + ATLASSERT(nRefs > 0); + _InterlockedIncrement(&nRefs); + } + + void Release() throw() + { + ATLASSERT(nRefs != 0); + + if (_InterlockedDecrement(&nRefs) <= 0) + { + pStringMgr->Free(this); + } + } + + bool IsLocked() const throw() + { + return (nRefs < 0); + } + + bool IsShared() const throw() + { + return (nRefs > 1); + } +}; + +class CNilStringData : + public CStringData +{ +public: + CNilStringData() throw() + { + pStringMgr = NULL; + nRefs = 2; + nDataLength = 0; + nAllocLength = 0; + achNil[0] = 0; + achNil[1] = 0; + } + + void SetManager(_In_ IAtlStringMgr* pMgr) throw() + { + ATLASSERT(pStringMgr == NULL); + pStringMgr = pMgr; + } + +public: + wchar_t achNil[2]; +}; + + +template< typename BaseType = char > +class ChTraitsBase +{ +public: + typedef char XCHAR; + typedef LPSTR PXSTR; + typedef LPCSTR PCXSTR; + typedef wchar_t YCHAR; + typedef LPWSTR PYSTR; + typedef LPCWSTR PCYSTR; +}; + +template<> +class ChTraitsBase +{ +public: + typedef wchar_t XCHAR; + typedef LPWSTR PXSTR; + typedef LPCWSTR PCXSTR; + typedef char YCHAR; + typedef LPSTR PYSTR; + typedef LPCSTR PCYSTR; +}; + +template< typename BaseType, bool t_bMFCDLL = false> +class CSimpleStringT +{ +public: + typedef typename ChTraitsBase::XCHAR XCHAR; + typedef typename ChTraitsBase::PXSTR PXSTR; + typedef typename ChTraitsBase::PCXSTR PCXSTR; + typedef typename ChTraitsBase::YCHAR YCHAR; + typedef typename ChTraitsBase::PYSTR PYSTR; + typedef typename ChTraitsBase::PCYSTR PCYSTR; + +private: + PXSTR m_pszData; + +public: + explicit CSimpleStringT(_Inout_ IAtlStringMgr* pStringMgr) + { + CStringData* pData = pStringMgr->GetNilString(); + Attach(pData); + } + + CSimpleStringT(_In_ const CSimpleStringT& strSrc) + { + CStringData* pSrcData = strSrc.GetData(); + CStringData* pNewData = CloneData(pSrcData); + Attach(pNewData); + } + + CSimpleStringT( + _In_z_ PCXSTR pszSrc, + _Inout_ IAtlStringMgr* pStringMgr) + { + int nLength = StringLength(pszSrc); + CStringData* pData = pStringMgr->Allocate(nLength, sizeof(XCHAR)); + if (pData == NULL) + ThrowMemoryException(); + + Attach(pData); + SetLength(nLength); + CopyChars(m_pszData, nLength, pszSrc, nLength); + } + + CSimpleStringT( + _In_count_(nLength) const XCHAR* pchSrc, + _In_ int nLength, + _Inout_ IAtlStringMgr* pStringMgr) + { + if (pchSrc == NULL && nLength != 0) + ThrowInvalidArgException(); + + CStringData* pData = pStringMgr->Allocate(nLength, sizeof(XCHAR)); + if (pData == NULL) + { + ThrowMemoryException(); + } + Attach(pData); + SetLength(nLength); + CopyChars(m_pszData, nLength, pchSrc, nLength); + } + + ~CSimpleStringT() throw() + { + CStringData* pData = GetData(); + pData->Release(); + } + + CSimpleStringT& operator=(_In_opt_z_ PCXSTR pszSrc) + { + SetString(pszSrc); + return *this; + } + + CSimpleStringT& operator=(_In_ const CSimpleStringT& strSrc) + { + CStringData* pData = GetData(); + CStringData* pNewData = strSrc.GetData(); + + if (pNewData != pData) + { + if (!pData->IsLocked() && (pNewData->pStringMgr == pData->pStringMgr)) + { + pNewData = CloneData(pNewData); + pData->Release(); + Attach(pNewData); + } + else + { + SetString(strSrc.GetString(), strSrc.GetLength()); + } + } + + return *this; + } + + CSimpleStringT& operator+=(_In_ const CSimpleStringT& strSrc) + { + Append(strSrc); + return *this; + } + + CSimpleStringT& operator+=(_In_z_ PCXSTR pszSrc) + { + Append(pszSrc); + return *this; + } + + CSimpleStringT& operator+=(XCHAR ch) + { + Append(&ch, 1); + return *this; + } + + operator PCXSTR() const throw() + { + return m_pszData; + } + + void Empty() throw() + { + CStringData* pOldData = GetData(); + IAtlStringMgr* pStringMgr = pOldData->pStringMgr; + if (pOldData->nDataLength == 0) return; + + if (pOldData->IsLocked()) + { + SetLength(0); + } + else + { + pOldData->Release(); + CStringData* pNewData = pStringMgr->GetNilString(); + Attach(pNewData); + } + } + + void Append( + _In_count_(nLength) PCXSTR pszSrc, + _In_ int nLength) + { + UINT_PTR nOffset = pszSrc - GetString(); + + int nOldLength = GetLength(); + if (nOldLength < 0) + nOldLength = 0; + + ATLASSERT(nLength >= 0); + +#if 0 // FIXME: See comment for StringLengthN below. + nLength = StringLengthN(pszSrc, nLength); + if (!(INT_MAX - nLength >= nOldLength)) + throw; +#endif + + int nNewLength = nOldLength + nLength; + PXSTR pszBuffer = GetBuffer(nNewLength); + if (nOffset <= (UINT_PTR)nOldLength) + { + pszSrc = pszBuffer + nOffset; + } + CopyChars(pszBuffer + nOldLength, nLength, pszSrc, nLength); + ReleaseBufferSetLength(nNewLength); + } + + void Append(_In_z_ PCXSTR pszSrc) + { + Append(pszSrc, StringLength(pszSrc)); + } + + void Append(_In_ const CSimpleStringT& strSrc) + { + Append(strSrc.GetString(), strSrc.GetLength()); + } + + void SetString(_In_opt_z_ PCXSTR pszSrc) + { + SetString(pszSrc, StringLength(pszSrc)); + } + + void SetString(_In_reads_opt_(nLength) PCXSTR pszSrc, + _In_ int nLength) + { + if (nLength == 0) + { + Empty(); + } + else + { + UINT nOldLength = GetLength(); + UINT_PTR nOffset = pszSrc - GetString(); + + PXSTR pszBuffer = GetBuffer(nLength); + if (nOffset <= nOldLength) + { + CopyCharsOverlapped(pszBuffer, GetAllocLength(), + pszBuffer + nOffset, nLength); + } + else + { + CopyChars(pszBuffer, GetAllocLength(), pszSrc, nLength); + } + ReleaseBufferSetLength(nLength); + } + } + + PXSTR GetBuffer() + { + CStringData* pData = GetData(); + if (pData->IsShared()) + { + // We should fork here + Fork(pData->nDataLength); + } + + return m_pszData; + } + + _Ret_notnull_ _Post_writable_size_(nMinBufferLength + 1) PXSTR GetBuffer(_In_ int nMinBufferLength) + { + return PrepareWrite(nMinBufferLength); + } + + int GetAllocLength() const throw() + { + return GetData()->nAllocLength; + } + + int GetLength() const throw() + { + return GetData()->nDataLength; + } + + PCXSTR GetString() const throw() + { + return m_pszData; + } + + void ReleaseBufferSetLength(_In_ int nNewLength) + { + ATLASSERT(nNewLength >= 0); + SetLength(nNewLength); + } + + void ReleaseBuffer(_In_ int nNewLength = -1) + { + if (nNewLength < 0) + nNewLength = StringLength(m_pszData); + ReleaseBufferSetLength(nNewLength); + } + + bool IsEmpty() const throw() + { + return (GetLength() == 0); + } + + CStringData* GetData() const throw() + { + return (reinterpret_cast(m_pszData) - 1); + } + + IAtlStringMgr* GetManager() const throw() + { + IAtlStringMgr* pStringMgr = GetData()->pStringMgr; + return (pStringMgr ? pStringMgr->Clone() : NULL); + } + +public: + friend CSimpleStringT operator+( + _In_ const CSimpleStringT& str1, + _In_ const CSimpleStringT& str2) + { + CSimpleStringT s(str1.GetManager()); + Concatenate(s, str1, str1.GetLength(), str2, str2.GetLength()); + return s; + } + + friend CSimpleStringT operator+( + _In_ const CSimpleStringT& str1, + _In_z_ PCXSTR psz2) + { + CSimpleStringT s(str1.GetManager()); + Concatenate(s, str1, str1.GetLength(), psz2, StringLength(psz2)); + return s; + } + + friend CSimpleStringT operator+( + _In_z_ PCXSTR psz1, + _In_ const CSimpleStringT& str2) + { + CSimpleStringT s(str2.GetManager()); + Concatenate(s, psz1, StringLength(psz1), str2, str2.GetLength()); + return s; + } + + static void __cdecl CopyChars( + _Out_writes_to_(nDestLen, nChars) XCHAR* pchDest, + _In_ size_t nDestLen, + _In_reads_opt_(nChars) const XCHAR* pchSrc, + _In_ int nChars) throw() + { + memcpy(pchDest, pchSrc, nChars * sizeof(XCHAR)); + } + + static void __cdecl CopyCharsOverlapped( + _Out_writes_to_(nDestLen, nDestLen) XCHAR* pchDest, + _In_ size_t nDestLen, + _In_reads_(nChars) const XCHAR* pchSrc, + _In_ int nChars) throw() + { + memmove(pchDest, pchSrc, nChars * sizeof(XCHAR)); + } + + static int __cdecl StringLength(_In_opt_z_ const char* psz) throw() + { + if (psz == NULL) return 0; + return (int)strlen(psz); + } + + static int __cdecl StringLength(_In_opt_z_ const wchar_t* psz) throw() + { + if (psz == NULL) return 0; + return (int)wcslen(psz); + } + +#if 0 // For whatever reason we do not link with strnlen / wcsnlen. Please investigate! + // strnlen / wcsnlen are available in MSVCRT starting Vista+. + static int __cdecl StringLengthN( + _In_opt_z_count_(sizeInXChar) const char* psz, + _In_ size_t sizeInXChar) throw() + { + if (psz == NULL) return 0; + return (int)strnlen(psz, sizeInXChar); + } + + static int __cdecl StringLengthN( + _In_opt_z_count_(sizeInXChar) const wchar_t* psz, + _In_ size_t sizeInXChar) throw() + { + if (psz == NULL) return 0; + return (int)wcsnlen(psz, sizeInXChar); + } +#endif + +protected: + static void __cdecl Concatenate( + _Inout_ CSimpleStringT& strResult, + _In_count_(nLength1) PCXSTR psz1, + _In_ int nLength1, + _In_count_(nLength2) PCXSTR psz2, + _In_ int nLength2) + { + int nNewLength = nLength1 + nLength2; + PXSTR pszBuffer = strResult.GetBuffer(nNewLength); + CopyChars(pszBuffer, nLength1, psz1, nLength1); + CopyChars(pszBuffer + nLength1, nLength2, psz2, nLength2); + strResult.ReleaseBufferSetLength(nNewLength); + } + +private: + void Attach(_Inout_ CStringData* pData) throw() + { + m_pszData = static_cast(pData->data()); + } + + __declspec(noinline) void Fork(_In_ int nLength) + { + CStringData* pOldData = GetData(); + int nOldLength = pOldData->nDataLength; + CStringData* pNewData = pOldData->pStringMgr->Clone()->Allocate(nLength, sizeof(XCHAR)); + if (pNewData == NULL) + { + ThrowMemoryException(); + } + int nCharsToCopy = ((nOldLength < nLength) ? nOldLength : nLength) + 1; + CopyChars(PXSTR(pNewData->data()), nCharsToCopy, + PCXSTR(pOldData->data()), nCharsToCopy); + pNewData->nDataLength = nOldLength; + pOldData->Release(); + Attach(pNewData); + } + + PXSTR PrepareWrite(_In_ int nLength) + { + CStringData* pOldData = GetData(); + int nShared = 1 - pOldData->nRefs; + int nTooShort = pOldData->nAllocLength - nLength; + if ((nShared | nTooShort) < 0) + { + PrepareWrite2(nLength); + } + + return m_pszData; + } + void PrepareWrite2(_In_ int nLength) + { + CStringData* pOldData = GetData(); + if (pOldData->nDataLength > nLength) + { + nLength = pOldData->nDataLength; + } + if (pOldData->IsShared()) + { + Fork(nLength); + //ATLASSERT(FALSE); + } + else if (pOldData->nAllocLength < nLength) + { + int nNewLength = pOldData->nAllocLength; + if (nNewLength > 1024 * 1024 * 1024) + { + nNewLength += 1024 * 1024; + } + else + { + nNewLength = nNewLength + nNewLength / 2; + } + if (nNewLength < nLength) + { + nNewLength = nLength; + } + Reallocate(nNewLength); + } + } + + void Reallocate(_In_ int nLength) + { + CStringData* pOldData = GetData(); + ATLASSERT(pOldData->nAllocLength < nLength); + IAtlStringMgr* pStringMgr = pOldData->pStringMgr; + if (pOldData->nAllocLength >= nLength || nLength <= 0) + { + return; + } + CStringData* pNewData = pStringMgr->Reallocate(pOldData, nLength, sizeof(XCHAR)); + if (pNewData == NULL) + { + ThrowMemoryException(); + } + + Attach(pNewData); + } + + void SetLength(_In_ int nLength) + { + ATLASSERT(nLength >= 0); + ATLASSERT(nLength <= GetData()->nAllocLength); + + if (nLength < 0 || nLength > GetData()->nAllocLength) + { + AtlThrow(E_INVALIDARG); + } + + GetData()->nDataLength = nLength; + m_pszData[nLength] = 0; + } + + static CStringData* __cdecl CloneData(_Inout_ CStringData* pData) + { + CStringData* pNewData = NULL; + + IAtlStringMgr* pNewStringMgr = pData->pStringMgr->Clone(); + if (!pData->IsLocked() && (pNewStringMgr == pData->pStringMgr)) + { + pNewData = pData; + pNewData->AddRef(); + } + else + { + pNewData = pNewStringMgr->Allocate(pData->nDataLength, sizeof(XCHAR)); + if (pNewData == NULL) + { + ThrowMemoryException(); + } + + pNewData->nDataLength = pData->nDataLength; + CopyChars(PXSTR(pNewData->data()), pData->nDataLength + 1, + PCXSTR(pData->data()), pData->nDataLength + 1); + } + + return pNewData; + } + +protected: + static void ThrowMemoryException() + { + AtlThrow(E_OUTOFMEMORY); + } + + static void ThrowInvalidArgException() + { + AtlThrow(E_INVALIDARG); + } +}; + +#ifdef UNICODE +typedef CSimpleStringT CSimpleString; +#else +typedef CSimpleStringT CSimpleString; +#endif +} + +#endif diff --git a/src/3rd_party/reactos-atl/atl/atlstr.h b/src/3rd_party/reactos-atl/atl/atlstr.h new file mode 100644 index 00000000..9131bab5 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlstr.h @@ -0,0 +1,145 @@ +#ifndef __ATLSTR_H__ +#define __ATLSTR_H__ + +#pragma once +#include "atlbase.h" +#include "cstringt.h" + +namespace ATL +{ + +class CAtlStringMgr : public IAtlStringMgr +{ +protected: + IAtlMemMgr* m_MemMgr; + CNilStringData m_NilStrData; + +public: + CAtlStringMgr(_In_opt_ IAtlMemMgr* MemMgr = NULL): + m_MemMgr(MemMgr) + { + m_NilStrData.SetManager(this); + } + + virtual ~CAtlStringMgr(void) + { + } + + static IAtlStringMgr* GetInstance(void) + { + static CWin32Heap Win32Heap(::GetProcessHeap()); + static CAtlStringMgr StringMgr(&Win32Heap); + return &StringMgr; + } + + virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + NumChars * CharSize) CStringData* Allocate( + _In_ int NumChars, + _In_ int CharSize) + { + size_t SizeBytes; + CStringData* StrData; + + SizeBytes = sizeof(CStringData) + ((NumChars + 1) * CharSize); + + StrData = static_cast(m_MemMgr->Allocate(SizeBytes)); + if (StrData == NULL) return NULL; + + StrData->pStringMgr = this; + StrData->nRefs = 1; + StrData->nAllocLength = NumChars; + StrData->nDataLength = 0; + + return StrData; + } + + virtual void Free(_In_ CStringData* StrData) + { + ATLASSERT(StrData->pStringMgr == this); + m_MemMgr->Free(StrData); + } + + virtual _Ret_maybenull_ _Post_writable_byte_size_(sizeof(CStringData) + nChars*nCharSize) CStringData* Reallocate( + _Inout_ _Post_readable_byte_size_(sizeof(CStringData)) CStringData* StrData, + _In_ int nChars, + _In_ int nCharSize) throw() + { + ATLASSERT(StrData->pStringMgr == this); + + CStringData* pNewData; + ULONG SizeBytes; + ULONG nDataBytes; + + nChars++; + nDataBytes = nChars * nCharSize; + SizeBytes = sizeof(CStringData) + nDataBytes; + + pNewData = static_cast(m_MemMgr->Reallocate(StrData, SizeBytes)); + if (pNewData == NULL) return NULL; + + pNewData->nAllocLength = nChars - 1; + return pNewData; + } + virtual CStringData* GetNilString() throw() + { + m_NilStrData.AddRef(); + return &m_NilStrData; + } + virtual IAtlStringMgr* Clone() throw() + { + return this; + } + +private: + static bool StaticInitialize() + { + GetInstance(); + return true; + } +}; + + +template< typename _CharType = wchar_t > +class ChTraitsOS : + public ChTraitsBase < _CharType > +{ + +}; + + +template > +class StrTraitATL : + public StringIterator +{ +public: + static HINSTANCE FindStringResourceInstance(_In_ UINT nID) throw() + { + return AtlFindStringResourceInstance(nID); + } + + static IAtlStringMgr* GetDefaultManager() throw() + { + return CAtlStringMgr::GetInstance(); + } +}; + + +typedef CStringT< wchar_t, StrTraitATL< wchar_t, ChTraitsCRT > > CAtlStringW; +typedef CStringT< char, StrTraitATL< char, ChTraitsCRT > > CAtlStringA; + + +typedef CAtlStringW CStringW; +typedef CAtlStringA CStringA; + + +#ifdef UNICODE +typedef CAtlStringW CAtlString; +typedef CStringW CString; +#else +typedef CAtlStringA CAtlString; +typedef CStringA CString; +#endif + + +} + +#endif \ No newline at end of file diff --git a/src/3rd_party/reactos-atl/atl/atltime.h b/src/3rd_party/reactos-atl/atl/atltime.h new file mode 100644 index 00000000..c1b88983 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atltime.h @@ -0,0 +1,662 @@ +// PROJECT: ReactOS ATL CTime, CFileTime, CTimeSpan, CFileTimeSpan +// LICENSE: Public Domain +// PURPOSE: Provides compatibility to Microsoft ATL +// PROGRAMMERS: Benedikt Freisen + +#ifndef __ATLTIME_H__ +#define __ATLTIME_H__ + +// WARNING: Untested code + +#pragma once + +#include +#include +#include +#include +#include + +namespace ATL +{ + +class CTimeSpan +{ + __time64_t m_nSpan; +public: + CTimeSpan() throw() + { + // leave uninitialized + } + + CTimeSpan(__time64_t time) throw() + { + m_nSpan = time; + } + + CTimeSpan(LONG lDays, int nHours, int nMins, int nSecs) throw() + { + ATLASSERT(lDays >= 0 && nHours >= 0 && nHours <= 23 && nMins >= 0 && nMins <= 59 && nSecs >= 0 && nSecs <= 59); + m_nSpan = ((((LONGLONG)lDays) * 24 + nHours) * 60 + nMins) * 60 + nSecs; + } + + CString Format(LPCSTR pFormat) const + { + struct tm time; + _localtime64_s(&time, &m_nSpan); + CStringA strTime; + strftime(strTime.GetBuffer(256), 256, pFormat, &time); + strTime.ReleaseBuffer(); + return CString(strTime); + } + + CString Format(LPCTSTR pszFormat) const + { + struct tm time; + _localtime64_s(&time, &m_nSpan); + CString strTime; +#ifdef UNICODE + wcsftime(strTime.GetBuffer(256), 256, pszFormat, &time); +#else + strftime(strTime.GetBuffer(256), 256, pszFormat, &time); +#endif + strTime.ReleaseBuffer(); + return strTime; + } + + CString Format(UINT nID) const + { + struct tm time; + _localtime64_s(&time, &m_nSpan); + CString strFormat; + strFormat.LoadString(nID); + CString strTime; +#ifdef UNICODE + wcsftime(strTime.GetBuffer(256), 256, strFormat, &time); +#else + strftime(strTime.GetBuffer(256), 256, strFormat, &time); +#endif + strTime.ReleaseBuffer(); + return strTime; + } + + LONGLONG GetTotalHours() const throw() + { + return m_nSpan / 60 / 60; + } + + LONGLONG GetTotalMinutes() const throw() + { + return m_nSpan / 60; + } + + LONGLONG GetTotalSeconds() const throw() + { + return m_nSpan; + } + + LONGLONG GetDays() const throw() + { + return m_nSpan / 60 / 60 / 24; + } + + LONG GetHours() const throw() + { + return GetTotalHours() - GetDays() * 24; + } + + LONG GetMinutes() const throw() + { + return GetTotalMinutes() - GetTotalHours() * 60; + } + + LONG GetSeconds() const throw() + { + return GetTotalSeconds() - GetTotalMinutes() * 60; + } + + __time64_t GetTimeSpan() const throw() + { + return m_nSpan; + } + +// CArchive& Serialize64(CArchive& ar) // MFC only +// { +// // TODO +// } + +}; + +class CTime +{ + __time64_t m_nTime; +public: + CTime() throw() + { + // leave uninitialized + } + + CTime(__time64_t time) throw() + { + m_nTime = time; + } + + CTime(int nYear, int nMonth, int nDay, int nHour, int nMin, int nSec, int nDST = -1) + { + struct tm time; + time.tm_year = nYear; + time.tm_mon = nMonth; + time.tm_mday = nDay; + time.tm_hour = nHour; + time.tm_min = nMin; + time.tm_sec = nSec; + time.tm_isdst = nDST; + m_nTime = _mktime64(&time); + } + + CTime(WORD wDosDate, WORD wDosTime, int nDST = -1) + { + FILETIME ft; + DosDateTimeToFileTime(wDosDate, wDosTime, &ft); + SYSTEMTIME st; + FileTimeToSystemTime(&ft, &st); + struct tm time; + time.tm_year = st.wYear; + time.tm_mon = st.wMonth; + time.tm_wday = st.wDayOfWeek; + time.tm_hour = st.wHour; + time.tm_min = st.wMinute; + time.tm_sec = st.wSecond; + time.tm_isdst = nDST; + m_nTime = _mktime64(&time); + } + + CTime(const SYSTEMTIME& st, int nDST = -1) throw() + { + struct tm time; + time.tm_year = st.wYear; + time.tm_mon = st.wMonth; + time.tm_wday = st.wDayOfWeek; + time.tm_hour = st.wHour; + time.tm_min = st.wMinute; + time.tm_sec = st.wSecond; + time.tm_isdst = nDST; + m_nTime = _mktime64(&time); + } + + CTime(const FILETIME& ft, int nDST = -1) + { + SYSTEMTIME st; + FileTimeToSystemTime(&ft, &st); + struct tm time; + time.tm_year = st.wYear; + time.tm_mon = st.wMonth; + time.tm_wday = st.wDayOfWeek; + time.tm_hour = st.wHour; + time.tm_min = st.wMinute; + time.tm_sec = st.wSecond; + time.tm_isdst = nDST; + m_nTime = _mktime64(&time); + } + + CTime(const DBTIMESTAMP& dbts, int nDST = -1) throw() + { + struct tm time; + time.tm_year = dbts.year; + time.tm_mon = dbts.month; + time.tm_hour = dbts.hour; + time.tm_min = dbts.minute; + time.tm_sec = dbts.second; + time.tm_isdst = nDST; + m_nTime = _mktime64(&time); + } + + CString Format(LPCTSTR pszFormat) const + { + struct tm time; + _localtime64_s(&time, &m_nTime); + CString strTime; +#ifdef UNICODE + wcsftime(strTime.GetBuffer(256), 256, pszFormat, &time); +#else + strftime(strTime.GetBuffer(256), 256, pszFormat, &time); +#endif + strTime.ReleaseBuffer(); + return strTime; + } + + CString Format(UINT nFormatID) const + { + struct tm time; + _localtime64_s(&time, &m_nTime); + CString strFormat; + strFormat.LoadString(nFormatID); + CString strTime; +#ifdef UNICODE + wcsftime(strTime.GetBuffer(256), 256, strFormat, &time); +#else + strftime(strTime.GetBuffer(256), 256, strFormat, &time); +#endif + strTime.ReleaseBuffer(); + return strTime; + } + + CString FormatGmt(LPCTSTR pszFormat) const + { + struct tm time; + _gmtime64_s(&time, &m_nTime); + CString strTime; +#ifdef UNICODE + wcsftime(strTime.GetBuffer(256), 256, pszFormat, &time); +#else + strftime(strTime.GetBuffer(256), 256, pszFormat, &time); +#endif + strTime.ReleaseBuffer(); + return strTime; + } + + CString FormatGmt(UINT nFormatID) const + { + struct tm time; + _gmtime64_s(&time, &m_nTime); + CString strFormat; + strFormat.LoadString(nFormatID); + CString strTime; +#ifdef UNICODE + wcsftime(strTime.GetBuffer(256), 256, strFormat, &time); +#else + strftime(strTime.GetBuffer(256), 256, strFormat, &time); +#endif + strTime.ReleaseBuffer(); + return strTime; + } + + bool GetAsDBTIMESTAMP(DBTIMESTAMP& dbts) const throw() + { + struct tm time; + _gmtime64_s(&time, &m_nTime); + dbts.year = time.tm_year; + dbts.month = time.tm_mon; + dbts.day = time.tm_mday; + dbts.hour = time.tm_hour; + dbts.minute = time.tm_min; + dbts.second = time.tm_sec; + dbts.fraction = 0; + return true; // TODO: error handling? + } + + bool GetAsSystemTime(SYSTEMTIME& st) const throw() + { + struct tm time; + _gmtime64_s(&time, &m_nTime); + st.wYear = time.tm_year; + st.wMonth = time.tm_mon; + st.wDayOfWeek = time.tm_wday; + st.wDay = time.tm_mday; + st.wHour = time.tm_hour; + st.wMinute = time.tm_min; + st.wSecond = time.tm_sec; + st.wMilliseconds = 0; + return true; // TODO: error handling? + } + + static CTime WINAPI GetCurrentTime() throw() + { + __time64_t time; + _time64(&time); + return CTime(time); + } + + int GetDay() const throw() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_mday; + } + + int GetDayOfWeek() const throw() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_wday; + } + + struct tm* GetGmtTm(struct tm* ptm) const + { + _gmtime64_s(ptm, &m_nTime); + return ptm; + } + + int GetHour() const throw() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_hour; + } + + struct tm* GetLocalTm(struct tm* ptm) const + { + _localtime64_s(ptm, &m_nTime); + return ptm; + } + + int GetMinute() const throw() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_min; + } + + int GetMonth() const throw() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_mon; + } + + int GetSecond() const throw() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_sec; + } + + __time64_t GetTime() const throw() + { + return m_nTime; + } + + int GetYear() + { + struct tm time; + _localtime64_s(&time, &m_nTime); + return time.tm_year; + } + +// CArchive& Serialize64(CArchive& ar) // MFC only +// { +// // TODO +// } + + CTime operator+(CTimeSpan timeSpan) const throw() + { + return CTime(m_nTime + timeSpan.GetTimeSpan()); + } + + CTime operator-(CTimeSpan timeSpan) const throw() + { + return CTime(m_nTime - timeSpan.GetTimeSpan()); + } + + CTimeSpan operator-(CTime time) const throw() + { + return CTimeSpan(m_nTime - time.GetTime()); + } + + CTime& operator+=(CTimeSpan span) throw() + { + m_nTime += span.GetTimeSpan(); + return *this; + } + + CTime& operator-=(CTimeSpan span) throw() + { + m_nTime -= span.GetTimeSpan(); + return *this; + } + + CTime& operator=(__time64_t time) throw() + { + m_nTime = time; + return *this; + } + + bool operator==(CTime time) const throw() + { + return m_nTime == time.GetTime(); + } + + bool operator!=(CTime time) const throw() + { + return m_nTime != time.GetTime(); + } + + bool operator<(CTime time) const throw() + { + return m_nTime < time.GetTime(); + } + + bool operator>(CTime time) const throw() + { + return m_nTime > time.GetTime(); + } + + bool operator<=(CTime time) const throw() + { + return m_nTime <= time.GetTime(); + } + + bool operator>=(CTime time) const throw() + { + return m_nTime >= time.GetTime(); + } + +}; + +class CFileTimeSpan +{ + LONGLONG m_nSpan; +public: + CFileTimeSpan() throw() + { + m_nSpan = 0; + } + + CFileTimeSpan(const CFileTimeSpan& span) throw() + { + m_nSpan = span.GetTimeSpan(); + } + + CFileTimeSpan(LONGLONG nSpan) throw() + { + m_nSpan = nSpan; + } + + LONGLONG GetTimeSpan() const throw() + { + return m_nSpan; + } + + void SetTimeSpan(LONGLONG nSpan) throw() + { + m_nSpan = nSpan; + } + + CFileTimeSpan operator-(CFileTimeSpan span) const throw() + { + return CFileTimeSpan(m_nSpan - span.GetTimeSpan()); + } + + bool operator!=(CFileTimeSpan span) const throw() + { + return m_nSpan != span.GetTimeSpan(); + } + + CFileTimeSpan operator+(CFileTimeSpan span) const throw() + { + return CFileTimeSpan(m_nSpan + span.GetTimeSpan()); + } + + CFileTimeSpan& operator+=(CFileTimeSpan span) throw() + { + m_nSpan += span.GetTimeSpan(); + return *this; + } + + bool operator<(CFileTimeSpan span) const throw() + { + return m_nSpan < span.GetTimeSpan(); + } + + bool operator<=(CFileTimeSpan span) const throw() + { + return m_nSpan <= span.GetTimeSpan(); + } + + CFileTimeSpan& operator=(const CFileTimeSpan& span) throw() + { + m_nSpan = span.GetTimeSpan(); + return *this; + } + + CFileTimeSpan& operator-=(CFileTimeSpan span) throw() + { + m_nSpan -= span.GetTimeSpan(); + return *this; + } + + bool operator==(CFileTimeSpan span) const throw() + { + return m_nSpan == span.GetTimeSpan(); + } + + bool operator>(CFileTimeSpan span) const throw() + { + return m_nSpan > span.GetTimeSpan(); + } + + bool operator>=(CFileTimeSpan span) const throw() + { + return m_nSpan >= span.GetTimeSpan(); + } + +}; + +class CFileTime : public FILETIME +{ +public: + static const ULONGLONG Millisecond = 10000; + static const ULONGLONG Second = Millisecond * 1000; + static const ULONGLONG Minute = Second * 60; + static const ULONGLONG Hour = Minute * 60; + static const ULONGLONG Day = Hour * 24; + static const ULONGLONG Week = Day * 7; + + CFileTime() throw() + { + this->dwLowDateTime = 0; + this->dwHighDateTime = 0; + } + + CFileTime(const FILETIME& ft) throw() + { + this->dwLowDateTime = ft.dwLowDateTime; + this->dwHighDateTime = ft.dwHighDateTime; + } + + CFileTime(ULONGLONG nTime) throw() + { + this->dwLowDateTime = (DWORD) nTime; + this->dwHighDateTime = nTime >> 32; + } + + static CFileTime GetCurrentTime() throw() + { + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + return CFileTime(ft); + } + + ULONGLONG GetTime() const throw() + { + return ((ULONGLONG)this->dwLowDateTime) | (((ULONGLONG)this->dwHighDateTime) << 32); + } + + CFileTime LocalToUTC() const throw() + { + FILETIME ft; + LocalFileTimeToFileTime(this, &ft); + return CFileTime(ft); + } + + void SetTime(ULONGLONG nTime) throw() + { + this->dwLowDateTime = (DWORD) nTime; + this->dwHighDateTime = nTime >> 32; + } + + CFileTime UTCToLocal() const throw() + { + FILETIME ft; + FileTimeToLocalFileTime(this, &ft); + return CFileTime(ft); + } + + CFileTime operator-(CFileTimeSpan span) const throw() + { + return CFileTime(this->GetTime() - span.GetTimeSpan()); + } + + CFileTimeSpan operator-(CFileTime ft) const throw() + { + return CFileTimeSpan(this->GetTime() - ft.GetTime()); + } + + bool operator!=(CFileTime ft) const throw() + { + return this->GetTime() != ft.GetTime(); + } + + CFileTime operator+(CFileTimeSpan span) const throw() + { + return CFileTime(this->GetTime() + span.GetTimeSpan()); + } + + CFileTime& operator+=(CFileTimeSpan span) throw() + { + this->SetTime(this->GetTime() + span.GetTimeSpan()); + return *this; + } + + bool operator<(CFileTime ft) const throw() + { + return this->GetTime() < ft.GetTime(); + } + + bool operator<=(CFileTime ft) const throw() + { + return this->GetTime() <= ft.GetTime(); + } + + CFileTime& operator=(const FILETIME& ft) throw() + { + this->dwLowDateTime = ft.dwLowDateTime; + this->dwHighDateTime = ft.dwHighDateTime; + return *this; + } + + CFileTime& operator-=(CFileTimeSpan span) throw() + { + this->SetTime(this->GetTime() - span.GetTimeSpan()); + return *this; + } + + bool operator==(CFileTime ft) const throw() + { + return this->GetTime() == ft.GetTime(); + } + + bool operator>(CFileTime ft) const throw() + { + return this->GetTime() > ft.GetTime(); + } + + bool operator>=(CFileTime ft) const throw() + { + return this->GetTime() >= ft.GetTime(); + } + +}; + +} // namespace ATL + +#endif diff --git a/src/3rd_party/reactos-atl/atl/atltypes.h b/src/3rd_party/reactos-atl/atl/atltypes.h new file mode 100644 index 00000000..a4559c5e --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atltypes.h @@ -0,0 +1,569 @@ +/* + * ReactOS ATL + * + * Copyright 2016 Mark Jansen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + + +class CSize; +class CRect; + + +class CPoint : public tagPOINT +{ +public: + + CPoint() throw() + { + x = y = 0; + } + + CPoint(int initX, int initY) throw() + { + x = initX; + y = initY; + } + + CPoint(POINT initPt) throw() + { + *((POINT*)this) = initPt; + } + + CPoint(SIZE initSize) throw() + { + *((SIZE*)this) = initSize; + } + + CPoint(LPARAM dwPoint) throw() + { + x = LOWORD(dwPoint); + y = HIWORD(dwPoint); + } + + void Offset(int xOffset, int yOffset) throw() + { + x += xOffset; + y += yOffset; + } + + void Offset(POINT point) throw() + { + Offset(point.x, point.y); + } + + void Offset(SIZE size) throw() + { + Offset(size.cx, size.cy); + } + + BOOL operator==(POINT point) const throw() + { + return (x == point.x && y == point.y); + } + + BOOL operator!=(POINT point) const throw() + { + return !(*this == point); + } + + void operator+=(SIZE size) throw() + { + Offset(size); + } + + void operator+=(POINT point) throw() + { + Offset(point); + } + + void operator-=(SIZE size) throw() + { + Offset(-size.cx, -size.cy); + } + + void operator-=(POINT point) throw() + { + Offset(-point.x, -point.y); + } + + CPoint operator+(SIZE size) const throw() + { + return CPoint(x + size.cx, y + size.cy); + } + + CPoint operator+(POINT point) const throw() + { + return CPoint(x + point.x, y + point.y); + } + + CRect operator+(const RECT* lpRect) const throw(); + + CSize operator-(POINT point) const throw(); + + CPoint operator-(SIZE size) const throw() + { + return CPoint(x - size.cx, y - size.cy); + } + + CRect operator-(const RECT* lpRect) const throw(); + + CPoint operator-() const throw() + { + return CPoint(-x, -y); + } +}; + +class CSize : public tagSIZE +{ +public: + CSize() throw() + { + cx = cy = 0; + } + + CSize(int initCX, int initCY) throw() + { + cx = initCX; + cy = initCY; + } + + CSize(SIZE initSize) throw() + { + *((SIZE*)this) = initSize; + } + + CSize(POINT initPt) throw() + { + *((POINT*)this) = initPt; + } + + CSize(DWORD dwSize) throw() + { + cx = LOWORD(dwSize); + cy = HIWORD(dwSize); + } + + BOOL operator==(SIZE size) const throw() + { + return (size.cx == cx && size.cy == cy); + } + + BOOL operator!=(SIZE size) const throw() + { + return !(*this == size); + } + + void operator+=(SIZE size) throw() + { + cx += size.cx; + cy += size.cy; + } + + void operator-=(SIZE size) throw() + { + cx -= size.cx; + cy -= size.cy; + } + + CSize operator+(SIZE size) const throw() + { + return CSize(cx + size.cx, cy + size.cy); + } + + CPoint operator+(POINT point) const throw() + { + return CPoint(cx + point.x, cy + point.y); + } + + CRect operator+(const RECT* lpRect) const throw(); + + CSize operator-(SIZE size) const throw() + { + return CSize(cx - size.cx, cy - size.cy); + } + + CPoint operator-(POINT point) const throw() + { + return CPoint(cx - point.x, cy - point.y); + } + + CRect operator-(const RECT* lpRect) const throw(); + + CSize operator-() const throw() + { + return CSize(-cx, -cy); + } +}; + + +inline CSize CPoint::operator-(POINT point) const throw() +{ + return CSize(x - point.x, y - point.y); +} + + +class CRect : public tagRECT +{ +public: + CRect() throw() + { + left = top = right = bottom = 0; + } + + CRect(int l, int t, int r, int b) throw() + { + left = l; + top = t; + right = r; + bottom = b; + } + + CRect(const RECT& srcRect) throw() + { + left = srcRect.left; + top = srcRect.top; + right = srcRect.right; + bottom = srcRect.bottom; + } + + CRect(LPCRECT lpSrcRect) throw() + { + left = lpSrcRect->left; + top = lpSrcRect->top; + right = lpSrcRect->right; + bottom = lpSrcRect->bottom; + } + + CRect(POINT point, SIZE size) throw() + { + left = point.x; + top = point.y; + right = point.x + size.cx; + bottom = point.y + size.cy; + } + + CRect(POINT topLeft, POINT bottomRight) throw() + { + left = topLeft.x; + top = topLeft.y; + right = bottomRight.x; + bottom = bottomRight.y; + } + + CPoint& BottomRight() throw() + { + return ((CPoint*)this)[1]; + } + + const CPoint& BottomRight() const throw() + { + return ((const CPoint*)this)[1]; + } + + CPoint CenterPoint() const throw() + { + return CPoint(left + (Width() >> 1), top + (Height() >> 1)); + } + + void CopyRect(LPCRECT lpSrcRect) throw() + { + ::CopyRect(this, lpSrcRect); + } + + void DeflateRect(int x, int y) throw() + { + ::InflateRect(this, -x, -y); + } + + void DeflateRect(SIZE size) throw() + { + ::InflateRect(this, -size.cx, -size.cy); + } + + void DeflateRect(LPCRECT lpRect) throw() + { + DeflateRect(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + void DeflateRect(int l, int t, int r, int b) throw() + { + left += l; + top += t; + right -= r; + bottom -= b; + } + + BOOL EqualRect(LPCRECT lpRect) const throw() + { + return ::EqualRect(this, lpRect); + } + + + int Height() const throw() + { + return bottom - top; + } + + void InflateRect(int x, int y) throw() + { + ::InflateRect(this, x, y); + } + + void InflateRect(SIZE size) throw() + { + ::InflateRect(this, size.cx, size.cy); + } + + void InflateRect(LPCRECT lpRect) throw() + { + InflateRect(lpRect->left, lpRect->top, lpRect->right, lpRect->bottom); + } + + void InflateRect(int l, int t, int r, int b) throw() + { + left -= l; + top -= t; + right += r; + bottom += b; + } + + BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2) throw() + { + return ::IntersectRect(this, lpRect1, lpRect2); + } + + BOOL IsRectEmpty() const throw() + { + return ::IsRectEmpty(this); + } + + BOOL IsRectNull() const throw() + { + return (left == 0 && right == 0 && + top == 0 && bottom == 0); + } + + //void MoveToX(int x) throw() + //void MoveToXY(int x, int y) throw() + //void MoveToXY(POINT point) throw() + //void MoveToY(int y) throw() + //void NormalizeRect() throw() + + void OffsetRect(int x, int y) throw() + { + ::OffsetRect(this, x, y); + } + + void OffsetRect(POINT point) throw() + { + ::OffsetRect(this, point.x, point.y); + } + + void OffsetRect(SIZE size) throw() + { + ::OffsetRect(this, size.cx, size.cy); + } + + BOOL PtInRect(POINT point) const throw() + { + return ::PtInRect(this, point); + } + //void SetRect(int x1, int y1, int x2, int y2) throw() + //void SetRectEmpty() throw() + //CSize Size() const throw() + //BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2) throw() + + CPoint& TopLeft() throw() + { + return ((CPoint*)this)[0]; + } + + const CPoint& TopLeft() const throw() + { + return ((const CPoint*)this)[0]; + } + + BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2) throw() + { + return ::UnionRect(this, lpRect1, lpRect2); + } + + int Width() const throw() + { + return right - left; + } + + + BOOL operator==(const RECT& rect) const throw() + { + return (left == rect.left && + top == rect.top && + right == rect.right && + bottom == rect.bottom); + } + + BOOL operator!=(const RECT& rect) const throw() + { + return !(*this == rect); + } + + void operator=(const RECT& srcRect) throw() + { + left = srcRect.left; + top = srcRect.top; + right = srcRect.right; + bottom = srcRect.bottom; + } + + void operator+=(POINT point) throw() + { + OffsetRect(point); + } + + void operator+=(SIZE size) throw() + { + OffsetRect(size); + } + + void operator+=(LPCRECT lpRect) throw() + { + InflateRect(lpRect); + } + + void operator-=(POINT point) throw() + { + OffsetRect(-point.x, -point.y); + } + + void operator-=(SIZE size) throw() + { + OffsetRect(-size.cx, -size.cy); + } + + void operator-=(LPCRECT lpRect) throw() + { + DeflateRect(lpRect); + } + + + CRect operator+(POINT point) const throw() + { + CRect r(this); + r.OffsetRect(point); + return r; + } + + CRect operator+(LPCRECT lpRect) const throw() + { + CRect r(this); + r.InflateRect(lpRect); + return r; + } + + CRect operator+(SIZE size) const throw() + { + CRect r(this); + r.OffsetRect(size); + return r; + } + + CRect operator-(POINT point) const throw() + { + CRect r(this); + r.OffsetRect(-point.x, -point.y); + return r; + } + + CRect operator-(SIZE size) const throw() + { + CRect r(this); + r.OffsetRect(-size.cx, -size.cy); + return r; + } + + CRect operator-(LPCRECT lpRect) const throw() + { + CRect r(this); + r.DeflateRect(lpRect); + return r; + } + + void operator&=(const RECT& rect) throw() + { + IntersectRect(this, &rect); + } + + CRect operator&(const RECT& rect2) const throw() + { + CRect r; + r.IntersectRect(this, &rect2); + return r; + } + + void operator|=(const RECT& rect) throw() + { + UnionRect(this, &rect); + } + + CRect operator|(const RECT& rect2) const throw() + { + CRect r; + r.UnionRect(this, &rect2); + return r; + } + + operator LPRECT() throw() + { + return this; + } + + operator LPCRECT() const throw() + { + return this; + } +}; + +inline CRect CPoint::operator+(const RECT* lpRect) const throw() +{ + CRect r(lpRect); + r += *this; + return r; +} + +inline CRect CPoint::operator-(const RECT* lpRect) const throw() +{ + CRect r(lpRect); + r -= *this; + return r; +} + +inline CRect CSize::operator+(const RECT* lpRect) const throw() +{ + CRect r(lpRect); + r += *this; + return r; +} + +inline CRect CSize::operator-(const RECT* lpRect) const throw() +{ + CRect r(lpRect); + r -= *this; + return r; +} + diff --git a/src/3rd_party/reactos-atl/atl/atlwin.h b/src/3rd_party/reactos-atl/atl/atlwin.h new file mode 100644 index 00000000..214c2959 --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/atlwin.h @@ -0,0 +1,1978 @@ +/* + * ReactOS ATL + * + * Copyright 2009 Andrew Hill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +#if defined(__GNUC__) || defined(__clang__) +#define GCCU(x) x __attribute__((unused)) +#define Unused(x) +#else +#define GCCU(x) (x) +#define Unused(x) (x); +#endif // __GNUC__ + +#if !defined(_WIN64) +#ifdef SetWindowLongPtr +#undef SetWindowLongPtr +inline LONG_PTR SetWindowLongPtr(HWND hWnd, int nIndex, LONG_PTR dwNewLong) +{ + return SetWindowLong(hWnd, nIndex, (LONG)dwNewLong); +} +#endif + +#ifdef GetWindowLongPtr +#undef GetWindowLongPtr +inline LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) +{ + return (LONG_PTR)GetWindowLong(hWnd, nIndex); +} +#endif +#endif // !_WIN64 + +#pragma push_macro("SubclassWindow") +#undef SubclassWindow + +namespace ATL +{ + +#ifndef GET_X_LPARAM +#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) +#endif +#ifndef GET_Y_LPARAM +#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) +#endif + + + +struct _ATL_WNDCLASSINFOW; +typedef _ATL_WNDCLASSINFOW CWndClassInfo; + +template +class CWinTraits +{ +public: + static DWORD GetWndStyle(DWORD dwStyle) + { + if (dwStyle == 0) + return t_dwStyle; + return dwStyle; + } + + static DWORD GetWndExStyle(DWORD dwExStyle) + { + if (dwExStyle == 0) + return t_dwExStyle; + return dwExStyle; + } +}; + +typedef CWinTraits CControlWinTraits; +typedef CWinTraits CFrameWinTraits; +typedef CWinTraits CMDIChildWinTraits; + +template +class CWinTraitsOR +{ +public: + static DWORD GetWndStyle(DWORD dwStyle) + { + return dwStyle | t_dwStyle | TWinTraits::GetWndStyle(dwStyle); + } + + static DWORD GetWndExStyle(DWORD dwExStyle) + { + return dwExStyle | t_dwExStyle | TWinTraits::GetWndExStyle(dwExStyle); + } +}; + +class _U_MENUorID +{ +public: + HMENU m_hMenu; +public: + _U_MENUorID(HMENU hMenu) + { + m_hMenu = hMenu; + } + + _U_MENUorID(UINT nID) + { + m_hMenu = (HMENU)(UINT_PTR)nID; + } +}; + +class _U_RECT +{ +public: + LPRECT m_lpRect; +public: + _U_RECT(LPRECT lpRect) + { + m_lpRect = lpRect; + } + + _U_RECT(RECT &rc) + { + m_lpRect = &rc; + } +}; + +struct _ATL_MSG : public MSG +{ +public: + BOOL bHandled; +public: + _ATL_MSG(HWND hWnd, UINT uMsg, WPARAM wParamIn, LPARAM lParamIn, BOOL bHandledIn = TRUE) + { + hwnd = hWnd; + message = uMsg; + wParam = wParamIn; + lParam = lParamIn; + time = 0; + pt.x = 0; + pt.y = 0; + bHandled = bHandledIn; + } +}; + +#if defined(_M_IX86) + +#pragma pack(push,1) +struct thunkCode +{ + DWORD m_mov; /* mov dword ptr [esp+4], m_this */ + DWORD m_this; + BYTE m_jmp; /* jmp relproc */ + DWORD m_relproc; + + void + Init(WNDPROC proc, void *pThis) + { + m_mov = 0x042444C7; + m_this = PtrToUlong(pThis); + m_jmp = 0xe9; + m_relproc = DWORD(reinterpret_cast(proc) - (reinterpret_cast(this) + sizeof(thunkCode))); + FlushInstructionCache(GetCurrentProcess(), this, sizeof(thunkCode)); + } +}; +#pragma pack(pop) + +#elif defined(_AMD64_) + +#pragma pack(push,1) +struct thunkCode +{ + USHORT m_mov_rcx; /* mov rcx, m_this */ + ULONG64 m_this; + USHORT m_mov_rax; /* mov rax, m_proc */ + ULONG64 m_proc; + USHORT m_jmp; /* jmp rax */ + + void + Init(WNDPROC proc, void *pThis) + { + m_mov_rcx = 0xb948; + m_this = (ULONG64)pThis; + m_mov_rax = 0xb848; + m_proc = (ULONG64)proc; + m_jmp = 0xe0ff; + FlushInstructionCache(GetCurrentProcess(), this, sizeof(thunkCode)); + } +}; +#pragma pack(pop) + +#elif defined(_M_ARM) + +#pragma pack(push,4) +struct thunkCode +{ + DWORD m_mov_r0; /* mov r0, m_this */ + DWORD m_mov_pc; /* mov pc, m_proc */ + DWORD m_this; + DWORD m_proc; + + void + Init(WNDPROC proc, void *pThis) + { + m_mov_r0 = 0xE59F0000; + m_mov_pc = 0xE59FF000; + m_this = (DWORD)pThis; + m_proc = (DWORD)proc; + FlushInstructionCache(GetCurrentProcess(), this, sizeof(thunkCode)); + } +}; +#pragma pack(pop) + +#else +#error ARCH not supported +#endif + +class CWndProcThunk +{ +public: + thunkCode *m_pthunk; + _AtlCreateWndData cd; +public: + + CWndProcThunk() + { + m_pthunk = (thunkCode*)VirtualAlloc(NULL, sizeof(thunkCode), MEM_COMMIT, PAGE_EXECUTE_READWRITE); + } + + ~CWndProcThunk() + { + if (m_pthunk != NULL) + VirtualFree(m_pthunk, 0, MEM_RELEASE); + } + + BOOL Init(WNDPROC proc, void *pThis) + { + if (m_pthunk == NULL) + return FALSE; + m_pthunk->Init(proc, pThis); + return TRUE; + } + + WNDPROC GetWNDPROC() + { + return reinterpret_cast(m_pthunk); + } +}; + +class CMessageMap +{ +public: + virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID) = 0; +}; + +class CWindow +{ +public: + HWND m_hWnd; + static RECT rcDefault; +public: + CWindow(HWND hWnd = NULL) + { + m_hWnd = hWnd; + } + + operator HWND() const + { + return m_hWnd; + } + + static LPCTSTR GetWndClassName() + { + return NULL; + } + + UINT ArrangeIconicWindows() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ArrangeIconicWindows(m_hWnd); + } + + void Attach(HWND hWndNew) + { + m_hWnd = hWndNew; + } + + HDC BeginPaint(LPPAINTSTRUCT lpPaint) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::BeginPaint(m_hWnd, lpPaint); + } + + BOOL BringWindowToTop() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::BringWindowToTop(m_hWnd); + } + + BOOL CenterWindow(HWND hWndCenter = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + if (hWndCenter == NULL) + hWndCenter = ::GetParent(m_hWnd); + if (hWndCenter == NULL) + return FALSE; + RECT wndCenterRect, wndRect; + if (!::GetWindowRect(hWndCenter, &wndCenterRect) || !::GetWindowRect(m_hWnd, &wndRect)) + return FALSE; + int wndCenterWidth = wndCenterRect.right - wndCenterRect.left; + int wndCenterHeight = wndCenterRect.bottom - wndCenterRect.top; + int wndWidth = wndRect.right - wndRect.left; + int wndHeight = wndRect.bottom - wndRect.top; + return ::MoveWindow(m_hWnd, + wndCenterRect.left + ((wndCenterWidth - wndWidth + 1) >> 1), + wndCenterRect.top + ((wndCenterHeight - wndHeight + 1) >> 1), + wndWidth, wndHeight, TRUE); + } + + BOOL ChangeClipboardChain(HWND hWndNewNext) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ChangeClipboardChain(m_hWnd, hWndNewNext); + } + + BOOL CheckDlgButton(int nIDButton, UINT nCheck) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CheckDlgButton(m_hWnd, nIDButton, nCheck); + } + + BOOL CheckRadioButton(int nIDFirstButton, int nIDLastButton, int nIDCheckButton) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CheckRadioButton(m_hWnd, nIDFirstButton, nIDLastButton, nIDCheckButton); + } + + HWND ChildWindowFromPoint(POINT point) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ChildWindowFromPoint(m_hWnd, point); + } + + HWND ChildWindowFromPointEx(POINT point, UINT uFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ChildWindowFromPointEx(m_hWnd, point, uFlags); + } + + BOOL ClientToScreen(LPPOINT lpPoint) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ClientToScreen(m_hWnd, lpPoint); + } + + BOOL ClientToScreen(LPRECT lpRect) const + { + if (lpRect == NULL) + return FALSE; + ATLASSERT(::IsWindow(m_hWnd)); + POINT leftTop = {lpRect->left, lpRect->top}; + POINT rightBottom = {lpRect->right, lpRect->bottom}; + BOOL success = ::ClientToScreen(m_hWnd, &leftTop) && ::ClientToScreen(m_hWnd, &rightBottom); + if (success) + { + lpRect->left = leftTop.x; + lpRect->top = leftTop.y; + lpRect->right = rightBottom.x; + lpRect->bottom = rightBottom.y; + } + return success; + } + + HWND Create(LPCTSTR lpstrWndClass, HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + HWND hWnd; + ATLASSERT(m_hWnd == NULL); + hWnd = ::CreateWindowEx(dwExStyle, + lpstrWndClass, + szWindowName, + dwStyle, + rect.m_lpRect->left, + rect.m_lpRect->top, + rect.m_lpRect->right - rect.m_lpRect->left, + rect.m_lpRect->bottom - rect.m_lpRect->top, + hWndParent, + MenuOrID.m_hMenu, + _AtlBaseModule.GetModuleInstance(), + lpCreateParam); + if (hWnd != NULL) + m_hWnd = hWnd; + return hWnd; + } + + BOOL CreateCaret(HBITMAP pBitmap) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CreateCaret(m_hWnd, pBitmap, 0, 0); + } + + BOOL CreateGrayCaret(int nWidth, int nHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CreateCaret(m_hWnd, (HBITMAP)1, nWidth, nHeight); + } + + BOOL CreateSolidCaret(int nWidth, int nHeight) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::CreateCaret(m_hWnd, (HBITMAP)0, nWidth, nHeight); + } + + HDWP DeferWindowPos(HDWP hWinPosInfo, HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT uFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::DeferWindowPos(hWinPosInfo, m_hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + } + + BOOL DestroyWindow() + { + ATLASSERT(::IsWindow(m_hWnd)); + + if (!::DestroyWindow(m_hWnd)) + return FALSE; + + m_hWnd = NULL; + return TRUE; + } + + HWND Detach() + { + HWND hWnd = m_hWnd; + m_hWnd = NULL; + return hWnd; + } + + int DlgDirList(LPTSTR lpPathSpec, int nIDListBox, int nIDStaticPath, UINT nFileType) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::DlgDirList(m_hWnd, lpPathSpec, nIDListBox, nIDStaticPath, nFileType); + } + + int DlgDirListComboBox(LPTSTR lpPathSpec, int nIDComboBox, int nIDStaticPath, UINT nFileType) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::DlgDirListComboBox(m_hWnd, lpPathSpec, nIDComboBox, nIDStaticPath, nFileType); + } + + BOOL DlgDirSelect(LPTSTR lpString, int nCount, int nIDListBox) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::DlgDirSelectEx(m_hWnd, lpString, nCount, nIDListBox); + } + + BOOL DlgDirSelectComboBox(LPTSTR lpString, int nCount, int nIDComboBox) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::DlgDirSelectComboBoxEx(m_hWnd, lpString, nCount, nIDComboBox); + } + + void DragAcceptFiles(BOOL bAccept = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); +// FIXME following line requires shellapi.h +// ::DragAcceptFiles(m_hWnd, bAccept); + } + + BOOL DrawMenuBar() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::DrawMenuBar(m_hWnd); + } + + BOOL EnableScrollBar(UINT uSBFlags, UINT uArrowFlags = ESB_ENABLE_BOTH) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::EnableScrollBar(m_hWnd, uSBFlags, uArrowFlags); + } + + BOOL EnableWindow(BOOL bEnable = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::EnableWindow(m_hWnd, bEnable); + } + + void EndPaint(LPPAINTSTRUCT lpPaint) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::EndPaint(m_hWnd, lpPaint); + } + + BOOL FlashWindow(BOOL bInvert) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::FlashWindow(m_hWnd, bInvert); + } + + BOOL GetClientRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetClientRect(m_hWnd, lpRect); + } + + HDC GetDC() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetDC(m_hWnd); + } + + HDC GetDCEx(HRGN hRgnClip, DWORD flags) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetDCEx(m_hWnd, hRgnClip, flags); + } + +private: + typedef struct _IDHWNDPAIR { + int nID; + HWND hWnd; + } IDHWNDPAIR, *PIDHWNDPAIR; + + static BOOL CALLBACK GetDescendantWindowCallback(HWND hWnd, LPARAM lParam) + { + if (::GetWindowLong(hWnd, GWL_ID) == ((PIDHWNDPAIR)lParam)->nID) + { + ((PIDHWNDPAIR)lParam)->hWnd = hWnd; + return FALSE; + } + ::EnumChildWindows(hWnd, &GetDescendantWindowCallback, lParam); + return (((PIDHWNDPAIR)lParam)->hWnd == NULL); + } + +public: + HWND GetDescendantWindow(int nID) const + { + ATLASSERT(::IsWindow(m_hWnd)); + IDHWNDPAIR idHWndPair; + idHWndPair.nID = nID; + idHWndPair.hWnd = NULL; + ::EnumChildWindows(m_hWnd, &GetDescendantWindowCallback, (LPARAM)&idHWndPair); + return idHWndPair.hWnd; + } + + HRESULT GetDlgControl(int nID, REFIID iid, void** ppCtrl) + { + ATLASSERT(::IsWindow(m_hWnd)); + return E_FAIL;//FIXME stub + } + + int GetDlgCtrlID() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetDlgCtrlID(m_hWnd); + } + + HRESULT GetDlgHost(int nID, REFIID iid, void** ppHost) + { + ATLASSERT(::IsWindow(m_hWnd)); + return E_FAIL;//FIXME stub + } + + HWND GetDlgItem(int nID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetDlgItem(m_hWnd, nID); + } + + UINT GetDlgItemInt(int nID, BOOL* lpTrans = NULL, BOOL bSigned = TRUE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetDlgItemInt(m_hWnd, nID, lpTrans, bSigned); + } + + UINT GetDlgItemText(int nID, LPTSTR lpStr, int nMaxCount) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetDlgItemText(m_hWnd, nID, lpStr, nMaxCount); + } + +#ifdef __ATLSTR_H__ + UINT GetDlgItemText(int nID, CSimpleString& string) + { + HWND item = GetDlgItem(nID); + int len = ::GetWindowTextLength(item); + len = GetDlgItemText(nID, string.GetBuffer(len+1), len+1); + string.ReleaseBuffer(len); + return len; + } +#endif + + BOOL GetDlgItemText(int nID, BSTR& bstrText) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return FALSE;//FIXME stub + } + + DWORD GetExStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowLong(m_hWnd, GWL_EXSTYLE); + } + + HFONT GetFont() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HFONT)::SendMessage(m_hWnd, WM_GETFONT, 0, 0); + } + + DWORD GetHotKey() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (DWORD)::SendMessage(m_hWnd, WM_GETHOTKEY, 0, 0); + } + + HICON GetIcon(BOOL bBigIcon = TRUE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, WM_GETICON, (WPARAM)bBigIcon, 0); + } + + HWND GetLastActivePopup() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetLastActivePopup(m_hWnd); + } + + HMENU GetMenu() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetMenu(m_hWnd); + } + + HWND GetNextDlgGroupItem(HWND hWndCtl, BOOL bPrevious = FALSE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetNextDlgGroupItem(m_hWnd, hWndCtl, bPrevious); + } + + HWND GetNextDlgTabItem(HWND hWndCtl, BOOL bPrevious = FALSE) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetNextDlgTabItem(m_hWnd, hWndCtl, bPrevious); + } + + CWindow GetParent() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return CWindow(::GetParent(m_hWnd)); + } + + BOOL GetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetScrollInfo(m_hWnd, nBar, lpScrollInfo); + } + + BOOL GetScrollPos(int nBar) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetScrollPos(m_hWnd, nBar); + } + + BOOL GetScrollRange(int nBar, LPINT lpMinPos, LPINT lpMaxPos) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetScrollRange(m_hWnd, nBar, lpMinPos, lpMaxPos); + } + + DWORD GetStyle() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowLong(m_hWnd, GWL_STYLE); + } + + HMENU GetSystemMenu(BOOL bRevert) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetSystemMenu(m_hWnd, bRevert); + } + + HWND GetTopLevelParent() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return NULL;//FIXME stub + } + + HWND GetTopLevelWindow() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return NULL;//FIXME stub + } + + HWND GetTopWindow() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetTopWindow(m_hWnd); + } + + BOOL GetUpdateRect(LPRECT lpRect, BOOL bErase = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetUpdateRect(m_hWnd, lpRect, bErase); + } + + int GetUpdateRgn(HRGN hRgn, BOOL bErase = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return :: GetUpdateRgn(m_hWnd, hRgn, bErase); + } + + HWND GetWindow(UINT nCmd) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindow(m_hWnd, nCmd); + } + + DWORD GetWindowContextHelpId() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowContextHelpId(m_hWnd); + } + + HDC GetWindowDC() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowDC(m_hWnd); + } + + LONG GetWindowLong(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowLong(m_hWnd, nIndex); + } + + LONG_PTR GetWindowLongPtr(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowLongPtr(m_hWnd, nIndex); + } + + BOOL GetWindowPlacement(WINDOWPLACEMENT* lpwndpl) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowPlacement(m_hWnd, lpwndpl); + } + + DWORD GetWindowProcessID() + { + ATLASSERT(::IsWindow(m_hWnd)); + DWORD processID; + ::GetWindowThreadProcessId(m_hWnd, &processID); + return processID; + } + + BOOL GetWindowRect(LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowRect(m_hWnd, lpRect); + } + + int GetWindowRgn(HRGN hRgn) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowRgn(m_hWnd, hRgn); + } + + int GetWindowText(LPTSTR lpszStringBuf, int nMaxCount) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowText(m_hWnd, lpszStringBuf, nMaxCount); + } + + BOOL GetWindowText(BSTR& bstrText) + { + ATLASSERT(::IsWindow(m_hWnd)); + INT length = ::GetWindowTextLengthW(m_hWnd); + if (!::SysReAllocStringLen(&bstrText, NULL, length)) + return FALSE; + if (::GetWindowTextW(m_hWnd, bstrText, length + 1)) + return TRUE; + ::SysFreeString(bstrText); + bstrText = NULL; + return FALSE; + } + + int GetWindowTextLength() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowTextLength(m_hWnd); + } + + DWORD GetWindowThreadID() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::GetWindowThreadProcessId(m_hWnd, NULL); + } + + WORD GetWindowWord(int nIndex) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return (WORD)::GetWindowLong(m_hWnd, nIndex); + } + + void GotoDlgCtrl(HWND hWndCtrl) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0); + } + + BOOL HideCaret() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::HideCaret(m_hWnd); + } + + BOOL HiliteMenuItem(HMENU hMenu, UINT uHiliteItem, UINT uHilite) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::HiliteMenuItem(m_hWnd, hMenu, uHiliteItem, uHilite); + } + + BOOL Invalidate(BOOL bErase = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::InvalidateRect(m_hWnd, NULL, bErase); + } + + BOOL InvalidateRect(LPCRECT lpRect, BOOL bErase = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::InvalidateRect(m_hWnd, lpRect, bErase); + } + + void InvalidateRgn(HRGN hRgn, BOOL bErase = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::InvalidateRgn(m_hWnd, hRgn, bErase); + } + + BOOL IsChild(const HWND hWnd) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsChild(m_hWnd, hWnd); + } + + BOOL IsDialogMessage(LPMSG lpMsg) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsDialogMessage(m_hWnd, lpMsg); + } + + UINT IsDlgButtonChecked(int nIDButton) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsDlgButtonChecked(m_hWnd, nIDButton); + } + + BOOL IsIconic() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsIconic(m_hWnd); + } + + BOOL IsParentDialog() + { + ATLASSERT(::IsWindow(m_hWnd)); + TCHAR pszType[10]; + if (!RealGetWindowClass(::GetParent(m_hWnd), pszType, sizeof(pszType) / sizeof(pszType[0]))) + return FALSE; + return !_tcscmp(pszType, _T("#32770")); + } + + BOOL IsWindow() const + { + return ::IsWindow(m_hWnd); + } + + BOOL IsWindowEnabled() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsWindowEnabled(m_hWnd); + } + + BOOL IsWindowVisible() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsWindowVisible(m_hWnd); + } + + BOOL IsWindowUnicode() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsWindowUnicode(m_hWnd); + } + + BOOL IsZoomed() const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::IsZoomed(m_hWnd); + } + + BOOL KillTimer(UINT_PTR nIDEvent) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::KillTimer(m_hWnd, nIDEvent); + } + + BOOL LockWindowUpdate(BOOL bLock = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + if (bLock) + return ::LockWindowUpdate(m_hWnd); + return ::LockWindowUpdate(NULL); + } + + int MapWindowPoints(HWND hWndTo, LPPOINT lpPoint, UINT nCount) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::MapWindowPoints(m_hWnd, hWndTo, lpPoint, nCount); + } + + int MapWindowPoints(HWND hWndTo, LPRECT lpRect) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::MapWindowPoints(m_hWnd, hWndTo, (LPPOINT)lpRect, sizeof(RECT) / sizeof(POINT)); + } + + int MessageBox(LPCTSTR lpszText, LPCTSTR lpszCaption = NULL, UINT nType = MB_OK) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::MessageBox(m_hWnd, lpszText, lpszCaption, nType); + } + + BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SetWindowLong(m_hWnd, GWL_STYLE, (::GetWindowLong(m_hWnd, GWL_STYLE) & ~dwRemove) | dwAdd); + if (nFlags != 0) + return ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, nFlags | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + return TRUE; + } + + BOOL ModifyStyleEx(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SetWindowLong(m_hWnd, GWL_EXSTYLE, (::GetWindowLong(m_hWnd, GWL_EXSTYLE) & ~dwRemove) | dwAdd); + if (nFlags != 0) + return ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0, nFlags | SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + return TRUE; + } + + BOOL MoveWindow(int x, int y, int nWidth, int nHeight, BOOL bRepaint = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::MoveWindow(m_hWnd, x, y, nWidth, nHeight, bRepaint); + } + + void NextDlgCtrl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 0, 0); + } + + BOOL OpenClipboard() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::OpenClipboard(m_hWnd); + } + + BOOL PostMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::PostMessage(m_hWnd, message, wParam, lParam); + } + + void PrevDlgCtrl() const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_NEXTDLGCTL, 1, 0); + } + + void Print(HDC hDC, DWORD dwFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_PRINT, (WPARAM)hDC, (LPARAM)dwFlags); + } + + void PrintClient(HDC hDC, DWORD dwFlags) const + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_PRINTCLIENT, (WPARAM)hDC, (LPARAM)dwFlags); + } + + BOOL RedrawWindow(LPCRECT lpRectUpdate = NULL, HRGN hRgnUpdate = NULL, UINT flags = RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::RedrawWindow(m_hWnd, lpRectUpdate, hRgnUpdate, flags); + } + + int ReleaseDC(HDC hDC) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ReleaseDC(m_hWnd, hDC); + } + + BOOL ResizeClient(int nWidth, int nHeight, BOOL bRedraw = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + RECT clientRect, wndRect; + ::GetClientRect(m_hWnd, &clientRect); + ::GetWindowRect(m_hWnd, &wndRect); + return ::MoveWindow(m_hWnd, wndRect.left, wndRect.top, + nWidth + (wndRect.right - wndRect.left) - (clientRect.right - clientRect.left), + nHeight + (wndRect.bottom - wndRect.top) - (clientRect.bottom - clientRect.top), + bRedraw); + } + + BOOL ScreenToClient(LPPOINT lpPoint) const + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ScreenToClient(m_hWnd, lpPoint); + } + + BOOL ScrollWindow(int xAmount, int yAmount, LPCRECT lpRect = NULL, LPCRECT lpClipRect = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ScrollWindow(m_hWnd, xAmount, yAmount, lpRect, lpClipRect); + } + + int ScrollWindowEx(int dx, int dy, LPCRECT lpRectScroll, LPCRECT lpRectClip, HRGN hRgnUpdate, LPRECT lpRectUpdate, UINT flags) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ScrollWindowEx(m_hWnd, dx, dy, lpRectScroll, lpRectClip, hRgnUpdate, lpRectUpdate, flags); + } + + LRESULT SendDlgItemMessage(int nID, UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SendDlgItemMessage(m_hWnd, nID, message, wParam, lParam); + } + + LRESULT SendMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SendMessage(m_hWnd, message, wParam, lParam); + } + + static LRESULT SendMessage(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) + { + ATLASSERT(::IsWindow(hWnd)); + return ::SendMessage(hWnd, message, wParam, lParam); + } + +private: + static BOOL CALLBACK SendMessageToDescendantsCallback(HWND hWnd, LPARAM lParam) + { + ::SendMessage(hWnd, ((LPMSG)lParam)->message, ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam); + return TRUE; + } + + static BOOL CALLBACK SendMessageToDescendantsCallbackDeep(HWND hWnd, LPARAM lParam) + { + ::SendMessage(hWnd, ((LPMSG)lParam)->message, ((LPMSG)lParam)->wParam, ((LPMSG)lParam)->lParam); + ::EnumChildWindows(hWnd, &SendMessageToDescendantsCallbackDeep, lParam); + return TRUE; + } + +public: + void SendMessageToDescendants(UINT message, WPARAM wParam = 0, LPARAM lParam = 0, BOOL bDeep = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + MSG msg; + msg.message = message; + msg.wParam = wParam; + msg.lParam = lParam; + if (bDeep) + ::EnumChildWindows(m_hWnd, &SendMessageToDescendantsCallback, (LPARAM)&msg); + else + ::EnumChildWindows(m_hWnd, &SendMessageToDescendantsCallbackDeep, (LPARAM)&msg); + } + + BOOL SendNotifyMessage(UINT message, WPARAM wParam = 0, LPARAM lParam = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SendNotifyMessage(m_hWnd, message, wParam, lParam); + } + + HWND SetActiveWindow() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetActiveWindow(m_hWnd); + } + + HWND SetCapture() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetCapture(m_hWnd); + } + + HWND SetClipboardViewer() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetClipboardViewer(m_hWnd); + } + + int SetDlgCtrlID(int nID) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowLong(m_hWnd, GWL_ID, nID); + } + + BOOL SetDlgItemInt(int nID, UINT nValue, BOOL bSigned = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetDlgItemInt(m_hWnd, nID, nValue, bSigned); + } + + BOOL SetDlgItemText(int nID, LPCTSTR lpszString) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetDlgItemText(m_hWnd, nID, lpszString); + } + + HWND SetFocus() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetFocus(m_hWnd); + } + + void SetFont(HFONT hFont, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_SETFONT, (WPARAM)hFont, (LPARAM)bRedraw); + } + + int SetHotKey(WORD wVirtualKeyCode, WORD wModifiers) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SendMessage(m_hWnd, WM_SETHOTKEY, MAKEWPARAM(wVirtualKeyCode, wModifiers), 0); + } + + HICON SetIcon(HICON hIcon, BOOL bBigIcon = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return (HICON)::SendMessage(m_hWnd, WM_SETICON, (WPARAM)bBigIcon, (LPARAM)hIcon); + } + + BOOL SetMenu(HMENU hMenu) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetMenu(m_hWnd, hMenu); + } + + HWND SetParent(HWND hWndNewParent) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetParent(m_hWnd, hWndNewParent); + } + + void SetRedraw(BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + ::SendMessage(m_hWnd, WM_SETREDRAW, (WPARAM)bRedraw, 0); + } + + int SetScrollInfo(int nBar, LPSCROLLINFO lpScrollInfo, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetScrollInfo(m_hWnd, nBar, lpScrollInfo, bRedraw); + } + + int SetScrollPos(int nBar, int nPos, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetScrollPos(m_hWnd, nBar, nPos, bRedraw); + } + + BOOL SetScrollRange(int nBar, int nMinPos, int nMaxPos, BOOL bRedraw = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetScrollRange(m_hWnd, nBar, nMinPos, nMaxPos, bRedraw); + } + + UINT_PTR SetTimer(UINT_PTR nIDEvent, UINT nElapse, void (CALLBACK *lpfnTimer)(HWND, UINT, UINT_PTR, DWORD) = NULL) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetTimer(m_hWnd, nIDEvent, nElapse, reinterpret_cast(lpfnTimer)); + } + + BOOL SetWindowContextHelpId(DWORD dwContextHelpId) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowContextHelpId(m_hWnd, dwContextHelpId); + } + + LONG SetWindowLong(int nIndex, LONG dwNewLong) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowLong(m_hWnd, nIndex, dwNewLong); + } + + LONG_PTR SetWindowLongPtr(int nIndex, LONG_PTR dwNewLong) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowLongPtr(m_hWnd, nIndex, dwNewLong); + } + + BOOL SetWindowPlacement(const WINDOWPLACEMENT* lpwndpl) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowPlacement(m_hWnd, lpwndpl); + } + + BOOL SetWindowPos(HWND hWndInsertAfter, int x, int y, int cx, int cy, UINT nFlags) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowPos(m_hWnd, hWndInsertAfter, x, y, cx, cy, nFlags); + } + + int SetWindowRgn(HRGN hRgn, BOOL bRedraw = FALSE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowRgn(m_hWnd, hRgn, bRedraw); + } + + BOOL SetWindowText(LPCTSTR lpszString) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::SetWindowText(m_hWnd, lpszString); + } + + WORD SetWindowWord(int nIndex, WORD wNewWord) + { + ATLASSERT(::IsWindow(m_hWnd)); + if (nIndex >= -4) + return ::SetWindowLong(m_hWnd, nIndex - 2, MAKELONG(LOWORD(::GetWindowLong(m_hWnd, nIndex - 2)), wNewWord)); + else + return ::SetWindowLong(m_hWnd, nIndex, MAKELONG(wNewWord, HIWORD(::GetWindowLong(m_hWnd, nIndex)))); + } + + BOOL ShowCaret() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ShowCaret(m_hWnd); + } + + BOOL ShowOwnedPopups(BOOL bShow = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ShowOwnedPopups(m_hWnd, bShow); + } + + BOOL ShowScrollBar(UINT nBar, BOOL bShow = TRUE) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ShowScrollBar(m_hWnd, nBar, bShow); + } + + BOOL ShowWindow(int nCmdShow) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ShowWindow(m_hWnd, nCmdShow); + } + + BOOL ShowWindowAsync(int nCmdShow) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ShowWindowAsync(m_hWnd, nCmdShow); + } + + BOOL UpdateWindow() + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::UpdateWindow(m_hWnd); + } + + BOOL ValidateRect(LPCRECT lpRect) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ValidateRect(m_hWnd, lpRect); + } + + BOOL ValidateRgn(HRGN hRgn) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::ValidateRgn(m_hWnd, hRgn); + } + + BOOL WinHelp(LPCTSTR lpszHelp, UINT nCmd = HELP_CONTEXT, DWORD dwData = 0) + { + ATLASSERT(::IsWindow(m_hWnd)); + return ::WinHelp(m_hWnd, lpszHelp, nCmd, dwData); + } +}; + +__declspec(selectany) RECT CWindow::rcDefault = { CW_USEDEFAULT, CW_USEDEFAULT, 0, 0 }; + +template +class CWindowImplRoot : public TBase, public CMessageMap +{ +public: + enum { WINSTATE_DESTROYED = 0x00000001 }; + +public: + CWndProcThunk m_thunk; + const _ATL_MSG *m_pCurrentMsg; + DWORD m_dwState; + + CWindowImplRoot() + : m_pCurrentMsg(NULL) + , m_dwState(0) + { + } + + virtual ~CWindowImplRoot() + { + } +}; + + +template +class CDialogImplBaseT : public CWindowImplRoot +{ +public: + // + Hacks for gcc + using CWindowImplRoot::WINSTATE_DESTROYED; + // - Hacks for gcc + + virtual ~CDialogImplBaseT() + { + } + virtual DLGPROC GetDialogProc() + { + return DialogProc; + } + + static INT_PTR CALLBACK StartDialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CDialogImplBaseT *pThis; + DLGPROC newDlgProc; + DLGPROC GCCU(pOldProc); + + pThis = reinterpret_cast*>(_AtlWinModule.ExtractCreateWndData()); + ATLASSERT(pThis != NULL); + if (pThis == NULL) + return 0; + pThis->m_thunk.Init((WNDPROC)pThis->GetDialogProc(), pThis); + newDlgProc = reinterpret_cast(pThis->m_thunk.GetWNDPROC()); + pOldProc = reinterpret_cast(::SetWindowLongPtr(hWnd, DWLP_DLGPROC, reinterpret_cast(newDlgProc))); + Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass + pThis->m_hWnd = hWnd; + return newDlgProc(hWnd, uMsg, wParam, lParam); + } + + static INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CDialogImplBaseT *pThis = reinterpret_cast*>(hWnd); + _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); + LRESULT lResult = 0; + const _ATL_MSG *previousMessage; + BOOL handled; + + hWnd = pThis->m_hWnd; + previousMessage = pThis->m_pCurrentMsg; + pThis->m_pCurrentMsg = &msg; + + handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0); + ATLASSERT(pThis->m_pCurrentMsg == &msg); + + if (handled) + { + if ((pThis->m_dwState & WINSTATE_DESTROYED) == 0) + { + ::SetWindowLongPtr(pThis->m_hWnd, DWLP_MSGRESULT, lResult); + } + } + else + { + if (uMsg == WM_NCDESTROY) + { + pThis->m_dwState |= WINSTATE_DESTROYED; + } + } + + ATLASSERT(pThis->m_pCurrentMsg == &msg); + pThis->m_pCurrentMsg = previousMessage; + + if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0) + { + pThis->m_dwState &= ~WINSTATE_DESTROYED; + pThis->m_hWnd = NULL; + pThis->OnFinalMessage(hWnd); + } + return lResult; + } + + virtual void OnFinalMessage(HWND) + { + } +}; + + +template +class CDialogImpl : public CDialogImplBaseT< TBase > +{ +public: + // + Hacks for gcc + using CWindowImplRoot::m_thunk; + using CWindowImplRoot::m_hWnd; + // - Hacks for gcc + + HWND Create(HWND hWndParent, LPARAM dwInitParam = NULL) + { + BOOL result; + HWND hWnd; + T* pImpl; + + result = m_thunk.Init(NULL, NULL); + if (result == FALSE) + return NULL; + + _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); + + pImpl = static_cast(this); + hWnd = ::CreateDialogParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pImpl->IDD), hWndParent, T::StartDialogProc, dwInitParam); + return hWnd; + } + + INT_PTR DoModal(HWND hWndParent = ::GetActiveWindow(), LPARAM dwInitParam = NULL) + { + BOOL result; + T* pImpl; + + result = m_thunk.Init(NULL, NULL); + if (result == FALSE) + return -1; + + _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); + + pImpl = static_cast(this); + return ::DialogBoxParam(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(pImpl->IDD), hWndParent, T::StartDialogProc, dwInitParam); + } + + BOOL EndDialog(_In_ int nRetCode) + { + return ::EndDialog(m_hWnd, nRetCode); + } + + BOOL DestroyWindow() + { + return ::DestroyWindow(m_hWnd); + } +}; + +template +class CWindowImplBaseT : public CWindowImplRoot +{ +public: + // + Hacks for gcc + using CWindowImplRoot::WINSTATE_DESTROYED; + using CWindowImplRoot::m_thunk; + using CWindowImplRoot::m_hWnd; + // - Hacks for gcc + + WNDPROC m_pfnSuperWindowProc; + +public: + CWindowImplBaseT() + { + m_pfnSuperWindowProc = ::DefWindowProc; + } + + virtual void OnFinalMessage(HWND /* hWnd */) + { + } + + BOOL SubclassWindow(HWND hWnd) + { + ATLASSERT(m_hWnd == NULL); + ATLASSERT(::IsWindow(hWnd)); + + CWindowImplBaseT *pThis; + pThis = reinterpret_cast*>(this); + + BOOL result = m_thunk.Init(GetWindowProc(), this); + if (result == FALSE) + return FALSE; + + WNDPROC newWindowProc = m_thunk.GetWNDPROC(); + WNDPROC oldWindowProc = reinterpret_cast( + ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWindowProc))); + if (oldWindowProc == NULL) + return FALSE; + + pThis->m_pfnSuperWindowProc = oldWindowProc; + pThis->m_hWnd = hWnd; + return TRUE; + } + + HWND UnsubclassWindow(BOOL bForce = FALSE) + { + ATLASSERT(m_hWnd != NULL); + ATLASSERT(::IsWindow(m_hWnd)); + + CWindowImplBaseT* pThis; + pThis = reinterpret_cast*>(this); + + HWND hwndOld = pThis->m_hWnd; + WNDPROC oldWindowProc = m_thunk.GetWNDPROC(); + WNDPROC subclassedProc = reinterpret_cast( + ::GetWindowLongPtr(hwndOld, GWLP_WNDPROC)); + if (!bForce && oldWindowProc != subclassedProc) + return NULL; + + ::SetWindowLongPtr(hwndOld, GWLP_WNDPROC, + (LONG_PTR)pThis->m_pfnSuperWindowProc); + pThis->m_pfnSuperWindowProc = ::DefWindowProc; + pThis->m_hWnd = NULL; + return hwndOld; + } + + virtual WNDPROC GetWindowProc() + { + return WindowProc; + } + + static DWORD GetWndStyle(DWORD dwStyle) + { + return TWinTraits::GetWndStyle(dwStyle); + } + + static DWORD GetWndExStyle(DWORD dwExStyle) + { + return TWinTraits::GetWndExStyle(dwExStyle); + } + + LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CWindowImplBaseT *pThis; + + pThis = reinterpret_cast *>(this); + return ::CallWindowProc(m_pfnSuperWindowProc, pThis->m_hWnd, uMsg, wParam, lParam); + } + + static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CWindowImplBaseT *pThis; + WNDPROC newWindowProc; + WNDPROC GCCU(pOldProc); + + pThis = reinterpret_cast *>(_AtlWinModule.ExtractCreateWndData()); + ATLASSERT(pThis != NULL); + if (pThis == NULL) + return 0; + pThis->m_thunk.Init(pThis->GetWindowProc(), pThis); + newWindowProc = pThis->m_thunk.GetWNDPROC(); + pOldProc = reinterpret_cast(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWindowProc))); + Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass + pThis->m_hWnd = hWnd; + return newWindowProc(hWnd, uMsg, wParam, lParam); + } + + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CWindowImplBaseT *pThis = reinterpret_cast *>(hWnd); + _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); + LRESULT lResult; + const _ATL_MSG *previousMessage; + BOOL handled; + LONG_PTR saveWindowProc; + + ATLASSERT(pThis != NULL); + if (pThis == NULL) + return 0; + + ATLASSERT((pThis->m_dwState & WINSTATE_DESTROYED) == 0); + ATLASSERT(pThis->m_hWnd != NULL); + if ((pThis->m_dwState & WINSTATE_DESTROYED) != 0 || pThis->m_hWnd == NULL) + return 0; + + hWnd = pThis->m_hWnd; + previousMessage = pThis->m_pCurrentMsg; + pThis->m_pCurrentMsg = &msg; + + handled = pThis->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, 0); + ATLASSERT(pThis->m_pCurrentMsg == &msg); + + if (handled == FALSE) + { + if (uMsg == WM_NCDESTROY) + { + saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC); + lResult = pThis->DefWindowProc(uMsg, wParam, lParam); + if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC)) + ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(pThis->m_pfnSuperWindowProc)); + pThis->m_dwState |= WINSTATE_DESTROYED; + } + else + lResult = pThis->DefWindowProc(uMsg, wParam, lParam); + } + ATLASSERT(pThis->m_pCurrentMsg == &msg); + pThis->m_pCurrentMsg = previousMessage; + if (previousMessage == NULL && (pThis->m_dwState & WINSTATE_DESTROYED) != 0) + { + pThis->m_dwState &= ~WINSTATE_DESTROYED; + pThis->m_hWnd = NULL; + pThis->OnFinalMessage(hWnd); + } + return lResult; + } + + HWND Create(HWND hWndParent, _U_RECT rect, LPCTSTR szWindowName, DWORD dwStyle, DWORD dwExStyle, + _U_MENUorID MenuOrID, ATOM atom, LPVOID lpCreateParam) + { + HWND hWnd; + + ATLASSERT(m_hWnd == NULL); + ATLASSERT(atom != 0); + if (atom == 0) + return NULL; + if (m_thunk.Init(NULL, NULL) == FALSE) + { + SetLastError(ERROR_OUTOFMEMORY); + return NULL; + } + + _AtlWinModule.AddCreateWndData(&m_thunk.cd, this); + if (MenuOrID.m_hMenu == NULL && (dwStyle & WS_CHILD) != 0) + MenuOrID.m_hMenu = (HMENU)(UINT_PTR)this; + if (rect.m_lpRect == NULL) + rect.m_lpRect = &TBase::rcDefault; + hWnd = ::CreateWindowEx(dwExStyle, MAKEINTATOM(atom), szWindowName, dwStyle, rect.m_lpRect->left, + rect.m_lpRect->top, rect.m_lpRect->right - rect.m_lpRect->left, rect.m_lpRect->bottom - rect.m_lpRect->top, + hWndParent, MenuOrID.m_hMenu, _AtlBaseModule.GetModuleInstance(), lpCreateParam); + + ATLASSERT(m_hWnd == hWnd); + + return hWnd; + } +}; + + +template +class CWindowImpl : public CWindowImplBaseT +{ +public: + // + Hacks for gcc + using CWindowImplRoot::m_hWnd; + // - Hacks for gcc + + + static LPCTSTR GetWndCaption() + { + return NULL; + } + + HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL, DWORD dwStyle = 0, + DWORD dwExStyle = 0, _U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL) + { + CWindowImplBaseT *pThis; + ATOM atom; + + ATLASSERT(m_hWnd == NULL); + pThis = reinterpret_cast*>(this); + + if (T::GetWndClassInfo().m_lpszOrigName == NULL) + T::GetWndClassInfo().m_lpszOrigName = pThis->GetWndClassName(); + atom = T::GetWndClassInfo().Register(&pThis->m_pfnSuperWindowProc); + + if (szWindowName == NULL) + szWindowName = T::GetWndCaption(); + dwStyle = T::GetWndStyle(dwStyle); + dwExStyle = T::GetWndExStyle(dwExStyle); + + return CWindowImplBaseT::Create(hWndParent, rect, szWindowName, dwStyle, + dwExStyle, MenuOrID, atom, lpCreateParam); + } +}; + +template +class CContainedWindowT : public TBase +{ +public: + // + Hacks for gcc + using TBase::m_hWnd; + // - Hacks for gcc + + CWndProcThunk m_thunk; + LPCTSTR m_lpszClassName; + WNDPROC m_pfnSuperWindowProc; + CMessageMap *m_pObject; + DWORD m_dwMsgMapID; + const _ATL_MSG *m_pCurrentMsg; +public: + CContainedWindowT(CMessageMap *pObject, DWORD dwMsgMapID = 0) + { + m_lpszClassName = TBase::GetWndClassName(); + m_pfnSuperWindowProc = ::DefWindowProc; + m_pObject = pObject; + m_dwMsgMapID = dwMsgMapID; + m_pCurrentMsg = NULL; + } + + CContainedWindowT(LPCTSTR lpszClassName, CMessageMap *pObject, DWORD dwMsgMapID = 0) + { + m_lpszClassName = lpszClassName; + m_pfnSuperWindowProc = ::DefWindowProc; + m_pObject = pObject; + m_dwMsgMapID = dwMsgMapID; + m_pCurrentMsg = NULL; + } + + LRESULT DefWindowProc(UINT uMsg, WPARAM wParam, LPARAM lParam) + { + return ::CallWindowProc(m_pfnSuperWindowProc, this->m_hWnd, uMsg, wParam, lParam); + } + + BOOL SubclassWindow(HWND hWnd) + { + ATLASSERT(m_hWnd == NULL); + ATLASSERT(::IsWindow(hWnd)); + + CContainedWindowT *pThis; + pThis = reinterpret_cast *>(this); + + BOOL result = m_thunk.Init(WindowProc, pThis); + if (result == FALSE) + return FALSE; + + WNDPROC newWindowProc = m_thunk.GetWNDPROC(); + WNDPROC oldWindowProc = reinterpret_cast( + ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWindowProc))); + if (oldWindowProc == NULL) + return FALSE; + + pThis->m_pfnSuperWindowProc = oldWindowProc; + pThis->m_hWnd = hWnd; + return TRUE; + } + + HWND UnsubclassWindow(BOOL bForce = FALSE) + { + ATLASSERT(m_hWnd != NULL); + ATLASSERT(::IsWindow(m_hWnd)); + + CContainedWindowT* pThis; + pThis = reinterpret_cast*>(this); + HWND hwndOld = pThis->m_hWnd; + + WNDPROC subclassedProc = reinterpret_cast( + ::GetWindowLongPtr(hwndOld, GWLP_WNDPROC)); + if (!bForce && m_thunk.GetWNDPROC() != subclassedProc) + return NULL; + + ::SetWindowLongPtr(hwndOld, GWLP_WNDPROC, + (LONG_PTR)pThis->m_pfnSuperWindowProc); + pThis->m_pfnSuperWindowProc = ::DefWindowProc; + pThis->m_hWnd = NULL; + return hwndOld; + } + + static LRESULT CALLBACK StartWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CContainedWindowT *pThis; + WNDPROC newWindowProc; + WNDPROC GCCU(pOldProc); + + pThis = reinterpret_cast *>(_AtlWinModule.ExtractCreateWndData()); + ATLASSERT(pThis != NULL); + if (pThis == NULL) + return 0; + pThis->m_thunk.Init(WindowProc, pThis); + newWindowProc = pThis->m_thunk.GetWNDPROC(); + pOldProc = reinterpret_cast(::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(newWindowProc))); + Unused(pOldProc); // TODO: should generate trace message if overwriting another subclass + pThis->m_hWnd = hWnd; + return newWindowProc(hWnd, uMsg, wParam, lParam); + } + + static LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) + { + CContainedWindowT *pThis = reinterpret_cast *>(hWnd); + _ATL_MSG msg(pThis->m_hWnd, uMsg, wParam, lParam); + LRESULT lResult; + const _ATL_MSG *previousMessage; + BOOL handled; + LONG_PTR saveWindowProc; + + ATLASSERT(pThis != NULL && pThis->m_hWnd != NULL && pThis->m_pObject != NULL); + if (pThis == NULL || pThis->m_hWnd == NULL || pThis->m_pObject == NULL) + return 0; + + hWnd = pThis->m_hWnd; + previousMessage = pThis->m_pCurrentMsg; + pThis->m_pCurrentMsg = &msg; + + handled = pThis->m_pObject->ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult, pThis->m_dwMsgMapID); + ATLASSERT(pThis->m_pCurrentMsg == &msg); + + pThis->m_pCurrentMsg = previousMessage; + if (handled == FALSE) + { + if (uMsg == WM_NCDESTROY) + { + saveWindowProc = ::GetWindowLongPtr(hWnd, GWLP_WNDPROC); + lResult = pThis->DefWindowProc(uMsg, wParam, lParam); + if (pThis->m_pfnSuperWindowProc != ::DefWindowProc && saveWindowProc == ::GetWindowLongPtr(hWnd, GWLP_WNDPROC)) + ::SetWindowLongPtr(hWnd, GWLP_WNDPROC, reinterpret_cast(pThis->m_pfnSuperWindowProc)); + pThis->m_hWnd = NULL; + } + else + lResult = pThis->DefWindowProc(uMsg, wParam, lParam); + } + return lResult; + } + +}; +typedef CContainedWindowT CContainedWindow; + +#define BEGIN_MSG_MAP(theClass) \ +public: \ + BOOL ProcessWindowMessage(HWND GCCU(hWnd), UINT GCCU(uMsg), WPARAM GCCU(wParam), LPARAM GCCU(lParam), LRESULT &GCCU(lResult), DWORD dwMsgMapID = 0) \ + { \ + BOOL GCCU(bHandled) = TRUE; \ + Unused(hWnd); \ + Unused(uMsg); \ + Unused(wParam); \ + Unused(lParam); \ + Unused(lResult); \ + Unused(bHandled); \ + switch(dwMsgMapID) \ + { \ + case 0: + +#define ALT_MSG_MAP(map) \ + break; \ + case map: + +#define END_MSG_MAP() \ + break; \ + default: \ + ATLASSERT(FALSE); \ + break; \ + } \ + return FALSE; \ + } + +#define MESSAGE_HANDLER(msg, func) \ + if (uMsg == msg) \ + { \ + bHandled = TRUE; \ + lResult = func(uMsg, wParam, lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define MESSAGE_RANGE_HANDLER(msgFirst, msgLast, func) \ + if (uMsg >= msgFirst && uMsg <= msgLast) \ + { \ + bHandled = TRUE; \ + lResult = func(uMsg, wParam, lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define COMMAND_HANDLER(id, code, func) \ + if (uMsg == WM_COMMAND && id == LOWORD(wParam) && code == HIWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define COMMAND_ID_HANDLER(id, func) \ + if (uMsg == WM_COMMAND && id == LOWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define COMMAND_CODE_HANDLER(code, func) \ + if (uMsg == WM_COMMAND && code == HIWORD(wParam)) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define COMMAND_RANGE_HANDLER(idFirst, idLast, func) \ + if (uMsg == WM_COMMAND && LOWORD(wParam) >= idFirst && LOWORD(wParam) <= idLast) \ + { \ + bHandled = TRUE; \ + lResult = func(HIWORD(wParam), LOWORD(wParam), (HWND)lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define NOTIFY_CODE_HANDLER(cd, func) \ + if(uMsg == WM_NOTIFY && cd == ((LPNMHDR)lParam)->code) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define NOTIFY_HANDLER(id, cd, func) \ + if(uMsg == WM_NOTIFY && id == ((LPNMHDR)lParam)->idFrom && cd == ((LPNMHDR)lParam)->code) \ + { \ + bHandled = TRUE; \ + lResult = func((int)wParam, (LPNMHDR)lParam, bHandled); \ + if (bHandled) \ + return TRUE; \ + } + +#define CHAIN_MSG_MAP(theChainClass) \ + { \ + if (theChainClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, lResult)) \ + return TRUE; \ + } + +#define DECLARE_WND_CLASS_EX(WndClassName, style, bkgnd) \ +static ATL::CWndClassInfo& GetWndClassInfo() \ +{ \ + static ATL::CWndClassInfo wc = \ + { \ + { sizeof(WNDCLASSEX), style, StartWindowProc, \ + 0, 0, NULL, NULL, NULL, (HBRUSH)(bkgnd + 1), NULL, WndClassName, NULL }, \ + NULL, NULL, IDC_ARROW, TRUE, 0, _T("") \ + }; \ + return wc; \ +} + +struct _ATL_WNDCLASSINFOW +{ + WNDCLASSEX m_wc; + LPCTSTR m_lpszOrigName; + WNDPROC pWndProc; + LPCTSTR m_lpszCursorID; + BOOL m_bSystemCursor; + ATOM m_atom; + TCHAR m_szAutoName[sizeof("ATL:") + sizeof(void *) * 2]; // == 4 characters + NULL + number of hexadecimal digits describing a pointer. + + ATOM Register(WNDPROC *p) + { + if (m_wc.hInstance == NULL) + m_wc.hInstance = _AtlBaseModule.GetModuleInstance(); + if (m_atom == 0) + { + if (m_bSystemCursor) + m_wc.hCursor = ::LoadCursor(NULL, m_lpszCursorID); + else + m_wc.hCursor = ::LoadCursor(_AtlBaseModule.GetResourceInstance(), m_lpszCursorID); + + m_atom = RegisterClassEx(&m_wc); + } + + return m_atom; + } +}; + +}; // namespace ATL + +#pragma pop_macro("SubclassWindow") + diff --git a/src/3rd_party/reactos-atl/atl/cstringt.h b/src/3rd_party/reactos-atl/atl/cstringt.h new file mode 100644 index 00000000..f0dccbeb --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/cstringt.h @@ -0,0 +1,998 @@ +#ifndef __CSTRINGT_H__ +#define __CSTRINGT_H__ + +#pragma once +#include +#include +#include +#include +#include + +namespace ATL +{ + +inline UINT WINAPI _AtlGetConversionACP() throw() +{ +#ifdef _CONVERSION_DONT_USE_THREAD_LOCALE + return CP_ACP; +#else + return CP_THREAD_ACP; +#endif +} + + +template +class ChTraitsCRT : public ChTraitsBase<_CharType> +{ +public: + + static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw() + { + if (pszSource == NULL) return -1; + return static_cast(wcslen(pszSource)); + } + + static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw() + { + if (pszSource == NULL) return 0; + return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0) - 1; + } + + static int __cdecl GetBaseTypeLength( + _In_reads_(nLength) LPCWSTR pszSource, + _In_ int nLength) throw() + { + return nLength; + } + + static int __cdecl GetBaseTypeLength( + _In_reads_(nLength) LPCSTR pszSource, + _In_ int nLength) throw() + { + return ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0); + } + + static void __cdecl ConvertToBaseType( + _Out_writes_(nDestLength) LPWSTR pszDest, + _In_ int nDestLength, + _In_ LPCWSTR pszSrc, + _In_ int nSrcLength = -1) + { + if (nSrcLength == -1) + nSrcLength = 1 + GetBaseTypeLength(pszSrc); + + wmemcpy(pszDest, pszSrc, nSrcLength); + } + + static void __cdecl ConvertToBaseType( + _Out_writes_(nDestLength) LPWSTR pszDest, + _In_ int nDestLength, + _In_ LPCSTR pszSrc, + _In_ int nSrcLength = -1) + { + if (nSrcLength == -1) + nSrcLength = 1 + GetBaseTypeLength(pszSrc); + + ::MultiByteToWideChar(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength); + } + + static void __cdecl MakeLower( + _Out_writes_(nSrcLength) LPWSTR pszSource, + _In_ int nSrcLength) + { + ::CharLowerBuffW(pszSource, nSrcLength); + } + + static DWORD GetEnvironmentVariable( + _In_z_ LPCWSTR pszVar, + _Out_writes_opt_(nBufLength) LPWSTR pszBuf, + _In_opt_ int nBufLength) + { + return ::GetEnvironmentVariableW(pszVar, pszBuf, nBufLength); + } + + static void __cdecl MakeUpper( + _Out_writes_(nSrcLength) LPWSTR pszSource, + _In_ int nSrcLength) + { + ::CharUpperBuffW(pszSource, nSrcLength); + } + + static LPWSTR __cdecl FindString( + _In_z_ LPCWSTR pszSource, + _In_z_ LPCWSTR pszSub) + { + return ::wcsstr(pszSource, pszSub); + } + + static LPWSTR __cdecl FindChar( + _In_z_ LPCWSTR pszSource, + _In_ WCHAR ch) + { + return ::wcschr(pszSource, ch); + } + + static LPWSTR __cdecl FindCharReverse( + _In_z_ LPCWSTR pszSource, + _In_ WCHAR ch) + { + return ::wcsrchr(pszSource, ch); + } + + static LPWSTR __cdecl FindOneOf( + _In_z_ LPCWSTR pszSource, + _In_z_ LPCWSTR pszCharSet) + { + return ::wcspbrk(pszSource, pszCharSet); + } + + static int __cdecl Compare( + _In_z_ LPCWSTR psz1, + _In_z_ LPCWSTR psz2) + { + return ::wcscmp(psz1, psz2); + } + + static int __cdecl CompareNoCase( + _In_z_ LPCWSTR psz1, + _In_z_ LPCWSTR psz2) + { + return ::_wcsicmp(psz1, psz2); + } + + static int __cdecl StringSpanIncluding( + _In_z_ LPCWSTR pszBlock, + _In_z_ LPCWSTR pszSet) + { + return (int)::wcsspn(pszBlock, pszSet); + } + + static int __cdecl StringSpanExcluding( + _In_z_ LPCWSTR pszBlock, + _In_z_ LPCWSTR pszSet) + { + return (int)::wcscspn(pszBlock, pszSet); + } + + static int __cdecl FormatV( + _In_opt_z_ LPWSTR pszDest, + _In_z_ LPCWSTR pszFormat, + _In_ va_list args) + { + if (pszDest == NULL) + return ::_vscwprintf(pszFormat, args); + return ::vswprintf(pszDest, pszFormat, args); + } + + static LPWSTR + FormatMessageV(_In_z_ LPCWSTR pszFormat, _In_opt_ va_list *pArgList) + { + LPWSTR psz; + ::FormatMessageW( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, + reinterpret_cast(&psz), 0, pArgList); + return psz; + } + + static BSTR __cdecl AllocSysString( + _In_z_ LPCWSTR pszSource, + _In_ int nLength) + { + return ::SysAllocStringLen(pszSource, nLength); + } +}; + + +// Template specialization + +template<> +class ChTraitsCRT : public ChTraitsBase +{ +public: + + static int __cdecl GetBaseTypeLength(_In_z_ LPCWSTR pszSource) throw() + { + return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, -1, NULL, 0, NULL, NULL) - 1; + } + + static int __cdecl GetBaseTypeLength(_In_z_ LPCSTR pszSource) throw() + { + if (pszSource == NULL) return 0; + return static_cast(strlen(pszSource)); + } + + static int __cdecl GetBaseTypeLength( + _In_reads_(nLength) LPCWSTR pszSource, + _In_ int nLength) throw() + { + return ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSource, nLength, NULL, 0, NULL, NULL); + } + + static int __cdecl GetBaseTypeLength( + _In_reads_(nLength) LPCSTR pszSource, + _In_ int nLength) throw() + { + return nLength; + } + + static void __cdecl ConvertToBaseType( + _Out_writes_(nDestLength) LPSTR pszDest, + _In_ int nDestLength, + _In_ LPCWSTR pszSrc, + _In_ int nSrcLength = -1) + { + if (nSrcLength == -1) + nSrcLength = 1 + GetBaseTypeLength(pszSrc); + + ::WideCharToMultiByte(_AtlGetConversionACP(), 0, pszSrc, nSrcLength, pszDest, nDestLength, NULL, NULL); + } + + static void __cdecl ConvertToBaseType( + _Out_writes_(nDestLength) LPSTR pszDest, + _In_ int nDestLength, + _In_ LPCSTR pszSrc, + _In_ int nSrcLength = -1) + { + if (nSrcLength == -1) + nSrcLength = 1 + GetBaseTypeLength(pszSrc); + + memcpy(pszDest, pszSrc, nSrcLength); + } + + static void __cdecl MakeLower( + _Out_writes_(nSrcLength) LPSTR pszSource, + _In_ int nSrcLength) + { + ::CharLowerBuffA(pszSource, nSrcLength); + } + + static DWORD GetEnvironmentVariable( + _In_z_ LPCSTR pszVar, + _Out_writes_opt_(nBufLength) LPSTR pszBuf, + _In_opt_ int nBufLength) + { + return ::GetEnvironmentVariableA(pszVar, pszBuf, nBufLength); + } + + static void __cdecl MakeUpper( + _Out_writes_(nSrcLength) LPSTR pszSource, + _In_ int nSrcLength) + { + ::CharUpperBuffA(pszSource, nSrcLength); + } + + static LPSTR __cdecl FindString( + _In_z_ LPCSTR pszSource, + _In_z_ LPCSTR pszSub) + { + return ::strstr(pszSource, pszSub); + } + + static LPSTR __cdecl FindChar( + _In_z_ LPCSTR pszSource, + _In_ CHAR ch) + { + return ::strchr(pszSource, ch); + } + + static LPSTR __cdecl FindCharReverse( + _In_z_ LPCSTR pszSource, + _In_ CHAR ch) + { + return ::strrchr(pszSource, ch); + } + + static LPSTR __cdecl FindOneOf( + _In_z_ LPCSTR pszSource, + _In_z_ LPCSTR pszCharSet) + { + return ::strpbrk(pszSource, pszCharSet); + } + + static int __cdecl Compare( + _In_z_ LPCSTR psz1, + _In_z_ LPCSTR psz2) + { + return ::strcmp(psz1, psz2); + } + + static int __cdecl CompareNoCase( + _In_z_ LPCSTR psz1, + _In_z_ LPCSTR psz2) + { + return ::_stricmp(psz1, psz2); + } + + static int __cdecl StringSpanIncluding( + _In_z_ LPCSTR pszBlock, + _In_z_ LPCSTR pszSet) + { + return (int)::strspn(pszBlock, pszSet); + } + + static int __cdecl StringSpanExcluding( + _In_z_ LPCSTR pszBlock, + _In_z_ LPCSTR pszSet) + { + return (int)::strcspn(pszBlock, pszSet); + } + + static int __cdecl FormatV( + _In_opt_z_ LPSTR pszDest, + _In_z_ LPCSTR pszFormat, + _In_ va_list args) + { + if (pszDest == NULL) + return ::_vscprintf(pszFormat, args); + return ::vsprintf(pszDest, pszFormat, args); + } + + static LPSTR + FormatMessageV(_In_z_ LPCSTR pszFormat, _In_opt_ va_list *pArgList) + { + LPSTR psz; + ::FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, pszFormat, 0, 0, reinterpret_cast(&psz), + 0, pArgList); + return psz; + } + + static BSTR __cdecl AllocSysString( + _In_z_ LPCSTR pszSource, + _In_ int nLength) + { + int nLen = ChTraitsCRT::GetBaseTypeLength(pszSource, nLength); + BSTR bstr = ::SysAllocStringLen(NULL, nLen); + if (bstr) + { + ChTraitsCRT::ConvertToBaseType(bstr, nLen, pszSource, nLength); + } + return bstr; + } + +}; + + +namespace _CSTRING_IMPL_ +{ + template + struct _MFCDLLTraitsCheck + { + const static bool c_bIsMFCDLLTraits = false; + }; +} + + +// TODO: disable conversion functions when _CSTRING_DISABLE_NARROW_WIDE_CONVERSION is defined. + +template +class CStringT : + public CSimpleStringT ::c_bIsMFCDLLTraits> +{ +public: + typedef CSimpleStringT::c_bIsMFCDLLTraits> CThisSimpleString; + typedef StringTraits StrTraits; + typedef typename CThisSimpleString::XCHAR XCHAR; + typedef typename CThisSimpleString::PXSTR PXSTR; + typedef typename CThisSimpleString::PCXSTR PCXSTR; + typedef typename CThisSimpleString::YCHAR YCHAR; + typedef typename CThisSimpleString::PYSTR PYSTR; + typedef typename CThisSimpleString::PCYSTR PCYSTR; + +public: + CStringT() throw() : + CThisSimpleString(StringTraits::GetDefaultManager()) + { + } + + explicit CStringT( _In_ IAtlStringMgr* pStringMgr) throw() : + CThisSimpleString(pStringMgr) + { + } + + static void __cdecl Construct(_In_ CStringT* pString) + { + new(pString) CStringT; + } + + CStringT(_In_ const CStringT& strSrc) : + CThisSimpleString(strSrc) + { + } + + CStringT(_In_ const CThisSimpleString& strSrc) : + CThisSimpleString(strSrc) + { + } + + template + CStringT(_In_ const CStringT & strSrc) : + CThisSimpleString(StringTraits::GetDefaultManager()) + { + *this = static_cast(strSrc); + } + +protected: + /* helper function */ + template + void LoadFromPtr_(_In_opt_z_ const T_CHAR* pszSrc) + { + if (pszSrc == NULL) + return; + if (IS_INTRESOURCE(pszSrc)) + LoadString(LOWORD(pszSrc)); + else + *this = pszSrc; + } + +public: + CStringT(_In_opt_z_ const XCHAR* pszSrc) : + CThisSimpleString(StringTraits::GetDefaultManager()) + { + LoadFromPtr_(pszSrc); + } + + CStringT(_In_opt_z_ const XCHAR* pszSrc, + _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr) + { + LoadFromPtr_(pszSrc); + } + + CStringT(_In_opt_z_ const YCHAR* pszSrc) : + CThisSimpleString(StringTraits::GetDefaultManager()) + { + LoadFromPtr_(pszSrc); + } + + CStringT(_In_opt_z_ const YCHAR* pszSrc, + _In_ IAtlStringMgr* pStringMgr) : CThisSimpleString(pStringMgr) + { + LoadFromPtr_(pszSrc); + } + + CStringT(_In_reads_z_(nLength) const XCHAR* pch, + _In_ int nLength) : + CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager()) + { + } + + CStringT(_In_reads_z_(nLength) const YCHAR* pch, + _In_ int nLength) : + CThisSimpleString(pch, nLength, StringTraits::GetDefaultManager()) + { + } + + CStringT& operator=(_In_ const CStringT& strSrc) + { + CThisSimpleString::operator=(strSrc); + return *this; + } + + CStringT& operator=(_In_opt_z_ PCXSTR pszSrc) + { + CThisSimpleString::operator=(pszSrc); + return *this; + } + + CStringT& operator=(_In_opt_z_ PCYSTR pszSrc) + { + int length = pszSrc ? StringTraits::GetBaseTypeLength(pszSrc) : 0; + if (length > 0) + { + PXSTR result = CThisSimpleString::GetBuffer(length); + StringTraits::ConvertToBaseType(result, length, pszSrc); + CThisSimpleString::ReleaseBufferSetLength(length); + } + else + { + CThisSimpleString::Empty(); + } + return *this; + } + + CStringT& operator=(_In_ const CThisSimpleString &strSrc) + { + CThisSimpleString::operator=(strSrc); + return *this; + } + + friend bool operator==(const CStringT& str1, const CStringT& str2) throw() + { + return str1.Compare(str2) == 0; + } + + friend bool operator==(const CStringT& str1, PCXSTR psz2) throw() + { + return str1.Compare(psz2) == 0; + } + + friend bool operator==(const CStringT& str1, PCYSTR psz2) throw() + { + CStringT tmp(psz2, str1.GetManager()); + return tmp.Compare(str1) == 0; + } + + friend bool operator==(const CStringT& str1, XCHAR ch2) throw() + { + return str1.GetLength() == 1 && str1[0] == ch2; + } + + friend bool operator==(PCXSTR psz1, const CStringT& str2) throw() + { + return str2.Compare(psz1) == 0; + } + + friend bool operator==(PCYSTR psz1, const CStringT& str2) throw() + { + CStringT tmp(psz1, str2.GetManager()); + return tmp.Compare(str2) == 0; + } + + friend bool operator==(XCHAR ch1, const CStringT& str2) throw() + { + return str2.GetLength() == 1 && str2[0] == ch1; + } + + friend bool operator!=(const CStringT& str1, const CStringT& str2) throw() + { + return str1.Compare(str2) != 0; + } + + friend bool operator!=(const CStringT& str1, PCXSTR psz2) throw() + { + return str1.Compare(psz2) != 0; + } + + friend bool operator!=(const CStringT& str1, PCYSTR psz2) throw() + { + CStringT tmp(psz2, str1.GetManager()); + return tmp.Compare(str1) != 0; + } + + friend bool operator!=(const CStringT& str1, XCHAR ch2) throw() + { + return str1.GetLength() != 1 || str1[0] != ch2; + } + + friend bool operator!=(PCXSTR psz1, const CStringT& str2) throw() + { + return str2.Compare(psz1) != 0; + } + + friend bool operator!=(PCYSTR psz1, const CStringT& str2) throw() + { + CStringT tmp(psz1, str2.GetManager()); + return tmp.Compare(str2) != 0; + } + + friend bool operator!=(XCHAR ch1, const CStringT& str2) throw() + { + return str2.GetLength() != 1 || str2[0] != ch1; + } + + CStringT& operator+=(_In_ const CThisSimpleString& str) + { + CThisSimpleString::operator+=(str); + return *this; + } + + CStringT& operator+=(_In_z_ PCXSTR pszSrc) + { + CThisSimpleString::operator+=(pszSrc); + return *this; + } + + CStringT& operator+=(_In_ XCHAR ch) + { + CThisSimpleString::operator+=(ch); + return *this; + } + + BOOL LoadString(_In_ UINT nID) + { + return LoadString(_AtlBaseModule.GetResourceInstance(), nID); + } + + _Check_return_ BOOL LoadString(_In_ HINSTANCE hInstance, + _In_ UINT nID) + { + const ATLSTRINGRESOURCEIMAGE* pImage = AtlGetStringResourceImage(hInstance, nID); + if (pImage == NULL) return FALSE; + + int nLength = StringTraits::GetBaseTypeLength(pImage->achString, pImage->nLength); + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + StringTraits::ConvertToBaseType(pszBuffer, nLength, pImage->achString, pImage->nLength); + CThisSimpleString::ReleaseBufferSetLength(nLength); + + return TRUE; + } + + BOOL GetEnvironmentVariable(_In_z_ PCXSTR pszVar) + { + int nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0); + + if (nLength > 0) + { + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength); + CThisSimpleString::ReleaseBuffer(); + return TRUE; + } + + CThisSimpleString::Empty(); + return FALSE; + } + + CStringT& MakeLower() + { + int nLength = CThisSimpleString::GetLength(); + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + + StringTraits::MakeLower(pszBuffer, nLength); + CThisSimpleString::ReleaseBufferSetLength(nLength); + + return *this; + } + + CStringT& MakeUpper() + { + int nLength = CThisSimpleString::GetLength(); + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + + StringTraits::MakeUpper(pszBuffer, nLength); + CThisSimpleString::ReleaseBufferSetLength(nLength); + + return *this; + } + + int Find(_In_ PCXSTR pszSub, _In_opt_ int iStart = 0) const throw() + { + int nLength = CThisSimpleString::GetLength(); + + if (iStart >= nLength || iStart < 0) + return -1; + + PCXSTR pszString = CThisSimpleString::GetString(); + PCXSTR pszResult = StringTraits::FindString(pszString + iStart, pszSub); + + return pszResult ? ((int)(pszResult - pszString)) : -1; + } + + int Find(_In_ XCHAR ch, _In_opt_ int iStart = 0) const throw() + { + int nLength = CThisSimpleString::GetLength(); + + if (iStart >= nLength || iStart < 0) + return -1; + + PCXSTR pszString = CThisSimpleString::GetString(); + PCXSTR pszResult = StringTraits::FindChar(pszString + iStart, ch); + + return pszResult ? ((int)(pszResult - pszString)) : -1; + } + + int FindOneOf(_In_ PCXSTR pszCharSet) const throw() + { + PCXSTR pszString = CThisSimpleString::GetString(); + PCXSTR pszResult = StringTraits::FindOneOf(pszString, pszCharSet); + + return pszResult ? ((int)(pszResult - pszString)) : -1; + } + + int ReverseFind(_In_ XCHAR ch) const throw() + { + PCXSTR pszString = CThisSimpleString::GetString(); + PCXSTR pszResult = StringTraits::FindCharReverse(pszString, ch); + + return pszResult ? ((int)(pszResult - pszString)) : -1; + } + + int Compare(_In_z_ PCXSTR psz) const + { + return StringTraits::Compare(CThisSimpleString::GetString(), psz); + } + + int CompareNoCase(_In_z_ PCXSTR psz) const + { + return StringTraits::CompareNoCase(CThisSimpleString::GetString(), psz); + } + + CStringT Mid(int iFirst, int nCount) const + { + int nLength = CThisSimpleString::GetLength(); + + if (iFirst < 0) + iFirst = 0; + if (nCount < 0) + nCount = 0; + if (iFirst > nLength) + iFirst = nLength; + if (iFirst + nCount > nLength) + nCount = nLength - iFirst; + + return CStringT(CThisSimpleString::GetString() + iFirst, nCount); + } + + CStringT Mid(int iFirst) const + { + int nLength = CThisSimpleString::GetLength(); + + if (iFirst < 0) + iFirst = 0; + if (iFirst > nLength) + iFirst = nLength; + + return CStringT(CThisSimpleString::GetString() + iFirst, nLength - iFirst); + } + + CStringT Left(int nCount) const + { + int nLength = CThisSimpleString::GetLength(); + + if (nCount < 0) + nCount = 0; + if (nCount > nLength) + nCount = nLength; + + return CStringT(CThisSimpleString::GetString(), nCount); + } + + CStringT Right(int nCount) const + { + int nLength = CThisSimpleString::GetLength(); + + if (nCount < 0) + nCount = 0; + if (nCount > nLength) + nCount = nLength; + + return CStringT(CThisSimpleString::GetString() + nLength - nCount, nCount); + } + + + void __cdecl Format(UINT nFormatID, ...) + { + va_list args; + va_start(args, nFormatID); + CStringT formatString; + if (formatString.LoadString(nFormatID)) + FormatV(formatString, args); + va_end(args); + } + + void __cdecl Format(PCXSTR pszFormat, ...) + { + va_list args; + va_start(args, pszFormat); + FormatV(pszFormat, args); + va_end(args); + } + + void FormatV(PCXSTR pszFormat, va_list args) + { + int nLength = StringTraits::FormatV(NULL, pszFormat, args); + + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + StringTraits::FormatV(pszBuffer, pszFormat, args); + CThisSimpleString::ReleaseBufferSetLength(nLength); + } + + void __cdecl FormatMessage(UINT nFormatID, ...) + { + va_list va; + va_start(va, nFormatID); + + CStringT str; + if (str.LoadString(nFormatID)) + FormatMessageV(str, &va); + + va_end(va); + } + + void __cdecl FormatMessage(PCXSTR pszFormat, ...) + { + va_list va; + va_start(va, pszFormat); + FormatMessageV(pszFormat, &va); + va_end(va); + } + + void + FormatMessageV(PCXSTR pszFormat, va_list *pArgList) + { + PXSTR psz = StringTraits::FormatMessageV(pszFormat, pArgList); + if (!psz) + CThisSimpleString::ThrowMemoryException(); + + *this = psz; + ::LocalFree(psz); + } + + int Replace(PCXSTR pszOld, PCXSTR pszNew) + { + PCXSTR pszString = CThisSimpleString::GetString(); + + const int nLength = CThisSimpleString::GetLength(); + const int nOldLen = StringTraits::GetBaseTypeLength(pszOld); + const int nNewLen = StringTraits::GetBaseTypeLength(pszNew); + const int nDiff = nNewLen - nOldLen; + int nResultLength = nLength; + + PCXSTR pszFound; + while ((pszFound = StringTraits::FindString(pszString, pszOld))) + { + nResultLength += nDiff; + pszString = pszFound + nOldLen; + } + + if (pszString == CThisSimpleString::GetString()) + return 0; + + PXSTR pszResult = CThisSimpleString::GetBuffer(nResultLength); + PXSTR pszNext; + int nCount = 0, nRemaining = nLength; + while (nRemaining && (pszNext = StringTraits::FindString(pszResult, pszOld))) + { + nRemaining -= (pszNext - pszResult); + nRemaining -= nOldLen; + if (nRemaining > 0) + CThisSimpleString::CopyCharsOverlapped(pszNext + nNewLen, nRemaining + 1, pszNext + nOldLen, nRemaining + 1); + CThisSimpleString::CopyCharsOverlapped(pszNext, nNewLen, pszNew, nNewLen); + pszResult = pszNext + nNewLen; + nCount++; + } + + CThisSimpleString::ReleaseBufferSetLength(nResultLength); + + return nCount; + } + + int Replace(XCHAR chOld, XCHAR chNew) + { + PCXSTR pszString = CThisSimpleString::GetString(); + PXSTR pszFirst = StringTraits::FindChar(pszString, chOld); + if (!pszFirst) + return 0; + + int nLength = CThisSimpleString::GetLength(); + int nCount = 0; + + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + pszFirst = pszBuffer + (pszFirst - pszString); + do { + *pszFirst = chNew; + ++nCount; + } while ((pszFirst = StringTraits::FindChar(pszFirst + 1, chOld))); + + CThisSimpleString::ReleaseBufferSetLength(nLength); + return nCount; + } + + + CStringT Tokenize(_In_z_ PCXSTR pszTokens, _Inout_ int& iStart) const + { + ATLASSERT(iStart >= 0); + + if (iStart < 0) + AtlThrow(E_INVALIDARG); + + if (!pszTokens || !pszTokens[0]) + { + if (iStart < CThisSimpleString::GetLength()) + { + return Mid(iStart); + } + iStart = -1; + return CStringT(); + } + + if (iStart < CThisSimpleString::GetLength()) + { + int iRangeOffset = StringTraits::StringSpanIncluding(CThisSimpleString::GetString() + iStart, pszTokens); + + if (iRangeOffset + iStart < CThisSimpleString::GetLength()) + { + int iNewStart = iStart + iRangeOffset; + int nCount = StringTraits::StringSpanExcluding(CThisSimpleString::GetString() + iNewStart, pszTokens); + + iStart = iNewStart + nCount + 1; + + return Mid(iNewStart, nCount); + } + } + + iStart = -1; + return CStringT(); + } + + static PCXSTR DefaultTrimChars() + { + static XCHAR str[] = { ' ', '\t', '\r', '\n', 0 }; + return str; + } + + + CStringT& TrimLeft() + { + return TrimLeft(DefaultTrimChars()); + } + + CStringT& TrimLeft(XCHAR chTarget) + { + XCHAR str[2] = { chTarget, 0 }; + return TrimLeft(str); + } + + CStringT& TrimLeft(PCXSTR pszTargets) + { + int nLength = CThisSimpleString::GetLength(); + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + int nCount = 0; + + while (nCount < nLength && StringTraits::FindChar(pszTargets, pszBuffer[nCount])) + nCount++; + + if (nCount > 0) + { + CThisSimpleString::CopyCharsOverlapped(pszBuffer, nLength - nCount, pszBuffer + nCount, nLength - nCount); + nLength -= nCount; + } + CThisSimpleString::ReleaseBufferSetLength(nLength); + + return *this; + } + + + CStringT& TrimRight() + { + return TrimRight(DefaultTrimChars()); + } + + CStringT& TrimRight(XCHAR chTarget) + { + XCHAR str[2] = { chTarget, 0 }; + return TrimRight(str); + } + + CStringT& TrimRight(PCXSTR pszTargets) + { + int nLength = CThisSimpleString::GetLength(); + PXSTR pszBuffer = CThisSimpleString::GetBuffer(nLength); + + while (nLength > 0 && StringTraits::FindChar(pszTargets, pszBuffer[nLength-1])) + nLength--; + + CThisSimpleString::ReleaseBufferSetLength(nLength); + + return *this; + } + + + CStringT& Trim() + { + return Trim(DefaultTrimChars()); + } + + CStringT& Trim(XCHAR chTarget) + { + XCHAR str[2] = { chTarget, 0 }; + return Trim(str); + } + + CStringT& Trim(PCXSTR pszTargets) + { + return TrimRight(pszTargets).TrimLeft(pszTargets); + } + + + BSTR AllocSysString() const + { + return StringTraits::AllocSysString(CThisSimpleString::GetString(), CThisSimpleString::GetLength()); + } + + +}; + +} //namespace ATL + +#endif diff --git a/src/3rd_party/reactos-atl/atl/statreg.h b/src/3rd_party/reactos-atl/atl/statreg.h new file mode 100644 index 00000000..b027d31c --- /dev/null +++ b/src/3rd_party/reactos-atl/atl/statreg.h @@ -0,0 +1,765 @@ +/* + * ReactOS ATL + * + * Copyright 2005 Jacek Caban + * Copyright 2009 Andrew Hill + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#pragma once + +class IRegistrarBase : public IUnknown +{ +public: + virtual HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR key, LPCOLESTR item) = 0; + virtual HRESULT STDMETHODCALLTYPE ClearReplacements() = 0; +}; + +namespace ATL +{ + +class CRegObject : public IRegistrarBase +{ +public: + typedef struct rep_list_str + { + LPOLESTR key; + LPOLESTR item; + int key_len; + struct rep_list_str *next; + } rep_list; + + typedef struct + { + LPOLESTR str; + DWORD alloc; + DWORD len; + } strbuf; + + rep_list *m_rep; + +public: + CRegObject() + { + m_rep = NULL; + } + + ~CRegObject() + { + HRESULT hResult; + + hResult = ClearReplacements(); + ATLASSERT(SUCCEEDED(hResult)); + (void)hResult; + } + + HRESULT STDMETHODCALLTYPE QueryInterface(const IID & /* riid */, void ** /* ppvObject */ ) + { + ATLASSERT(FALSE && TEXT("statically linked in CRegObject is not a com object. Do not call this function")); + return E_NOTIMPL; + } + + ULONG STDMETHODCALLTYPE AddRef() + { + ATLASSERT(FALSE && TEXT("statically linked in CRegObject is not a com object. Do not call this function")); + return 1; + } + + ULONG STDMETHODCALLTYPE Release() + { + ATLASSERT(FALSE && TEXT("statically linked in CRegObject is not a com object. Do not call this function")); + return 0; + } + + HRESULT STDMETHODCALLTYPE AddReplacement(LPCOLESTR key, LPCOLESTR item) + { + int len; + rep_list *new_rep; + + new_rep = reinterpret_cast(HeapAlloc(GetProcessHeap(), 0, sizeof(rep_list))); + if (new_rep == NULL) + return E_OUTOFMEMORY; + + new_rep->key_len = lstrlenW(key); + new_rep->key = reinterpret_cast(HeapAlloc(GetProcessHeap(), 0, (new_rep->key_len + 1) * sizeof(OLECHAR))); + if (new_rep->key == NULL) + { + HeapFree(GetProcessHeap(), 0, new_rep); + return E_OUTOFMEMORY; + } + memcpy(new_rep->key, key, (new_rep->key_len + 1) * sizeof(OLECHAR)); + + len = lstrlenW(item) + 1; + new_rep->item = reinterpret_cast(HeapAlloc(GetProcessHeap(), 0, len * sizeof(OLECHAR))); + if (new_rep->item == NULL) + { + HeapFree(GetProcessHeap(), 0, new_rep->key); + HeapFree(GetProcessHeap(), 0, new_rep); + return E_OUTOFMEMORY; + } + memcpy(new_rep->item, item, len * sizeof(OLECHAR)); + + new_rep->next = m_rep; + m_rep = new_rep; + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE ClearReplacements() + { + rep_list *iter; + rep_list *iter2; + + iter = m_rep; + while (iter) + { + iter2 = iter->next; + HeapFree(GetProcessHeap(), 0, iter->key); + HeapFree(GetProcessHeap(), 0, iter->item); + HeapFree(GetProcessHeap(), 0, iter); + iter = iter2; + } + + m_rep = NULL; + return S_OK; + } + + HRESULT STDMETHODCALLTYPE ResourceRegisterSz(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType) + { + return RegisterWithResource(resFileName, szID, szType, TRUE); + } + + HRESULT STDMETHODCALLTYPE ResourceUnregisterSz(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType) + { + return RegisterWithResource(resFileName, szID, szType, FALSE); + } + + HRESULT STDMETHODCALLTYPE FileRegister(LPCOLESTR fileName) + { + return RegisterWithFile(fileName, TRUE); + } + + HRESULT STDMETHODCALLTYPE FileUnregister(LPCOLESTR fileName) + { + return RegisterWithFile(fileName, FALSE); + } + + HRESULT STDMETHODCALLTYPE StringRegister(LPCOLESTR data) + { + return RegisterWithString(data, TRUE); + } + + HRESULT STDMETHODCALLTYPE StringUnregister(LPCOLESTR data) + { + return RegisterWithString(data, FALSE); + } + + HRESULT STDMETHODCALLTYPE ResourceRegister(LPCOLESTR resFileName, UINT nID, LPCOLESTR szType) + { + return ResourceRegisterSz(resFileName, MAKEINTRESOURCEW(nID), szType); + } + + HRESULT STDMETHODCALLTYPE ResourceUnregister(LPCOLESTR resFileName, UINT nID, LPCOLESTR szType) + { + return ResourceUnregisterSz(resFileName, MAKEINTRESOURCEW(nID), szType); + } + +protected: + HRESULT STDMETHODCALLTYPE RegisterWithResource(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType, BOOL doRegister) + { + return resource_register(resFileName, szID, szType, doRegister); + } + + HRESULT STDMETHODCALLTYPE RegisterWithFile(LPCOLESTR fileName, BOOL doRegister) + { + return file_register(fileName, doRegister); + } + + HRESULT STDMETHODCALLTYPE RegisterWithString(LPCOLESTR data, BOOL doRegister) + { + return string_register(data, doRegister); + } + +private: + inline LONG RegDeleteTreeX(HKEY parentKey, LPCWSTR subKeyName) + { + wchar_t szBuffer[256]; + DWORD dwSize; + FILETIME time; + HKEY childKey; + LONG lRes; + + ATLASSERT(parentKey != NULL); + lRes = RegOpenKeyExW(parentKey, subKeyName, 0, KEY_READ | KEY_WRITE, &childKey); + if (lRes != ERROR_SUCCESS) + return lRes; + + dwSize = sizeof(szBuffer) / sizeof(szBuffer[0]); + while (RegEnumKeyExW(parentKey, 0, szBuffer, &dwSize, NULL, NULL, NULL, &time) == ERROR_SUCCESS) + { + lRes = RegDeleteTreeX(childKey, szBuffer); + if (lRes != ERROR_SUCCESS) + return lRes; + dwSize = sizeof(szBuffer) / sizeof(szBuffer[0]); + } + RegCloseKey(childKey); + return RegDeleteKeyW(parentKey, subKeyName); + } + + HRESULT strbuf_init(strbuf *buf) + { + buf->str = reinterpret_cast(HeapAlloc(GetProcessHeap(), 0, 128 * sizeof(WCHAR))); + if (buf->str == NULL) + return E_OUTOFMEMORY; + buf->alloc = 128; + buf->len = 0; + return S_OK; + } + + HRESULT strbuf_write(LPCOLESTR str, strbuf *buf, int len) + { + LPOLESTR newBuffer; + + if (len == -1) + len = lstrlenW(str); + if (buf->len + len + 1 >= buf->alloc) + { + buf->alloc = (buf->len + len) * 2; + newBuffer = reinterpret_cast(HeapReAlloc(GetProcessHeap(), 0, buf->str, buf->alloc * sizeof(WCHAR))); + if (newBuffer == NULL) + return E_OUTOFMEMORY; + buf->str = newBuffer; + } + memcpy(buf->str + buf->len, str, len * sizeof(OLECHAR)); + buf->len += len; + buf->str[buf->len] = '\0'; + return S_OK; + } + + + HRESULT file_register(LPCOLESTR fileName, BOOL do_register) + { + HANDLE file; + DWORD filelen; + DWORD len; + LPWSTR regstrw; + LPSTR regstra; + LRESULT lres; + HRESULT hResult; + + file = CreateFileW(fileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); + if (file != INVALID_HANDLE_VALUE) + { + filelen = GetFileSize(file, NULL); + regstra = reinterpret_cast(HeapAlloc(GetProcessHeap(), 0, filelen)); + if (regstra == NULL) + return E_OUTOFMEMORY; + lres = ReadFile(file, regstra, filelen, NULL, NULL); + if (lres == ERROR_SUCCESS) + { + len = MultiByteToWideChar(CP_ACP, 0, regstra, filelen, NULL, 0) + 1; + regstrw = reinterpret_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR))); + if (regstrw == NULL) + { + HeapFree(GetProcessHeap(), 0, regstra); + return E_OUTOFMEMORY; + } + MultiByteToWideChar(CP_ACP, 0, regstra, filelen, regstrw, len); + regstrw[len - 1] = '\0'; + + hResult = string_register(regstrw, do_register); + + HeapFree(GetProcessHeap(), 0, regstrw); + } + else + { + hResult = HRESULT_FROM_WIN32(lres); + } + HeapFree(GetProcessHeap(), 0, regstra); + CloseHandle(file); + } + else + { + hResult = HRESULT_FROM_WIN32(GetLastError()); + } + + return hResult; + } + + HRESULT resource_register(LPCOLESTR resFileName, LPCOLESTR szID, LPCOLESTR szType, BOOL do_register) + { + HINSTANCE hins; + HRSRC src; + HGLOBAL regstra; + LPWSTR regstrw; + DWORD len; + DWORD reslen; + HRESULT hResult; + + hins = LoadLibraryExW(resFileName, NULL, LOAD_LIBRARY_AS_DATAFILE); + if (hins) + { + src = FindResourceW(hins, szID, szType); + if (src) + { + regstra = LoadResource(hins, src); + reslen = SizeofResource(hins, src); + if (regstra) + { + len = MultiByteToWideChar(CP_ACP, 0, reinterpret_cast(regstra), reslen, NULL, 0) + 1; + regstrw = reinterpret_cast(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len * sizeof(WCHAR))); + if (regstrw == NULL) + return E_OUTOFMEMORY; + MultiByteToWideChar(CP_ACP, 0, reinterpret_cast(regstra), reslen, regstrw, len); + regstrw[len - 1] = '\0'; + + hResult = string_register(regstrw, do_register); + + HeapFree(GetProcessHeap(), 0, regstrw); + } + else + hResult = HRESULT_FROM_WIN32(GetLastError()); + } + else + hResult = HRESULT_FROM_WIN32(GetLastError()); + FreeLibrary(hins); + } + else + hResult = HRESULT_FROM_WIN32(GetLastError()); + + return hResult; + } + + HRESULT string_register(LPCOLESTR data, BOOL do_register) + { + strbuf buf; + HRESULT hResult; + + hResult = strbuf_init(&buf); + if (FAILED(hResult)) + return hResult; + hResult = do_preprocess(data, &buf); + if (SUCCEEDED(hResult)) + { + hResult = do_process_root_key(buf.str, do_register); + if (FAILED(hResult) && do_register) + do_process_root_key(buf.str, FALSE); + } + + HeapFree(GetProcessHeap(), 0, buf.str); + return hResult; + } + + HRESULT do_preprocess(LPCOLESTR data, strbuf *buf) + { + LPCOLESTR iter; + LPCOLESTR iter2; + rep_list *rep_iter; + HRESULT hResult; + + iter2 = data; + iter = wcschr(data, '%'); + while (iter) + { + hResult = strbuf_write(iter2, buf, static_cast(iter - iter2)); + if (FAILED(hResult)) + return hResult; + + iter2 = ++iter; + if (!*iter2) + return DISP_E_EXCEPTION; + iter = wcschr(iter2, '%'); + if (!iter) + return DISP_E_EXCEPTION; + + if (iter == iter2) + { + hResult = strbuf_write(L"%", buf, 1); + if (FAILED(hResult)) + return hResult; + } + else + { + for (rep_iter = m_rep; rep_iter; rep_iter = rep_iter->next) + { + if (rep_iter->key_len == iter - iter2 && !_memicmp(iter2, rep_iter->key, rep_iter->key_len * sizeof(wchar_t))) + break; + } + if (!rep_iter) + return DISP_E_EXCEPTION; + + hResult = strbuf_write(rep_iter->item, buf, -1); + if (FAILED(hResult)) + return hResult; + } + + iter2 = ++iter; + iter = wcschr(iter, '%'); + } + + hResult = strbuf_write(iter2, buf, -1); + if (FAILED(hResult)) + return hResult; + + return S_OK; + } + + HRESULT get_word(LPCOLESTR *str, strbuf *buf) + { + LPCOLESTR iter; + LPCOLESTR iter2; + HRESULT hResult; + + iter2 = *str; + buf->len = 0; + buf->str[0] = '\0'; + + while (iswspace (*iter2)) + iter2++; + iter = iter2; + if (!*iter) + { + *str = iter; + return S_OK; + } + + if (*iter == '}' || *iter == '=') + { + hResult = strbuf_write(iter++, buf, 1); + if (FAILED(hResult)) + return hResult; + } + else if (*iter == '\'') + { + iter2 = ++iter; + iter = wcschr(iter, '\''); + if (!iter) + { + *str = iter; + return DISP_E_EXCEPTION; + } + hResult = strbuf_write(iter2, buf, static_cast(iter - iter2)); + if (FAILED(hResult)) + return hResult; + iter++; + } + else + { + while (*iter && !iswspace(*iter)) + iter++; + hResult = strbuf_write(iter2, buf, static_cast(iter - iter2)); + if (FAILED(hResult)) + return hResult; + } + + while (iswspace(*iter)) + iter++; + *str = iter; + return S_OK; + } + + inline unsigned int HexToBin(OLECHAR a) + { + if (a >= '0' && a <= '9') + return a - '0'; + if (a >= 'A' && a <= 'F') + return a - 'A' + 10; + if (a >= 'a' && a <= 'f') + return a - 'a' + 10; + ATLASSERT(false); + return 0; + } + + HRESULT do_process_key(LPCOLESTR *pstr, HKEY parent_key, strbuf *buf, BOOL do_register) + { + LPCOLESTR iter; + HRESULT hres; + LONG lres; + HKEY hkey; + strbuf name; + + enum { + NORMAL, + NO_REMOVE, + IS_VAL, + FORCE_REMOVE, + DO_DELETE + } key_type = NORMAL; + + static const wchar_t *wstrNoRemove = L"NoRemove"; + static const wchar_t *wstrForceRemove = L"ForceRemove"; + static const wchar_t *wstrDelete = L"Delete"; + static const wchar_t *wstrval = L"val"; + + iter = *pstr; + hkey = NULL; + hres = get_word(&iter, buf); + if (FAILED(hres)) + return hres; + hres = strbuf_init(&name); + if (FAILED(hres)) + return hres; + + while(buf->str[1] || buf->str[0] != '}') + { + key_type = NORMAL; + if (!lstrcmpiW(buf->str, wstrNoRemove)) + key_type = NO_REMOVE; + else if (!lstrcmpiW(buf->str, wstrForceRemove)) + key_type = FORCE_REMOVE; + else if (!lstrcmpiW(buf->str, wstrval)) + key_type = IS_VAL; + else if (!lstrcmpiW(buf->str, wstrDelete)) + key_type = DO_DELETE; + + if (key_type != NORMAL) + { + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + } + + if (do_register) + { + if (key_type == IS_VAL) + { + hkey = parent_key; + hres = strbuf_write(buf->str, &name, -1); + if (FAILED(hres)) + return hres; + } + else if (key_type == DO_DELETE) + { + RegDeleteTreeX(parent_key, buf->str); + } + else + { + if (key_type == FORCE_REMOVE) + RegDeleteTreeX(parent_key, buf->str); + lres = RegCreateKeyW(parent_key, buf->str, &hkey); + if (lres != ERROR_SUCCESS) + { + hres = HRESULT_FROM_WIN32(lres); + break; + } + } + } + else if (key_type != IS_VAL && key_type != DO_DELETE) + { + hres = strbuf_write(buf->str, &name, -1); + if (FAILED(hres)) + return hres; + lres = RegOpenKeyW(parent_key, buf->str, &hkey); + if (lres != ERROR_SUCCESS) + { + } + } + + if (key_type != DO_DELETE && *iter == '=') + { + iter++; + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + if (buf->len != 1) + { + hres = DISP_E_EXCEPTION; + break; + } + if (do_register) + { + switch(buf->str[0]) + { + case 's': + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_SZ, (PBYTE)buf->str, + (lstrlenW(buf->str) + 1) * sizeof(WCHAR)); + if (lres != ERROR_SUCCESS) + hres = HRESULT_FROM_WIN32(lres); + break; + case 'e': + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_EXPAND_SZ, (PBYTE)buf->str, + (lstrlenW(buf->str) + 1) * sizeof(WCHAR)); + if (lres != ERROR_SUCCESS) + hres = HRESULT_FROM_WIN32(lres); + break; + case 'd': + { + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + WCHAR *end; + DWORD dw; + if ((buf->str[0] == '0' && buf->str[1] == 'x') || (buf->str[0] == '&' && buf->str[1] == 'H')) + dw = wcstoul(&buf->str[2], &end, 16); + else + dw = wcstol(&buf->str[0], &end, 10); + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_DWORD, (PBYTE)&dw, sizeof(dw)); + if (lres != ERROR_SUCCESS) + hres = HRESULT_FROM_WIN32(lres); + break; + } + case 'b': + { + DWORD count; + DWORD curIndex; + + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + count = buf->len; + if ((count & 1) != 0) + return DISP_E_EXCEPTION; + count = count / 2; + for (curIndex = 0; curIndex < count; curIndex++) + ((BYTE*)buf->str)[curIndex] = (HexToBin(buf->str[curIndex * 2]) << 4) | HexToBin(buf->str[curIndex * 2 + 1]); + lres = RegSetValueExW(hkey, name.len ? name.str : NULL, 0, REG_BINARY, (PBYTE)buf->str, count); + if (lres != ERROR_SUCCESS) + hres = HRESULT_FROM_WIN32(lres); + break; + } + default: + hres = DISP_E_EXCEPTION; + } + if (FAILED(hres)) + break; + } + else + { + if (*iter == '-') + iter++; + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + } + } + else if(key_type == IS_VAL) + { + hres = DISP_E_EXCEPTION; + break; + } + + if (key_type != IS_VAL && key_type != DO_DELETE && *iter == '{' && iswspace(iter[1])) + { + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + hres = do_process_key(&iter, hkey, buf, do_register); + if (FAILED(hres)) + break; + } + + if (!do_register && (key_type == NORMAL || key_type == FORCE_REMOVE)) + { + RegDeleteKeyW(parent_key, name.str); + } + + if (hkey && key_type != IS_VAL) + RegCloseKey(hkey); + hkey = 0; + name.len = 0; + + hres = get_word(&iter, buf); + if (FAILED(hres)) + break; + } + + HeapFree(GetProcessHeap(), 0, name.str); + if (hkey && key_type != IS_VAL) + RegCloseKey(hkey); + *pstr = iter; + return hres; + } + + HRESULT do_process_root_key(LPCOLESTR data, BOOL do_register) + { + LPCOLESTR iter; + strbuf buf; + unsigned int i; + HRESULT hResult; + static const struct { + const wchar_t *name; + HKEY key; + } root_keys[] = { + {L"HKEY_CLASSES_ROOT", HKEY_CLASSES_ROOT}, + {L"HKEY_CURRENT_USER", HKEY_CURRENT_USER}, + {L"HKEY_LOCAL_MACHINE", HKEY_LOCAL_MACHINE}, + {L"HKEY_USERS", HKEY_USERS}, + {L"HKEY_PERFORMANCE_DATA", HKEY_PERFORMANCE_DATA}, + {L"HKEY_DYN_DATA", HKEY_DYN_DATA}, + {L"HKEY_CURRENT_CONFIG", HKEY_CURRENT_CONFIG}, + {L"HKCR", HKEY_CLASSES_ROOT}, + {L"HKCU", HKEY_CURRENT_USER}, + {L"HKLM", HKEY_LOCAL_MACHINE}, + {L"HKU", HKEY_USERS}, + {L"HKPD", HKEY_PERFORMANCE_DATA}, + {L"HKDD", HKEY_DYN_DATA}, + {L"HKCC", HKEY_CURRENT_CONFIG}, + }; + + iter = data; + + hResult = strbuf_init(&buf); + if (FAILED(hResult)) + return hResult; + hResult = get_word(&iter, &buf); + if (FAILED(hResult)) + return hResult; + + while (*iter) + { + if (!buf.len) + { + hResult = DISP_E_EXCEPTION; + break; + } + for (i = 0; i < sizeof(root_keys) / sizeof(root_keys[0]); i++) + { + if (!lstrcmpiW(buf.str, root_keys[i].name)) + break; + } + if (i == sizeof(root_keys) / sizeof(root_keys[0])) + { + hResult = DISP_E_EXCEPTION; + break; + } + hResult = get_word(&iter, &buf); + if (FAILED(hResult)) + break; + if (buf.str[1] || buf.str[0] != '{') + { + hResult = DISP_E_EXCEPTION; + break; + } + hResult = do_process_key(&iter, root_keys[i].key, &buf, do_register); + if (FAILED(hResult)) + break; + hResult = get_word(&iter, &buf); + if (FAILED(hResult)) + break; + } + HeapFree(GetProcessHeap(), 0, buf.str); + return hResult; + } + +}; + +}; //namespace ATL diff --git a/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp b/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp index 29483432..1aa5e252 100644 --- a/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp +++ b/src/3rd_party/rewolf-wow64ext/src/wow64ext.cpp @@ -85,6 +85,7 @@ extern "C" DWORD64 __cdecl X64Call(DWORD64 func, int argC, ...) reg64 _r9 = { (argC > 0) ? argC--, va_arg(args, DWORD64) : 0 }; reg64 _rax = { 0 }; +#ifdef _MSC_VER reg64 restArgs = { (DWORD64)&va_arg(args, DWORD64) }; // conversion to QWORD for easier use in inline assembly @@ -173,6 +174,7 @@ _ls_e: ;// mov fs, ax } #endif // _M_IX86 +#endif // _MSC_VER return _rax.v; } diff --git a/src/BlackBone/Asm/AsmHelper32.cpp b/src/BlackBone/Asm/AsmHelper32.cpp index ab8eccc8..36879140 100644 --- a/src/BlackBone/Asm/AsmHelper32.cpp +++ b/src/BlackBone/Asm/AsmHelper32.cpp @@ -1,5 +1,6 @@ #include "AsmHelper32.h" +#include #include #include diff --git a/src/BlackBone/CMakeLists.txt b/src/BlackBone/CMakeLists.txt index 42e05f88..810c0613 100644 --- a/src/BlackBone/CMakeLists.txt +++ b/src/BlackBone/CMakeLists.txt @@ -7,6 +7,11 @@ endif() include_directories(..) +if(NOT MSVC) + # Standard ATL headers aren't compatible with MinGW/Clang, so we use the ones from ReactOS. + include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../3rd_party/reactos-atl/atl") +endif() + ########################################################## set(SOURCE_ASMJIT ../3rd_party/asmjit/base/assembler.cpp ../3rd_party/Asmjit/base/codegen.cpp diff --git a/src/BlackBone/Include/CallResult.h b/src/BlackBone/Include/CallResult.h index 3a5c88e5..99f52458 100644 --- a/src/BlackBone/Include/CallResult.h +++ b/src/BlackBone/Include/CallResult.h @@ -46,6 +46,7 @@ struct call_result_t #else #include +#include #include namespace blackbone diff --git a/src/BlackBone/Include/Macro.h b/src/BlackBone/Include/Macro.h index 5ab0cdf8..da956c62 100644 --- a/src/BlackBone/Include/Macro.h +++ b/src/BlackBone/Include/Macro.h @@ -79,7 +79,7 @@ struct CompileTimeSizeOf; template constexpr size_t offsetOf( U T::*member ) { - return reinterpret_cast(&(reinterpret_cast(nullptr)->*member)); + return reinterpret_cast(&(static_cast(nullptr)->*member)); } template diff --git a/src/BlackBone/Misc/NameResolve.cpp b/src/BlackBone/Misc/NameResolve.cpp index 1cd68fb6..13331433 100644 --- a/src/BlackBone/Misc/NameResolve.cpp +++ b/src/BlackBone/Misc/NameResolve.cpp @@ -314,7 +314,7 @@ NTSTATUS NameResolve::ProbeSxSRedirect( std::wstring& path, Process& proc, HANDL SAFE_CALL( RtlInitUnicodeString, &OriginalName, path.c_str() ); DllName1.Buffer = wBuf; - DllName1.Length = NULL; + DllName1.Length = 0; DllName1.MaximumLength = sizeof( wBuf ); // Use activation context diff --git a/src/BlackBone/PE/PEImage.cpp b/src/BlackBone/PE/PEImage.cpp index f929789a..b10b816f 100644 --- a/src/BlackBone/PE/PEImage.cpp +++ b/src/BlackBone/PE/PEImage.cpp @@ -407,11 +407,13 @@ uintptr_t PEImage::ResolveRVAToVA( uintptr_t Rva, AddressType type /*= VA*/ ) co { for (auto& sec : _sections) { - if (Rva >= sec.VirtualAddress && Rva < sec.VirtualAddress + sec.Misc.VirtualSize) - if (type == VA) + if (Rva >= sec.VirtualAddress && Rva < sec.VirtualAddress + sec.Misc.VirtualSize) { + if (type == VA) { return reinterpret_cast(_pFileBase.get()) + Rva - sec.VirtualAddress + sec.PointerToRawData; - else + } else { return Rva - sec.VirtualAddress + sec.PointerToRawData; + } + } } return 0; diff --git a/src/BlackBone/PE/PEImage.h b/src/BlackBone/PE/PEImage.h index 59eaa530..69287137 100644 --- a/src/BlackBone/PE/PEImage.h +++ b/src/BlackBone/PE/PEImage.h @@ -67,12 +67,12 @@ struct ExportData : name( name_ ) , RVA( rva_ ) { } - bool operator == (const ExportData& other) + bool operator == (const ExportData& other) const { return name == other.name; } - bool operator < (const ExportData& other) + bool operator < (const ExportData& other) const { return name < other.name; } diff --git a/src/BlackBone/Process/MemBlock.cpp b/src/BlackBone/Process/MemBlock.cpp index 0b73a0eb..bbeb28df 100644 --- a/src/BlackBone/Process/MemBlock.cpp +++ b/src/BlackBone/Process/MemBlock.cpp @@ -189,7 +189,7 @@ call_result_t MemBlock::AllocateClosest( if (!buf.valid()) return MemBlock::Allocate( process, size, desired, protection, own ); - return buf; + return std::move(buf); } /// diff --git a/src/BlackBone/Process/Process.h b/src/BlackBone/Process/Process.h index 8bdc75b6..918c35ef 100644 --- a/src/BlackBone/Process/Process.h +++ b/src/BlackBone/Process/Process.h @@ -39,7 +39,7 @@ struct ProcessInfo std::wstring imageName; std::vector threads; - bool operator < (const ProcessInfo& other) + bool operator < (const ProcessInfo& other) const { return this->pid < other.pid; } diff --git a/src/BlackBone/Process/ProcessModules.cpp b/src/BlackBone/Process/ProcessModules.cpp index f4683e99..220e1294 100644 --- a/src/BlackBone/Process/ProcessModules.cpp +++ b/src/BlackBone/Process/ProcessModules.cpp @@ -7,6 +7,7 @@ #include "../Symbols/SymbolData.h" #include "../Asm/AsmFactory.h" +#include #include #include #include @@ -270,7 +271,7 @@ call_result_t ProcessModules::GetExport( const ModuleData& hMod, con // New size should take care of max number of present names (max name length is assumed to be 255 chars) expSize = static_cast( pExpData->AddressOfNameOrdinals - expBase - + max( pExpData->NumberOfFunctions, pExpData->NumberOfNames ) * 255 + + (std::max)( pExpData->NumberOfFunctions, pExpData->NumberOfNames ) * 255 ); expData.reset( reinterpret_cast(malloc( expSize )) ); @@ -407,7 +408,7 @@ call_result_t ProcessModules::Inject( const std::wstring& path, T img.Release(); // Already loaded - if (mod = GetModule( path, LdrList, img.mType() )) + if ((mod = GetModule( path, LdrList, img.mType() ))) return call_result_t( mod, STATUS_IMAGE_ALREADY_LOADED ); // Image path @@ -418,7 +419,7 @@ call_result_t ProcessModules::Inject( const std::wstring& path, T // Write dll name into target process auto fillDllName = [&modName, &path]( auto& ustr ) { - ustr.Buffer = modName->ptr::type>() + sizeof( ustr ); + ustr.Buffer = modName->ptr::type>() + sizeof( ustr ); ustr.MaximumLength = ustr.Length = static_cast(path.size() * sizeof( wchar_t )); modName->Write( 0, ustr ); diff --git a/src/BlackBone/Process/RPC/RemoteExec.cpp b/src/BlackBone/Process/RPC/RemoteExec.cpp index f907df9b..6b89ed3b 100644 --- a/src/BlackBone/Process/RPC/RemoteExec.cpp +++ b/src/BlackBone/Process/RPC/RemoteExec.cpp @@ -57,6 +57,9 @@ NTSTATUS RemoteExec::ExecInNewThread( case blackbone::AutoSwitch: switchMode = _process.barrier().type == wow_32_64; break; + + default: + break; } auto a = switchMode ? AsmFactory::GetAssembler( AsmFactory::asm64 ) diff --git a/src/BlackBone/Process/Threads/Thread.h b/src/BlackBone/Process/Threads/Thread.h index f82a6497..39251892 100644 --- a/src/BlackBone/Process/Threads/Thread.h +++ b/src/BlackBone/Process/Threads/Thread.h @@ -79,9 +79,42 @@ struct regDR7 uint32_t rw3 : 2; uint32_t len3 : 2; - inline void setLocal( int idx, int val ) { idx == 0 ? l0 = val : (idx == 1 ? l1 = val : (idx == 2 ? l2 = val : l3 = val)); } - inline void setRW ( int idx, int val ) { idx == 0 ? rw0 = val : (idx == 1 ? rw1 = val : (idx == 2 ? rw2 = val : rw3 = val)); } - inline void setLen ( int idx, int val ) { idx == 0 ? len0 = val : (idx == 1 ? len1 = val : (idx == 2 ? len2 = val : len3 = val)); } + inline void setLocal( int idx, int val ) + { + if (idx == 0) { + l0 = val; + } else if (idx == 1) { + l1 = val; + } else if (idx == 2) { + l2 = val; + } else { + l3 = val; + } + } + inline void setRW( int idx, int val ) + { + if (idx == 0) { + rw0 = val; + } else if (idx == 1) { + rw1 = val; + } else if (idx == 2) { + rw2 = val; + } else { + rw3 = val; + } + } + inline void setLen( int idx, int val ) + { + if (idx == 0) { + len0 = val; + } else if (idx == 1) { + len1 = val; + } else if (idx == 2) { + len2 = val; + } else { + len3 = val; + } + } inline bool empty() const { return (l0 | l1 | l2 | l3) ? false : true; } inline int getFreeIndex() const { return !l0 ? 0 : (!l1 ? 1 : (!l2 ? 2 : (!l3 ? 3 : -1))); } diff --git a/src/BlackBone/Process/Threads/Threads.h b/src/BlackBone/Process/Threads/Threads.h index f34152c6..fd3d316c 100644 --- a/src/BlackBone/Process/Threads/Threads.h +++ b/src/BlackBone/Process/Threads/Threads.h @@ -1,6 +1,7 @@ #pragma once #include "../../Include/Winheaders.h" +#include "../../Subsystem/NativeSubsystem.h" #include "Thread.h" #include @@ -72,4 +73,4 @@ class ProcessThreads class ProcessCore& _core; // Core process functions }; -} \ No newline at end of file +} diff --git a/src/BlackBone/Subsystem/Wow64Subsystem.cpp b/src/BlackBone/Subsystem/Wow64Subsystem.cpp index 6a67abd4..e75b8bf3 100644 --- a/src/BlackBone/Subsystem/Wow64Subsystem.cpp +++ b/src/BlackBone/Subsystem/Wow64Subsystem.cpp @@ -202,7 +202,7 @@ NTSTATUS NativeWow64::CreateRemoteThreadT( HANDLE& hThread, ptr_t entry, ptr_t a return STATUS_ORDINAL_NOT_FOUND; // hThread can't be used directly because x64Call will zero stack space near variable - DWORD64 hThd2 = NULL; + DWORD64 hThd2 = 0; NTSTATUS status = static_cast(X64Call( NtCreateThreadEx, 11, (DWORD64)&hThd2, (DWORD64)access, 0ull, diff --git a/src/BlackBone/Symbols/PDBHelper.cpp b/src/BlackBone/Symbols/PDBHelper.cpp index bd3e0002..4e4b2e10 100644 --- a/src/BlackBone/Symbols/PDBHelper.cpp +++ b/src/BlackBone/Symbols/PDBHelper.cpp @@ -14,6 +14,16 @@ } \ } +#ifndef _MSC_VER +// The version of __uuidof() provided by MinGW/Clang requires us defining UUIDs +// manually. See: https://stackoverflow.com/a/22518905/1566841 +// The UUID itself was copied from dia2.idl from the DIA SDK. + +// 79F1BB5F-B66E-48e5-B6A9-1545C323CA3D +__CRT_UUID_DECL(IDiaDataSource, 0x79F1BB5F, 0xB66E, 0x48e5, 0xB6, 0xA9, 0x15, 0x45, 0xC3, 0x23, 0xCA, 0x3D); +#endif + + namespace blackbone { diff --git a/src/BlackBone/Symbols/SymbolData.cpp b/src/BlackBone/Symbols/SymbolData.cpp index 19cc6167..ad4702b2 100644 --- a/src/BlackBone/Symbols/SymbolData.cpp +++ b/src/BlackBone/Symbols/SymbolData.cpp @@ -1,4 +1,3 @@ -#pragma once #include "SymbolData.h" namespace blackbone diff --git a/src/BlackBone/Syscalls/Syscall.h b/src/BlackBone/Syscalls/Syscall.h index f070a4e8..dda8f320 100644 --- a/src/BlackBone/Syscalls/Syscall.h +++ b/src/BlackBone/Syscalls/Syscall.h @@ -29,6 +29,10 @@ namespace syscall #ifdef USE32 return error( STATUS_NOT_SUPPORTED ); +#elif !defined(_MSC_VER) + // The Syscall*.asm files use MASM syntax, so they only work with MSVC. + // TODO: Port them for GCC/Clang + return error( STATUS_NOT_SUPPORTED ); #else static_assert(sizeof( R ) <= sizeof( void* ), "Return types larger than void* aren't supported"); if (index == -1) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8230182f..ed6cd2be 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -4,5 +4,13 @@ project (BlackBone) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + string(APPEND CMAKE_CXX_FLAGS " -Wno-multichar -Wno-nonportable-include-path") + string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " -lshlwapi") +elseif(MINGW) + string(APPEND CMAKE_CXX_FLAGS " -Wno-multichar") + string(APPEND CMAKE_CXX_STANDARD_LIBRARIES " -lshlwapi") +endif() + add_subdirectory(BlackBone) add_subdirectory(Samples) \ No newline at end of file diff --git a/src/Samples/Main.cpp b/src/Samples/Main.cpp index 939ddb5f..0b30aede 100644 --- a/src/Samples/Main.cpp +++ b/src/Samples/Main.cpp @@ -3,13 +3,14 @@ #include #include #include +#include using namespace blackbone; void MapCalcFromFile(); void MapCmdFromMem(); -int main( int /*argc*/, char* /*argv[]*/ ) +int main( int /*argc*/, char** /*argv[]*/ ) { // List all process PIDs matching name auto pids = Process::EnumByName( L"explorer.exe" ); @@ -49,7 +50,7 @@ int main( int /*argc*/, char* /*argv[]*/ ) { // do stuff... notepad.Resume(); - std::this_thread::sleep_for( std::chrono::milliseconds( 100 ) ); + Sleep(100); } // Process modules manipulation @@ -273,4 +274,4 @@ int main( int /*argc*/, char* /*argv[]*/ ) MapCmdFromMem(); return 0; -} \ No newline at end of file +}