├── tests ├── bar │ └── wincache_005_2.php ├── foo │ └── wincache_005_1.php ├── wincache_004_require.php ├── Wincache_require.php ├── skipif.inc ├── Wincache_004.phpt ├── wincache_ucache_cas.phpt ├── Wincache_002.phpt ├── Wincache_005.phpt ├── Wincache_003.phpt ├── wincache_001.phpt ├── Wincache_007.phpt ├── wincache_ucache_inc.phpt ├── Wincache_006.phpt ├── wincache_ucache_unset_string.phpt ├── wincache_ucache_errors.phpt ├── wincache_reroute.phpt ├── wincache_ucache_serialization.phpt ├── wincache_ucache_string.phpt ├── wincache_ucache_array.phpt ├── wincache_ucache_nested_arrays.phpt ├── wincache_ucache_set_array.phpt ├── wincache_ucache_reference.phpt └── wincache_ucache_sparse_array.phpt ├── MSG00001.bin ├── template.rc ├── wincache_etwTEMP.BIN ├── wincache_etw.rc ├── Makefile.frag ├── README.TXT ├── INSTALL ├── LICENSE ├── wincache_session.h ├── wincache_debug.h ├── wincache_dummy_etw.h ├── config.w32 ├── wincache_utils.h ├── wincache_lock.h ├── wincache_error.c ├── wincache_debug.c ├── wincache_rplist.h ├── precomp.h ├── wincache_fcache.h ├── wincache_fcnotify.h ├── wincache_aplist.h ├── wincache_zvcache.h ├── php_wincache.h ├── wincache_etw.man ├── wincache_alloc.h ├── wincache_filemap.h ├── wincache_error.h ├── wincache_session.c └── wincache_lock.c /tests/bar/wincache_005_2.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/foo/wincache_005_1.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /MSG00001.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-caching-wincache/master/MSG00001.bin -------------------------------------------------------------------------------- /template.rc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-caching-wincache/master/template.rc -------------------------------------------------------------------------------- /tests/wincache_004_require.php: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /tests/Wincache_require.php: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /wincache_etwTEMP.BIN: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-caching-wincache/master/wincache_etwTEMP.BIN -------------------------------------------------------------------------------- /wincache_etw.rc: -------------------------------------------------------------------------------- 1 | LANGUAGE 0x9,0x1 2 | 1 11 "MSG00001.bin" 3 | 1 WEVT_TEMPLATE "wincache_etwTEMP.BIN" 4 | -------------------------------------------------------------------------------- /tests/skipif.inc: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /Makefile.frag: -------------------------------------------------------------------------------- 1 | ..\pecl\wincache2\template.rc: ..\pecl\wincache2\wincache_etw.rc 2 | 3 | ..\pecl\wincache2\wincache_etw.h ..\pecl\wincache2\wincache_etw.rc: ..\pecl\wincache2\wincache_etw.man 4 | $(MC) -um -e h -h ..\pecl\wincache2\ -r ..\pecl\wincache2\ wincache_etw.man 5 | -------------------------------------------------------------------------------- /tests/Wincache_004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing return statement from an included file 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 14 | ==DONE== 15 | --EXPECTF-- 16 | Wincache 17 | ==DONE== 18 | 19 | -------------------------------------------------------------------------------- /tests/wincache_ucache_cas.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_cas function 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.ucenabled=1 8 | --FILE-- 9 | 14 | ==DONE== 15 | --EXPECTF-- 16 | bool(true) 17 | int(1) 18 | ==DONE== 19 | -------------------------------------------------------------------------------- /tests/Wincache_002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing Function call in case insensitive way 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 18 | ==DONE== 19 | --EXPECTF-- 20 | string(11) "Hello World" 21 | string(11) "Hello World" 22 | ==DONE== 23 | 24 | -------------------------------------------------------------------------------- /tests/Wincache_005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing ini directive include_path 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 16 | ==DONE== 17 | --EXPECTF-- 18 | foo subdir 19 | bar subdir 20 | ==DONE== 21 | 22 | 23 | -------------------------------------------------------------------------------- /tests/Wincache_003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing require directive 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 22 | ==DONE== 23 | --EXPECTF-- 24 | A green apple 25 | A green 26 | ==DONE== 27 | 28 | -------------------------------------------------------------------------------- /tests/wincache_001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing Global Variables 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 23 | ==DONE== 24 | --EXPECTF-- 25 | float(2) 26 | float(3) 27 | string(19) "Changing to string." 28 | ==DONE== 29 | -------------------------------------------------------------------------------- /tests/Wincache_007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | p . "\r\n"); // declared public member value is empty 18 | $c->p = 5 ; 19 | echo($c->p . "\r\n"); // declared public member value is 5 20 | unset($c->p) ; 21 | echo($c->p . "\r\n"); // after unset, value is "__get of p" 22 | ?> 23 | ==DONE== 24 | --EXPECTF-- 25 | 26 | 5 27 | __get of p 28 | ==DONE== 29 | 30 | -------------------------------------------------------------------------------- /tests/wincache_ucache_inc.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_[inc|dec] functions 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 23 | ==DONE== 24 | --EXPECTF-- 25 | bool(false) 26 | bool(true) 27 | bool(true) 28 | ==DONE== 29 | -------------------------------------------------------------------------------- /tests/Wincache_006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Testing static variables inside class 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | set(); 33 | $c2 = new Child2(); 34 | $c2->show(); // prints 2 35 | ?> 36 | ==DONE== 37 | --EXPECTF-- 38 | 2 39 | ==DONE== 40 | 41 | -------------------------------------------------------------------------------- /tests/wincache_ucache_unset_string.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - unset string data fetched from user cache 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.ucenabled=1 8 | --FILE-- 9 | "page_cache_response_policy"), array("name" => "dynamic_page_response_policy")); 12 | $cid = 'cacheid'; 13 | 14 | wincache_ucache_set($cid, $tags); 15 | $data = wincache_ucache_get($cid); 16 | 17 | $tagdef1 = serialize($data); 18 | 19 | foreach ($data as $tag_key => $tag){ 20 | $name = $tag['name']; 21 | unset($tag['name']); 22 | $tagdef2 = serialize($data); 23 | 24 | if ($tagdef1 != $tagdef2) { 25 | // By some sort of magic the $data array was modified, and what is 26 | // worse, is now populated with some content that I don't know where it 27 | // came from. 28 | echo('This is bad.'); 29 | exit(); 30 | } 31 | } 32 | ?> 33 | ==DONE== 34 | --EXPECTF-- 35 | ==DONE== -------------------------------------------------------------------------------- /tests/wincache_ucache_errors.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* known-bad conditions 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | getMessage()); 35 | } 36 | 37 | echo ("Done!"); 38 | ?> 39 | --EXPECTF-- 40 | clearing ucache 41 | bool(true) 42 | setting 'foo' 43 | bool(true) 44 | bool(true) 45 | bool(false) 46 | string(3) "BAR" 47 | string(41) "Serialization of 'Closure' is not allowed" 48 | Done! -------------------------------------------------------------------------------- /tests/wincache_reroute.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing Reroute 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | wincache.reroute_enabled=1 10 | --FILE-- 11 | 42 | ==DONE== 43 | --EXPECTF-- 44 | bool(true) 45 | bool(true) 46 | bool(true) 47 | bool(true) 48 | string(%d) "Hello World!" 49 | int(%d) 50 | bool(false) 51 | bool(true) 52 | bool(true) 53 | bool(true) 54 | bool(true) 55 | Hello World!int(%d) 56 | string(%d) "%sok.txt" 57 | bool(false) 58 | bool(false) 59 | bool(false) 60 | ==DONE== 61 | -------------------------------------------------------------------------------- /README.TXT: -------------------------------------------------------------------------------- 1 | ETW Tracing & Manifest file: 2 | ---------------------------- 3 | 4 | As of May 26, 2015, there is no mechanism to have the Win32 build environment 5 | call the $(MC) command with the right parameters against the ETW Manifest file. 6 | So, if you make changes to the ETW manifest file, you'll need to hand-execute 7 | the $(MC) command with the right parameters, and check in the changed files. 8 | 9 | Command to execute (in the pecl\wincache directory): 10 | mc -um -e h -h .\ -r .\ wincache_etw.man 11 | 12 | Files generated by 'mc': 13 | wincache_etw.h 14 | wincache_etw.rc 15 | MSG00001.bin 16 | wincache_etwTEMP.BIN 17 | 18 | To register the manifest, open an admin cmd window, and execute the following 19 | command: 20 | wevtutil im wincache_etw.man 21 | 22 | If you've previously registered a manifest, you'll have to unregister the 23 | manifest, and then re-register it. 24 | wevtutil um wincache_etw.man 25 | wevtutil im wincache_etw.man 26 | 27 | To capture ETW traces, you can create a log profile with logman: 28 | 29 | logman create trace wincache_etw -p "{F7AD0093-D5C3-46B9-BEEA-A9FCEC7E1408}" -o c:\temp\wincache_etw 30 | logman start wincache_etw 31 | <...do your repro...> 32 | logman stop wincache_etw 33 | tracerpt wincache_etw_000001.etl -import wincache_etw.man 34 | 35 | You'll need to copy the wincache_etw.man to the machine where you're executing 36 | wincache, and wherever you're running tracerpt.exe. 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /tests/wincache_ucache_serialization.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with IS_OBJECT data 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | getMessage()); 28 | } 29 | 30 | /* Setting a user-defined class should work */ 31 | 32 | class Connection 33 | { 34 | private $dsn, $username, $password; 35 | 36 | public function __construct($dsn, $username, $password) 37 | { 38 | $this->dsn = $dsn; 39 | $this->username = $username; 40 | $this->password = $password; 41 | } 42 | 43 | public function __sleep() 44 | { 45 | return array('dsn', 'username', 'password'); 46 | } 47 | 48 | public function __wakeup() 49 | { 50 | echo 'waking up: ' . $this . "\n"; 51 | } 52 | 53 | public function __toString() 54 | { 55 | return $this->dsn . ':' . $this->username . ':*****'; 56 | } 57 | } 58 | 59 | $bar2 = new Connection('MyDsn', 'MyUsername', 'MyPassword'); 60 | 61 | try 62 | { 63 | var_dump(wincache_ucache_add('foo2', $bar2)); 64 | } 65 | catch (Exception $e) 66 | { 67 | var_dump($e->getMessage()); 68 | } 69 | 70 | $bar3 = wincache_ucache_get('foo2'); 71 | echo "Fetched: {$bar3}\n"; 72 | var_dump($bar3); 73 | 74 | 75 | echo("Done!"); 76 | 77 | ?> 78 | --EXPECTF-- 79 | clearing ucache 80 | bool(true) 81 | string(41) "Serialization of 'Closure' is not allowed" 82 | bool(true) 83 | waking up: MyDsn:MyUsername:***** 84 | Fetched: MyDsn:MyUsername:***** 85 | object(Connection)#4 (3) { 86 | ["dsn":"Connection":private]=> 87 | string(5) "MyDsn" 88 | ["username":"Connection":private]=> 89 | string(10) "MyUsername" 90 | ["password":"Connection":private]=> 91 | string(10) "MyPassword" 92 | } 93 | Done! 94 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions for WinCache 2 | -------------------------------------- 3 | 4 | Requirements 5 | ------------ 6 | The extension is currently supported only on the following 7 | configurations: 8 | 9 | Windows OS: 10 | - Windows XP SP3 with IIS 5.1 and FastCGI Extension 11 | - Windows Server 2003 with IIS 6.0 and FastCGI Extension 12 | - Windows Vista SP1 with IIS 7.0 and FastCGI Module 13 | - Windows Server 2008 with IIS 7.0 and FastCGI Module 14 | 15 | PHP: 16 | - PHP 5.2.X, Non-thread-safe build 17 | - PHP 5.3 X86, Non-thread-safe VC9 build 18 | 19 | Note: The WinCache Extension can only be used when IIS is 20 | configured to run PHP via FastCGI. 21 | 22 | Installation 23 | ------------ 24 | There are two packages for this extension: one package is for PHP 25 | versions 5.2.X, and the other package is for PHP 5.3.X. Select the 26 | package that is appropriate for the PHP version being used. 27 | 28 | To install and enable the extension, follow these steps: 29 | 30 | 1.Unpack the package into some temporary location. 31 | 32 | 2.Copy the php_wincache.dll file into the PHP extensions folder. Typically 33 | this folder is called "ext" and it is located in the same folder with 34 | all PHP binary files. For example: C:\Program Files\PHP\ext. 35 | 36 | 3.Using a text editor, open the php.ini file, which is usually located 37 | in the same folder where all PHP binary files are. For example: 38 | C:\Program Files\PHP\php.ini. 39 | 40 | 4.Add the following line at the end of the php.ini file: extension = 41 | php_wincache.dll. 42 | 43 | 5.Save and close the php.ini file. 44 | 45 | 6.Recycle the IIS Application Pools for PHP to pick up the configuration 46 | changes. To check that the extension has been enabled, create a file 47 | called phpinfo.php with a PHP code that calls phpinfo function. 48 | 49 | 7.Save the phpinfo.php file in the root folder of a IIS web site that 50 | uses PHP, then open a browser and make a request to 51 | http://localhost/phpinfo.php. Search within the returned web page for a 52 | section called wincache. If the extension is enabled, then the phpinfo 53 | output will list the configuration settings provided by the WinCache. 54 | 55 | Note: Do not forget to remove phpinfo.php file from the web site's root 56 | folder after verifying that extension has been enabled. 57 | 58 | For instructions on how to use the extension refer to 59 | http://docs.php.net/wincache. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | +----------------------------------------------------------------------------------------------+ 2 | | Windows Cache for PHP | 3 | +----------------------------------------------------------------------------------------------+ 4 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 5 | | | 6 | | Redistribution and use in source and binary forms, with or without modification, are | 7 | | permitted provided that the following conditions are met: | 8 | | - Redistributions of source code must retain the above copyright notice, this list of | 9 | | conditions and the following disclaimer. | 10 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 11 | | conditions and the following disclaimer in the documentation and/or other materials provided | 12 | | with the distribution. | 13 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 14 | | used to endorse or promote products derived from this software without specific prior written| 15 | | permission. | 16 | | | 17 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 18 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 19 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 20 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 21 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 22 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 23 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 24 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 25 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 26 | +----------------------------------------------------------------------------------------------+ 27 | | Authors: Kanwaljeet Singla | 28 | | Don Venkat Raman | 29 | | Ruslan Yakushev | 30 | | Updated: Eric Stenson | 31 | +----------------------------------------------------------------------------------------------+ 32 | -------------------------------------------------------------------------------- /tests/wincache_ucache_string.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with simple strings 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 42 | --EXPECTF-- 43 | clearing ucache 44 | bool(true) 45 | setting 'foo' 46 | bool(true) 47 | 48 | Warning: wincache_ucache_add(): function called with a key which already exists in %swincache_ucache_string.php on line %d 49 | bool(false) 50 | string(3) "BAR" 51 | bool(true) 52 | string(4) "BAR2" 53 | bool(true) 54 | array(6) { 55 | ["total_cache_uptime"]=> 56 | int(0) 57 | ["is_local_cache"]=> 58 | bool(false) 59 | ["total_item_count"]=> 60 | int(1) 61 | ["total_hit_count"]=> 62 | int(2) 63 | ["total_miss_count"]=> 64 | int(0) 65 | ["ucache_entries"]=> 66 | array(1) { 67 | [1]=> 68 | array(6) { 69 | ["key_name"]=> 70 | string(3) "foo" 71 | ["value_type"]=> 72 | string(6) "string" 73 | ["value_size"]=> 74 | int(%d) 75 | ["ttl_seconds"]=> 76 | int(0) 77 | ["age_seconds"]=> 78 | int(0) 79 | ["hitcount"]=> 80 | int(1) 81 | } 82 | } 83 | } 84 | bool(true) 85 | setting $foo 86 | bool(true) 87 | 88 | Warning: wincache_ucache_add(): function called with a key which already exists in %swincache_ucache_string.php on line %d 89 | bool(false) 90 | string(3) "BAR" 91 | bool(true) 92 | string(4) "BAR2" 93 | bool(true) 94 | array(6) { 95 | ["total_cache_uptime"]=> 96 | int(0) 97 | ["is_local_cache"]=> 98 | bool(false) 99 | ["total_item_count"]=> 100 | int(1) 101 | ["total_hit_count"]=> 102 | int(4) 103 | ["total_miss_count"]=> 104 | int(0) 105 | ["ucache_entries"]=> 106 | array(1) { 107 | [1]=> 108 | array(6) { 109 | ["key_name"]=> 110 | string(3) "FOO" 111 | ["value_type"]=> 112 | string(6) "string" 113 | ["value_size"]=> 114 | int(%d) 115 | ["ttl_seconds"]=> 116 | int(0) 117 | ["age_seconds"]=> 118 | int(0) 119 | ["hitcount"]=> 120 | int(1) 121 | } 122 | } 123 | } 124 | bool(true) 125 | Done! -------------------------------------------------------------------------------- /wincache_session.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_session.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #ifndef _WINCACHE_SESSION_H_ 35 | #define _WINCACHE_SESSION_H_ 36 | 37 | extern ps_module ps_mod_wincache; 38 | #define ps_wincache_ptr &ps_mod_wincache 39 | 40 | PS_FUNCS(wincache); 41 | 42 | #endif /* _WINCACHE_SESSION_H_ */ 43 | -------------------------------------------------------------------------------- /wincache_debug.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_debug.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #ifndef _WINCACHE_DEBUG_H_ 35 | #define _WINCACHE_DEBUG_H_ 36 | 37 | extern void dprintsetlevel(unsigned int level); 38 | extern void dprintmessage(char * format, va_list args); 39 | extern void dprintalways(char * format, ...); 40 | extern void dprintcritical(char * format, ...); 41 | extern void dprintimportant(char * format, ...); 42 | extern void dprintverbose(char * format, ...); 43 | extern void dprintdecorate(char * format, ...); 44 | 45 | ZEND_INI_MH(wincache_modify_debuglevel); 46 | 47 | #endif /* _WINCACHE_DEBUG_H_ */ 48 | -------------------------------------------------------------------------------- /wincache_dummy_etw.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2015, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_dummy_etw.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Eric Stenson | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #pragma once 35 | 36 | #define EventRegisterPHP_Wincache() 37 | #define EventUnregisterPHP_Wincache() 38 | #define EventWriteModuleInitErrorEvent(Error) 39 | #define EventWriteInitMutexErrorEvent(Name, Handle) 40 | #define EventWriteInitOpcacheLocalFallbackEvent() 41 | #define EventWriteMemBlockNotInUse(Block, AllocContext, File, Line) 42 | #define EventWriteMemFreeAddrNotInSegment(Block, AllocContext, File, Line) 43 | #define EventWriteMemCombineNonFreeBlock(Block, AllocContext, File, Line) 44 | #define EventWriteMemFreeListCorrupt(Block, AllocContext, File, Line) 45 | #define EventWriteLockAbandonedMutex(LockName, LastReaderPid, LastWriterPid, File, Line) 46 | #define EventWriteLockFailedWaitForLock(LockName, LastReaderPid, LastWriterPid, File, Line) 47 | #define EventWriteUnlockAbandonedMutex(LockName, LastReaderPid, LastWriterPid, File, Line) 48 | #define EventWriteUnlockFailedWaitForLock(LockName, LastReaderPid, LastWriterPid, File, Line) 49 | 50 | -------------------------------------------------------------------------------- /tests/wincache_ucache_array.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with IS_ARRAY data 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 5, 'Blue' => '6', 'yellow', 'cyan' => 'eight'); 17 | 18 | var_dump(wincache_ucache_add('foo', $bar)); 19 | var_dump(wincache_ucache_add('foo', $bar)); 20 | var_dump(wincache_ucache_get('foo')); 21 | var_dump(wincache_ucache_set('foo', array('pink' => 9, 'chartruce' => '10', 'brown', 'magenta' => 'twelve'))); 22 | var_dump(wincache_ucache_get('foo')); 23 | var_dump(wincache_ucache_exists('foo')); 24 | var_dump(wincache_ucache_info(false, 'foo')); 25 | var_dump(wincache_ucache_delete('foo')); 26 | 27 | echo("setting \$foo\n"); 28 | $foo = "FOO"; 29 | 30 | var_dump(wincache_ucache_add($foo, $bar)); 31 | var_dump(wincache_ucache_add($foo, $bar)); 32 | var_dump(wincache_ucache_get($foo)); 33 | var_dump(wincache_ucache_set($foo, array('pink' => 9, 'chartruce' => '10', 'brown', 'magenta' => 'twelve'))); 34 | var_dump(wincache_ucache_get($foo)); 35 | var_dump(wincache_ucache_exists($foo)); 36 | var_dump(wincache_ucache_info(false, $foo)); 37 | var_dump(wincache_ucache_delete($foo)); 38 | 39 | echo("Done!"); 40 | 41 | ?> 42 | --EXPECTF-- 43 | clearing ucache 44 | bool(true) 45 | setting 'foo' 46 | bool(true) 47 | 48 | Warning: wincache_ucache_add(): function called with a key which already exists in %s on line %d 49 | bool(false) 50 | array(4) { 51 | ["green"]=> 52 | int(5) 53 | ["Blue"]=> 54 | string(1) "6" 55 | [0]=> 56 | string(6) "yellow" 57 | ["cyan"]=> 58 | string(5) "eight" 59 | } 60 | bool(true) 61 | array(4) { 62 | ["pink"]=> 63 | int(9) 64 | ["chartruce"]=> 65 | string(2) "10" 66 | [0]=> 67 | string(5) "brown" 68 | ["magenta"]=> 69 | string(6) "twelve" 70 | } 71 | bool(true) 72 | array(6) { 73 | ["total_cache_uptime"]=> 74 | int(0) 75 | ["is_local_cache"]=> 76 | bool(false) 77 | ["total_item_count"]=> 78 | int(1) 79 | ["total_hit_count"]=> 80 | int(2) 81 | ["total_miss_count"]=> 82 | int(0) 83 | ["ucache_entries"]=> 84 | array(1) { 85 | [1]=> 86 | array(6) { 87 | ["key_name"]=> 88 | string(3) "foo" 89 | ["value_type"]=> 90 | string(5) "array" 91 | ["value_size"]=> 92 | int(%d) 93 | ["ttl_seconds"]=> 94 | int(0) 95 | ["age_seconds"]=> 96 | int(0) 97 | ["hitcount"]=> 98 | int(1) 99 | } 100 | } 101 | } 102 | bool(true) 103 | setting $foo 104 | bool(true) 105 | 106 | Warning: wincache_ucache_add(): function called with a key which already exists in %s on line %d 107 | bool(false) 108 | array(4) { 109 | ["green"]=> 110 | int(5) 111 | ["Blue"]=> 112 | string(1) "6" 113 | [0]=> 114 | string(6) "yellow" 115 | ["cyan"]=> 116 | string(5) "eight" 117 | } 118 | bool(true) 119 | array(4) { 120 | ["pink"]=> 121 | int(9) 122 | ["chartruce"]=> 123 | string(2) "10" 124 | [0]=> 125 | string(5) "brown" 126 | ["magenta"]=> 127 | string(6) "twelve" 128 | } 129 | bool(true) 130 | array(6) { 131 | ["total_cache_uptime"]=> 132 | int(0) 133 | ["is_local_cache"]=> 134 | bool(false) 135 | ["total_item_count"]=> 136 | int(1) 137 | ["total_hit_count"]=> 138 | int(4) 139 | ["total_miss_count"]=> 140 | int(0) 141 | ["ucache_entries"]=> 142 | array(1) { 143 | [1]=> 144 | array(6) { 145 | ["key_name"]=> 146 | string(3) "FOO" 147 | ["value_type"]=> 148 | string(5) "array" 149 | ["value_size"]=> 150 | int(%d) 151 | ["ttl_seconds"]=> 152 | int(0) 153 | ["age_seconds"]=> 154 | int(0) 155 | ["hitcount"]=> 156 | int(1) 157 | } 158 | } 159 | } 160 | bool(true) 161 | Done! 162 | -------------------------------------------------------------------------------- /tests/wincache_ucache_nested_arrays.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with nested arrays as a value 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 13, 'black' => 14); 22 | $bar1 = array('green' => 5, 'Blue' => '6', 'yellow', 'cyan' => 'eight'); 23 | $bar2 = array('greenish' => 9, 'Blueish' => '10', 'yellowish', 'cyanish' => 'twelve', 'blackish' => $frag1); 24 | $bar3 = array('greenlike' => 9, 'pink' => 10, 'chartruce' => '11', 'brown', 'magenta' => 'thirteen'); 25 | $master = array('first' => $bar1, 'second' => $bar2, 'third' => $bar3, 'fourth' => $bar1, 'fifth' => $bar2, '6th' => $bar2); 26 | 27 | 28 | var_dump(wincache_ucache_add('master', $master)); 29 | var_dump(wincache_ucache_exists('master')); 30 | var_dump(wincache_ucache_get('master')); 31 | var_dump(wincache_ucache_info(false, 'master')); 32 | var_dump(wincache_ucache_delete('master')); 33 | 34 | echo("clearing ucache\n"); 35 | var_dump(wincache_ucache_clear()); 36 | 37 | echo("Done!"); 38 | 39 | ?> 40 | --EXPECTF-- 41 | clearing ucache 42 | bool(true) 43 | setting array 44 | bool(true) 45 | bool(true) 46 | array(6) { 47 | ["first"]=> 48 | array(4) { 49 | ["green"]=> 50 | int(5) 51 | ["Blue"]=> 52 | string(1) "6" 53 | [0]=> 54 | string(6) "yellow" 55 | ["cyan"]=> 56 | string(5) "eight" 57 | } 58 | ["second"]=> 59 | array(5) { 60 | ["greenish"]=> 61 | int(9) 62 | ["Blueish"]=> 63 | string(2) "10" 64 | [0]=> 65 | string(9) "yellowish" 66 | ["cyanish"]=> 67 | string(6) "twelve" 68 | ["blackish"]=> 69 | array(2) { 70 | ["green"]=> 71 | int(13) 72 | ["black"]=> 73 | int(14) 74 | } 75 | } 76 | ["third"]=> 77 | array(5) { 78 | ["greenlike"]=> 79 | int(9) 80 | ["pink"]=> 81 | int(10) 82 | ["chartruce"]=> 83 | string(2) "11" 84 | [0]=> 85 | string(5) "brown" 86 | ["magenta"]=> 87 | string(8) "thirteen" 88 | } 89 | ["fourth"]=> 90 | array(4) { 91 | ["green"]=> 92 | int(5) 93 | ["Blue"]=> 94 | string(1) "6" 95 | [0]=> 96 | string(6) "yellow" 97 | ["cyan"]=> 98 | string(5) "eight" 99 | } 100 | ["fifth"]=> 101 | array(5) { 102 | ["greenish"]=> 103 | int(9) 104 | ["Blueish"]=> 105 | string(2) "10" 106 | [0]=> 107 | string(9) "yellowish" 108 | ["cyanish"]=> 109 | string(6) "twelve" 110 | ["blackish"]=> 111 | array(2) { 112 | ["green"]=> 113 | int(13) 114 | ["black"]=> 115 | int(14) 116 | } 117 | } 118 | ["6th"]=> 119 | array(5) { 120 | ["greenish"]=> 121 | int(9) 122 | ["Blueish"]=> 123 | string(2) "10" 124 | [0]=> 125 | string(9) "yellowish" 126 | ["cyanish"]=> 127 | string(6) "twelve" 128 | ["blackish"]=> 129 | array(2) { 130 | ["green"]=> 131 | int(13) 132 | ["black"]=> 133 | int(14) 134 | } 135 | } 136 | } 137 | array(6) { 138 | ["total_cache_uptime"]=> 139 | int(0) 140 | ["is_local_cache"]=> 141 | bool(false) 142 | ["total_item_count"]=> 143 | int(1) 144 | ["total_hit_count"]=> 145 | int(1) 146 | ["total_miss_count"]=> 147 | int(0) 148 | ["ucache_entries"]=> 149 | array(1) { 150 | [1]=> 151 | array(6) { 152 | ["key_name"]=> 153 | string(6) "master" 154 | ["value_type"]=> 155 | string(5) "array" 156 | ["value_size"]=> 157 | int(%d) 158 | ["ttl_seconds"]=> 159 | int(0) 160 | ["age_seconds"]=> 161 | int(0) 162 | ["hitcount"]=> 163 | int(1) 164 | } 165 | } 166 | } 167 | bool(true) 168 | clearing ucache 169 | bool(true) 170 | Done! -------------------------------------------------------------------------------- /tests/wincache_ucache_set_array.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with arrays of values 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 5, 'Blue' => '6', 'yellow', 'cyan' => 'eight'); 22 | 23 | var_dump(wincache_ucache_add($bar, NULL)); 24 | var_dump(wincache_ucache_add(array('green' => 13, 'black' => 14))); 25 | var_dump(wincache_ucache_get(array('green', 'Blue', 'cyan'))); 26 | var_dump(wincache_ucache_get('yellow')); /* should be not found! */ 27 | var_dump(wincache_ucache_set(array('green' => 9, 'Blue' => '10', 'yellow', 'cyan' => 'twelve'))); 28 | var_dump(wincache_ucache_get('green')); 29 | var_dump(wincache_ucache_exists('green')); 30 | var_dump(wincache_ucache_info(false, 'green')); 31 | var_dump(wincache_ucache_delete(array('green', 'Blue', 'yellow', 'cyan'))); 32 | 33 | echo("clearing ucache\n"); 34 | var_dump(wincache_ucache_clear()); 35 | 36 | echo("setting \$foo\n"); 37 | $foo = array('green' => 5, 'Blue' => '6', 'yellow', 'cyan' => 'eight'); 38 | $foo_get = array('green', 'Blue', 'cyan'); 39 | 40 | var_dump(wincache_ucache_add($foo, NULL)); 41 | var_dump(wincache_ucache_add($foo, NULL)); 42 | var_dump(wincache_ucache_get($foo_get)); 43 | var_dump(wincache_ucache_set(array('green' => 9, 'pink' => 10, 'chartruce' => '11', 'brown', 'magenta' => 'thirteen'))); 44 | var_dump(wincache_ucache_get($foo)); 45 | var_dump(wincache_ucache_exists('pink')); 46 | var_dump(wincache_ucache_info(false, 'pink')); 47 | var_dump(wincache_ucache_delete($foo_get)); 48 | 49 | echo("Done!"); 50 | 51 | ?> 52 | --EXPECTF-- 53 | clearing ucache 54 | bool(true) 55 | setting array 56 | array(0) { 57 | } 58 | array(1) { 59 | ["green"]=> 60 | int(-1) 61 | } 62 | array(3) { 63 | ["green"]=> 64 | int(5) 65 | ["Blue"]=> 66 | string(1) "6" 67 | ["cyan"]=> 68 | string(5) "eight" 69 | } 70 | bool(false) 71 | array(0) { 72 | } 73 | int(9) 74 | bool(true) 75 | array(6) { 76 | ["total_cache_uptime"]=> 77 | int(0) 78 | ["is_local_cache"]=> 79 | bool(false) 80 | ["total_item_count"]=> 81 | int(5) 82 | ["total_hit_count"]=> 83 | int(4) 84 | ["total_miss_count"]=> 85 | int(1) 86 | ["ucache_entries"]=> 87 | array(1) { 88 | [1]=> 89 | array(6) { 90 | ["key_name"]=> 91 | string(5) "green" 92 | ["value_type"]=> 93 | string(4) "long" 94 | ["value_size"]=> 95 | int(16) 96 | ["ttl_seconds"]=> 97 | int(0) 98 | ["age_seconds"]=> 99 | int(0) 100 | ["hitcount"]=> 101 | int(1) 102 | } 103 | } 104 | } 105 | array(3) { 106 | [0]=> 107 | string(5) "green" 108 | [1]=> 109 | string(4) "Blue" 110 | [2]=> 111 | string(4) "cyan" 112 | } 113 | clearing ucache 114 | bool(true) 115 | setting $foo 116 | array(0) { 117 | } 118 | array(4) { 119 | ["green"]=> 120 | int(-1) 121 | ["Blue"]=> 122 | int(-1) 123 | [0]=> 124 | int(-1) 125 | ["cyan"]=> 126 | int(-1) 127 | } 128 | array(3) { 129 | ["green"]=> 130 | int(5) 131 | ["Blue"]=> 132 | string(1) "6" 133 | ["cyan"]=> 134 | string(5) "eight" 135 | } 136 | array(0) { 137 | } 138 | array(0) { 139 | } 140 | bool(true) 141 | array(6) { 142 | ["total_cache_uptime"]=> 143 | int(0) 144 | ["is_local_cache"]=> 145 | bool(false) 146 | ["total_item_count"]=> 147 | int(7) 148 | ["total_hit_count"]=> 149 | int(7) 150 | ["total_miss_count"]=> 151 | int(5) 152 | ["ucache_entries"]=> 153 | array(1) { 154 | [1]=> 155 | array(6) { 156 | ["key_name"]=> 157 | string(4) "pink" 158 | ["value_type"]=> 159 | string(4) "long" 160 | ["value_size"]=> 161 | int(16) 162 | ["ttl_seconds"]=> 163 | int(0) 164 | ["age_seconds"]=> 165 | int(0) 166 | ["hitcount"]=> 167 | int(0) 168 | } 169 | } 170 | } 171 | array(3) { 172 | [0]=> 173 | string(5) "green" 174 | [1]=> 175 | string(4) "Blue" 176 | [2]=> 177 | string(4) "cyan" 178 | } 179 | Done! -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP v2 | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: config.w32 | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | ARG_ENABLE("wincache", "Windows PHP Cache 2", "no"); 36 | 37 | if (PHP_WINCACHE != "no") { 38 | if (PHP_ZTS != "no") { 39 | WARNING("WinCache module requires --disable-zts build of PHP on windows"); 40 | } else { 41 | EXTENSION('wincache', "php_wincache.c wincache_utils.c wincache_error.c \ 42 | wincache_debug.c wincache_lock.c wincache_filemap.c \ 43 | wincache_alloc.c \ 44 | wincache_fcache.c wincache_rplist.c wincache_aplist.c \ 45 | wincache_zvcache.c wincache_session.c \ 46 | wincache_fcnotify.c", 47 | true, 48 | "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); 49 | 50 | ADD_EXTENSION_DEP('wincache', 'session'); 51 | AC_DEFINE('HAVE_WINCACHE', 1); 52 | 53 | DEFINE('WINCACHE_ETW_RC', configure_module_dirname + '\\wincache_etw.rc'); 54 | 55 | ADD_FLAG('LDFLAGS_WINCACHE', '/NXCOMPAT'); 56 | if (!X64) { 57 | ADD_FLAG('LDFLAGS_WINCACHE', '/SAFESEH'); 58 | } 59 | 60 | ADD_FLAG('CFLAGS_WINCACHE', '/GS'); 61 | ADD_FLAG('CFLAGS_WINCACHE', '/I' + configure_module_dirname + ' '); 62 | 63 | if (PHP_DEBUG == "yes") { 64 | ADD_FLAG('LDFLAGS_WINCACHE', '/debug /debugtype:cv,fixup'); 65 | ADD_FLAG('CFLAGS_WINCACHE', '/D WINCACHE_DEBUG'); 66 | ADD_FLAG('CFLAGS_WINCACHE', '/Zi'); 67 | ADD_FLAG('CFLAGS_WINCACHE', '/WX'); 68 | } 69 | 70 | ADD_FLAG('DEPS_WINCACHE', configure_module_dirname + '\\wincache_etw.rc'); 71 | 72 | CHECK_LIB("Kernel32.lib", "wincache", PHP_WINCACHE); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /wincache_utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_utils.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_UTILS_H_ 36 | #define _WINCACHE_UTILS_H_ 37 | 38 | extern uint32_t utils_hashcalc(const char * str, size_t strlen); 39 | extern uint32_t utils_getindex(const char * filename, unsigned int numfiles); 40 | extern const char * utils_filepath(zend_file_handle * file_handle); 41 | extern char * utils_fullpath(const char * filename, size_t filename_len); 42 | extern int utils_cwdcexec(char * buffer, size_t length); 43 | extern int utils_filefolder(const char * filepath, size_t flength, char * pbuffer, size_t length); 44 | extern int utils_apoolpid(); 45 | extern unsigned int utils_ticksdiff(unsigned int present, unsigned int past); 46 | extern char * utils_resolve_path(const char *filename, size_t filename_length, const char *path); 47 | extern char * utils_build_temp_filename(char * suffix); 48 | extern void utils_get_filename_and_line(const char **filename, uint32_t *linenumber); 49 | extern void utils_wait_for_listener(const char * respath, unsigned int timeout); 50 | extern unsigned int utils_get_prime_less_than(size_t num); 51 | 52 | extern int 53 | utils_create_init_event( 54 | char * prefix, 55 | char * name, 56 | HANDLE *pinit_event, 57 | unsigned char *pisfirst 58 | ); 59 | 60 | #if (defined(_MSC_VER) && (_MSC_VER < 1500)) 61 | extern int wincache_php_snprintf_s(char *buf, size_t len, size_t len2, const char *format,...); 62 | #endif 63 | 64 | extern const char * 65 | utils_get_apppool_name(); 66 | 67 | extern int 68 | utils_set_apppool_acl( 69 | char * filename 70 | ); 71 | 72 | extern int utils_revert_if_necessary(HANDLE *phOriginalToken); 73 | extern void utils_reimpersonate_if_necessary(HANDLE hOriginalToken); 74 | 75 | extern const char * utils_get_typename(zend_uchar type); 76 | 77 | #endif /* _WINCACHE_UTILS_H_ */ 78 | -------------------------------------------------------------------------------- /wincache_lock.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_lock.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_LOCK_H_ 36 | #define _WINCACHE_LOCK_H_ 37 | 38 | #define PID_MAX_LENGTH 6 /* 999999 being maximum */ 39 | #define LOCK_WAIT_TIMEOUT 200 /* Wait timeout is 200 ms */ 40 | #define LOCK_NUMBER_MAXIMUM 65535 /* Maximum number of instances for same type */ 41 | #define LOCK_NUMBER_MAX_STRLEN 5 /* 65535 is the maximum cachekey supported */ 42 | 43 | #define LOCK_TYPE_INVALID 0 /* Invalid type */ 44 | #define LOCK_TYPE_SHARED 1 /* Lock shared by child processes. Use PPID */ 45 | #define LOCK_TYPE_LOCAL 2 /* Lock used by this process. Use PID in name */ 46 | #define LOCK_TYPE_GLOBAL 3 /* Global lock. Use exact name as specified */ 47 | #define LOCK_TYPE_MAXIMUM 7 /* type is a 3 bit field. Max value is 7 */ 48 | 49 | #define LOCK_STATE_UNLOCKED 0 /* Lock is not acquired */ 50 | #define LOCK_STATE_LOCKED 1 /* Lock is acquired */ 51 | #define LOCK_STATE_MAXIMUM 1 /* state is a 1 bit field. Max value is 1 */ 52 | 53 | /* lock_context - LOCAL - 32 bytes */ 54 | /* last_owner - SHARED */ 55 | 56 | typedef struct lock_context lock_context; 57 | struct lock_context 58 | { 59 | unsigned id:8; /* Unique identifier for the lock */ 60 | unsigned type:3; /* Type of lock (shared/local/global) */ 61 | unsigned unused:3; /* padding */ 62 | unsigned state:2; /* Current state of the lock for debugging */ 63 | unsigned namelen:16; /* length of name buffers */ 64 | 65 | char * nameprefix; /* Name prefix to use for named objects */ 66 | HANDLE hxlock; /* Handle to mutex to prevent multiple writers */ 67 | unsigned int * last_owner; /* Pointer to shared memory which has the last owner PID */ 68 | }; 69 | 70 | extern int lock_create(lock_context ** pplock); 71 | extern void lock_destroy(lock_context * plock); 72 | 73 | extern int lock_get_nameprefix( 74 | char * name, 75 | unsigned short cachekey, 76 | unsigned short type, 77 | char **ppnew_prefix, 78 | size_t * pcchnew_prefix 79 | ); 80 | extern int lock_initialize(lock_context * plock, char * name, unsigned short cachekey, unsigned short type, unsigned int * plast_owner); 81 | extern void lock_terminate(lock_context * plock); 82 | 83 | extern void lock_lock(lock_context * plock); 84 | extern void lock_unlock(lock_context * plock); 85 | 86 | extern void lock_runtest(); 87 | 88 | #endif /* _WINCACHE_LOCK_H_ */ 89 | -------------------------------------------------------------------------------- /wincache_error.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_error.c | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #include "precomp.h" 35 | 36 | error_context wincache_errors[] = 37 | { 38 | { FATAL_OUT_OF_MEMORY, "Fatal: Out of memory error" }, 39 | { FATAL_OUT_OF_LMEMORY, "Fatal: Out of local memory error" }, 40 | { FATAL_OUT_OF_SMEMORY, "Fatal: Out of shared memor error" }, 41 | { FATAL_ACCESS_DENIED, "Fatal: Access Denied" }, 42 | { FATAL_LOCK_INIT_CREATEMUTEX, "Fatal: CreateMutex operation failed in lock_initialize" }, 43 | { FATAL_LOCK_LONGNAME, "Fatal: Lock prefix is too long" }, 44 | { FATAL_FILEMAP_CREATION, "Fatal: Filemap creation error" }, 45 | { FATAL_FILEMAP_INFOCREATE, "Fatal: CreateFileMapping operation for information filemap failed" }, 46 | { FATAL_FILEMAP_INFOMAP, "Fatal: MapViewOfFileEx operation for information filemap failed" }, 47 | { FATAL_FILEMAP_CREATE_SNAPSHOT, "Fatal: CreateToolhelp32Snapshot call failed unexpectedly" }, 48 | { FATAL_FILEMAP_INITIALIZE, "Fatal: New filemap couldn't be created" }, 49 | { FATAL_FILEMAP_NOFREE, "Fatal: No free filemap_information_entry found in info filemap" }, 50 | { FATAL_ALLOC_NO_MEMORY, "Fatal: Shared memory segment is completely full" }, 51 | { FATAL_FCACHE_CREATION, "" }, 52 | { FATAL_FCACHE_CREATEFILE, "Fatal: CreateFile call failed" }, 53 | { FATAL_FCACHE_GETFILETYPE, "Fatal: GetFileType call failed" }, 54 | { FATAL_FCACHE_GETFILESIZE, "Fatal: GetFileSize call failed" }, 55 | { FATAL_FCACHE_READFILE, "Fatal: ReadFile call failed" }, 56 | { FATAL_FCACHE_INITIALIZE, "Fatal: Failure while initializing file cache module" }, 57 | { WARNING_FCACHE_TOOBIG, "Warning: File too big for file cache" }, 58 | { FATAL_FCACHE_FILEINFO, "Fatal: Failure in FileInfo" } 59 | }; 60 | 61 | /* Windows maintain last error code for each thread */ 62 | /* We are only maintaining for the process */ 63 | unsigned int error_glerror = 0; 64 | 65 | unsigned int error_getlasterror() 66 | { 67 | return error_glerror; 68 | } 69 | 70 | unsigned int error_setlasterror() 71 | { 72 | error_glerror = GetLastError(); 73 | WCG(lasterror) = error_glerror; 74 | return error_glerror; 75 | } 76 | 77 | char * error_gethrmessage() 78 | { 79 | return error_getmessage(error_glerror); 80 | } 81 | 82 | char * error_getmessage(unsigned int error_code) 83 | { 84 | int count = 0; 85 | int index = 0; 86 | char * message = NULL; 87 | 88 | count = sizeof(wincache_errors)/sizeof(wincache_errors[0]); 89 | for(index = 0; index < count; index++) 90 | { 91 | if(wincache_errors[index].error_code == error_glerror) 92 | { 93 | message = wincache_errors[index].error_message; 94 | break; 95 | } 96 | } 97 | 98 | return message; 99 | } 100 | -------------------------------------------------------------------------------- /wincache_debug.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_debug.c | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #include "precomp.h" 35 | 36 | #define WINCACHE_DEBUG_MTYPE_DISABLED 0 37 | #define WINCACHE_DEBUG_MTYPE_ALWAYS 101 38 | #define WINCACHE_DEBUG_MTYPE_CRITICAL 201 39 | #define WINCACHE_DEBUG_MTYPE_IMPORTANT 301 40 | #define WINCACHE_DEBUG_MTYPE_VERBOSE 401 41 | #define WINCACHE_DEBUG_MTYPE_DECORATE 501 42 | 43 | unsigned int gdebuglevel = 0; 44 | 45 | void dprintsetlevel(unsigned int level) 46 | { 47 | if(level == WINCACHE_DEBUG_MTYPE_DISABLED || 48 | level == WINCACHE_DEBUG_MTYPE_ALWAYS || 49 | level == WINCACHE_DEBUG_MTYPE_CRITICAL || 50 | level == WINCACHE_DEBUG_MTYPE_IMPORTANT || 51 | level == WINCACHE_DEBUG_MTYPE_VERBOSE || 52 | level == WINCACHE_DEBUG_MTYPE_DECORATE) 53 | { 54 | gdebuglevel = level; 55 | } 56 | 57 | return; 58 | } 59 | 60 | void dprintmessage(char * format, va_list args) 61 | { 62 | char debug_message[255]; 63 | 64 | sprintf_s(debug_message, 255, "WINCACHE: "); 65 | vsprintf_s(debug_message + 10, 245, format, args); 66 | 67 | OutputDebugStringA(debug_message); 68 | if(IsDebuggerPresent()) 69 | { 70 | OutputDebugStringA("\n"); 71 | } 72 | 73 | return; 74 | } 75 | 76 | void dprintalways(char * format, ...) 77 | { 78 | va_list args; 79 | if(gdebuglevel >= WINCACHE_DEBUG_MTYPE_ALWAYS) 80 | { 81 | va_start(args, format); 82 | dprintmessage(format, args); 83 | va_end(args); 84 | } 85 | } 86 | 87 | void dprintcritical(char * format, ...) 88 | { 89 | va_list args; 90 | if(gdebuglevel >= WINCACHE_DEBUG_MTYPE_CRITICAL) 91 | { 92 | va_start(args, format); 93 | dprintmessage(format, args); 94 | va_end(args); 95 | } 96 | } 97 | 98 | void dprintimportant(char * format, ...) 99 | { 100 | va_list args; 101 | if(gdebuglevel >= WINCACHE_DEBUG_MTYPE_IMPORTANT) 102 | { 103 | va_start(args, format); 104 | dprintmessage(format, args); 105 | va_end(args); 106 | } 107 | } 108 | 109 | void dprintverbose(char * format, ...) 110 | { 111 | va_list args; 112 | if(gdebuglevel >= WINCACHE_DEBUG_MTYPE_VERBOSE) 113 | { 114 | va_start(args, format); 115 | dprintmessage(format, args); 116 | va_end(args); 117 | } 118 | } 119 | 120 | void dprintdecorate(char * format, ...) 121 | { 122 | va_list args; 123 | if(gdebuglevel >= WINCACHE_DEBUG_MTYPE_DECORATE) 124 | { 125 | va_start(args, format); 126 | dprintmessage(format, args); 127 | va_end(args); 128 | } 129 | } 130 | 131 | ZEND_INI_MH(wincache_modify_debuglevel) 132 | { 133 | if (ZSTR_LEN(new_value) == 0) 134 | { 135 | dprintsetlevel(WINCACHE_DEBUG_MTYPE_DISABLED); 136 | } 137 | else 138 | { 139 | dprintsetlevel(atoi(ZSTR_VAL(new_value))); 140 | WCG(debuglevel) = gdebuglevel; 141 | } 142 | return SUCCESS; 143 | } 144 | -------------------------------------------------------------------------------- /tests/wincache_ucache_reference.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with IS_REFERENCE data 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 5, 'Blue' => '6', 'yellow', 'cyan' => 'eight'); 35 | $arr2 = &$arr; 36 | echo("wincache_ucache_add('foo3', \$arr2)"); 37 | var_dump(wincache_ucache_add('foo3', $arr2)); 38 | echo("wincache_ucache_get('foo3')"); 39 | var_dump(wincache_ucache_get('foo3')); 40 | 41 | /* update an element in the array, and push back into the user cache */ 42 | $arr3 = wincache_ucache_get('foo3'); 43 | echo("set \$arr3['green'] = 57\n"); 44 | $arr3['green'] = 57; 45 | var_dump(wincache_ucache_set('foo3', $arr3)); 46 | var_dump(wincache_ucache_get('foo3')); 47 | 48 | /* bizzare reference problem: reference to an array element, and does it 49 | * change arrays that were copied from the original array? 50 | */ 51 | 52 | $arr4 = array('pink' => 9, 'chartruce' => '10', 'brown', 'magenta' => 'twelve'); 53 | 54 | echo("\$my_ref = &\$arr4['chartruce']\n"); 55 | $my_ref = &$arr4['chartruce']; 56 | echo("setting 'foo4' with \$arr4\n"); 57 | var_dump(wincache_ucache_add('foo4', $arr4)); 58 | echo("wincache_ucache_get('foo4'):\n"); 59 | var_dump(wincache_ucache_get('foo4')); 60 | 61 | /* Arrays with references to other things */ 62 | $arr6 = array('black' => &$bar, 'black2' => &$bar1, 'gray' => &$arr, 'ref_to_arr' => &$arr2, 'midnight', 'dusk' => $arr3['Blue']); 63 | echo("Nasty arr6:\n"); 64 | var_dump($arr6); 65 | var_dump(wincache_ucache_set('foo6', $arr6)); 66 | echo("wincache_ucache_get('foo6'):\n"); 67 | var_dump(wincache_ucache_get('foo6')); 68 | 69 | /* modify complex array and set back on top of the same key */ 70 | echo("\$arr6['gray']['Blue'] = 9\n"); 71 | $arr6['gray']['Blue'] = 9; 72 | echo("Nasty arr6:\n"); 73 | var_dump($arr6); 74 | 75 | echo("wincache_ucache_get('foo6'):\n"); 76 | var_dump(wincache_ucache_get('foo6')); 77 | 78 | echo ("Done!"); 79 | ?> 80 | --EXPECTF-- 81 | clearing ucache 82 | bool(true) 83 | setting 'foo' with $bar 84 | bool(true) 85 | setting 'foo2' with reference to $bar 86 | bool(true) 87 | $bar = "BAR++" 88 | $bar: 89 | string(5) "BAR++" 90 | $bar1: 91 | string(5) "BAR++" 92 | wincache_ucache_get('foo2'): 93 | string(3) "BAR" 94 | wincache_ucache_add('foo3', $arr2)bool(true) 95 | wincache_ucache_get('foo3')array(4) { 96 | ["green"]=> 97 | int(5) 98 | ["Blue"]=> 99 | string(1) "6" 100 | [0]=> 101 | string(6) "yellow" 102 | ["cyan"]=> 103 | string(5) "eight" 104 | } 105 | set $arr3['green'] = 57 106 | bool(true) 107 | array(4) { 108 | ["green"]=> 109 | int(57) 110 | ["Blue"]=> 111 | string(1) "6" 112 | [0]=> 113 | string(6) "yellow" 114 | ["cyan"]=> 115 | string(5) "eight" 116 | } 117 | $my_ref = &$arr4['chartruce'] 118 | setting 'foo4' with $arr4 119 | bool(true) 120 | wincache_ucache_get('foo4'): 121 | array(4) { 122 | ["pink"]=> 123 | int(9) 124 | ["chartruce"]=> 125 | %Sstring(2) "10" 126 | [0]=> 127 | string(5) "brown" 128 | ["magenta"]=> 129 | string(6) "twelve" 130 | } 131 | Nasty arr6: 132 | array(6) { 133 | ["black"]=> 134 | &string(5) "BAR++" 135 | ["black2"]=> 136 | &string(5) "BAR++" 137 | ["gray"]=> 138 | &array(4) { 139 | ["green"]=> 140 | int(5) 141 | ["Blue"]=> 142 | string(1) "6" 143 | [0]=> 144 | string(6) "yellow" 145 | ["cyan"]=> 146 | string(5) "eight" 147 | } 148 | ["ref_to_arr"]=> 149 | &array(4) { 150 | ["green"]=> 151 | int(5) 152 | ["Blue"]=> 153 | string(1) "6" 154 | [0]=> 155 | string(6) "yellow" 156 | ["cyan"]=> 157 | string(5) "eight" 158 | } 159 | [0]=> 160 | string(8) "midnight" 161 | ["dusk"]=> 162 | string(1) "6" 163 | } 164 | bool(true) 165 | wincache_ucache_get('foo6'): 166 | array(6) { 167 | ["black"]=> 168 | &string(5) "BAR++" 169 | ["black2"]=> 170 | &string(5) "BAR++" 171 | ["gray"]=> 172 | &array(4) { 173 | ["green"]=> 174 | int(5) 175 | ["Blue"]=> 176 | string(1) "6" 177 | [0]=> 178 | string(6) "yellow" 179 | ["cyan"]=> 180 | string(5) "eight" 181 | } 182 | ["ref_to_arr"]=> 183 | &array(4) { 184 | ["green"]=> 185 | int(5) 186 | ["Blue"]=> 187 | string(1) "6" 188 | [0]=> 189 | string(6) "yellow" 190 | ["cyan"]=> 191 | string(5) "eight" 192 | } 193 | [0]=> 194 | string(8) "midnight" 195 | ["dusk"]=> 196 | string(1) "6" 197 | } 198 | $arr6['gray']['Blue'] = 9 199 | Nasty arr6: 200 | array(6) { 201 | ["black"]=> 202 | &string(5) "BAR++" 203 | ["black2"]=> 204 | &string(5) "BAR++" 205 | ["gray"]=> 206 | &array(4) { 207 | ["green"]=> 208 | int(5) 209 | ["Blue"]=> 210 | int(9) 211 | [0]=> 212 | string(6) "yellow" 213 | ["cyan"]=> 214 | string(5) "eight" 215 | } 216 | ["ref_to_arr"]=> 217 | &array(4) { 218 | ["green"]=> 219 | int(5) 220 | ["Blue"]=> 221 | int(9) 222 | [0]=> 223 | string(6) "yellow" 224 | ["cyan"]=> 225 | string(5) "eight" 226 | } 227 | [0]=> 228 | string(8) "midnight" 229 | ["dusk"]=> 230 | string(1) "6" 231 | } 232 | wincache_ucache_get('foo6'): 233 | array(6) { 234 | ["black"]=> 235 | &string(5) "BAR++" 236 | ["black2"]=> 237 | &string(5) "BAR++" 238 | ["gray"]=> 239 | &array(4) { 240 | ["green"]=> 241 | int(5) 242 | ["Blue"]=> 243 | string(1) "6" 244 | [0]=> 245 | string(6) "yellow" 246 | ["cyan"]=> 247 | string(5) "eight" 248 | } 249 | ["ref_to_arr"]=> 250 | &array(4) { 251 | ["green"]=> 252 | int(5) 253 | ["Blue"]=> 254 | string(1) "6" 255 | [0]=> 256 | string(6) "yellow" 257 | ["cyan"]=> 258 | string(5) "eight" 259 | } 260 | [0]=> 261 | string(8) "midnight" 262 | ["dusk"]=> 263 | string(1) "6" 264 | } 265 | Done! 266 | -------------------------------------------------------------------------------- /wincache_rplist.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_rplist.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #ifndef _WINCACHE_RPLIST_H_ 35 | #define _WINCACHE_RPLIST_H_ 36 | 37 | /* rplist_value - SHARED */ 38 | /* rplist_header - SHARED */ 39 | /* rplist_context - LOCAL */ 40 | 41 | #define VERIFICATION_NOTDONE 0 42 | #define VERIFICATION_PASSED 1 43 | #define VERIFICATION_FAILED 2 44 | 45 | typedef struct rplist_value rplist_value; 46 | struct rplist_value 47 | { 48 | size_t file_path; /* resolve file path */ 49 | size_t cwd_cexec; /* cwdir|cexec */ 50 | size_t inc_path; /* current include path */ 51 | size_t open_based; /* open_basedir set */ 52 | 53 | unsigned int is_deleted; /* If set to 1, entry is marked deleted */ 54 | unsigned int is_verified;/* entry passed openbased check status */ 55 | size_t absentry; /* offset of entry in aplist */ 56 | size_t same_value; /* rplist entry pointing to same absentry */ 57 | size_t prev_value; /* previous rplist_value offset */ 58 | size_t next_value; /* next rplist_value offset */ 59 | }; 60 | 61 | typedef struct rplist_header rplist_header; 62 | struct rplist_header 63 | { 64 | unsigned int itemcount; /* Number of valid items */ 65 | unsigned int last_owner; /* PID of last owner of lock */ 66 | unsigned int valuecount; /* Total values starting from last entry */ 67 | size_t values[1]; /* valuecount rplist_value offsets */ 68 | }; 69 | 70 | typedef struct rplist_context rplist_context; 71 | struct rplist_context 72 | { 73 | char * rpmemaddr; /* base memory address of rplist */ 74 | rplist_header * rpheader; /* rplist cache header */ 75 | filemap_context * rpfilemap; /* filemap where rplist is kept */ 76 | lock_context * rplock; /* lock for rplist_header */ 77 | alloc_context * rpalloc; /* alloc context for rplist segment */ 78 | }; 79 | 80 | typedef struct rplist_entry_info rplist_entry_info; 81 | struct rplist_entry_info 82 | { 83 | char * pathkey; /* resolve file path */ 84 | char * subkey; /* cwdir|cexec subkey entry */ 85 | char * abspath; /* absolute path to use */ 86 | rplist_entry_info * next; /* next entry */ 87 | }; 88 | 89 | typedef struct rplist_info rplist_info; 90 | struct rplist_info 91 | { 92 | unsigned int itemcount; /* Total number of items in subcache */ 93 | rplist_entry_info * entries; /* Individual entries */ 94 | }; 95 | 96 | extern int rplist_create(rplist_context ** ppcache); 97 | extern void rplist_destroy(rplist_context * pcache); 98 | extern int rplist_initialize(rplist_context * pcache, unsigned short islocal, unsigned char isfirst, unsigned short cachekey, unsigned int filecount); 99 | extern void rplist_initheader(rplist_context * pcache, unsigned int filecount); 100 | extern void rplist_terminate(rplist_context * pcache); 101 | 102 | extern int rplist_getentry(rplist_context * pcache, const char * filename, rplist_value ** ppvalue, size_t * poffset); 103 | extern void rplist_setabsval(rplist_context * pcache, rplist_value * pvalue, size_t absentry, size_t prevsame); 104 | extern void rplist_deleteval(rplist_context * pcache, size_t valoffset); 105 | extern void rplist_markdeleted(rplist_context * pcache, size_t valoffset); 106 | extern int rplist_getinfo(rplist_context * pcache, zend_bool summaryonly, rplist_info ** ppinfo); 107 | extern void rplist_freeinfo(rplist_info * pinfo); 108 | 109 | extern void rplist_runtest(); 110 | 111 | #endif /* _WINCACHE_RPLIST_H_ */ 112 | -------------------------------------------------------------------------------- /tests/wincache_ucache_sparse_array.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Wincache - Testing wincache_ucache_* functions with a sparse array as a value 3 | --SKIPIF-- 4 | 5 | --INI-- 6 | wincache.enablecli=1 7 | wincache.fcenabled=1 8 | wincache.ucenabled=1 9 | --FILE-- 10 | 51 | --EXPECTF-- 52 | clearing ucache 53 | bool(true) 54 | setting large array 55 | count: 101 56 | adding 57 | bool(true) 58 | exists 59 | bool(true) 60 | get 61 | array(101) { 62 | [0]=> 63 | string(10) "fill value" 64 | [1]=> 65 | string(10) "fill value" 66 | [2]=> 67 | string(10) "fill value" 68 | [3]=> 69 | string(10) "fill value" 70 | [5]=> 71 | string(10) "fill value" 72 | [7]=> 73 | string(10) "fill value" 74 | [11]=> 75 | string(10) "fill value" 76 | [13]=> 77 | string(10) "fill value" 78 | [17]=> 79 | string(10) "fill value" 80 | [19]=> 81 | string(10) "fill value" 82 | [23]=> 83 | string(10) "fill value" 84 | [29]=> 85 | string(10) "fill value" 86 | [31]=> 87 | string(10) "fill value" 88 | [37]=> 89 | string(10) "fill value" 90 | [41]=> 91 | string(10) "fill value" 92 | [43]=> 93 | string(10) "fill value" 94 | [47]=> 95 | string(10) "fill value" 96 | [53]=> 97 | string(10) "fill value" 98 | [59]=> 99 | string(10) "fill value" 100 | [61]=> 101 | string(10) "fill value" 102 | [67]=> 103 | string(10) "fill value" 104 | [71]=> 105 | string(10) "fill value" 106 | [73]=> 107 | string(10) "fill value" 108 | [79]=> 109 | string(10) "fill value" 110 | [83]=> 111 | string(10) "fill value" 112 | [89]=> 113 | string(10) "fill value" 114 | [97]=> 115 | string(10) "fill value" 116 | [101]=> 117 | string(10) "fill value" 118 | [103]=> 119 | string(10) "fill value" 120 | [107]=> 121 | string(10) "fill value" 122 | [109]=> 123 | string(10) "fill value" 124 | [113]=> 125 | string(10) "fill value" 126 | [127]=> 127 | string(10) "fill value" 128 | [131]=> 129 | string(10) "fill value" 130 | [137]=> 131 | string(10) "fill value" 132 | [139]=> 133 | string(10) "fill value" 134 | [149]=> 135 | string(10) "fill value" 136 | [151]=> 137 | string(10) "fill value" 138 | [157]=> 139 | string(10) "fill value" 140 | [163]=> 141 | string(10) "fill value" 142 | [167]=> 143 | string(10) "fill value" 144 | [173]=> 145 | string(10) "fill value" 146 | [179]=> 147 | string(10) "fill value" 148 | [181]=> 149 | string(10) "fill value" 150 | [191]=> 151 | string(10) "fill value" 152 | [193]=> 153 | string(10) "fill value" 154 | [197]=> 155 | string(10) "fill value" 156 | [199]=> 157 | string(10) "fill value" 158 | [211]=> 159 | string(10) "fill value" 160 | [223]=> 161 | string(10) "fill value" 162 | [227]=> 163 | string(10) "fill value" 164 | [229]=> 165 | string(10) "fill value" 166 | [233]=> 167 | string(10) "fill value" 168 | [239]=> 169 | string(10) "fill value" 170 | [241]=> 171 | string(10) "fill value" 172 | [251]=> 173 | string(10) "fill value" 174 | [257]=> 175 | string(10) "fill value" 176 | [263]=> 177 | string(10) "fill value" 178 | [269]=> 179 | string(10) "fill value" 180 | [271]=> 181 | string(10) "fill value" 182 | [277]=> 183 | string(10) "fill value" 184 | [281]=> 185 | string(10) "fill value" 186 | [283]=> 187 | string(10) "fill value" 188 | [293]=> 189 | string(10) "fill value" 190 | [307]=> 191 | string(10) "fill value" 192 | [311]=> 193 | string(10) "fill value" 194 | [313]=> 195 | string(10) "fill value" 196 | [317]=> 197 | string(10) "fill value" 198 | [331]=> 199 | string(10) "fill value" 200 | [337]=> 201 | string(10) "fill value" 202 | [347]=> 203 | string(10) "fill value" 204 | [349]=> 205 | string(10) "fill value" 206 | [353]=> 207 | string(10) "fill value" 208 | [359]=> 209 | string(10) "fill value" 210 | [361]=> 211 | string(10) "fill value" 212 | [367]=> 213 | string(10) "fill value" 214 | [373]=> 215 | string(10) "fill value" 216 | [379]=> 217 | string(10) "fill value" 218 | [383]=> 219 | string(10) "fill value" 220 | [389]=> 221 | string(10) "fill value" 222 | [397]=> 223 | string(10) "fill value" 224 | [401]=> 225 | string(10) "fill value" 226 | [409]=> 227 | string(10) "fill value" 228 | [419]=> 229 | string(10) "fill value" 230 | [421]=> 231 | string(10) "fill value" 232 | [431]=> 233 | string(10) "fill value" 234 | [433]=> 235 | string(10) "fill value" 236 | [437]=> 237 | string(10) "fill value" 238 | [439]=> 239 | string(10) "fill value" 240 | [443]=> 241 | string(10) "fill value" 242 | [449]=> 243 | string(10) "fill value" 244 | [457]=> 245 | string(10) "fill value" 246 | [461]=> 247 | string(10) "fill value" 248 | [463]=> 249 | string(10) "fill value" 250 | [467]=> 251 | string(10) "fill value" 252 | [479]=> 253 | string(10) "fill value" 254 | [487]=> 255 | string(10) "fill value" 256 | [491]=> 257 | string(10) "fill value" 258 | [499]=> 259 | string(10) "fill value" 260 | [503]=> 261 | string(10) "fill value" 262 | [509]=> 263 | string(10) "fill value" 264 | } 265 | info 266 | array(6) { 267 | ["total_cache_uptime"]=> 268 | int(0) 269 | ["is_local_cache"]=> 270 | bool(false) 271 | ["total_item_count"]=> 272 | int(1) 273 | ["total_hit_count"]=> 274 | int(1) 275 | ["total_miss_count"]=> 276 | int(0) 277 | ["ucache_entries"]=> 278 | array(1) { 279 | [1]=> 280 | array(6) { 281 | ["key_name"]=> 282 | string(12) "sparse_array" 283 | ["value_type"]=> 284 | string(5) "array" 285 | ["value_size"]=> 286 | int(%d) 287 | ["ttl_seconds"]=> 288 | int(0) 289 | ["age_seconds"]=> 290 | int(0) 291 | ["hitcount"]=> 292 | int(1) 293 | } 294 | } 295 | } 296 | delete 297 | bool(true) 298 | get after delete 299 | bool(false) 300 | clearing ucache 301 | bool(true) 302 | Done! -------------------------------------------------------------------------------- /precomp.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | Copyright (c) 2024, Hao Lu. All rights reserved. | 7 | | | 8 | | Redistribution and use in source and binary forms, with or without modification, are | 9 | | permitted provided that the following conditions are met: | 10 | | - Redistributions of source code must retain the above copyright notice, this list of | 11 | | conditions and the following disclaimer. | 12 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 13 | | conditions and the following disclaimer in the documentation and/or other materials provided | 14 | | with the distribution. | 15 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 16 | | used to endorse or promote products derived from this software without specific prior written| 17 | | permission. | 18 | | | 19 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 20 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 21 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 22 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 23 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 24 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 25 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 26 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 27 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 28 | +----------------------------------------------------------------------------------------------+ 29 | | Module: precomp.h | 30 | +----------------------------------------------------------------------------------------------+ 31 | | Author: Kanwaljeet Singla | 32 | | Updated: Eric Stenson | 33 | | Hao Lu | 34 | +----------------------------------------------------------------------------------------------+ 35 | */ 36 | 37 | #ifndef _PRECOMP_H_ 38 | #define _PRECOMP_H_ 39 | 40 | #define PHP_WINCACHE_EXTNAME "wincache" 41 | #define PHP_WINCACHE_VERSION "2.0.0.9" 42 | #define PHP_WINCACHE_VERSION_LEN (sizeof(PHP_WINCACHE_VERSION)-1) 43 | 44 | /* comment following line for release builds */ 45 | /* #define WINCACHE_DEBUG */ 46 | 47 | #ifdef PHP_WIN32 48 | #define PHP_WINCACHE_API __declspec(dllexport) 49 | #else 50 | #define PHP_WINCACHE_API 51 | #endif 52 | 53 | #ifdef HAVE_CONFIG_H 54 | #include "config.h" 55 | #endif 56 | 57 | #ifdef ZTS 58 | #include "TSRM.h" 59 | #endif 60 | 61 | #include "php.h" 62 | #include "php_ini.h" 63 | #include "sapi.h" 64 | #include "ext/standard/info.h" 65 | #include "zend_smart_str.h" 66 | #include "ext/session/php_session.h" 67 | #include "zend_extensions.h" 68 | #include "php_open_temporary_file.h" 69 | 70 | #include 71 | 72 | #define ALIGNDWORD(size) (((size) % 4) ? ((size)+(4-((size) % 4))) : (size)) 73 | #define ALIGNQWORD(size) (((size) % 8) ? ((size)+(8-((size) % 8))) : (size)) 74 | 75 | #define XSTRVER2(maj, min) #maj "." #min 76 | #define STRVER2(maj, min) XSTRVER2(maj, min) 77 | 78 | #ifdef _ASSERT 79 | #undef _ASSERT 80 | #endif 81 | 82 | #ifdef WINCACHE_DEBUG 83 | # define WINCACHE_TEST 84 | # define _ASSERT(x) if(!(x)) { dprintalways("%s(%d): " #x "\n", __FILE__, __LINE__ ); if(IsDebuggerPresent()) { DebugBreak(); } } 85 | #else 86 | # define _ASSERT(x) 87 | #endif 88 | 89 | #if (defined(_MSC_VER) && (_MSC_VER < 1500)) 90 | # define IsDebuggerPresent() (0) 91 | # define memcpy_s(dst, size, src, cnt) memcpy(dst, src, cnt) 92 | # define sprintf_s(buffer, size, format) sprintf(buffer, format) 93 | # define _snprintf_s wincache_php_snprintf_s 94 | # define vsprintf_s(buffer, size, format, va_alist) vsprintf(buffer, format, va_alist) 95 | # define strcpy_s(src, size, dst) strcpy(src, dst) 96 | #endif 97 | 98 | #if PHP_API_VERSION >= 20180731 99 | # define PHP_73_API 100 | #endif 101 | 102 | #if ZEND_MODULE_API_NO >= 20190128 103 | typedef unsigned long ulong; 104 | #endif 105 | 106 | #define CACHE_TYPE_FILELIST 1 107 | #define CACHE_TYPE_RESPATHS 2 108 | #define CACHE_TYPE_FILECONTENT 3 109 | #define CACHE_TYPE_BYTECODES 4 110 | #define CACHE_TYPE_USERZVALS 5 111 | #define CACHE_TYPE_SESSZVALS 6 112 | #define CACHE_TYPE_FCNOTIFY 7 113 | 114 | #define APLIST_TYPE_INVALID 255 115 | #define APLIST_TYPE_GLOBAL 0 116 | 117 | #define NUM_FILES_MINIMUM 1024 118 | #define NUM_FILES_MAXIMUM 16384 119 | #define FCACHE_SIZE_MINIMUM 5 120 | #define FCACHE_SIZE_MAXIMUM 255 121 | #define ZCACHE_SIZE_MINIMUM 5 122 | #define ZCACHE_SIZE_MAXIMUM 930 123 | #define SCACHE_SIZE_MINIMUM 5 124 | #define SCACHE_SIZE_MAXIMUM 85 125 | #define FILE_SIZE_MINIMUM 10 126 | #define FILE_SIZE_MAXIMUM 4096 127 | #define FCHECK_FREQ_MINIMUM 2 128 | #define FCHECK_FREQ_MAXIMUM 300 129 | #define TTL_VALUE_MINIMUM 60 130 | #define TTL_VALUE_MAXIMUM 7200 131 | 132 | #define FIVE_SECOND_WAIT 5000 133 | #define MAX_INIT_EVENT_WAIT 30000 134 | 135 | #include "wincache_error.h" 136 | #include "wincache_debug.h" 137 | #include "wincache_utils.h" 138 | #include "wincache_lock.h" 139 | #include "wincache_filemap.h" 140 | #include "wincache_alloc.h" 141 | #include "wincache_fcnotify.h" 142 | #include "wincache_fcache.h" 143 | #include "wincache_rplist.h" 144 | #include "wincache_aplist.h" 145 | #include "wincache_zvcache.h" 146 | #include "wincache_session.h" 147 | 148 | #if (_MSC_VER >= 1700) 149 | #include "wincache_etw.h" 150 | #else 151 | /* PHP 5.4 supports XP, which *doesn't* support Manifest based ETW events*/ 152 | #include "wincache_dummy_etw.h" 153 | #endif /* _MSC_VER 1700 */ 154 | 155 | #include "php_wincache.h" 156 | 157 | #endif /* _PRECOMP_H_ */ 158 | -------------------------------------------------------------------------------- /wincache_fcache.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_fcache.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_FCACHE_H_ 36 | #define _WINCACHE_FCACHE_H_ 37 | 38 | /* fcache_value - SHARED */ 39 | /* fcache_header - SHARED */ 40 | /* fcache_context - LOCAL */ 41 | /* fcache_entry_info - LOCAL */ 42 | 43 | #define FILE_IS_FOLDER 1 44 | #define FILE_IS_RUNAWARE 2 45 | #define FILE_IS_READABLE 4 46 | #define FILE_IS_WUNAWARE 8 47 | #define FILE_IS_WRITABLE 16 48 | 49 | typedef struct fcache_value fcache_value; 50 | struct fcache_value 51 | { 52 | size_t file_sec; /* File security information */ 53 | size_t file_content; /* Pointer to content saved in shared memory */ 54 | unsigned int file_size; /* File size in bytes (Max is 2 MB) */ 55 | unsigned int file_flags; /* Boolean information about this file */ 56 | unsigned int is_deleted; /* If 1, this entry is marked for deletion */ 57 | unsigned int hitcount; /* Number of times this file entry got used */ 58 | unsigned int refcount; /* How many processes are currently using this */ 59 | }; 60 | 61 | typedef struct fcache_header fcache_header; 62 | struct fcache_header 63 | { 64 | unsigned int mapcount; /* Number of processes using this file cache */ 65 | unsigned int itemcount; /* Number of items in file cache */ 66 | unsigned int hitcount; /* Cache items cumulative hit count */ 67 | unsigned int misscount; /* Cache items cumulative miss count */ 68 | }; 69 | 70 | typedef struct fcache_context fcache_context; 71 | struct fcache_context 72 | { 73 | unsigned int id; /* unique identifier for cache */ 74 | unsigned short islocal; /* is cache local to process */ 75 | unsigned short cachekey; /* unique cache key used in names */ 76 | HANDLE hinitdone; /* event indicating if memory is initialized */ 77 | unsigned int maxfsize; /* maximum size of file in bytes */ 78 | char * memaddr; /* base memory address of segment */ 79 | fcache_header * header; /* cache header */ 80 | filemap_context * pfilemap; /* filemap where file content is kept */ 81 | lock_context * prwlock; /* writer lock for filecache header */ 82 | alloc_context * palloc; /* alloc context for filecache segment */ 83 | }; 84 | 85 | typedef struct fcache_handle fcache_handle; 86 | struct fcache_handle 87 | { 88 | php_stream wrapper; /* Dummy php_stream wrapper, MUST BE FIRST! */ 89 | fcache_context * pfcache; /* Cache context for this process */ 90 | fcache_value * pfvalue; /* Cache value which has file content */ 91 | size_t len; /* Length of file in bytes */ 92 | size_t pos; /* Current position where read is active */ 93 | void * map; /* Address where file content is present */ 94 | char * buf; /* Buffer pointing to file content */ 95 | }; 96 | 97 | typedef struct fcache_entry_info fcache_entry_info; 98 | struct fcache_entry_info 99 | { 100 | unsigned int filesize; /* Size of file content */ 101 | unsigned int hitcount; /* Hit count for this file entry */ 102 | }; 103 | 104 | extern int fcache_create(fcache_context ** ppfcache); 105 | extern void fcache_destroy(fcache_context * pfcache); 106 | extern int fcache_initialize(fcache_context * pfcache, unsigned short islocal, unsigned short cachekey, unsigned int cachesize, unsigned int maxfsize); 107 | extern void fcache_terminate(fcache_context * pfcache); 108 | 109 | extern int fcache_createval(fcache_context * pfcache, const char * filename, fcache_value ** ppvalue); 110 | extern void fcache_destroyval(fcache_context * pfcache, fcache_value * pvalue); 111 | extern int fcache_useval(fcache_context * pcache, const char * filename, fcache_value * pvalue, zend_file_handle ** pphandle); 112 | extern fcache_value * fcache_getvalue(fcache_context * pfcache, size_t offset); 113 | extern size_t fcache_getoffset(fcache_context * pfcache, fcache_value * pvalue); 114 | extern void fcache_refinc(fcache_context * pfcache, fcache_value * pvalue); 115 | extern void fcache_refdec(fcache_context * pfcache, fcache_value * pvalue); 116 | extern int fcache_getinfo(fcache_value * pvalue, fcache_entry_info ** ppinfo); 117 | extern void fcache_freeinfo(fcache_entry_info * pinfo); 118 | 119 | extern size_t fcache_fsizer(void * handle); 120 | extern size_t fcache_reader(void * handle, char * buf, size_t length); 121 | extern void fcache_closer(void * handle); 122 | 123 | extern void fcache_runtest(); 124 | 125 | #endif /* _WINCACHE_FCACHE_H_ */ 126 | -------------------------------------------------------------------------------- /wincache_fcnotify.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_fcnotify.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #ifndef _WINCACHE_FCNOTIFY_H_ 35 | #define _WINCACHE_FCNOTIFY_H_ 36 | 37 | /* fcnotify_value - LOCAL */ 38 | /* fcnotify_context - LOCAL */ 39 | 40 | struct fcnotify_value; 41 | typedef struct fcnotify_value fcnotify_value; 42 | 43 | typedef struct fcnotify_listen fcnotify_listen; 44 | struct fcnotify_listen 45 | { 46 | unsigned int lrefcount; /* reference count for fcnotify_listen */ 47 | unsigned int stopcalled; /* indicates if handle is getting closed */ 48 | fcnotify_value * pfcnvalue; /* fcnotify_value with pointer to this */ 49 | char * folder_path; /* path to folder excluding '\\' */ 50 | HANDLE folder_handle; /* handle to folder */ 51 | OVERLAPPED overlapped; /* overlapped structure */ 52 | BYTE fninfo[1024]; /* file notify information */ 53 | }; 54 | 55 | typedef struct fcnotify_value fcnotify_value; 56 | struct fcnotify_value 57 | { 58 | size_t folder_path; /* folder path */ 59 | unsigned int owner_pid; /* pid listening to changes */ 60 | unsigned int palivechk; /* last process alive check tickcount */ 61 | unsigned int reusecount; /* count of reuses after handoff */ 62 | FILETIME listen_time; /* system time when listener was activated */ 63 | fcnotify_listen * plistener; /* listener information */ 64 | unsigned int refcount; /* number of aplist entries for this folder */ 65 | size_t prev_value; /* previous aplist_value offset */ 66 | size_t next_value; /* next aplist_value offset */ 67 | }; 68 | 69 | typedef struct fcnotify_header fcnotify_header; 70 | struct fcnotify_header 71 | { 72 | unsigned int last_owner; /* PID of last process to acquire the fcnotify_context lock */ 73 | unsigned int itemcount; /* Folders count which have active listeners */ 74 | unsigned int valuecount; /* Total number of entries in entries */ 75 | size_t values[1]; /* HashTable for fcnotify_value entries */ 76 | }; 77 | 78 | typedef struct fcnotify_context fcnotify_context; 79 | struct fcnotify_context 80 | { 81 | unsigned short islocal; /* Is local or shared */ 82 | unsigned char isshutting; /* True means process is shutting down */ 83 | unsigned char iswow64; /* Take care of wow64 when handling paths */ 84 | unsigned int processid; /* Process id of this process */ 85 | unsigned int lscavenge; /* Last scavenger run for this process */ 86 | unsigned int ttlticks; /* How frequently scavenger should run */ 87 | 88 | char * fcmemaddr; /* Memory address where data is stored */ 89 | fcnotify_header * fcheader; /* Pointer to fcnotify_header */ 90 | alloc_context * fcalloc; /* Allocator to be used for fcnotify */ 91 | lock_context * fclock; /* Lock to deal with data in shared memory */ 92 | void * fcaplist; /* Aplist which receives change notification */ 93 | 94 | HANDLE listen_thread; /* Change listener thread handle */ 95 | HANDLE port_handle; /* Completion port for change notifications */ 96 | HashTable * pidhandles; /* Key = processid, value = process handle */ 97 | }; 98 | 99 | typedef struct fcnotify_entry_info fcnotify_entry_info; 100 | struct fcnotify_entry_info 101 | { 102 | char * folderpath; /* folder path for which fcn is active */ 103 | unsigned int ownerpid; /* owner pid listening to changes */ 104 | unsigned int filecount; /* Number of files under this folder */ 105 | fcnotify_entry_info * next; /* next entry */ 106 | }; 107 | 108 | typedef struct fcnotify_info fcnotify_info; 109 | struct fcnotify_info 110 | { 111 | unsigned int itemcount; /* Total number of items in subcache */ 112 | fcnotify_entry_info * entries; /* Individual entries */ 113 | }; 114 | 115 | extern int fcnotify_create(fcnotify_context ** ppnotify); 116 | extern void fcnotify_destroy(fcnotify_context * pnotify); 117 | extern int fcnotify_initialize(fcnotify_context * pnotify, unsigned short islocal, void * paplist, alloc_context * palloc, unsigned int filecount); 118 | extern void fcnotify_initheader(fcnotify_context * pnotify, unsigned int filecount); 119 | extern void fcnotify_terminate(fcnotify_context * pnotify); 120 | 121 | extern int fcnotify_check(fcnotify_context * pnotify, const char * filepath, size_t * poffset, unsigned int * pcount); 122 | extern void fcnotify_close(fcnotify_context * pnotify, size_t * poffset, unsigned int * pcount); 123 | extern int fcnotify_getinfo(fcnotify_context * pcache, zend_bool summaryonly, fcnotify_info ** ppinfo); 124 | extern void fcnotify_freeinfo(fcnotify_info * pinfo); 125 | 126 | extern int fcnotify_listenerexists(fcnotify_context *pnotify, const char * folderpath, unsigned char* listenerexists); 127 | 128 | extern void fcnotify_runtest(); 129 | 130 | #endif /* _WINCACHE_FCNOTIFY_H_ */ 131 | -------------------------------------------------------------------------------- /wincache_aplist.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_aplist.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_APLIST_H_ 36 | #define _WINCACHE_APLIST_H_ 37 | 38 | /* aplist_value - SHARED */ 39 | /* aplist_header - SHARED */ 40 | /* aplist_context - LOCAL */ 41 | 42 | #define USE_STREAM_OPEN_CHECK 1 43 | #define SKIP_STREAM_OPEN_CHECK 0 44 | 45 | typedef struct aplist_value aplist_value; 46 | struct aplist_value 47 | { 48 | size_t file_path; /* Full path to file */ 49 | FILETIME modified_time; /* Modified time of file */ 50 | unsigned int attributes; /* File attributes */ 51 | unsigned int file_size; /* File size in bytes */ 52 | 53 | unsigned int add_ticks; /* Ticks when this entry was created */ 54 | unsigned int use_ticks; /* Ticks when this entry was last used */ 55 | unsigned int last_check; /* Ticks when last file change check was made */ 56 | unsigned short is_deleted; /* If set to 1, value is marked for deletion */ 57 | unsigned short is_changed; /* If set to 1, value is marked changed */ 58 | 59 | size_t fcacheval; /* File cache value offset */ 60 | size_t resentry; /* Offset of first entry in rplist */ 61 | size_t fcnotify; /* Offset of file change notification entry */ 62 | unsigned int fcncount; /* fcnotify_value reusecount to detect handoff */ 63 | size_t prev_value; /* previous aplist_value offset */ 64 | size_t next_value; /* next aplist_value offset */ 65 | }; 66 | 67 | typedef struct aplist_header aplist_header; 68 | struct aplist_header 69 | { 70 | unsigned int mapcount; /* Number of processes using this file cache */ 71 | unsigned int init_ticks; /* Tick count when the cache first got created */ 72 | unsigned int last_owner; /* PID of last owner of lock */ 73 | 74 | unsigned int ttlmax; /* Max time a file can stay w/o being used */ 75 | unsigned int scfreq; /* How frequently should scavenger run */ 76 | unsigned int lscavenge; /* Ticks when last scavenger run happened */ 77 | unsigned int scstart; /* Index from where scavenger should start */ 78 | 79 | unsigned int itemcount; /* Number of valid items */ 80 | unsigned int valuecount; /* Total values starting from last entry */ 81 | size_t values[1]; /* Valuecount aplist_value offsets */ 82 | }; 83 | 84 | typedef struct aplist_context aplist_context; 85 | struct aplist_context 86 | { 87 | unsigned short id; /* Unique identifier for cache */ 88 | unsigned short islocal; /* islocal value for lock/alloc/filemap */ 89 | unsigned short apctype; /* Is the list shared or separate */ 90 | unsigned short scstatus; /* Indicates if scavenger is active or not */ 91 | HANDLE hinitdone; /* Event indicating if memory is initialized */ 92 | unsigned int fchangefreq; /* File change check frequency in mseconds */ 93 | 94 | char * apmemaddr; /* Base addr of memory segment */ 95 | aplist_header * apheader; /* Aplist cache header */ 96 | filemap_context * apfilemap; /* Filemap where aplist is kept */ 97 | lock_context * aplock; /* Lock for aplist header */ 98 | alloc_context * apalloc; /* Alloc context for aplist segment */ 99 | 100 | rplist_context * prplist; /* Resolve path cache to resolve all paths */ 101 | fcache_context * pfcache; /* File cache containing file content */ 102 | fcnotify_context * pnotify; /* File change notification context */ 103 | int resnumber; /* Resource number for this extension */ 104 | }; 105 | 106 | typedef struct cache_entry_info cache_entry_info; 107 | struct cache_entry_info 108 | { 109 | char * filename; /* File name */ 110 | unsigned int addage; /* Seconds elapsed after add */ 111 | unsigned int useage; /* Seconds elapsed after last use */ 112 | unsigned int lchkage; /* Seconds elapsed after last check */ 113 | void * cdata; /* Custom data for file cache */ 114 | cache_entry_info * next; /* Next entry */ 115 | }; 116 | 117 | typedef struct cache_info cache_info; 118 | struct cache_info 119 | { 120 | unsigned int initage; /* Seconds elapsed after cache init */ 121 | unsigned int islocal; /* Is the aplist local or global */ 122 | unsigned int itemcount; /* Total number of items in subcache */ 123 | unsigned int hitcount; /* Hit count of subcache */ 124 | unsigned int misscount; /* Miss count of subcache */ 125 | cache_entry_info * entries; /* Individual entries */ 126 | }; 127 | 128 | extern int aplist_create(aplist_context ** ppcache); 129 | extern void aplist_destroy(aplist_context * pcache); 130 | extern int aplist_initialize(aplist_context * pcache, unsigned short apctype, unsigned int filecount, unsigned int fchangefreq, unsigned int ttlmax); 131 | extern void aplist_terminate(aplist_context * pcache); 132 | 133 | extern void aplist_setsc_olocal(aplist_context * pcache, aplist_context * plocal); 134 | extern int aplist_getinfo(aplist_context * pcache, unsigned char type, zend_bool summaryonly, cache_info ** ppinfo); 135 | extern void aplist_freeinfo(unsigned char type, cache_info * pinfo); 136 | extern int aplist_getentry(aplist_context * pcache, const char * filename, unsigned int findex, aplist_value ** ppvalue); 137 | extern int aplist_force_fccheck(aplist_context * pcache, zval * filelist); 138 | extern void aplist_mark_changed(aplist_context * pcache, char * folderpath, char * filename); 139 | extern void aplist_mark_file_changed(aplist_context * pcache, char * filepath); 140 | 141 | extern int aplist_fcache_initialize(aplist_context * plcache, unsigned int size, unsigned int maxfilesize); 142 | extern int aplist_fcache_get(aplist_context * pcache, const char * filename, unsigned char usesopen, char ** ppfullpath, fcache_value ** ppvalue); 143 | extern int aplist_fcache_use(aplist_context * pcache, const char * fullpath, fcache_value * pvalue, zend_file_handle ** pphandle); 144 | extern void aplist_fcache_close(aplist_context * pcache, fcache_value * pvalue); 145 | extern int aplist_fcache_delete(aplist_context * pcache, const char * filename); 146 | 147 | extern void aplist_runtest(); 148 | 149 | #endif /* _WINCACHE_APLIST_H_ */ 150 | 151 | -------------------------------------------------------------------------------- /wincache_zvcache.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_zvcache.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_ZVCACHE_H_ 36 | #define _WINCACHE_ZVCACHE_H_ 37 | 38 | typedef struct _zvcache_hashtable_pool_tracker zvcache_hashtable_pool_tracker; 39 | struct _zvcache_hashtable_pool_tracker 40 | { 41 | size_t val; /* Hashtable *ht; Offset */ 42 | size_t hoff; /* Memory pool offset */ 43 | }; 44 | 45 | typedef struct zvcache_value zvcache_value; 46 | struct zvcache_value 47 | { 48 | size_t zvalue; /* Offset of zval value stored */ 49 | size_t keystr; /* Offset of key string */ 50 | unsigned short keylen; /* Length of key string */ 51 | size_t sizeb; /* Memory allocated for zvalue in bytes */ 52 | 53 | unsigned int add_ticks; /* Tick count when entry was created */ 54 | unsigned int use_ticks; /* Tick count when entry was last used */ 55 | unsigned int ttlive; /* Max time to live for this entry */ 56 | 57 | unsigned int hitcount; /* Hit count for this entry */ 58 | size_t next_value; /* Next value with same index */ 59 | size_t prev_value; /* Previous value with same index */ 60 | }; 61 | 62 | typedef struct zvcache_header zvcache_header; 63 | struct zvcache_header 64 | { 65 | unsigned int mapcount; /* Number of processes using this zval cache */ 66 | unsigned int hitcount; /* Cache items cumulative hit count */ 67 | unsigned int misscount; /* Cache items cumulative miss count */ 68 | unsigned int init_ticks; /* Tick count when the cache first got created */ 69 | unsigned int last_owner; /* PID of last owner for lock */ 70 | 71 | unsigned int lscavenge; /* Ticks when last scavenger run happened */ 72 | unsigned int scstart; /* Index from where scavenger should start */ 73 | unsigned int itemcount; /* Number of active items in zval cache */ 74 | unsigned int valuecount; /* Total values starting from last entry */ 75 | size_t values[1]; /* valuecount zvcache_value offsets */ 76 | }; 77 | 78 | typedef struct zvcopy_context zvcopy_context; 79 | struct zvcopy_context 80 | { 81 | unsigned int oomcode; /* Out of memory error code to use */ 82 | void * palloc; /* Allocator for alloc_a* functions */ 83 | char * pbaseadr; /* Base address of the segment */ 84 | size_t hoffset; /* Offset of mpool_header */ 85 | size_t allocsize; /* Amount of memory allocated */ 86 | 87 | fn_malloc fnmalloc; /* Function to use for malloc */ 88 | fn_realloc fnrealloc; /* Function to use for realloc */ 89 | fn_strdup fnstrdup; /* Function to use for strdup */ 90 | fn_free fnfree; /* Function to use for free */ 91 | }; 92 | 93 | typedef struct zvcache_context zvcache_context; 94 | struct zvcache_context 95 | { 96 | unsigned int id; /* unique identifier for cache */ 97 | unsigned int issession; /* session cache or user cache */ 98 | unsigned short islocal; /* is the cache local or shared */ 99 | unsigned short cachekey; /* unique cache key used in names */ 100 | HANDLE hinitdone; /* event indicating if memory is initialized */ 101 | 102 | zvcopy_context * incopy; /* zvcopy context to use for non-array copyin */ 103 | zvcopy_context * outcopy; /* zvcopy context to use for all copyout */ 104 | 105 | char * zvmemaddr; /* base addr of memory segment */ 106 | zvcache_header * zvheader; /* zvcache cache header */ 107 | filemap_context * zvfilemap; /* filemap where zvcache is kept */ 108 | lock_context * zvlock; /* lock for zvcache header */ 109 | alloc_context * zvalloc; /* alloc context for zvcache segment */ 110 | }; 111 | 112 | typedef struct zvcache_info zvcache_info; 113 | struct zvcache_info 114 | { 115 | unsigned int initage; /* Seconds elapsed after cache init */ 116 | unsigned int islocal; /* Is the zvcache local or global */ 117 | unsigned int hitcount; /* Cumulative hitcount of zvcache */ 118 | unsigned int misscount; /* Cumulative misscount of zvcache */ 119 | unsigned int itemcount; /* Number of items including stale ones */ 120 | }; 121 | 122 | typedef struct zvcache_info_entry zvcache_info_entry; 123 | struct zvcache_info_entry 124 | { 125 | char * key; /* cache item key */ 126 | unsigned int ttl; /* ttl of this entry */ 127 | unsigned int age; /* Age in seconds */ 128 | zend_uchar type; /* type of zval which is stored as value */ 129 | size_t sizeb; /* memory allocated for zval in bytes */ 130 | unsigned int hitcount; /* hitcount for this entry */ 131 | }; 132 | 133 | extern int zvcache_create(zvcache_context ** ppcache); 134 | extern void zvcache_destroy(zvcache_context * pcache); 135 | 136 | extern int zvcache_initialize( 137 | zvcache_context * pcache, 138 | unsigned int issession, 139 | unsigned short islocal, 140 | unsigned short cachekey, 141 | unsigned int cachesize, 142 | char * shmfilepath 143 | ); 144 | 145 | extern void zvcache_terminate(zvcache_context * pcache); 146 | 147 | extern int zvcache_get(zvcache_context * pcache, const char * key, zval ** pvalue); 148 | extern int zvcache_set(zvcache_context * pcache, const char * key, zval * pzval, unsigned int ttl, unsigned char isadd); 149 | extern int zvcache_delete(zvcache_context * pcache, const char * key); 150 | extern int zvcache_clear(zvcache_context * pcache); 151 | extern int zvcache_exists(zvcache_context * pcache, const char * key, unsigned char * pexists); 152 | extern int zvcache_list(zvcache_context * pcache, zend_bool summaryonly, char * pkey, zvcache_info * pcinfo, zend_llist * plist); 153 | extern int zvcache_change(zvcache_context * pcache, const char * key, zend_long delta, zend_long * newvalue); 154 | extern int zvcache_compswitch(zvcache_context * pcache, const char * key, zend_long oldvalue, zend_long newvalue); 155 | 156 | #endif /* _WINCACHE_ZVCACHE_H_ */ 157 | -------------------------------------------------------------------------------- /php_wincache.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | Copyright (c) 2024, Hao Lu. All rights reserved. | 7 | | | 8 | | Redistribution and use in source and binary forms, with or without modification, are | 9 | | permitted provided that the following conditions are met: | 10 | | - Redistributions of source code must retain the above copyright notice, this list of | 11 | | conditions and the following disclaimer. | 12 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 13 | | conditions and the following disclaimer in the documentation and/or other materials provided | 14 | | with the distribution. | 15 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 16 | | used to endorse or promote products derived from this software without specific prior written| 17 | | permission. | 18 | | | 19 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 20 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 21 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 22 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 23 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 24 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 25 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 26 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 27 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 28 | +----------------------------------------------------------------------------------------------+ 29 | | Module: php_wincache.h | 30 | +----------------------------------------------------------------------------------------------+ 31 | | Author: Kanwaljeet Singla | 32 | | Updated: Eric Stenson | 33 | | Hao Lu | 34 | +----------------------------------------------------------------------------------------------+ 35 | */ 36 | 37 | #ifndef _PHP_WINCACHE_H_ 38 | #define _PHP_WINCACHE_H_ 39 | 40 | extern zend_module_entry wincache_module_entry; 41 | #define phpext_wincache_ptr &wincache_module_entry 42 | 43 | /* For static builds we need all the headers as this */ 44 | /* file is included in main/internal_functions.c */ 45 | #ifndef COMPILE_DL_WINCACHE 46 | #include "precomp.h" 47 | #endif 48 | 49 | typedef struct wclock_context wclock_context; 50 | struct wclock_context 51 | { 52 | lock_context * lockobj; /* Internal lock context for this wclock */ 53 | unsigned int tcreate; /* Tick count when this was created */ 54 | unsigned int tuse; /* Tick count when this was last used */ 55 | }; 56 | 57 | #if PHP_VERSION_ID >= 70200 58 | # define wincache_zif_handler zif_handler 59 | #else 60 | typedef void (*wincache_zif_handler)(INTERNAL_FUNCTION_PARAMETERS); 61 | #endif 62 | 63 | /* Module globals */ 64 | ZEND_BEGIN_MODULE_GLOBALS(wincache) 65 | aplist_context * lfcache; /* Shared memory for fcache filelist */ 66 | zvcache_context * zvucache; /* User controlled user cache */ 67 | zvcache_context * zvscache; /* Zval cache used to store session data */ 68 | HashTable * phscache; /* Hashtable for session caches for modified savepaths */ 69 | unsigned int numfiles; /* Configured number of files to handle */ 70 | unsigned int fcchkfreq; /* File change check frequency in seconds */ 71 | unsigned int ttlmax; /* Seconds a cache entry can stay dormant */ 72 | wincache_zif_handler orig_rmdir; /* Pointer to the original rmdir function */ 73 | /* Pointer to the original file_exists function */ 74 | wincache_zif_handler orig_file_exists; 75 | /* Pointer to the original file_get_contents function */ 76 | wincache_zif_handler orig_file_get_contents; 77 | /* Pointer to the original filesize function */ 78 | wincache_zif_handler orig_filesize; 79 | wincache_zif_handler orig_is_dir; /* Pointer to the original is_dir function */ 80 | /* Pointer to the original is_file function */ 81 | wincache_zif_handler orig_is_file; 82 | /* Pointer to the original is_readable function */ 83 | wincache_zif_handler orig_is_readable; 84 | /* Pointer to the original is_writable function */ 85 | wincache_zif_handler orig_is_writable; 86 | /* Pointer to the original is_writeable function */ 87 | wincache_zif_handler orig_is_writeable; 88 | /* Pointer to the original readfile function */ 89 | wincache_zif_handler orig_readfile; 90 | /* Pointer to the original realpath function */ 91 | wincache_zif_handler orig_realpath; 92 | wincache_zif_handler orig_unlink; /* Pointer to the original unlink function */ 93 | wincache_zif_handler orig_rename; /* Pointer to the original rename function */ 94 | zend_bool enablecli; /* Enable wincache for command line sapi */ 95 | zend_bool fcenabled; /* File cache enabled or disabled */ 96 | unsigned int fcachesize; /* File cache size in MBs */ 97 | unsigned int maxfilesize; /* Max file size (kb) allowed in fcache */ 98 | zend_bool ucenabled; /* User cache enabled or disabled */ 99 | unsigned int ucachesize; /* User cache size in MBs */ 100 | unsigned int scachesize; /* Session cache size in MBs */ 101 | unsigned int debuglevel; /* Debug dump level (0/101/201/301/401/501) */ 102 | char * ignorelist; /* Pipe-separated list of files to ignore */ 103 | char * fcefilter; /* Comma-separated sitelist having fcenabled toggled */ 104 | char * namesalt; /* Salt to use in all the names */ 105 | zend_bool fcndetect; /* File change notication detection enabled */ 106 | zend_bool localheap; /* Local heap is enabled or disabled */ 107 | 108 | HashTable * wclocks; /* Locks created using wincache_lock call */ 109 | HashTable * zvcopied; /* Copied zvals to make refcounting work */ 110 | unsigned int lasterror; /* Last error value */ 111 | unsigned int uclasterror; /* Last error value encountered by user cache */ 112 | unsigned int parentpid; /* Parent process identifier */ 113 | filemap_global_context * fmapgdata; /* Global data for filemap */ 114 | zend_llist * errmsglist; /* List of errors generated by PHP */ 115 | zend_ini_entry * inifce; /* fcenabled ini_entry in ini_directives */ 116 | zend_ini_entry * inisavepath; /* save_path ini_entry in ini_directives */ 117 | unsigned char dofctoggle; /* Do toggle of fcenabled due to filter settigns */ 118 | /* Enable wrapper functions around standard PHP functions */ 119 | zend_bool reroute_enabled; 120 | const char * apppoolid; /* The application id. */ 121 | char * filemapdir; /* Directory where temp filemap files should be created */ 122 | ZEND_END_MODULE_GLOBALS(wincache) 123 | 124 | ZEND_EXTERN_MODULE_GLOBALS(wincache) 125 | 126 | #ifdef ZTS 127 | #define WCG(v) ZEND_TSRMG(wincache_globals_id, zend_wincache_globals *, v) 128 | # ifdef COMPILE_DL_WINCACHE 129 | ZEND_TSRMLS_CACHE_EXTERN(); 130 | # endif 131 | #else 132 | #define WCG(v) (wincache_globals.v) 133 | #endif 134 | 135 | #if PHP_API_VERSION >= 20210902 136 | typedef zend_string *(*fn_zend_resolve_path)(zend_string *filename_zstr); 137 | #elif PHP_API_VERSION >= 20180731 138 | typedef zend_string *(*fn_zend_resolve_path)(const char *filename, size_t filename_len); 139 | #else 140 | typedef zend_string *(*fn_zend_resolve_path)(const char *filename, int filename_len); 141 | #endif 142 | 143 | #if PHP_API_VERSION >= 20210902 144 | typedef zend_result (*fn_zend_stream_open_function)(zend_file_handle *handle); 145 | #else 146 | typedef int (*fn_zend_stream_open_function)(const char * filename, zend_file_handle *handle); 147 | #endif 148 | typedef zend_op_array * (*fn_zend_compile_file)(zend_file_handle *, int); 149 | typedef void (*fn_zend_error_cb)(int type, const char *error_filename, const uint32_t error_lineno, const char *format, va_list args); 150 | 151 | fn_zend_resolve_path original_resolve_path; 152 | fn_zend_stream_open_function original_stream_open_function; 153 | 154 | #if PHP_API_VERSION >= 20210902 155 | extern zend_string * wincache_resolve_path(zend_string * filename_zstr); 156 | #elif PHP_API_VERSION >= 20180731 157 | extern zend_string * wincache_resolve_path(const char * filename, size_t filename_len); 158 | #else 159 | extern zend_string * wincache_resolve_path(const char * filename, int filename_len); 160 | #endif 161 | 162 | #if PHP_API_VERSION >= 20210902 163 | extern zend_result wincache_stream_open_function(zend_file_handle * file_handle); 164 | #else 165 | extern int wincache_stream_open_function(const char * filename, zend_file_handle * file_handle); 166 | #endif 167 | 168 | extern void wincache_intercept_functions_init(); 169 | extern void wincache_intercept_functions_shutdown(); 170 | extern void wincache_save_orig_functions(); 171 | 172 | #endif /* _PHP_WINCACHE_H_ */ 173 | -------------------------------------------------------------------------------- /wincache_etw.man: -------------------------------------------------------------------------------- 1 | 2 | 34 | 39 | 40 | 41 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 62 | 66 | 72 | 79 | 80 | 81 | 82 | 88 | 94 | 99 | 100 | 101 | 107 | 113 | 119 | 125 | 126 | 127 | 133 | 139 | 145 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 164 | 168 | 172 | 176 | 180 | 184 | 188 | 192 | 196 | 200 | 204 | 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /wincache_alloc.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_alloc.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_ALLOC_H_ 36 | #define _WINCACHE_ALLOC_H_ 37 | 38 | /* Full fledged memory allocator to allocate memory from shared memory segments */ 39 | /* Has ability to manage shared memory in memory pools in which case */ 40 | /* free is only supported for the pool and not for individual allocation */ 41 | /* Also wrappers for emalloc, efree, pemalloc and pefree */ 42 | 43 | #define ALLOC_TYPE_INVALID 0 44 | #define ALLOC_TYPE_SHAREDMEM 1 45 | #define ALLOC_TYPE_PROCESS 2 46 | #define ALLOC_TYPE_PROCESS_PERSISTENT 3 47 | 48 | /* alloc_context - LOCAL */ 49 | /* alloc_info - LOCAL */ 50 | /* alloc_segment_header - SHARED */ 51 | /* alloc_free_header - SHARED */ 52 | /* alloc_used_header - SHARED */ 53 | /* alloc_mpool_header - SHARED */ 54 | /* alloc_mpool_segment - SHARED */ 55 | 56 | typedef void * (*fn_malloc)(void * palloc, size_t hoffset, size_t size); 57 | typedef void * (*fn_realloc)(void * palloc, size_t hoffset, void * addr, size_t size); 58 | typedef char * (*fn_strdup)(void * palloc, size_t hoffset, const char * str); 59 | typedef void (*fn_free)(void * palloc, size_t hoffset, void * addr); 60 | 61 | /* TBD? Right now I am doing a custom implementation which will probably work */ 62 | /* best for the problem at hand. Try a quick fit memory allocator later. */ 63 | 64 | typedef struct alloc_segment_header alloc_segment_header; 65 | struct alloc_segment_header 66 | { 67 | unsigned int mapcount; /* How many processes mapped this segment */ 68 | unsigned int usedcount; /* Number of used blocks. Determine fragmentation */ 69 | unsigned int freecount; /* Number of free blocks Determine when to defrag */ 70 | unsigned int last_owner; /* PID of last process to acquire the lock for this segment */ 71 | size_t total_size; /* Total size of shared memory segment */ 72 | size_t free_size; /* Bytes left to be allocated */ 73 | size_t cacheheader1;/* Offset to memory which contains 1st cache_header */ 74 | size_t cacheheader2;/* Offset to memory which contains 2nd cache header */ 75 | }; 76 | 77 | /* Each free block will have following information */ 78 | /* Each allocation will be appended by size in end as well */ 79 | typedef struct alloc_free_header alloc_free_header; 80 | struct alloc_free_header 81 | { 82 | size_t size; /* size of free segment including this header */ 83 | unsigned int is_free; /* marker which differentiate this block from used block */ 84 | size_t prev_free; /* offset to previous free block */ 85 | size_t next_free; /* offset to next free block */ 86 | /* free block will have size written in the end */ 87 | }; 88 | 89 | typedef struct alloc_used_header alloc_used_header; 90 | struct alloc_used_header 91 | { 92 | size_t size; /* size of this used block */ 93 | unsigned int is_free; /* marker which differentiate this block from free block */ 94 | size_t dummy1; /* Dummy variable to make size equal to free header */ 95 | size_t dummy2; /* Dummy variable to make size equal to free header */ 96 | /* used block will have size written in the end */ 97 | }; 98 | 99 | typedef struct alloc_mpool_header alloc_mpool_header; 100 | struct alloc_mpool_header 101 | { 102 | size_t foffset; /* First memory chunk offset */ 103 | size_t loffset; /* Last memory chunk offset */ 104 | size_t socurr; /* Current chunk for small allocations */ 105 | size_t mocurr; /* Current chunk for medium allocations */ 106 | size_t locurr; /* Current chunk for large allocations */ 107 | }; 108 | 109 | typedef struct alloc_mpool_segment alloc_mpool_segment; 110 | struct alloc_mpool_segment 111 | { 112 | size_t aoffset; /* Address of this memory chunk offset */ 113 | size_t size; /* Size of this memory chunk */ 114 | size_t position; /* Current position where allocation can be made */ 115 | size_t next; /* Next chunk of memory offset */ 116 | }; 117 | 118 | typedef struct alloc_context alloc_context; 119 | struct alloc_context 120 | { 121 | unsigned short id; /* Unique id of this alloc_context */ 122 | unsigned short islocal; /* Is this allocator local to this process */ 123 | HANDLE hinitdone; /* event to indicate if memory is initialized */ 124 | void * memaddr; /* Shared memory segment which is manipulated */ 125 | size_t size; /* Size of memory segment to be allocated */ 126 | lock_context * lock; /* Lock to acquire before manipulating segment */ 127 | alloc_segment_header * header; /* Address of header for this alloc_context */ 128 | unsigned int localheap; /* Set to 1 when localheap should be used */ 129 | }; 130 | 131 | typedef struct alloc_info alloc_info; 132 | struct alloc_info 133 | { 134 | size_t total_size; /* total size of memory segment */ 135 | size_t free_size; /* free memory */ 136 | unsigned int usedcount; /* number of used blocks */ 137 | unsigned int freecount; /* number of free blocks */ 138 | size_t mem_overhead;/* overhead of used/free headers */ 139 | }; 140 | 141 | extern int alloc_create(alloc_context ** ppalloc); 142 | extern void alloc_destroy(alloc_context * palloc); 143 | extern int alloc_initialize(alloc_context * palloc, unsigned short islocal, char * name, unsigned short cachekey, void * staddr, size_t size, unsigned char initmemory); 144 | extern void alloc_terminate(alloc_context * palloc); 145 | extern int alloc_create_mpool(alloc_context * palloc, size_t * phoffset); 146 | extern void alloc_free_mpool(alloc_context * palloc, size_t hoffset); 147 | 148 | extern void * alloc_get_cacheheader(alloc_context * palloc, unsigned int msize, unsigned int type); 149 | extern void * alloc_get_cachevalue(alloc_context * palloc, size_t offset); 150 | extern size_t alloc_get_valueoffset(alloc_context * palloc, void * value); 151 | extern int alloc_getinfo(alloc_context * palloc, alloc_info ** ppinfo); 152 | extern void alloc_freeinfo(alloc_info * pinfo); 153 | 154 | extern void * alloc_emalloc(size_t size); 155 | extern void * alloc_pemalloc(size_t size); 156 | extern void * alloc_smalloc(alloc_context * palloc, size_t size); 157 | 158 | extern void * alloc_erealloc(void * addr, size_t size); 159 | extern void * alloc_perealloc(void * addr, size_t size); 160 | extern void * alloc_srealloc(alloc_context * palloc, void * addr, size_t size); 161 | 162 | extern char * alloc_estrdup(const char * str); 163 | extern char * alloc_pestrdup(const char * str); 164 | extern char * alloc_sstrdup(alloc_context * palloc, const char * str); 165 | 166 | extern void alloc_efree(void * addr); 167 | extern void alloc_pefree(void * addr); 168 | extern void alloc_sfree(alloc_context * palloc, void * addr); 169 | 170 | extern void * alloc_oemalloc(alloc_context * palloc, size_t hoffset, size_t size); 171 | extern void * alloc_osmalloc(alloc_context * palloc, size_t hoffset, size_t size); 172 | extern void * alloc_ommalloc(alloc_context * palloc, size_t hoffset, size_t size); 173 | extern void * alloc_oerealloc(alloc_context * palloc, size_t hoffset, void * addr, size_t size); 174 | extern void * alloc_osrealloc(alloc_context * palloc, size_t hoffset, void * addr, size_t size); 175 | extern void * alloc_omrealloc(alloc_context * palloc, size_t hoffset, void * addr, size_t size); 176 | extern char * alloc_oestrdup(alloc_context * palloc, size_t hoffset, const char * str); 177 | extern char * alloc_osstrdup(alloc_context * palloc, size_t hoffset, const char * str); 178 | extern char * alloc_omstrdup(alloc_context * palloc, size_t hoffset, const char * str); 179 | extern void alloc_oefree(alloc_context * palloc, size_t hoffset, void * addr); 180 | extern void alloc_osfree(alloc_context * palloc, size_t hoffset, void * addr); 181 | extern void alloc_omfree(alloc_context * palloc, size_t hoffset, void * addr); 182 | 183 | extern void alloc_runtest(); 184 | 185 | #endif /* _WINCACHE_ALLOC_H_ */ 186 | -------------------------------------------------------------------------------- /wincache_filemap.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_filemap.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_FILEMAP_H_ 36 | #define _WINCACHE_FILEMAP_H_ 37 | 38 | /* TBD?? Below are the types of shared memory segments we will create. Their */ 39 | /* names will have corresponding prefix. Only one INFORMATION and FILELIST */ 40 | /* segment will be there but there will be multiple OPCODES segments. If */ 41 | /* FILELIST is finished, we will clean entries which aren't used for a while */ 42 | 43 | /* TBD?? Maintaining multiple segments will require one segment to not refer */ 44 | /* memory from other or would require using parts of pointer values to */ 45 | /* calculate segement number. For now I will go with one segment to keep */ 46 | /* opcodes. Will look into multiple segments later */ 47 | 48 | /* TBD?? Should we look at commandline arguments of the process to find what */ 49 | /* all processes got launched for a single fastcgi process pool. Using ppid */ 50 | /* won't work for per site php.ini configuration. We will end up sharing the */ 51 | /* cache with all processes which won't be too bad either */ 52 | 53 | #define PID_MAX_LENGTH 6 /* 999999 is the max value */ 54 | #define READWRITE_LOCK_MAX_COUNT 20 /* NOT USED */ 55 | 56 | #define FILEMAP_TYPE_INVALID 0 /* Invalid value */ 57 | #define FILEMAP_TYPE_FILELIST 1 /* File list map */ 58 | #define FILEMAP_TYPE_RESPATHS 2 /* Resolve path cache */ 59 | #define FILEMAP_TYPE_FILECONTENT 3 /* File cache map */ 60 | #define FILEMAP_TYPE_BYTECODES 4 /* Byte code map */ 61 | #define FILEMAP_TYPE_USERZVALS 5 /* User cache map */ 62 | #define FILEMAP_TYPE_SESSZVALS 6 /* Session cache map */ 63 | #define FILEMAP_TYPE_UNUSED 255 /* UNUSED SEGMENT MARKER */ 64 | #define FILEMAP_TYPE_MAX 255 65 | 66 | #define FILEMAP_MAP_INVALID 0 /* Invalid value */ 67 | #define FILEMAP_MAP_SRANDOM 1 /* Map at any random address */ 68 | #define FILEMAP_MAP_SFIXED 2 /* Try mapping at a particular address */ 69 | #define FILEMAP_MAP_LRANDOM 3 /* Create a local only filemap */ 70 | 71 | #define FILEMAP_MAX_COUNT 30 72 | #define FILEMAP_MIN_SIZE 1048576 /* 1 MB */ 73 | #define FILEMAP_MAX_SIZE 268435456 /* 256 MB */ 74 | 75 | /* Following prefixes should be less than 254 characters */ 76 | #define FILEMAP_INFORMATION_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_INFORMATION" 77 | #define FILEMAP_INFORMATION_PREFIX_LENGTH (sizeof(FILEMAP_INFORMATION_PREFIX)) 78 | 79 | #define FILEMAP_FILELIST_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_FILELIST" 80 | #define FILEMAP_FILELIST_PREFIX_LENGTH (sizeof(FILEMAP_FILELIST_PREFIX)) 81 | 82 | #define FILEMAP_RESPATHS_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_RESPATHS" 83 | #define FILEMAP_RESPATHS_PREFIX_LENGTH (sizeof(FILEMAP_RESPATHS_PREFIX)) 84 | 85 | #define FILEMAP_FILECONTENT_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_FILECONTENT" 86 | #define FILEMAP_FILECONTENT_PREFIX_LENGTH (sizeof(FILEMAP_FILECONTENT_PREFIX)) 87 | 88 | #define FILEMAP_BYTECODES_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_BYTECODES" 89 | #define FILEMAP_BYTECODES_PREFIX_LENGTH (sizeof(FILEMAP_BYTECODES_PREFIX)) 90 | 91 | #define FILEMAP_USERZVALS_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_USERZVALS" 92 | #define FILEMAP_USERZVALS_PREFIX_LENGTH (sizeof(FILEMAP_USERZVALS_PREFIX)) 93 | 94 | #define FILEMAP_SESSZVALS_PREFIX "WINCACHE_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION "_FILEMAP_SESSZVALS" 95 | #define FILEMAP_SESSZVALS_PREFIX_LENGTH (sizeof(FILEMAP_SESSZVALS_PREFIX)) 96 | 97 | /* filemap_information_header - SHARED - 16 bytes */ 98 | /* filemap_information_entry - SHARED - 276 bytes */ 99 | /* filemap_global_context - LOCAL - 8 bytes */ 100 | /* filemap_information - LOCAL - 20 bytes */ 101 | /* filemap_context - LOCAL - 14 bytes (not aligned at 4 bytes) */ 102 | 103 | typedef struct filemap_information_header filemap_information_header; 104 | struct filemap_information_header 105 | { 106 | size_t size; /* Total size of the memory map */ 107 | unsigned int mapcount; /* Total times this shared area got mapped */ 108 | unsigned short entry_count; /* How many other filemap objects are present */ 109 | unsigned short maxcount; /* Maximum number of filemaps which can be created */ 110 | }; 111 | 112 | typedef struct filemap_information_entry filemap_information_entry; 113 | struct filemap_information_entry 114 | { 115 | unsigned short fmaptype; /* Type which tells what is the purpose of this filemap */ 116 | unsigned short cachekey; /* short key which uniquely identifies fmap of this type */ 117 | char name[MAX_PATH];/* name of filemap */ 118 | size_t size; /* Size of this filemap */ 119 | unsigned int mapcount; /* How many processes mapped this filemap */ 120 | unsigned int cpid; /* ProcessID of process which initially created this map */ 121 | unsigned int opid; /* Current ProcessID which is the owner */ 122 | void * mapaddr; /* Map address where owner has this memory mapped */ 123 | }; 124 | 125 | typedef struct filemap_context filemap_context; 126 | struct filemap_context 127 | { 128 | unsigned short id; /* unique id of this filemap context */ 129 | unsigned short islocal; /* tells if specified address couldn't be used */ 130 | filemap_information_entry * infoentry; /* pointer to filemap information entry */ 131 | HANDLE hshmfile; /* file handle for file backed shared memory */ 132 | unsigned int existing; /* If value is 1, skip initialization for this */ 133 | HANDLE hfilemap; /* handle to memory map object */ 134 | void * mapaddr; /* local adddress mapped for this process */ 135 | }; 136 | 137 | typedef struct filemap_information filemap_information; 138 | struct filemap_information 139 | { 140 | HANDLE hinfomap; /* Handle to filemap object */ 141 | char * infoname; /* Name of memory map to store filemap info */ 142 | size_t infonlen; /* Length of name buffer */ 143 | filemap_information_header * header; /* Mapped memory address to information segment */ 144 | HANDLE hinitdone; /* event inidicating if memory is initialized */ 145 | lock_context * hlock; /* Lock object for info filemap */ 146 | }; 147 | 148 | typedef struct filemap_global_context filemap_global_context; 149 | struct filemap_global_context 150 | { 151 | unsigned int pid; /* PID of this process */ 152 | unsigned int ppid; /* Parent process id */ 153 | filemap_information * info; /* pointer to filemap_information */ 154 | }; 155 | 156 | extern int filemap_global_initialize(); 157 | extern void filemap_global_terminate(); 158 | extern unsigned int filemap_getpid(); 159 | extern unsigned int filemap_getppid(); 160 | 161 | extern int filemap_create(filemap_context ** ppfilemap); 162 | extern void filemap_destroy(filemap_context * pfilemap); 163 | 164 | extern int 165 | filemap_initialize( 166 | filemap_context * pfilemap, 167 | unsigned short fmaptype, 168 | unsigned short cachekey, 169 | unsigned short fmclass, 170 | unsigned int size_mb, 171 | unsigned char isfirst, 172 | char * shmfilepath); 173 | 174 | extern void filemap_terminate(filemap_context * pfilemap); 175 | 176 | extern size_t filemap_getsize(filemap_context * pfilemap); 177 | extern unsigned int filemap_getcpid(filemap_context * pfilemap); 178 | 179 | extern void filemap_runtest(); 180 | 181 | #endif /* _WINCACHE_FILEMAP_H_ */ 182 | -------------------------------------------------------------------------------- /wincache_error.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_error.h | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #ifndef _WINCACHE_FATAL_H_ 36 | #define _WINCACHE_FATAL_H_ 37 | 38 | /* Basic error codes */ 39 | #define NONFATAL 0 40 | #define FATAL 1 41 | 42 | /* General purpose error codes */ 43 | #define FATAL_OUT_OF_MEMORY 10 44 | #define FATAL_OUT_OF_LMEMORY 10 45 | #define FATAL_OUT_OF_SMEMORY 11 46 | #define FATAL_ACCESS_DENIED 12 47 | #define FATAL_FILE_NOT_FOUND 13 48 | #define FATAL_INVALID_DATA 14 49 | #define FATAL_INVALID_ARGUMENT 15 50 | #define FATAL_NEED_MORE_MEMORY 16 51 | #define FATAL_UNEXPECTED_DATA 17 52 | #define FATAL_UNEXPECTED_FCALL 18 53 | #define FATAL_CRYPTO_FAILED 19 54 | #define FATAL_ACL_FAILED 20 55 | 56 | #define FATAL_OPEN_TOKEN 97 57 | #define FATAL_ZEND_BAILOUT 98 58 | #define FATAL_UNKNOWN_FATAL 99 59 | 60 | /* Error codes used by lock functionality */ 61 | #define FATAL_LOCK_BASE 100 62 | #define FATAL_LOCK_INIT_CREATEMUTEX FATAL_LOCK_BASE + 1 63 | #define FATAL_LOCK_INIT_CREATEEVENT FATAL_LOCK_BASE + 2 64 | #define FATAL_LOCK_LONGNAME FATAL_LOCK_BASE + 3 65 | #define FATAL_LOCK_SHORT_BUFFER FATAL_LOCK_BASE + 4 66 | #define FATAL_LOCK_NUMBER_LARGE FATAL_LOCK_BASE + 5 67 | #define FATAL_LOCK_INVALID_TYPE FATAL_LOCK_BASE + 6 68 | #define FATAL_LOCK_NOT_FOUND FATAL_LOCK_BASE + 7 69 | 70 | /* Error codes used in filemap functionality */ 71 | #define FATAL_FILEMAP_BASE 200 72 | #define FATAL_FILEMAP_CREATION FATAL_FILEMAP_BASE + 1 73 | #define FATAL_FILEMAP_INFOCREATE FATAL_FILEMAP_BASE + 2 74 | #define FATAL_FILEMAP_INFOMAP FATAL_FILEMAP_BASE + 3 75 | #define FATAL_FILEMAP_CREATE_SNAPSHOT FATAL_FILEMAP_BASE + 4 76 | #define FATAL_FILEMAP_INITIALIZE FATAL_FILEMAP_BASE + 5 77 | #define FATAL_FILEMAP_NOFREE FATAL_FILEMAP_BASE + 6 78 | #define FATAL_FILEMAP_INIT_EVENT FATAL_FILEMAP_BASE + 7 79 | #define FATAL_FILEMAP_MAPVIEW FATAL_FILEMAP_BASE + 8 80 | #define FATAL_FILEMAP_CREATEFILE FATAL_FILEMAP_BASE + 9 81 | #define FATAL_FILEMAP_GETFILETIME FATAL_FILEMAP_BASE + 10 82 | #define FATAL_FILEMAP_SYSTOFILE FATAL_FILEMAP_BASE + 11 83 | #define FATAL_FILEMAP_CREATEFILEMAP FATAL_FILEMAP_BASE + 12 84 | #define FATAL_FILEMAP_ALLOC_LOCALFILEMAP FATAL_FILEMAP_BASE + 13 85 | #define FATAL_FILEMAP_REVERT_FAILED FATAL_FILEMAP_BASE + 14 86 | #define FATAL_FILEMAP_IMPERSONATE_FAILED FATAL_FILEMAP_BASE + 15 87 | 88 | /* Error codes used by shared memory allocator */ 89 | #define FATAL_ALLOC_BASE 300 90 | #define FATAL_ALLOC_NO_MEMORY FATAL_ALLOC_BASE + 1 91 | #define FATAL_ALLOC_INIT_EVENT FATAL_ALLOC_BASE + 2 92 | #define FATAL_ALLOC_SEGMENT_CORRUPT FATAL_ALLOC_BASE + 3 93 | 94 | /* Error codes used by aplist code */ 95 | #define FATAL_APLIST_BASE 400 96 | #define FATAL_APLIST_CREATION FATAL_APLIST_BASE + 1 97 | #define FATAL_APLIST_INIT_EVENT FATAL_APLIST_BASE + 2 98 | #define FATAL_APLIST_OCACHE_INIT_EVENT FATAL_APLIST_BASE + 3 99 | 100 | /* Error codes used by rplist code */ 101 | #define FATAL_RPLIST_BASE 500 102 | #define FATAL_RPLIST_CREATION FATAL_RPLIST_BASE + 1 103 | #define FATAL_RPLIST_INITIALIZE FATAL_RPLIST_BASE + 2 104 | 105 | /* Error codes used by file cache */ 106 | #define FATAL_FCACHE_BASE 600 107 | #define FATAL_FCACHE_CREATION FATAL_FCACHE_BASE + 1 108 | #define FATAL_FCACHE_CREATEFILE FATAL_FCACHE_BASE + 2 109 | #define FATAL_FCACHE_GETFILETYPE FATAL_FCACHE_BASE + 3 110 | #define FATAL_FCACHE_GETFILESIZE FATAL_FCACHE_BASE + 4 111 | #define FATAL_FCACHE_READFILE FATAL_FCACHE_BASE + 5 112 | #define FATAL_FCACHE_INITIALIZE FATAL_FCACHE_BASE + 6 113 | #define FATAL_FCACHE_FILEINFO FATAL_FCACHE_BASE + 7 114 | #define FATAL_FCACHE_FILECHANGED FATAL_FCACHE_BASE + 8 115 | #define FATAL_FCACHE_INIT_EVENT FATAL_FCACHE_BASE + 9 116 | #define FATAL_FCACHE_ORIGINAL_OPEN FATAL_FCACHE_BASE + 10 117 | #define FATAL_FCACHE_BYHANDLE_INFO FATAL_FCACHE_BASE + 11 118 | #define FATAL_FCACHE_FILE_TOO_BIG FATAL_FCACHE_BASE + 12 119 | 120 | /* Error codes used by opcode cache */ 121 | #define FATAL_OCACHE_BASE 700 122 | #define FATAL_OCACHE_CREATION FATAL_OCACHE_BASE + 1 123 | #define FATAL_OCACHE_INITIALIZE FATAL_OCACHE_BASE + 2 124 | #define FATAL_OCACHE_FIND FATAL_OCACHE_BASE + 3 125 | #define FATAL_OCACHE_ADD FATAL_OCACHE_BASE + 4 126 | #define FATAL_OCACHE_DELETE FATAL_OCACHE_BASE + 5 127 | #define FATAL_OCACHE_INIT_EVENT FATAL_OCACHE_BASE + 6 128 | #define FATAL_OCACHE_ORIGINAL_COMPILE FATAL_OCACHE_BASE + 7 129 | 130 | /* Error codes used by opcopy code */ 131 | #define FATAL_OPCOPY_BASE 800 132 | #define FATAL_OPCOPY_ZVAL FATAL_OPCOPY_BASE + 1 133 | #define FATAL_OPCOPY_ZNODE FATAL_OPCOPY_BASE + 2 134 | #define FATAL_OPCOPY_ZEND_ARG_INFO FATAL_OPCOPY_BASE + 3 135 | #define FATAL_OPCOPY_ZEND_PROPERTY_INFO FATAL_OPCOPY_BASE + 4 136 | #define FATAL_OPCOPY_ZEND_FUNCTION FATAL_OPCOPY_BASE + 5 137 | #define FATAL_OPCOPY_ZEND_CLASS FATAL_OPCOPY_BASE + 6 138 | #define FATAL_OPCOPY_ZEND_CLASS_ENTRY FATAL_OPCOPY_BASE + 7 139 | 140 | /* Error codes used by zvcache */ 141 | #define FATAL_ZVCACHE_BASE 900 142 | #define FATAL_ZVCACHE_INITIALIZE FATAL_ZVCACHE_BASE + 1 143 | #define FATAL_ZVCACHE_INIT_EVENT FATAL_ZVCACHE_BASE + 2 144 | #define FATAL_ZVCACHE_INVALID_ZVAL FATAL_ZVCACHE_BASE + 3 145 | #define FATAL_ZVCACHE_INVALID_KEY_LENGTH FATAL_ZVCACHE_BASE + 4 146 | 147 | /* Error codes used by session handler */ 148 | #define FATAL_SESSION_BASE 1000 149 | #define FATAL_SESSION_INITIALIZE FATAL_SESSION_BASE + 1 150 | #define FATAL_SESSION_PATHLONG FATAL_SESSION_BASE + 2 151 | #define FATAL_SESSION_EMPTY_ID FATAL_SESSION_BASE + 3 152 | 153 | /* Error codes used by file change notification */ 154 | #define FATAL_FCNOTIFY_BASE 1100 155 | #define FATAL_FCNOTIFY_INITIALIZE FATAL_FCNOTIFY_BASE + 1 156 | #define FATAL_FCNOTIFY_OPENPROCESS FATAL_FCNOTIFY_BASE + 2 157 | #define FATAL_FCNOTIFY_CREATEFILE FATAL_FCNOTIFY_BASE + 3 158 | #define FATAL_FCNOTIFY_COMPPORT FATAL_FCNOTIFY_BASE + 4 159 | #define FATAL_FCNOTIFY_RDCFAILURE FATAL_FCNOTIFY_BASE + 5 160 | 161 | /* Warning codes */ 162 | #define WARNING_COMMON_BASE 5000 163 | #define WARNING_FCACHE_TOOBIG WARNING_COMMON_BASE + 1 164 | #define WARNING_OPCOPY_MISSING_PARENT WARNING_COMMON_BASE + 2 165 | #define WARNING_FILEMAP_MAPVIEW WARNING_COMMON_BASE + 3 166 | #define WARNING_ZVCACHE_EMISSING WARNING_COMMON_BASE + 4 167 | #define WARNING_ZVCACHE_EXISTS WARNING_COMMON_BASE + 5 168 | #define WARNING_ZVCACHE_NOTLONG WARNING_COMMON_BASE + 6 169 | #define WARNING_ZVCACHE_ARGUMENT WARNING_COMMON_BASE + 7 170 | #define WARNING_ZVCACHE_RESCOPYIN WARNING_COMMON_BASE + 8 171 | #define WARNING_ZVCACHE_CASNEQ WARNING_COMMON_BASE + 9 172 | #define WARNING_LOCK_IGNORE WARNING_COMMON_BASE + 10 173 | #define WARNING_FCNOTIFY_FORCECHECK WARNING_COMMON_BASE + 11 174 | #define WARNING_ORESOLVE_FAILURE WARNING_COMMON_BASE + 12 175 | #define WARNING_APPPOOL_NAME_NOT_FOUND WARNING_COMMON_BASE + 13 176 | 177 | /* SUCCEEDED and FAILED macros */ 178 | #ifdef SUCCEEDED 179 | #undef SUCCEEDED 180 | #endif 181 | #define SUCCEEDED(r) ((r == NONFATAL) ? 1 : 0) 182 | #ifdef FAILED 183 | #undef FAILED 184 | #endif 185 | #define FAILED(r) ((r != NONFATAL) ? 1 : 0) 186 | 187 | typedef struct error_context error_context; 188 | struct error_context 189 | { 190 | unsigned int error_code; 191 | unsigned char * error_message; 192 | }; 193 | 194 | extern unsigned int error_getlasterror(); 195 | extern unsigned int error_setlasterror(); 196 | extern char * error_gethrmessage(); 197 | extern char * error_getmessage(unsigned int error_code); 198 | 199 | #endif /* _WINCACHE_FATAL_H_ */ 200 | -------------------------------------------------------------------------------- /wincache_session.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_session.c | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | +----------------------------------------------------------------------------------------------+ 32 | */ 33 | 34 | #include "precomp.h" 35 | 36 | #define ZVSCACHE_KEY 1 37 | 38 | #ifdef _WIN64 39 | #define SESSION_NAME_SUFFIX_FORMAT "_session_%u_%u_x64.tmp" 40 | #define SESSION_NAME_NAMESALT_SUFFIX_FORMAT "_session_%u_%s_%u_x64.tmp" 41 | #else /* not _WIN64 */ 42 | #define SESSION_NAME_SUFFIX_FORMAT "_session_%u_%u.tmp" 43 | #define SESSION_NAME_NAMESALT_SUFFIX_FORMAT "_session_%u_%s_%u.tmp" 44 | #endif /* _WIN64 */ 45 | 46 | 47 | ps_module ps_mod_wincache = { PS_MOD(wincache) }; 48 | 49 | static void scache_destructor(void * pdestination) 50 | { 51 | zvcache_context ** ppcache = NULL; 52 | 53 | _ASSERT(pdestination != NULL); 54 | ppcache = (zvcache_context **)pdestination; 55 | 56 | if (WCG(zvscache) && WCG(zvscache) == *ppcache) 57 | { 58 | WCG(zvscache) = NULL; 59 | } 60 | 61 | zvcache_terminate(*ppcache); 62 | zvcache_destroy(*ppcache); 63 | 64 | ppcache = NULL; 65 | return; 66 | } 67 | 68 | /* Called on session start. Nothing to do */ 69 | PS_OPEN_FUNC(wincache) 70 | { 71 | int result = NONFATAL; 72 | zvcache_context * pcache = NULL; 73 | zvcache_context * pzcache = NULL; 74 | zend_ini_entry * pinientry = NULL; 75 | HashTable * phtable = NULL; 76 | unsigned char hashupdate = 0; 77 | char * scolon = NULL; 78 | char * filepath = NULL; 79 | size_t fpathlen = 0; 80 | uint32_t cachekey = 0; 81 | HANDLE hOriginalToken = NULL; 82 | int fCreatedHashtable = 0; 83 | 84 | dprintverbose("start ps_open_func"); 85 | 86 | if(WCG(inisavepath) == NULL) 87 | { 88 | pinientry = zend_hash_str_find_ptr(EG(ini_directives), "session.save_path", sizeof("session.save_path")-1); 89 | _ASSERT(pinientry != NULL); 90 | WCG(inisavepath) = pinientry; 91 | } 92 | 93 | /* Create hashtable if not created yet */ 94 | if(WCG(phscache) == NULL) 95 | { 96 | phtable = alloc_pemalloc(sizeof(HashTable)); 97 | if(phtable == NULL) 98 | { 99 | result = FATAL_OUT_OF_LMEMORY; 100 | goto Finished; 101 | } 102 | 103 | zend_hash_init(phtable, 0, NULL, scache_destructor, 1); 104 | WCG(phscache) = phtable; 105 | phtable = NULL; 106 | fCreatedHashtable = 1; 107 | } 108 | 109 | /* Use zvscache for unmodified save_path. Else get zvcache_context from phscache */ 110 | /* If save path is modified but is same as PHP_INI_SYSTEM, use zvscache */ 111 | if(WCG(inisavepath)->modified == 0 || zend_string_equals(WCG(inisavepath)->orig_value, WCG(inisavepath)->value)) 112 | { 113 | pzcache = WCG(zvscache); 114 | cachekey = ZVSCACHE_KEY; 115 | hashupdate = 1; 116 | } 117 | else 118 | { 119 | /* If save path is modified and is not blank, use its own session cache */ 120 | /* savepath specific cache key minimum is 2 and maximum is 65535 */ 121 | cachekey = utils_hashcalc(save_path, strlen(save_path)); 122 | cachekey = (cachekey % 65534) + 2; 123 | 124 | pcache = zend_hash_index_find_ptr(WCG(phscache), (ulong)cachekey); 125 | if(pcache == NULL) 126 | { 127 | /* If cachekey cache is not found, update it after creating it */ 128 | hashupdate = 1; 129 | } 130 | else 131 | { 132 | pzcache = pcache; 133 | } 134 | } 135 | 136 | /* If session cache is not created yet create now */ 137 | /* Handling save_path as is done in ext\session\mod_files.c */ 138 | if(pzcache == NULL) 139 | { 140 | result = utils_revert_if_necessary(&hOriginalToken); 141 | if (FAILED(result)) 142 | { 143 | goto Finished; 144 | } 145 | 146 | if(*save_path != '\0') 147 | { 148 | /* Get last portion from [dirdepth;[filemode;]]dirpath */ 149 | scolon = strchr(save_path, ';'); 150 | while(scolon != NULL) 151 | { 152 | save_path = scolon + 1; 153 | scolon = strchr(save_path, ';'); 154 | } 155 | } 156 | 157 | /* Use temporary folder as save_path if its blank */ 158 | if(*save_path == '\0') 159 | { 160 | save_path = php_get_temporary_directory(); 161 | 162 | /* Check if path is accessible as per open_basedir */ 163 | if(php_check_open_basedir(save_path)) 164 | { 165 | result = FATAL_SESSION_INITIALIZE; 166 | goto Finished; 167 | } 168 | } 169 | 170 | _ASSERT(save_path != NULL); 171 | 172 | /* Create path as save_path\wincache__session_[_]ppid. 6 for _ */ 173 | fpathlen = strlen(save_path) + 1 + sizeof("wincache__session_x64_.tmp") + 6 + ((WCG(namesalt) == NULL) ? 0 : (strlen(WCG(namesalt)) + 1)) + 5; 174 | 175 | /* add the PHP_AND_WINCACHE_VERSION */ 176 | fpathlen += sizeof(STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION)); 177 | fpathlen += PHP_WINCACHE_VERSION_LEN; 178 | 179 | if(fpathlen > MAX_PATH) 180 | { 181 | result = FATAL_SESSION_PATHLONG; 182 | goto Finished; 183 | } 184 | 185 | filepath = (char *)alloc_pemalloc(fpathlen); 186 | if(filepath == NULL) 187 | { 188 | result = FATAL_OUT_OF_LMEMORY; 189 | goto Finished; 190 | } 191 | 192 | ZeroMemory(filepath, fpathlen); 193 | if(WCG(namesalt) == NULL) 194 | { 195 | _snprintf_s(filepath, fpathlen, fpathlen - 1, "%s\\wincache_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION SESSION_NAME_SUFFIX_FORMAT, save_path, cachekey, WCG(parentpid)); 196 | } 197 | else 198 | { 199 | _snprintf_s(filepath, fpathlen, fpathlen - 1, "%s\\wincache_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION SESSION_NAME_NAMESALT_SUFFIX_FORMAT, save_path, cachekey, WCG(namesalt), WCG(parentpid)); 200 | } 201 | 202 | /* Create session cache on call to session_start */ 203 | result = zvcache_create(&pzcache); 204 | if(FAILED(result)) 205 | { 206 | goto Finished; 207 | } 208 | 209 | /* issession = 1, islocal = 0, zvcount = 256 */ 210 | result = zvcache_initialize(pzcache, 1, 0, (unsigned short)cachekey, WCG(scachesize), filepath); 211 | if(FAILED(result)) 212 | { 213 | goto Finished; 214 | } 215 | 216 | if(hashupdate) 217 | { 218 | zend_hash_index_update_ptr(WCG(phscache), (ulong)cachekey, (void *) pzcache); 219 | } 220 | 221 | if(cachekey == ZVSCACHE_KEY) 222 | { 223 | WCG(zvscache) = pzcache; 224 | } 225 | } 226 | 227 | PS_SET_MOD_DATA(pzcache); 228 | 229 | Finished: 230 | 231 | utils_reimpersonate_if_necessary(hOriginalToken); 232 | hOriginalToken = NULL; 233 | 234 | if(filepath != NULL) 235 | { 236 | alloc_pefree(filepath); 237 | filepath = NULL; 238 | } 239 | 240 | if(FAILED(result)) 241 | { 242 | dprintimportant("failure %d in ps_open_func", result); 243 | 244 | if (fCreatedHashtable) 245 | { 246 | /* 247 | * If we failed after creating the hashtable and assigning it to 248 | * WCG(phscache), then we need to clear out WCG(phscache). 249 | */ 250 | phtable = WCG(phscache); 251 | WCG(phscache) = NULL; 252 | } 253 | 254 | if(phtable != NULL) 255 | { 256 | zend_hash_destroy(phtable); 257 | alloc_pefree(phtable); 258 | phtable = NULL; 259 | } 260 | 261 | if(pzcache != NULL) 262 | { 263 | if (WCG(zvscache) == pzcache) 264 | { 265 | WCG(zvscache) = NULL; 266 | } 267 | 268 | /* 269 | * NOTE: It should be safe to destroy the pzcache at this point, 270 | * since it should NOT have been added to the phtable. If it had, 271 | * this would lead to a double-deref of the pzcache. 272 | */ 273 | zvcache_terminate(pzcache); 274 | zvcache_destroy(pzcache); 275 | 276 | pzcache = NULL; 277 | } 278 | 279 | dprintverbose("end ps_open_func"); 280 | return FAILURE; 281 | } 282 | 283 | dprintverbose("end ps_open_func"); 284 | return SUCCESS; 285 | } 286 | 287 | /* Called on session close. Nothing to do. */ 288 | PS_CLOSE_FUNC(wincache) 289 | { 290 | dprintverbose("start ps_close_func"); 291 | 292 | PS_SET_MOD_DATA(NULL); 293 | 294 | dprintverbose("end ps_close_func"); 295 | return SUCCESS; 296 | } 297 | 298 | /* Called on session start which reads all values into memory */ 299 | PS_READ_FUNC(wincache) 300 | { 301 | int result = NONFATAL; 302 | zval tmp_zval; 303 | zval * pzval = &tmp_zval; 304 | zvcache_context * pzcache = NULL; 305 | 306 | dprintverbose("start ps_read_func"); 307 | 308 | _ASSERT(key != NULL); 309 | _ASSERT(val != NULL); 310 | 311 | pzcache = PS_GET_MOD_DATA(); 312 | if(pzcache == NULL) 313 | { 314 | result = FATAL_SESSION_INITIALIZE; 315 | goto Finished; 316 | } 317 | 318 | if (ZSTR_LEN(key) == 0 || ZSTR_VAL(key)[0] == '\0') 319 | { 320 | dprintverbose("ps_read_func: empty session ID name"); 321 | 322 | result = FATAL_SESSION_EMPTY_ID; 323 | goto Finished; 324 | } 325 | 326 | ZVAL_NULL(pzval); 327 | 328 | result = zvcache_get(pzcache, ZSTR_VAL(key), &pzval); 329 | if(FAILED(result)) 330 | { 331 | if (result == WARNING_ZVCACHE_EMISSING) 332 | { 333 | /* Ignore not-found values */ 334 | result = NONFATAL; 335 | *val = ZSTR_EMPTY_ALLOC(); 336 | } 337 | goto Finished; 338 | } 339 | 340 | *val = zend_string_copy(Z_STR_P(pzval)); 341 | 342 | Finished: 343 | 344 | if(FAILED(result)) 345 | { 346 | dprintimportant("failure %d in ps_read_func", result); 347 | 348 | *val = ZSTR_EMPTY_ALLOC(); 349 | return FAILURE; 350 | } 351 | 352 | dprintverbose("end ps_read_func"); 353 | return SUCCESS; 354 | } 355 | 356 | /* Called on session close which writes all values to memory */ 357 | PS_WRITE_FUNC(wincache) 358 | { 359 | int result = NONFATAL; 360 | zval tmp_zval; 361 | zvcache_context * pzcache = NULL; 362 | 363 | dprintverbose("start ps_write_func"); 364 | 365 | _ASSERT(key != NULL); 366 | _ASSERT(val != NULL); 367 | 368 | pzcache = PS_GET_MOD_DATA(); 369 | if(pzcache == NULL) 370 | { 371 | result = FATAL_SESSION_INITIALIZE; 372 | goto Finished; 373 | } 374 | 375 | if (ZSTR_LEN(key) == 0 || ZSTR_VAL(key)[0] == '\0') 376 | { 377 | dprintverbose("ps_write_func: empty session ID name"); 378 | 379 | result = FATAL_SESSION_EMPTY_ID; 380 | goto Finished; 381 | } 382 | 383 | ZVAL_STR(&tmp_zval, val); 384 | 385 | /* ttl = session.gc_maxlifetime, isadd = 0 */ 386 | result = zvcache_set(pzcache, ZSTR_VAL(key), &tmp_zval, (unsigned int)INI_INT("session.gc_maxlifetime"), 0); 387 | if(FAILED(result)) 388 | { 389 | goto Finished; 390 | } 391 | 392 | Finished: 393 | 394 | if(FAILED(result)) 395 | { 396 | dprintimportant("failure %d in ps_write_func", result); 397 | 398 | return FAILURE; 399 | } 400 | 401 | dprintverbose("end ps_write_func"); 402 | return SUCCESS; 403 | } 404 | 405 | /* Called on session_destroy */ 406 | PS_DESTROY_FUNC(wincache) 407 | { 408 | int result = NONFATAL; 409 | zvcache_context * pzcache = NULL; 410 | 411 | dprintverbose("start ps_destroy_func"); 412 | 413 | _ASSERT(key != NULL); 414 | 415 | pzcache = PS_GET_MOD_DATA(); 416 | if(pzcache == NULL) 417 | { 418 | result = FATAL_SESSION_INITIALIZE; 419 | goto Finished; 420 | } 421 | 422 | if (ZSTR_LEN(key) == 0 || ZSTR_VAL(key)[0] == '\0') 423 | { 424 | dprintverbose("ps_destroy_func: empty session ID name"); 425 | 426 | /* ignore this and carry on... */ 427 | goto Finished; 428 | } 429 | 430 | result = zvcache_delete(pzcache, ZSTR_VAL(key)); 431 | if(FAILED(result)) 432 | { 433 | /* Entry not found is not a fatal error */ 434 | if(result == WARNING_ZVCACHE_EMISSING) 435 | { 436 | result = NONFATAL; 437 | } 438 | 439 | goto Finished; 440 | } 441 | 442 | Finished: 443 | 444 | if(FAILED(result)) 445 | { 446 | dprintimportant("failure %d in ps_destroy_func", result); 447 | 448 | return FAILURE; 449 | } 450 | 451 | dprintverbose("end ps_destroy_func"); 452 | return SUCCESS; 453 | } 454 | 455 | /* Do garbage collection of entries which are older */ 456 | /* than the max life time maintained by session extension */ 457 | PS_GC_FUNC(wincache) 458 | { 459 | dprintverbose("start ps_gc_func"); 460 | 461 | dprintverbose("end ps_gc_func"); 462 | return SUCCESS; 463 | } 464 | -------------------------------------------------------------------------------- /wincache_lock.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------------------------------+ 3 | | Windows Cache for PHP | 4 | +----------------------------------------------------------------------------------------------+ 5 | | Copyright (c) 2009, Microsoft Corporation. All rights reserved. | 6 | | | 7 | | Redistribution and use in source and binary forms, with or without modification, are | 8 | | permitted provided that the following conditions are met: | 9 | | - Redistributions of source code must retain the above copyright notice, this list of | 10 | | conditions and the following disclaimer. | 11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of | 12 | | conditions and the following disclaimer in the documentation and/or other materials provided | 13 | | with the distribution. | 14 | | - Neither the name of the Microsoft Corporation nor the names of its contributors may be | 15 | | used to endorse or promote products derived from this software without specific prior written| 16 | | permission. | 17 | | | 18 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS | 19 | | OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | 20 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | 21 | | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | 22 | | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE| 23 | | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | 24 | | AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | 25 | | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | 26 | | OF THE POSSIBILITY OF SUCH DAMAGE. | 27 | +----------------------------------------------------------------------------------------------+ 28 | | Module: wincache_lock.c | 29 | +----------------------------------------------------------------------------------------------+ 30 | | Author: Kanwaljeet Singla | 31 | | Updated: Eric Stenson | 32 | +----------------------------------------------------------------------------------------------+ 33 | */ 34 | 35 | #include "precomp.h" 36 | 37 | #ifdef _WIN64 38 | #define LOCK_SUFFIX_FORMAT "_%u_%u_%u_x64_" 39 | #define LOCK_NAMESALT_SUFFIX_FORMAT "_%u_%s_%u_%u_x64_" 40 | #else /* not _WIN64 */ 41 | #define LOCK_SUFFIX_FORMAT "_%u_%u_%u_" 42 | #define LOCK_NAMESALT_SUFFIX_FORMAT "_%u_%s_%u_%u_" 43 | #endif /* _WIN64 */ 44 | 45 | 46 | /* Globals */ 47 | unsigned short glockid = 1; 48 | 49 | /* Create a new lock context */ 50 | /* Call lock_initialize to actually create the lock */ 51 | int lock_create(lock_context ** pplock) 52 | { 53 | int result = NONFATAL; 54 | lock_context * plock = NULL; 55 | 56 | dprintverbose("start lock_create"); 57 | 58 | _ASSERT( pplock != NULL ); 59 | *pplock = NULL; 60 | 61 | plock = (lock_context *)alloc_pemalloc(sizeof(lock_context)); 62 | if(plock == NULL) 63 | { 64 | result = FATAL_OUT_OF_LMEMORY; 65 | goto Finished; 66 | } 67 | 68 | /* Initialize lock_context structure with default values */ 69 | plock->id = glockid++; 70 | plock->type = LOCK_TYPE_INVALID; 71 | plock->unused = 0; 72 | plock->state = LOCK_STATE_UNLOCKED; 73 | plock->nameprefix = NULL; 74 | plock->namelen = 0; 75 | plock->hxlock = NULL; 76 | plock->last_owner = NULL; 77 | 78 | /* id is 8 bit field. Keep maximum to 255 */ 79 | if(glockid == 256) 80 | { 81 | glockid = 1; 82 | } 83 | 84 | *pplock = plock; 85 | _ASSERT(SUCCEEDED(result)); 86 | 87 | Finished: 88 | 89 | if(FAILED(result)) 90 | { 91 | dprintimportant("failure %d in lock_create", result); 92 | } 93 | 94 | dprintverbose("end lock_create"); 95 | 96 | return result; 97 | } 98 | 99 | /* Destroy the lock context */ 100 | void lock_destroy(lock_context * plock) 101 | { 102 | dprintverbose("start lock_destroy"); 103 | 104 | if( plock != NULL ) 105 | { 106 | _ASSERT(plock->nameprefix == NULL); 107 | _ASSERT(plock->hxlock == NULL); 108 | 109 | alloc_pefree(plock); 110 | plock = NULL; 111 | } 112 | 113 | dprintverbose("end lock_destroy"); 114 | } 115 | 116 | /* Caller must free ppnew_prefix using alloc_pefree() */ 117 | int lock_get_nameprefix( 118 | char * name, 119 | unsigned short cachekey, 120 | unsigned short type, 121 | char **ppnew_prefix, 122 | size_t * pcchnew_prefix 123 | ) 124 | { 125 | int result = NONFATAL; 126 | char * objname = 0; 127 | size_t namelen = 0; 128 | int actual_len = 0; 129 | int pid = 0; 130 | int ppid = 0; 131 | 132 | /* Get the initial length of name prefix */ 133 | namelen = strlen(name); 134 | _ASSERT(namelen > 0); 135 | 136 | /* If a namesalt is specified, put _ in the name */ 137 | if(WCG(namesalt) != NULL) 138 | { 139 | namelen += strlen(WCG(namesalt)) + 1; 140 | } 141 | 142 | /* Depending on what type of lock to create, get pid and ppid */ 143 | switch(type) 144 | { 145 | case LOCK_TYPE_SHARED: 146 | ppid = WCG(fmapgdata)->ppid; 147 | namelen += PID_MAX_LENGTH; 148 | break; 149 | case LOCK_TYPE_LOCAL: 150 | pid = WCG(fmapgdata)->pid; 151 | namelen += PID_MAX_LENGTH; 152 | break; 153 | case LOCK_TYPE_GLOBAL: 154 | break; 155 | default: 156 | result = FATAL_LOCK_INVALID_TYPE; 157 | goto Finished; 158 | } 159 | 160 | /* Add 6 for underscores, 1 for null termination, */ 161 | /* LOCK_NUMBER_MAX_STRLEN for adding cachekey, 2 for 0 (for global), */ 162 | /* PHP_WINCACHE_VERSION_LEN, plus the length of the PHP Maj.Min version. */ 163 | namelen = namelen + LOCK_NUMBER_MAX_STRLEN + 9; 164 | namelen += sizeof(STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION)); 165 | namelen += PHP_WINCACHE_VERSION_LEN; 166 | 167 | /* Add 2 for lock-type padding. The buffer will be used to tack on 168 | * an extra char for the lock type by the caller. */ 169 | namelen += 2; 170 | 171 | /* Synchronization object names are limited to MAX_PATH characters */ 172 | if(namelen >= MAX_PATH - 1) 173 | { 174 | result = FATAL_LOCK_LONGNAME; 175 | goto Finished; 176 | } 177 | 178 | objname = (char *)alloc_pemalloc(namelen + 1); 179 | if(objname == NULL) 180 | { 181 | result = FATAL_OUT_OF_LMEMORY; 182 | goto Finished; 183 | } 184 | 185 | ZeroMemory(objname, namelen + 1); 186 | 187 | /* Create nameprefix as name_pid_ppid_ */ 188 | if(WCG(namesalt) == NULL) 189 | { 190 | actual_len = _snprintf_s(objname, namelen + 1, namelen, "%s_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION LOCK_SUFFIX_FORMAT, name, cachekey, pid, ppid); 191 | } 192 | else 193 | { 194 | actual_len = _snprintf_s(objname, namelen + 1, namelen, "%s_" STRVER2(PHP_MAJOR_VERSION, PHP_MINOR_VERSION) "_" PHP_WINCACHE_VERSION LOCK_NAMESALT_SUFFIX_FORMAT, name, cachekey, WCG(namesalt), pid, ppid); 195 | } 196 | 197 | if (-1 == actual_len) 198 | { 199 | error_setlasterror(); 200 | result = FATAL_LOCK_LONGNAME; 201 | goto Finished; 202 | } 203 | 204 | /* Zero out the trailing portion of the buffer, for safety! */ 205 | ZeroMemory(objname + actual_len, namelen - actual_len); 206 | 207 | *ppnew_prefix = objname; 208 | *pcchnew_prefix = actual_len; 209 | 210 | Finished: 211 | return result; 212 | } 213 | 214 | /* Initialize the lock context with valid information */ 215 | /* lock is not ready to use unless initialize is called */ 216 | /*++ 217 | 218 | Arguments: 219 | 220 | plock pointer to lock_context to be initialized 221 | name unique name for this lock 222 | cachekey ? 223 | type scope of this lock (Local/Shared/Global) 224 | plast_owner Optional pointer to unsigned int that will receive the PID 225 | of the process which last successfully acquired the lock. 226 | 227 | Return Value: 228 | 229 | NONFATAL Success 230 | FAIL_LOCK_INIT_CREATMUTEX Failed to create named mutex. Call error_getlasterror() for more info. 231 | 232 | --*/ 233 | int lock_initialize(lock_context * plock, char * name, unsigned short cachekey, unsigned short type, unsigned int * plast_owner) 234 | { 235 | int result = NONFATAL; 236 | char * objname = 0; 237 | size_t namelen = 0; 238 | int pid = 0; 239 | int ppid = 0; 240 | 241 | dprintverbose("start lock_initialize"); 242 | 243 | _ASSERT(plock != NULL); 244 | _ASSERT(name != NULL); 245 | _ASSERT(cachekey != 0); 246 | _ASSERT(cachekey <= LOCK_NUMBER_MAXIMUM); 247 | _ASSERT(type <= LOCK_TYPE_MAXIMUM); 248 | 249 | if(cachekey > LOCK_NUMBER_MAXIMUM) 250 | { 251 | result = FATAL_LOCK_NUMBER_LARGE; 252 | goto Finished; 253 | } 254 | 255 | result = lock_get_nameprefix(name, cachekey, type, &objname, &namelen); 256 | if (FAILED(result)) 257 | { 258 | goto Finished; 259 | } 260 | 261 | /* lock_get_nameprefix validates that 'type' is a valid lock type */ 262 | plock->type = type; 263 | 264 | /* Use the name prefix as the lock name */ 265 | plock->nameprefix = objname; 266 | _ASSERT(namelen < (MAX_PATH)); 267 | plock->namelen = (unsigned short)namelen; 268 | 269 | /* Create mutex which will be used to synchronize access */ 270 | plock->hxlock = CreateMutex(NULL, FALSE, objname); 271 | if(plock->hxlock == NULL) 272 | { 273 | dprintimportant("Failed to create lock %s due to error %u", objname, error_setlasterror()); 274 | result = FATAL_LOCK_INIT_CREATEMUTEX; 275 | goto Finished; 276 | } 277 | 278 | plock->state = LOCK_STATE_UNLOCKED; 279 | plock->last_owner = plast_owner; 280 | _ASSERT(SUCCEEDED(result)); 281 | 282 | Finished: 283 | 284 | if(FAILED(result)) 285 | { 286 | dprintimportant("failure %d in lock_initialize", result); 287 | 288 | if(plock->hxlock != NULL) 289 | { 290 | CloseHandle(plock->hxlock); 291 | plock->hxlock = NULL; 292 | } 293 | 294 | if(plock->nameprefix != NULL) 295 | { 296 | alloc_pefree(plock->nameprefix); 297 | plock->nameprefix = NULL; 298 | 299 | plock->namelen = 0; 300 | } 301 | 302 | plock->type = LOCK_TYPE_INVALID; 303 | plock->last_owner = NULL; 304 | } 305 | 306 | dprintverbose("end lock_initialize"); 307 | 308 | return result; 309 | } 310 | 311 | void lock_terminate(lock_context * plock) 312 | { 313 | dprintverbose("start lock_terminate"); 314 | 315 | if(plock != NULL) 316 | { 317 | if(plock->hxlock != NULL) 318 | { 319 | CloseHandle(plock->hxlock); 320 | plock->hxlock = NULL; 321 | } 322 | 323 | if(plock->nameprefix != NULL) 324 | { 325 | alloc_pefree(plock->nameprefix); 326 | plock->nameprefix = NULL; 327 | 328 | plock->namelen = 0; 329 | } 330 | 331 | plock->type = LOCK_TYPE_INVALID; 332 | plock->state = LOCK_STATE_UNLOCKED; 333 | plock->last_owner = NULL; 334 | } 335 | 336 | dprintverbose("end lock_terminate"); 337 | } 338 | 339 | /* Acquire write lock */ 340 | void lock_lock(lock_context * plock) 341 | { 342 | DWORD ret = 0; 343 | const char *filename; 344 | uint32_t lineno; 345 | unsigned int last_owner = 0; 346 | 347 | dprintverbose("start lock_lock %p", plock); 348 | 349 | _ASSERT(plock != NULL); 350 | _ASSERT(plock->hxlock != NULL); 351 | 352 | /* Simple case. Just lock hxwrite */ 353 | ret = WaitForSingleObject(plock->hxlock, INFINITE); 354 | 355 | if (plock->last_owner) 356 | { 357 | last_owner = *plock->last_owner; 358 | } 359 | 360 | if (ret == WAIT_ABANDONED) 361 | { 362 | error_setlasterror(); 363 | dprintcritical("lock_lock: acquired abandoned mutex %s. Something bad happend in another process!", 364 | plock->nameprefix); 365 | utils_get_filename_and_line(&filename, &lineno); 366 | EventWriteLockAbandonedMutex(plock->nameprefix, 367 | last_owner, last_owner, filename, lineno); 368 | goto Finished; 369 | } 370 | 371 | if (ret == WAIT_FAILED) 372 | { 373 | dprintcritical("lock_lock: Failure waiting on lock %s (%d). Something bad happened!", 374 | plock->nameprefix, error_setlasterror()); 375 | utils_get_filename_and_line(&filename, &lineno); 376 | EventWriteLockFailedWaitForLock(plock->nameprefix, 377 | last_owner, last_owner, filename, lineno); 378 | goto Finished; 379 | } 380 | 381 | if (plock->last_owner) 382 | { 383 | *plock->last_owner = GetCurrentProcessId(); 384 | } 385 | 386 | _ASSERT(plock->state == LOCK_STATE_UNLOCKED); 387 | plock->state = LOCK_STATE_LOCKED; 388 | 389 | Finished: 390 | 391 | dprintverbose("end lock_lock %p", plock); 392 | return; 393 | } 394 | 395 | /* Release write lock */ 396 | void lock_unlock(lock_context * plock) 397 | { 398 | dprintverbose("start lock_unlock %p", plock); 399 | 400 | _ASSERT(plock != NULL); 401 | _ASSERT(plock->hxlock != NULL); 402 | _ASSERT(plock->state == LOCK_STATE_LOCKED); 403 | 404 | /* Simple case. Just release the mutex */ 405 | plock->state = LOCK_STATE_UNLOCKED; 406 | ReleaseMutex(plock->hxlock); 407 | 408 | dprintverbose("end lock_unlock %p", plock); 409 | return; 410 | } 411 | 412 | void lock_runtest() 413 | { 414 | int result = NONFATAL; 415 | unsigned int last_owner = 0; 416 | lock_context * plock1 = NULL; 417 | lock_context * plock2 = NULL; 418 | unsigned int pid = GetCurrentProcessId(); 419 | 420 | dprintverbose("*** STARTING LOCK TESTS ***"); 421 | 422 | /* Create two locks of different types */ 423 | result = lock_create(&plock1); 424 | if(FAILED(result)) 425 | { 426 | dprintverbose("lock_create for plock1 failed"); 427 | goto Finished; 428 | } 429 | 430 | result = lock_create(&plock2); 431 | if(FAILED(result)) 432 | { 433 | dprintverbose("lock_create for plock2 failed"); 434 | goto Finished; 435 | } 436 | 437 | /* Verify IDs of two locks are different */ 438 | _ASSERT(plock1->id != plock2->id); 439 | 440 | /* Initialize first lock */ 441 | result = lock_initialize(plock1, "LOCK_TEST1", 1, LOCK_TYPE_SHARED, &last_owner); 442 | if(FAILED(result)) 443 | { 444 | dprintverbose("lock_initialize for plock1 failed"); 445 | goto Finished; 446 | } 447 | 448 | /* Verify strings and handles got created properly */ 449 | _ASSERT(plock1->namelen == strlen(plock1->nameprefix)); 450 | _ASSERT(plock1->hxlock != NULL); 451 | 452 | /* Initialize second lock */ 453 | result = lock_initialize(plock2, "LOCK_TEST2", 1, LOCK_TYPE_LOCAL, NULL); 454 | if(FAILED(result)) 455 | { 456 | dprintverbose("lock_intialize for plock2 failed"); 457 | goto Finished; 458 | } 459 | 460 | /* Verify strings and handles got created properly */ 461 | _ASSERT(plock2->namelen == strlen(plock2->nameprefix)); 462 | _ASSERT(plock2->hxlock != NULL); 463 | 464 | /* Get lock on both locks */ 465 | lock_lock(plock1); 466 | lock_lock(plock2); 467 | 468 | /* Verify reader count for shared read lock */ 469 | _ASSERT(pid == last_owner); 470 | 471 | lock_unlock(plock2); 472 | lock_unlock(plock1); 473 | 474 | _ASSERT(SUCCEEDED(result)); 475 | 476 | Finished: 477 | 478 | if(plock1 != NULL) 479 | { 480 | lock_terminate(plock1); 481 | lock_destroy(plock1); 482 | 483 | plock1 = NULL; 484 | } 485 | 486 | if(plock2 != NULL) 487 | { 488 | lock_terminate(plock2); 489 | lock_destroy(plock2); 490 | 491 | plock2 = NULL; 492 | } 493 | 494 | dprintverbose("*** ENDING LOCK TESTS ***"); 495 | 496 | return; 497 | } 498 | --------------------------------------------------------------------------------